diff --git a/src/main/scala/inox/ast/SymbolOps.scala b/src/main/scala/inox/ast/SymbolOps.scala
index 82831049c87d9443a3fee78a3ff95487c93ef570..c966e166d0a7233b31e2163043ed744875532606 100644
--- a/src/main/scala/inox/ast/SymbolOps.scala
+++ b/src/main/scala/inox/ast/SymbolOps.scala
@@ -184,12 +184,16 @@ trait SymbolOps { self: TypeOps =>
         val (es, recons) = extractMatcher(map)
         (key +: es, { case key +: es => MapApply(recons(es), key) })
 
+      case FunctionInvocation(id, tps, args) =>
+        (args, es => FunctionInvocation(id, tps, es))
+
       case _ => (Seq(e), es => es.head)
     }
 
     def outer(vars: Set[Variable], body: Expr): Expr = {
       // this registers the argument images into subst
       val tvars = vars map (v => v.copy(id = transformId(v.id, v.tpe)))
+      subst --= tvars
 
       def isLocal(e: Expr, path: Path): Boolean = {
         val vs = variablesOf(e)
@@ -263,7 +267,6 @@ trait SymbolOps { self: TypeOps =>
           case Variable(id, tpe) =>
             Variable(transformId(id, tpe), tpe)
 
-          /*
           case (_: Application) | (_: MultiplicityInBag) | (_: ElementOfSet) | (_: MapApply) if (
             !isLocal(e, path) &&
             preserveApps
@@ -271,7 +274,6 @@ trait SymbolOps { self: TypeOps =>
             val (es, recons) = extractMatcher(e)
             val newEs = es.map(rec(_, path))
             recons(newEs)
-          */
 
           case Let(vd, e, b) if (
             isLocal(e, path) &&
@@ -306,15 +308,7 @@ trait SymbolOps { self: TypeOps =>
 
     val newExpr = outer(args.map(_.toVariable).toSet, expr)
     val bindings = args.map(vd => vd.copy(id = varSubst(vd.id)))
-
-    val bindingVars = bindings.map(_.toVariable).toSet
-    val freeVars = fixpoint { (vs: Set[Variable]) =>
-      vs ++ subst.filter(p => vs(p._1)).flatMap(p => variablesOf(p._2)) -- bindingVars
-    } (variablesOf(newExpr) -- bindings.map(_.toVariable))
-
-    val bodySubst = subst.filter(p => freeVars(p._1)).toMap
-
-    (bindings, newExpr, bodySubst)
+    (bindings, newExpr, subst.toMap)
   }
 
   def normalizeStructure(e: Expr): (Expr, Map[Variable, Expr]) = e match {
diff --git a/src/main/scala/inox/solvers/unrolling/QuantificationTemplates.scala b/src/main/scala/inox/solvers/unrolling/QuantificationTemplates.scala
index fac5a2213075f8a7883f945bcd31f087f1629793..b71a2b78e185bbc702e42490747d7bd1a2e9006d 100644
--- a/src/main/scala/inox/solvers/unrolling/QuantificationTemplates.scala
+++ b/src/main/scala/inox/solvers/unrolling/QuantificationTemplates.scala
@@ -918,90 +918,95 @@ trait QuantificationTemplates { self: Templates =>
   def instantiateQuantification(template: QuantificationTemplate): (Map[Encoded, Encoded], Clauses) = {
     templates.get(template.structure).orElse {
       templates.collectFirst { case (s, t) if s subsumes template.structure => t }
-    } match {
-      case Some((_, _, map)) =>
-        (map, Seq.empty)
-
-      case None =>
-        val newTemplate = template.concretize
-        val clauses = new scala.collection.mutable.ListBuffer[Encoded]
-        clauses ++= newTemplate.structure.instantiation
-
-        val (inst, mapping): (Encoded, Map[Encoded, Encoded]) = newTemplate.polarity match {
-          case Positive(guard) =>
-            val axiom = new Axiom(newTemplate.pathVar._2, guard,
-              newTemplate.quantifiers, newTemplate.condVars, newTemplate.exprVars, newTemplate.condTree,
-              newTemplate.clauses, newTemplate.blockers, newTemplate.applications, newTemplate.matchers,
-              newTemplate.lambdas, newTemplate.quantifications, newTemplate.pointers, newTemplate.body)
-
-            quantifications += axiom
-
-            for ((bs,m) <- handledMatchers) {
-              clauses ++= axiom.instantiate(bs, m)
-            }
+    }.map { case (tmpl, inst, _) =>
+      template.polarity match {
+        case Positive(guard) =>
+          (Map.empty[Encoded, Encoded], Seq(mkImplies(template.pathVar._2, inst)))
+        case Negative(insts) =>
+          (Map(insts._2 -> inst), Seq.empty[Encoded])
+        case Unknown(qs, q2s, insts, guard) =>
+          (Map(qs._2 -> inst), Seq.empty[Encoded])
+      }
+    }.getOrElse {
+      val newTemplate = template.concretize
+      val clauses = new scala.collection.mutable.ListBuffer[Encoded]
+      clauses ++= newTemplate.structure.instantiation
 
-            val groundGen = currentGeneration + 3
-            ignoredGrounds += groundGen -> (ignoredGrounds.getOrElse(groundGen, Set.empty) + axiom)
-            (trueT, Map.empty)
+      val (inst, mapping): (Encoded, Map[Encoded, Encoded]) = newTemplate.polarity match {
+        case Positive(guard) =>
+          val axiom = new Axiom(newTemplate.pathVar._2, guard,
+            newTemplate.quantifiers, newTemplate.condVars, newTemplate.exprVars, newTemplate.condTree,
+            newTemplate.clauses, newTemplate.blockers, newTemplate.applications, newTemplate.matchers,
+            newTemplate.lambdas, newTemplate.quantifications, newTemplate.pointers, newTemplate.body)
 
-          case Negative(insts) =>
-            val instT = encodeSymbol(insts._1)
-            val (substMap, substClauses) = Template.substitution(
-              newTemplate.condVars, newTemplate.exprVars, newTemplate.condTree,
-              newTemplate.lambdas, newTemplate.quantifications, newTemplate.pointers,
-              Map(insts._2 -> Left(instT)), newTemplate.pathVar._2)
-            clauses ++= substClauses
+          quantifications += axiom
 
-            // this will call `instantiateMatcher` on all matchers in `newTemplate.matchers`
-            clauses ++= Template.instantiate(newTemplate.clauses,
-              newTemplate.blockers, newTemplate.applications, newTemplate.matchers, substMap)
+          for ((bs,m) <- handledMatchers) {
+            clauses ++= axiom.instantiate(bs, m)
+          }
 
-            (instT, Map(insts._2 -> instT))
+          val groundGen = currentGeneration + 3
+          ignoredGrounds += groundGen -> (ignoredGrounds.getOrElse(groundGen, Set.empty) + axiom)
+          (trueT, Map.empty)
 
-          case Unknown(qs, q2s, insts, guard) =>
-            val qT = encodeSymbol(qs._1)
-            val substituter = mkSubstituter(Map(qs._2 -> qT))
+        case Negative(insts) =>
+          val instT = encodeSymbol(insts._1)
+          val (substMap, substClauses) = Template.substitution(
+            newTemplate.condVars, newTemplate.exprVars, newTemplate.condTree,
+            newTemplate.lambdas, newTemplate.quantifications, newTemplate.pointers,
+            Map(insts._2 -> Left(instT)), newTemplate.pathVar._2)
+          clauses ++= substClauses
 
-            val quantification = new GeneralQuantification(newTemplate.pathVar._2,
-              qs._1 -> qT, q2s, insts, guard,
-              newTemplate.quantifiers, newTemplate.condVars, newTemplate.exprVars, newTemplate.condTree,
-              newTemplate.clauses map substituter, // one clause depends on 'qs._2' (and therefore 'qT')
-              newTemplate.blockers, newTemplate.applications, newTemplate.matchers,
-              newTemplate.lambdas, newTemplate.quantifications, newTemplate.pointers, newTemplate.body)
+          // this will call `instantiateMatcher` on all matchers in `newTemplate.matchers`
+          clauses ++= Template.instantiate(newTemplate.clauses,
+            newTemplate.blockers, newTemplate.applications, newTemplate.matchers, substMap)
 
-            quantifications += quantification
+          (instT, Map(insts._2 -> instT))
 
-            for ((bs,m) <- handledMatchers) {
-              clauses ++= quantification.instantiate(bs, m)
-            }
+        case Unknown(qs, q2s, insts, guard) =>
+          val qT = encodeSymbol(qs._1)
+          val substituter = mkSubstituter(Map(qs._2 -> qT))
 
-            val freshQuantifiers = newTemplate.quantifiers.map(p => encodeSymbol(p._1))
-            val freshSubst = mkSubstituter((newTemplate.quantifiers.map(_._2) zip freshQuantifiers).toMap)
-            for ((b,ms) <- newTemplate.matchers; m <- ms) {
-              clauses ++= instantiateMatcher(Set.empty[Encoded], m, false)
-              // it is very rare that such instantiations are actually required, so we defer them
-              val gen = currentGeneration + 20
-              ignoredMatchers += ((gen, Set(b), m.substitute(freshSubst, Map.empty)))
-            }
+          val quantification = new GeneralQuantification(newTemplate.pathVar._2,
+            qs._1 -> qT, q2s, insts, guard,
+            newTemplate.quantifiers, newTemplate.condVars, newTemplate.exprVars, newTemplate.condTree,
+            newTemplate.clauses map substituter, // one clause depends on 'qs._2' (and therefore 'qT')
+            newTemplate.blockers, newTemplate.applications, newTemplate.matchers,
+            newTemplate.lambdas, newTemplate.quantifications, newTemplate.pointers, newTemplate.body)
 
-            clauses ++= quantification.ensureGrounds
-            (qT, Map(qs._2 -> qT))
-        }
+          quantifications += quantification
 
-        clauses ++= templates.flatMap { case (key, (tmpl, tinst, _)) =>
-          if (newTemplate.structure.body == tmpl.structure.body) {
-            val eqConds = (newTemplate.structure.locals zip tmpl.structure.locals)
-              .filter(p => p._1 != p._2)
-              .map(p => mkEquals(p._1._2, p._2._2))
-            val cond = mkAnd(newTemplate.pathVar._2 +: tmpl.pathVar._2 +: eqConds : _*)
-            Some(mkImplies(cond, mkEquals(inst, tinst)))
-          } else {
-            None
+          for ((bs,m) <- handledMatchers) {
+            clauses ++= quantification.instantiate(bs, m)
           }
+
+          val freshQuantifiers = newTemplate.quantifiers.map(p => encodeSymbol(p._1))
+          val freshSubst = mkSubstituter((newTemplate.quantifiers.map(_._2) zip freshQuantifiers).toMap)
+          for ((b,ms) <- newTemplate.matchers; m <- ms) {
+            clauses ++= instantiateMatcher(Set.empty[Encoded], m, false)
+            // it is very rare that such instantiations are actually required, so we defer them
+            val gen = currentGeneration + 20
+            ignoredMatchers += ((gen, Set(b), m.substitute(freshSubst, Map.empty)))
+          }
+
+          clauses ++= quantification.ensureGrounds
+          (qT, Map(qs._2 -> qT))
+      }
+
+      clauses ++= templates.flatMap { case (key, (tmpl, tinst, _)) =>
+        if (newTemplate.structure.body == tmpl.structure.body) {
+          val eqConds = (newTemplate.structure.locals zip tmpl.structure.locals)
+            .filter(p => p._1 != p._2)
+            .map(p => mkEquals(p._1._2, p._2._2))
+          val cond = mkAnd(newTemplate.pathVar._2 +: tmpl.pathVar._2 +: eqConds : _*)
+          Some(mkImplies(cond, mkEquals(inst, tinst)))
+        } else {
+          None
         }
+      }
 
-        templates += newTemplate.structure -> ((newTemplate, inst, mapping))
-        (mapping, clauses.toSeq)
+      templates += newTemplate.structure -> ((newTemplate, inst, mapping))
+      (mapping, clauses.toSeq)
     }
   }