diff --git a/src/main/scala/leon/purescala/Constructors.scala b/src/main/scala/leon/purescala/Constructors.scala
index 4404276cb9516ae211f2ab6705a9233c8310f7eb..0ba5436ed42004b888831fcc1c3e861113cc5a27 100644
--- a/src/main/scala/leon/purescala/Constructors.scala
+++ b/src/main/scala/leon/purescala/Constructors.scala
@@ -19,9 +19,10 @@ import Types._
   *  */
 object Constructors {
 
-  /** If `isTuple`, the whole expression is returned. This is to avoid a situation like
-    * `tupleSelect(tupleWrap(Seq(Tuple(x,y))),1) -> x`, which is not expected.
-    * Instead,
+  /** If `isTuple`:
+    * `tupleSelect(tupleWrap(Seq(Tuple(x,y))),1) -> x`
+    * `tupleSelect(tupleExpr,1) -> tupleExpr._1`
+    * If not `isTuple` (usually used only in the case of a tuple of arity 1)
     * `tupleSelect(tupleWrap(Seq(Tuple(x,y))),1) -> Tuple(x,y)`.
     * @see [[purescala.Expressions.TupleSelect]]
     */
diff --git a/src/main/scala/leon/synthesis/rules/StringRender.scala b/src/main/scala/leon/synthesis/rules/StringRender.scala
index 7df6ba9c908f3e35da0fe75970dfad1b8716dce3..b950213ce5a86fbbf9e0c7e164265e2c6b6cb8f0 100644
--- a/src/main/scala/leon/synthesis/rules/StringRender.scala
+++ b/src/main/scala/leon/synthesis/rules/StringRender.scala
@@ -95,7 +95,7 @@ case object StringRender extends Rule("StringRender") {
     }
   }
   
-  val booleanTemplate = (a: Identifier) => StringTemplateGenerator(Hole => IfExpr(Variable(a), Hole, Hole))
+  val booleanTemplate = (a: Expr) => StringTemplateGenerator(Hole => IfExpr(a, Hole, Hole))
   
   /** Returns a seq of expressions such as `x + y + "1" + y + "2" + z` associated to an expected result string `"1, 2"`.
     * We use these equations so that we can find the values of the constants x, y, z and so on.
@@ -242,13 +242,47 @@ case object StringRender extends Rule("StringRender") {
   
   case class DependentType(caseClassParent: Option[TypeTree], inputName: String, typeToConvert: TypeTree)
   
-  case class StringSynthesisContext(
-      currentCaseClassParent: Option[TypeTree],
-      adtToString: Map[DependentType, (FunDef, Stream[WithIds[Expr]])]
-  )(implicit hctx: SearchContext)
+  object StringSynthesisContext {
+    def empty(implicit hctx: SearchContext) = new StringSynthesisContext(None, new StringSynthesisResult(Map(), Set()))
+  }
+  
+  type MapFunctions = Map[DependentType, (FunDef, Stream[WithIds[Expr]])]
+  
+  /** Result of the current synthesis process */
+  class StringSynthesisResult(
+      val adtToString: MapFunctions,
+      val funNames: Set[String]
+  ) {
+    def add(d: DependentType, f: FunDef, s: Stream[WithIds[Expr]]): StringSynthesisResult = {
+      new StringSynthesisResult(adtToString + (d -> ((f, s))), funNames + f.id.name)
+    }
+    def freshFunName(s: String): String = {
+      if(!funNames(s)) return s
+      var i = 1
+      var s0 = s
+      do {
+        i += 1
+        s0 = s + i
+      } while(funNames(s+i))
+      s0
+    }
+  }
+  
+  /** Context for the current synthesis process */
+  class StringSynthesisContext(
+      val currentCaseClassParent: Option[TypeTree],
+      val result: StringSynthesisResult
+  )(implicit hctx: SearchContext) {
+    def add(d: DependentType, f: FunDef, s: Stream[WithIds[Expr]]): StringSynthesisContext = {
+      new StringSynthesisContext(currentCaseClassParent, result.add(d, f, s))
+    }
+    def copy(currentCaseClassParent: Option[TypeTree]=currentCaseClassParent, result: StringSynthesisResult = result): StringSynthesisContext = 
+      new StringSynthesisContext(currentCaseClassParent, result)
+    def freshFunName(s: String) = result.freshFunName(s)
+  }
   
   /** Creates an empty function definition for the dependent type */
-  def createEmptyFunDef(tpe: DependentType)(implicit hctx: SearchContext): FunDef = {
+  def createEmptyFunDef(ctx: StringSynthesisContext, tpe: DependentType)(implicit hctx: SearchContext): FunDef = {
     def defaultFunName(t: TypeTree) = t match {
       case AbstractClassType(c, d) => c.id.asString(hctx.context)
       case CaseClassType(c, d) => c.id.asString(hctx.context)
@@ -261,17 +295,17 @@ case object StringRender extends Rule("StringRender") {
     }
     val funName3 = funName2.replaceAll("[^a-zA-Z0-9_]","")
     val funName = funName3(0).toLower + funName3.substring(1) 
-    val funId = FreshIdentifier(funName, alwaysShowUniqueID = true)
+    val funId = FreshIdentifier(ctx.freshFunName(funName), alwaysShowUniqueID = true)
     val argId= FreshIdentifier(tpe.typeToConvert.asString(hctx.context).toLowerCase()(0).toString, tpe.typeToConvert)
     val fd = new FunDef(funId, Nil, ValDef(argId) :: Nil, StringType) // Empty function.
     fd
   }
   
   /** Pre-updates of the function definition */
-  def preUpdateFunDefBody(tpe: DependentType, fd: FunDef, assignments: Map[DependentType, (FunDef, Stream[WithIds[Expr]])]): Map[DependentType, (FunDef, Stream[WithIds[Expr]])] = {
-    assignments.get(tpe) match {
-      case None => assignments + (tpe -> ((fd, Stream.Empty)))
-      case Some(_) => assignments
+  def preUpdateFunDefBody(tpe: DependentType, fd: FunDef, ctx: StringSynthesisContext): StringSynthesisContext = {
+    ctx.result.adtToString.get(tpe) match {
+      case None => ctx.add(tpe, fd, Stream.Empty)
+      case Some(_) => ctx
     }
   }
 
@@ -285,17 +319,17 @@ case object StringRender extends Rule("StringRender") {
     **/
   def createFunDefsTemplates(
       ctx: StringSynthesisContext,
-      inputs: Seq[Identifier])(implicit hctx: SearchContext): (Stream[WithIds[Expr]], Map[DependentType, (FunDef, Stream[WithIds[Expr]])]) = {
+      inputs: Seq[Expr])(implicit hctx: SearchContext): (Stream[WithIds[Expr]], StringSynthesisResult) = {
     
-    def extractCaseVariants(cct: CaseClassType, assignments2: Map[DependentType, (FunDef, Stream[WithIds[Expr]])])
-      : (Map[DependentType, (FunDef, Stream[WithIds[Expr]])], Stream[WithIds[MatchCase]]) = cct match {
+    def extractCaseVariants(cct: CaseClassType, ctx: StringSynthesisContext)
+      : (Stream[WithIds[MatchCase]], StringSynthesisResult) = cct match {
       case CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tparams2) =>
         val typeMap = tparams.zip(tparams2).toMap
         val fields = ccd.fields.map(vd => TypeOps.instantiateType(vd, typeMap).id )
         val pattern = CaseClassPattern(None, ccd.typed(tparams2), fields.map(k => WildcardPattern(Some(k))))
-        val (rhs, assignments2tmp2) = createFunDefsTemplates(StringSynthesisContext(Some(cct), assignments2), fields) // Invoke functions for each of the fields.
+        val (rhs, result) = createFunDefsTemplates(ctx.copy(currentCaseClassParent=Some(cct)), fields.map(Variable)) // Invoke functions for each of the fields.
         val newCases = rhs.map(e => (MatchCase(pattern, None, e._1), e._2))
-        (assignments2tmp2, newCases)
+        (newCases, result)
     }
     
     /* Returns a constant pattern matching in which all classes are rendered using their proper name
@@ -332,27 +366,27 @@ case object StringRender extends Rule("StringRender") {
      * @return Along with the list, an updated function definitions to transform (parent-dependent) types to strings */
     @tailrec def gatherInputs(
         ctx: StringSynthesisContext,
-        inputs: List[Identifier],
-        result: ListBuffer[Stream[WithIds[Expr]]] = ListBuffer()): (List[Stream[WithIds[Expr]]], Map[DependentType, (FunDef, Stream[WithIds[Expr]])]) = inputs match {
-      case Nil => (result.toList, ctx.adtToString)
+        inputs: List[Expr],
+        result: ListBuffer[Stream[WithIds[Expr]]] = ListBuffer()): (List[Stream[WithIds[Expr]]], StringSynthesisResult) = inputs match {
+      case Nil => (result.toList, ctx.result)
       case input::q => 
         val dependentType = DependentType(ctx.currentCaseClassParent, input.asString(hctx.program)(hctx.context), input.getType)
-        ctx.adtToString.get(dependentType) match {
+        ctx.result.adtToString.get(dependentType) match {
         case Some(fd) =>
-          gatherInputs(ctx, q, result += Stream((functionInvocation(fd._1, Seq(Variable(input))), Nil)))
+          gatherInputs(ctx, q, result += Stream((functionInvocation(fd._1, Seq(input)), Nil)))
         case None => // No function can render the current type.
           input.getType match {
             case StringType =>
-              gatherInputs(ctx, q, result += Stream((Variable(input), Nil)))
+              gatherInputs(ctx, q, result += Stream((input, Nil)))
             case BooleanType =>
               val (bTemplate, vs) = booleanTemplate(input).instantiateWithVars
-              gatherInputs(ctx, q, result += Stream((BooleanToString(Variable(input)), Nil)) #::: Stream((bTemplate, vs)))
+              gatherInputs(ctx, q, result += Stream((BooleanToString(input), Nil)) #::: Stream((bTemplate, vs)))
             case WithStringconverter(converter) => // Base case
-              gatherInputs(ctx, q, result += Stream((converter(Variable(input)), Nil)))
+              gatherInputs(ctx, q, result += Stream((converter(input), Nil)))
             case t: ClassType =>
               // Create the empty function body and updates the assignments parts.
-              val fd = createEmptyFunDef(dependentType)
-              val assignments2 = preUpdateFunDefBody(dependentType, fd, ctx.adtToString) // Inserts the FunDef in the assignments so that it can already be used.
+              val fd = createEmptyFunDef(ctx, dependentType)
+              val ctx2 = preUpdateFunDefBody(dependentType, fd, ctx) // Inserts the FunDef in the assignments so that it can already be used.
               t.root match {
                 case act@AbstractClassType(acd@AbstractClassDef(id, tparams, parent), tps) =>
                   // Create a complete FunDef body with pattern matching
@@ -363,10 +397,11 @@ case object StringRender extends Rule("StringRender") {
                   }}
                   
                   //TODO: Test other templates not only with Wilcard patterns, but more cases options for non-recursive classes (e.g. Option, Boolean, Finite parameterless case classes.)
-                  val (assignments3, cases) = ((assignments2, ListBuffer[Stream[WithIds[MatchCase]]]()) /: act.knownCCDescendants) {
-                    case ((assignments2, acc), cct@CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tparams2)) =>
-                      val (assignments2tmp2, newCases) = extractCaseVariants(cct, assignments2)
-                      (assignments2tmp2, acc += newCases)
+                  val (ctx3, cases) = ((ctx2, ListBuffer[Stream[WithIds[MatchCase]]]()) /: act.knownCCDescendants) {
+                    case ((ctx22, acc), cct@CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tparams2)) =>
+                      val (newCases, result) = extractCaseVariants(cct, ctx22)
+                      val ctx23 = ctx22.copy(result = result)
+                      (ctx23, acc += newCases)
                     case ((adtToString, acc), e) => hctx.reporter.fatalError("Could not handle this class definition for string rendering " + e)
                   }
                   
@@ -374,13 +409,11 @@ case object StringRender extends Rule("StringRender") {
                   val allMatchExprs = if(allKnownDescendantsAreCCAndHaveZeroArgs) {
                     Stream(constantPatternMatching(fd, act)) ++ allMatchExprsEnd
                   } else allMatchExprsEnd
-                  val assignments4 = assignments3 + (dependentType -> (fd, allMatchExprs))
-                  gatherInputs(ctx.copy(adtToString = assignments4), q, result += Stream((functionInvocation(fd, Seq(Variable(input))), Nil)))
+                  gatherInputs(ctx3.add(dependentType, fd, allMatchExprs), q, result += Stream((functionInvocation(fd, Seq(input)), Nil)))
                 case cct@CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tparams2) =>
-                  val (assignments3, newCases) = extractCaseVariants(cct, assignments2)
+                  val (newCases, result3) = extractCaseVariants(cct, ctx2)
                   val allMatchExprs = newCases.map(acase => mergeMatchCases(fd)(Seq(acase)))
-                  val assignments4 = assignments3 + (dependentType -> (fd, allMatchExprs))
-                  gatherInputs(ctx.copy(adtToString = assignments4), q, result += Stream((functionInvocation(fd, Seq(Variable(input))), Nil)))
+                  gatherInputs(ctx2.copy(result = result3).add(dependentType, fd, allMatchExprs), q, result += Stream((functionInvocation(fd, Seq(input)), Nil)))
               }
             case TypeParameter(t) =>
               hctx.reporter.fatalError("Could not handle type parameter for string rendering " + t)
@@ -389,22 +422,37 @@ case object StringRender extends Rule("StringRender") {
           }
       }
     }
-    val (exprs, assignments) = gatherInputs(ctx, inputs.toList)
-    /* Add post, pre and in-between holes, and returns a single expr along with the new assignments. */
-    val template: Stream[WithIds[Expr]] = exprs match {
-      case Nil =>
-        Stream(StringTemplateGenerator(Hole => Hole).instantiateWithVars)
-      case exprList =>
-        JoinProgramSet(exprList.map(DirectProgramSet(_)), (exprs: Seq[WithIds[Expr]]) =>
-            StringTemplateGenerator.nested(Hole => {
-              val res = ((StringConcat(Hole, exprs.head._1), exprs.head._2) /: exprs.tail) {
-                case ((finalExpr, finalIds), (expr, ids)) => (StringConcat(StringConcat(finalExpr, Hole), expr), finalIds ++ ids)
-              }
-              (StringConcat(res._1, Hole), res._2)
-            }).instantiateWithVars
-        ).programs
+    var ctx2 = ctx // We gather the functions only once.
+    // Flatten tuple types
+    val newInputs = inputs.flatMap{ case input =>
+      input.getType match {
+        case TupleType(bases) =>
+          val blength = bases.length
+          for(index <- 1 to blength) yield tupleSelect(input, index, blength)
+        case _ => List(input)
+      }
+    }
+    // Get all permutations
+    val templates = for(inputPermutation <- newInputs.permutations.toStream) yield {
+      val (exprs, result3) = gatherInputs(ctx2, inputPermutation.toList)
+      ctx2 = ctx2.copy(result=result3)
+      /* Add post, pre and in-between holes, and returns a single expr along with the new assignments. */
+      val template: Stream[WithIds[Expr]] = exprs match {
+        case Nil =>
+          Stream(StringTemplateGenerator(Hole => Hole).instantiateWithVars)
+        case exprList =>
+          JoinProgramSet(exprList.map(DirectProgramSet(_)), (exprs: Seq[WithIds[Expr]]) =>
+              StringTemplateGenerator.nested(Hole => {
+                val res = ((StringConcat(Hole, exprs.head._1), exprs.head._2) /: exprs.tail) {
+                  case ((finalExpr, finalIds), (expr, ids)) => (StringConcat(StringConcat(finalExpr, Hole), expr), finalIds ++ ids)
+                }
+                (StringConcat(res._1, Hole), res._2)
+              }).instantiateWithVars
+          ).programs
+      }
+      template
     }
-    (template, assignments)
+    (templates.flatten, ctx2.result) // TODO: Flatten or interleave?
   }
   
   def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
@@ -420,7 +468,8 @@ case object StringRender extends Rule("StringRender") {
         
         val ruleInstantiations = ListBuffer[RuleInstantiation]()
         ruleInstantiations += RuleInstantiation("String conversion") {
-          val (expr, funDefs) = createFunDefsTemplates(StringSynthesisContext(None, Map()), p.as)
+          val (expr, synthesisResult) = createFunDefsTemplates(StringSynthesisContext.empty, p.as.map(Variable))
+          val funDefs = synthesisResult.adtToString
           
           val toDebug: String = (("\nInferred functions:" /: funDefs)( (t, s) =>
                 t + "\n" + s._2._1.toString
diff --git a/testcases/stringrender/OutOfOrder.scala b/testcases/stringrender/OutOfOrder.scala
new file mode 100644
index 0000000000000000000000000000000000000000..72785cf605cfbfe26bb70abd37651c32d5eddd42
--- /dev/null
+++ b/testcases/stringrender/OutOfOrder.scala
@@ -0,0 +1,57 @@
+import leon.lang._
+import leon.annotation._
+import leon.collection._
+import leon.collection.ListOps._
+import leon.lang.synthesis._
+
+object OutOfOrderToString {
+  def argumentsToString(i: Int, j: Int): String = {
+    ???
+  } ensuring { (res: String) => ((i, j), res) passes {
+    case (1, 2) => "2, 1"
+  } }
+  
+  def tupleToString(i: (Int, Int)): String = {
+    ???
+  } ensuring { (res: String) => (i, res) passes {
+    case (1, 2) => "2, 1"
+  } }
+  
+  
+  def reverseList(l : List[Int]): String =  {
+    ???[String]
+  } ensuring {
+    (res : String) => (l, res) passes {
+      case Cons(1, Cons(2, Nil())) =>
+        "2, 1"
+    }
+  }
+  
+  def listPairToString(l : List[(Int, Int)]): String =  {
+    ???[String]
+  } ensuring {
+    (res : String) => (l, res) passes {
+      case Cons((1, 2), Cons((3, 4), Nil())) =>
+        "2 -> 1, 4 -> 3"
+    }
+  }
+  
+  def reverselistPairToString(l: List[(Int, Int)]): String = {
+    ???
+  } ensuring { (res: String) => (l, res) passes {
+    case Cons((1, 2), Cons((3,4), Nil())) => "4 -> 3, 2 -> 1"
+  } }
+  
+  case class Rule(input: Int, applied: Option[Int])
+  
+  def ruleToString(r : Rule): String =  {
+    ???
+  } ensuring {
+    (res : String) => (r, res) passes {
+      case Rule(1, None()) =>
+        "res: 1"
+      case Rule(4, Some(2)) =>
+        "Push(2): 4"
+    }
+  }
+}
\ No newline at end of file
diff --git a/testcases/web/synthesis/25_String_OutOfOrder.scala b/testcases/web/synthesis/25_String_OutOfOrder.scala
new file mode 100644
index 0000000000000000000000000000000000000000..72785cf605cfbfe26bb70abd37651c32d5eddd42
--- /dev/null
+++ b/testcases/web/synthesis/25_String_OutOfOrder.scala
@@ -0,0 +1,57 @@
+import leon.lang._
+import leon.annotation._
+import leon.collection._
+import leon.collection.ListOps._
+import leon.lang.synthesis._
+
+object OutOfOrderToString {
+  def argumentsToString(i: Int, j: Int): String = {
+    ???
+  } ensuring { (res: String) => ((i, j), res) passes {
+    case (1, 2) => "2, 1"
+  } }
+  
+  def tupleToString(i: (Int, Int)): String = {
+    ???
+  } ensuring { (res: String) => (i, res) passes {
+    case (1, 2) => "2, 1"
+  } }
+  
+  
+  def reverseList(l : List[Int]): String =  {
+    ???[String]
+  } ensuring {
+    (res : String) => (l, res) passes {
+      case Cons(1, Cons(2, Nil())) =>
+        "2, 1"
+    }
+  }
+  
+  def listPairToString(l : List[(Int, Int)]): String =  {
+    ???[String]
+  } ensuring {
+    (res : String) => (l, res) passes {
+      case Cons((1, 2), Cons((3, 4), Nil())) =>
+        "2 -> 1, 4 -> 3"
+    }
+  }
+  
+  def reverselistPairToString(l: List[(Int, Int)]): String = {
+    ???
+  } ensuring { (res: String) => (l, res) passes {
+    case Cons((1, 2), Cons((3,4), Nil())) => "4 -> 3, 2 -> 1"
+  } }
+  
+  case class Rule(input: Int, applied: Option[Int])
+  
+  def ruleToString(r : Rule): String =  {
+    ???
+  } ensuring {
+    (res : String) => (r, res) passes {
+      case Rule(1, None()) =>
+        "res: 1"
+      case Rule(4, Some(2)) =>
+        "Push(2): 4"
+    }
+  }
+}
\ No newline at end of file