diff --git a/src/main/scala/inox/ast/Definitions.scala b/src/main/scala/inox/ast/Definitions.scala
index e9ab87604c5ef9709f1b0eb65f60476c2aeb4fca..3d398cebd409976d07360bee49ee1383b17d69d1 100644
--- a/src/main/scala/inox/ast/Definitions.scala
+++ b/src/main/scala/inox/ast/Definitions.scala
@@ -253,6 +253,13 @@ trait Definitions { self: Trees =>
       require(tps.length == tparams.length)
       TypedADTSort(this, tps)
     }
+
+    def copy(
+      id: Identifier = this.id,
+      tparams: Seq[TypeParameterDef] = this.tparams,
+      cons: Seq[Identifier] = this.cons,
+      flags: Set[Flag] = this.flags
+    ): ADTSort = new ADTSort(id, tparams, cons, flags)
   }
 
   /** Case classes/ ADT constructors. For single-case classes these may coincide
@@ -290,6 +297,14 @@ trait Definitions { self: Trees =>
       require(tps.length == tparams.length)
       TypedADTConstructor(this, tps)
     }
+
+    def copy(
+      id: Identifier = this.id,
+      tparams: Seq[TypeParameterDef] = this.tparams,
+      sort: Option[Identifier] = this.sort,
+      fields: Seq[ValDef] = this.fields,
+      flags: Set[Flag] = this.flags
+    ): ADTConstructor = new ADTConstructor(id, tparams, sort, fields, flags)
   }
 
   /** Represents an [[ADTDefinition]] whose type parameters have been instantiated to ''tps'' */
@@ -378,6 +393,15 @@ trait Definitions { self: Trees =>
     def applied(args: Seq[Expr])(implicit s: Symbols): FunctionInvocation = s.functionInvocation(this, args)
     /** Applies this function on its formal parameters */
     def applied = FunctionInvocation(id, typeArgs, params map (_.toVariable))
+
+    def copy(
+      id: Identifier = this.id,
+      tparams: Seq[TypeParameterDef] = this.tparams,
+      params: Seq[ValDef] = this.params,
+      returnType: Type = this.returnType,
+      fullBody: Expr = this.fullBody,
+      flags: Set[Flag] = this.flags
+    ): FunDef = new FunDef(id, tparams, params, returnType, fullBody, flags)
   }
 
 
@@ -393,15 +417,15 @@ trait Definitions { self: Trees =>
       }
     }
 
-    private lazy val typesMap: Map[TypeParameter, Type] = {
+    lazy val tpSubst: Map[TypeParameter, Type] = {
       (fd.typeArgs zip tps).toMap.filter(tt => tt._1 != tt._2)
     }
 
     /** A [[Type]] instantiated with this [[TypedFunDef]]'s type instantiation */
-    def instantiate(t: Type): Type = symbols.instantiateType(t, typesMap)
+    def instantiate(t: Type): Type = symbols.instantiateType(t, tpSubst)
 
     /** A [[Expr]] instantiated with this [[TypedFunDef]]'s type instantiation */
-    def instantiate(e: Expr): Expr = symbols.instantiateType(e, typesMap)
+    def instantiate(e: Expr): Expr = symbols.instantiateType(e, tpSubst)
 
     /** A mapping from this [[TypedFunDef]]'s formal parameters to real arguments
       *
@@ -431,7 +455,7 @@ trait Definitions { self: Trees =>
 
     /** The paremeters of the respective [[FunDef]] instantiated with the real type parameters */
     lazy val params: Seq[ValDef] = {
-      if (typesMap.isEmpty) {
+      if (tpSubst.isEmpty) {
         fd.params
       } else {
         fd.params.map(vd => vd.copy(tpe = instantiate(vd.getType)))
diff --git a/src/main/scala/inox/ast/Paths.scala b/src/main/scala/inox/ast/Paths.scala
index 9c78d2677efded9efd4010693cfb6b0d6adc0143..6e15804d1ff0dc2f2dee97e9e9f31205fb091001 100644
--- a/src/main/scala/inox/ast/Paths.scala
+++ b/src/main/scala/inox/ast/Paths.scala
@@ -3,7 +3,7 @@
 package inox
 package ast
 
-trait Paths { self: TypeOps with Constructors =>
+trait Paths { self: SymbolOps with TypeOps with Constructors =>
   import trees._
 
   object Path {
@@ -69,7 +69,19 @@ trait Paths { self: TypeOps with Constructors =>
       * Expressions in a path appear both on the right-hand side of let binders
       * and in boolean path conditions.
       */
-    def map(f: Expr => Expr) = new Path(elements.map(_.left.map { case (id, e) => id -> f(e) }.right.map(f)))
+    def map(f: Expr => Expr) = new Path(elements.map(_.left.map { case (vd, e) => vd -> f(e) }.right.map(f)))
+
+    /** Instantiates type parameters within the path
+      *
+      * Type parameters within a path may appear both inside expressions and in
+      * the type associated to a let binder.
+      */
+    def instantiate(tps: Map[TypeParameter, Type]) = {
+      val t = new TypeInstantiator(tps)
+      new Path(elements.map(_.left.map {
+        case (vd, e) => t.transform(vd) -> t.transform(e)
+      }.right.map(t.transform)))
+    }
 
     /** Splits the path on predicate `p`
       *
diff --git a/src/main/scala/inox/ast/TreeOps.scala b/src/main/scala/inox/ast/TreeOps.scala
index 5b44cc92d9ca408298940293036be4caf68739e1..67de1df3405fcb8f48e5a5235ed4f783d496cc7c 100644
--- a/src/main/scala/inox/ast/TreeOps.scala
+++ b/src/main/scala/inox/ast/TreeOps.scala
@@ -19,7 +19,7 @@ trait TreeOps { self: Trees =>
     } = self.deconstructor
   }
 
-  class TreeIdentity extends SelfTreeTransformer {
+  trait IdentityTreeTransformer extends SelfTreeTransformer {
     override def transform(id: Identifier, tpe: s.Type): (Identifier, t.Type) = (id, tpe)
     override def transform(v: s.Variable): t.Variable = v
     override def transform(vd: s.ValDef): t.ValDef = vd
@@ -28,17 +28,17 @@ trait TreeOps { self: Trees =>
     override def transform(flag: s.Flag): t.Flag = flag
   }
 
-  lazy val TreeIdentity: SelfTransformer = new TreeIdentity
+  trait IdentitySymbolTransformer extends SymbolTransformer {
+    /* For some reason, the scala compiler doesn't accept {{{
+     *   object transformer extends IdentityTreeTransformer
+     * }}} which would be nicer. */
+    val transformer = new IdentityTreeTransformer {}
 
-  class SymbolIdentity extends SymbolTransformer {
-    val transformer = TreeIdentity
     override protected final def transformFunction(fd: s.FunDef): t.FunDef = sys.error("unexpected")
     override protected final def transformADT(adt: s.ADTDefinition): t.ADTDefinition = sys.error("unexpected")
     override def transform(syms: s.Symbols): t.Symbols = syms
   }
 
-  lazy val SymbolIdentity: SymbolTransformer { val transformer: SelfTransformer } = new SymbolIdentity
-
   trait TreeTraverser {
     def traverse(vd: ValDef): Unit = traverse(vd.tpe)
 
diff --git a/src/main/scala/inox/solvers/SolverFactory.scala b/src/main/scala/inox/solvers/SolverFactory.scala
index d7b17734b2b3b39d30f4ae32a5a49fa82b75edef..3af74feb6e2a68e3ccbfab5e856d082ad3f7f2cc 100644
--- a/src/main/scala/inox/solvers/SolverFactory.scala
+++ b/src/main/scala/inox/solvers/SolverFactory.scala
@@ -19,6 +19,8 @@ trait SolverFactory {
   def reclaim(s: S) {
     s.free()
   }
+
+  def toAPI = SimpleSolverAPI(this)
 }
 
 object SolverFactory {
diff --git a/src/main/scala/inox/solvers/combinators/EncodingSolver.scala b/src/main/scala/inox/solvers/combinators/EncodingSolver.scala
index f32d2bd6da7f30e85a292f1d8c635dd89c501810..726cbe8c61138404c6976ff5fef9083ad952023f 100644
--- a/src/main/scala/inox/solvers/combinators/EncodingSolver.scala
+++ b/src/main/scala/inox/solvers/combinators/EncodingSolver.scala
@@ -33,8 +33,8 @@ object ProgramEncoder {
     val sourceProgram: p.type = p
     val t: p.trees.type = p.trees
 
-    val encoder = p.trees.SymbolIdentity
-    val decoder = p.trees.SymbolIdentity
+    object encoder extends p.trees.IdentitySymbolTransformer
+    object decoder extends p.trees.IdentitySymbolTransformer
   }
 }
 
diff --git a/src/main/scala/inox/solvers/theories/TheoryEncoder.scala b/src/main/scala/inox/solvers/theories/TheoryEncoder.scala
index 95ece9fb34adaa78cc1196ec30edd8222e030fac..225aa13a434c61f4c649765e024ab9a6ed183050 100644
--- a/src/main/scala/inox/solvers/theories/TheoryEncoder.scala
+++ b/src/main/scala/inox/solvers/theories/TheoryEncoder.scala
@@ -46,7 +46,7 @@ trait TheoryEncoder extends ast.TreeBijection {
 trait NoEncoder extends TheoryEncoder {
   import trees._
 
-  protected val treeEncoder: SelfTransformer = TreeIdentity
-  protected val treeDecoder: SelfTransformer = TreeIdentity
+  protected object treeEncoder extends IdentityTreeTransformer
+  protected object treeDecoder extends IdentityTreeTransformer
 }
 
diff --git a/src/main/scala/inox/transformers/Collector.scala b/src/main/scala/inox/transformers/Collector.scala
index 8097214e7078a14420770cbb352a8009176e2ac9..0da53d7668477d58d048443fa3ee0ea794f83a4f 100644
--- a/src/main/scala/inox/transformers/Collector.scala
+++ b/src/main/scala/inox/transformers/Collector.scala
@@ -4,13 +4,11 @@ package inox
 package transformers
 
 /** A common trait for objects that collect something from expressions.
-  * The [[Transformer]] environment will also be collected along the way.
   * This trait is meant to be mixed in with a specific [[Transformer]] to attach collect functionality.
   */
 trait Collector extends Transformer {
   /** The type of collected objects */
-  type R
-  final type Result = (R, Env)
+  type Result
   private var results: List[Result] = Nil
 
   import trees._
diff --git a/src/main/scala/inox/transformers/CollectorWithPC.scala b/src/main/scala/inox/transformers/CollectorWithPC.scala
index 823b351960bf3a2945f6e778b19159a146e2e7d4..0bad6300d08814ed56dee880989f9d5833df6865 100644
--- a/src/main/scala/inox/transformers/CollectorWithPC.scala
+++ b/src/main/scala/inox/transformers/CollectorWithPC.scala
@@ -14,19 +14,18 @@ trait CollectorWithPC extends TransformerWithPC with Collector {
 object CollectorWithPC {
   def apply[T](p: Program)
               (f: PartialFunction[(p.trees.Expr, p.symbols.Path), T]):
-               CollectorWithPC { type R = T; val program: p.type } = {
+               CollectorWithPC { type Result = T; val program: p.type } = {
     new CollectorWithPC {
-      type R = T
+      type Result = T
       val program: p.type = p
       import program.trees._
       import program.symbols._
 
       private val fLifted = f.lift
 
-      protected def step(e: Expr, env: Path): List[(T, Path)] = {
-        fLifted((e, env)).map((_, env)).toList
+      protected def step(e: Expr, env: Path): List[T] = {
+        fLifted((e, env)).toList
       }
-
     }
   }