diff --git a/src/main/scala/leon/purescala/Constructors.scala b/src/main/scala/leon/purescala/Constructors.scala
index 67dcf315770120734684a459bad0b0d3be96120e..8597a0af22859ba0f730a0b534dd0b244a79a2c0 100644
--- a/src/main/scala/leon/purescala/Constructors.scala
+++ b/src/main/scala/leon/purescala/Constructors.scala
@@ -61,7 +61,7 @@ object Constructors {
     else bd
   }
 
-  /** $encodingof ``val (id1, id2, ...) = e; bd``, and returns `bd` if the identifiers are not bound in `bd`.
+  /** $encodingof ``val (...binders...) = value; body`` which is translated to  ``value match { case (...binders...) => body }``, and returns `body` if the identifiers are not bound in `body`.
     * @see [[purescala.Expressions.Let]]
     */
   def letTuple(binders: Seq[Identifier], value: Expr, body: Expr) = binders match {
@@ -72,7 +72,7 @@ object Constructors {
     case xs =>
       require(
         value.getType.isInstanceOf[TupleType],
-        s"The definition value in LetTuple must be of some tuple type; yet we got [${value.getType}]. In expr: \n$this"
+        s"The definition value in LetTuple must be of some tuple type; yet we got [${value.getType}]. In expr: \n$value"
       )
 
       Extractors.LetPattern(TuplePattern(None,binders map { b => WildcardPattern(Some(b)) }), value, body)
diff --git a/src/main/scala/leon/synthesis/disambiguation/InputCoverage.scala b/src/main/scala/leon/synthesis/disambiguation/InputCoverage.scala
index 409e55440e7fbee137be1e2836786ca00eed9115..f2b0946c6036c422f07623d619eb2d7ebc13a548 100644
--- a/src/main/scala/leon/synthesis/disambiguation/InputCoverage.scala
+++ b/src/main/scala/leon/synthesis/disambiguation/InputCoverage.scala
@@ -33,10 +33,10 @@ class InputCoverage(fd: FunDef, fds: Set[FunDef])(implicit c: LeonContext, p: Pr
   /** If the sub-branches contain identifiers, it returns them unchanged.
       Else it creates a new boolean indicating this branch. */
   def wrapBranch(e: (Expr, Seq[Identifier])): (Expr, Seq[Identifier]) = {
-    if(e._2.isEmpty) { // No need to introduce a new boolean since if one of the child booleans is true, then this IfExpr has been called.
-      val b = FreshIdentifier("l" + e._1.getPos.line + "c" + e._1.getPos.col)
+    if(e._2.isEmpty) {
+      val b = FreshIdentifier("l" + e._1.getPos.line + "c" + e._1.getPos.col, BooleanType)
       (tupleWrap(Seq(e._1, Variable(b))), Seq(b))
-    } else e
+    } else e // No need to introduce a new boolean since if one of the child booleans is true, then this IfExpr has been called.
   }
   
   def hasConditionals(e: Expr) = {
@@ -53,8 +53,13 @@ class InputCoverage(fd: FunDef, fds: Set[FunDef])(implicit c: LeonContext, p: Pr
       val (c1, cv1) = markBranches(cond)
       val (t1, tv1) = wrapBranch(markBranches(thenn))
       val (e1, ev1) = wrapBranch(markBranches(elze))
-      // TODO: Deal with the case when t1 and e1 is empty.
-      (IfExpr(c1, t1, e1).copiedFrom(e), cv1 ++ tv1 ++ ev1)
+      if(cv1.isEmpty) {
+        (IfExpr(c1, t1, e1).copiedFrom(e), tv1 ++ ev1)
+      } else {
+        val arg_id = FreshIdentifier("arg", BooleanType)
+        val arg_b = FreshIdentifier("b", BooleanType)
+        (letTuple(Seq(arg_id, arg_b), c1, IfExpr(Variable(arg_id), t1, e1).copiedFrom(e)), cv1 ++ tv1 ++ ev1)
+      }
     case MatchExpr(scrut, cases) =>
       val (c1, cv1) = markBranches(scrut)
       val (new_cases, variables) = (cases map { case MatchCase(pattern, opt, rhs) =>
@@ -77,15 +82,21 @@ class InputCoverage(fd: FunDef, fds: Set[FunDef])(implicit c: LeonContext, p: Pr
           }
       }
       e match {
-        case FunctionInvocation(TypedFunDef(fd, targs), args) =>
-          // Should be different since functions will return a boolean as well.
+        case FunctionInvocation(TypedFunDef(fd, targs), args) if fds(fd) =>
+          val new_fd = wrapFunDef(fd)
+          // Is different since functions will return a boolean as well.
           val res_id = FreshIdentifier("res", fd.returnType)
           val res_b = FreshIdentifier("b", BooleanType)
-          val finalIds = (ids :+ res_b)
-          val finalExpr = 
-            tupleWrap(Seq(Variable(res_id), or(finalIds.map(Variable(_)): _*)))
-          val funCall = letTuple(Seq(res_id, res_b), builder(children).copiedFrom(e), finalExpr)
-          (exprBuilder(funCall), finalIds)
+          if(ids.isEmpty) {
+            val funCall = FunctionInvocation(TypedFunDef(new_fd, targs), children).copiedFrom(e)
+            (exprBuilder(funCall), Seq(res_b))
+          } else {
+            val finalIds = (ids :+ res_b)
+            val finalExpr = 
+              tupleWrap(Seq(Variable(res_id), or(finalIds.map(Variable(_)): _*)))
+            val funCall = letTuple(Seq(res_id, res_b), FunctionInvocation(TypedFunDef(new_fd, targs), children).copiedFrom(e), finalExpr)
+            (exprBuilder(funCall), finalIds)
+          }
         case _ =>
           if(ids.isEmpty) {
             (e, Seq.empty)
@@ -96,6 +107,17 @@ class InputCoverage(fd: FunDef, fds: Set[FunDef])(implicit c: LeonContext, p: Pr
       }
   }
   
+  var cache = Map[FunDef, FunDef]()
+  
+  def wrapFunDef(fd: FunDef): FunDef = {
+    if(!(cache contains fd)) {
+      val new_fd = fd.duplicate(returnType = TupleType(Seq(fd.returnType, BooleanType)))
+      new_fd.body = None
+      cache += fd -> new_fd
+    }
+    cache(fd)
+  }
+  
   /** The number of expressions is the same as the number of arguments. */
   def result(): Stream[Seq[Expr]] = {
     /* Algorithm:
diff --git a/src/test/scala/leon/integration/solvers/InputCoverageSuite.scala b/src/test/scala/leon/integration/solvers/InputCoverageSuite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..7bc13e757ead777a797a79fae98fb284c8089b98
--- /dev/null
+++ b/src/test/scala/leon/integration/solvers/InputCoverageSuite.scala
@@ -0,0 +1,184 @@
+package leon.integration.solvers
+
+import org.scalatest.FunSuite
+import org.scalatest.Matchers
+import leon.test.helpers.ExpressionsDSL
+import leon.solvers.string.StringSolver
+import leon.purescala.Common.FreshIdentifier
+import leon.purescala.Common.Identifier
+import leon.purescala.Expressions._
+import leon.purescala.Definitions._
+import leon.purescala.DefOps
+import leon.purescala.ExprOps
+import leon.purescala.Types._
+import leon.purescala.TypeOps
+import leon.purescala.Constructors._
+import leon.synthesis.rules.{StringRender, TypedTemplateGenerator}
+import scala.collection.mutable.{HashMap => MMap}
+import scala.concurrent.Future
+import scala.concurrent.ExecutionContext.Implicits.global
+import org.scalatest.concurrent.Timeouts
+import org.scalatest.concurrent.ScalaFutures
+import org.scalatest.time.SpanSugar._
+import org.scalatest.FunSuite
+import org.scalatest.concurrent.Timeouts
+import org.scalatest.concurrent.ScalaFutures
+import org.scalatest.time.SpanSugar._
+import leon.purescala.Types.Int32Type
+import leon.test.LeonTestSuiteWithProgram
+import leon.synthesis.SourceInfo
+import leon.synthesis.CostModels
+import leon.synthesis.graph.AndNode
+import leon.synthesis.SearchContext
+import leon.synthesis.Synthesizer
+import leon.synthesis.SynthesisSettings
+import leon.synthesis.RuleApplication
+import leon.synthesis.RuleClosed
+import leon.evaluators._
+import leon.LeonContext
+import leon.synthesis.rules.DetupleInput
+import leon.synthesis.Rules
+import leon.solvers.ModelBuilder
+import scala.language.implicitConversions
+import leon.LeonContext
+import leon.test.LeonTestSuiteWithProgram
+import leon.test.helpers.ExpressionsDSL
+import leon.synthesis.disambiguation.InputCoverage
+import leon.test.helpers.ExpressionsDSLProgram
+import leon.test.helpers.ExpressionsDSLVariables
+
+class InputCoverageSuite extends LeonTestSuiteWithProgram with Matchers with ScalaFutures with ExpressionsDSLProgram with ExpressionsDSLVariables {
+  val sources = List("""
+    |import leon.lang._
+    |import leon.collection._
+    |import leon.lang.synthesis._
+    |import leon.annotation._
+    |
+    |object InputCoverageSuite {
+    |  def dummy = 2
+    |  def withIf(cond: Boolean) = {
+    |    if(cond) {
+    |      1
+    |    } else {
+    |      2
+    |    }
+    |  }
+    |  def withIfInIf(cond: Boolean) = {
+    |    if(if(cond) false else true) {
+    |      1
+    |    } else {
+    |      2
+    |    }
+    |  }
+    |  
+    |  def withCoveredFun1(input: Int) = {
+    |    withCoveredFun2(input - 5) + withCoveredFun2(input + 5)
+    |  }
+    |  
+    |  def withCoveredFun2(input: Int) = {
+    |    if(input > 0) {
+    |      2
+    |    } else {
+    |      0
+    |    }
+    |  }
+    |  
+    |  def withCoveredFun3(input: Int) = {
+    |    withCoveredFun2(withCoveredFun2(input + 5))
+    |  }
+    |}""".stripMargin)
+    
+  test("wrapBranch should wrap expressions if they are not already containing wrapped calls"){ ctxprogram =>
+    implicit val (c, p) = ctxprogram
+    val dummy = funDef("InputCoverageSuite.dummy")
+    val coverage = new InputCoverage(dummy, Set(dummy))
+    val simpleExpr = Plus(IntLiteral(1), b)
+    coverage.wrapBranch((simpleExpr, Seq(p.id, q.id))) should equal ((simpleExpr, Seq(p.id, q.id)))
+    val (covered, ids) = coverage.wrapBranch((simpleExpr, Seq()))
+    ids should have size 1
+    covered should equal (Tuple(Seq(simpleExpr, Variable(ids.head))))
+  }
+  
+  test("If-coverage should work"){ ctxprogram =>
+    implicit val (c, p) = ctxprogram
+    val withIf = funDef("InputCoverageSuite.withIf")
+    val coverage = new InputCoverage(withIf, Set(withIf))
+    val expr = withIf.body.get
+    
+    val (res, ids) = coverage.markBranches(expr)
+    ids should have size 2
+    expr match {
+      case IfExpr(cond, thenn, elze) =>
+        res should equal (IfExpr(cond, Tuple(Seq(thenn, Variable(ids(0)))), Tuple(Seq(elze, Variable(ids(1))))))
+      case _ => fail(s"$expr is not an IfExpr")
+    }
+  }
+  
+  test("If-cond-coverage should work"){ ctxprogram =>
+    implicit val (c, p) = ctxprogram
+    val withIfInIf = funDef("InputCoverageSuite.withIfInIf")
+    val coverage = new InputCoverage(withIfInIf, Set(withIfInIf))
+    val expr = withIfInIf.body.get
+    
+    val (res, ids) = coverage.markBranches(expr)
+    ids should have size 4
+    expr match {
+      case IfExpr(IfExpr(cond, t1, e1), t2, e2) =>
+        res match {
+          case MatchExpr(IfExpr(c, t1, e1), Seq(MatchCase(TuplePattern(None, s), None, IfExpr(c2, t2, e2)))) if s.size == 2 =>
+          case _ => fail("should have a shape like (if() else ) match { case (a, b) => if(...) else }")
+        }
+      case _ => fail(s"$expr is not an IfExpr")
+    }
+  }
+  
+  test("fundef combination-coverage should work"){ ctxprogram =>
+    implicit val (c, p) = ctxprogram
+    val withCoveredFun1 = funDef("InputCoverageSuite.withCoveredFun1")
+    val withCoveredFun2 = funDef("InputCoverageSuite.withCoveredFun2")
+    val coverage = new InputCoverage(withCoveredFun1, Set(withCoveredFun1, withCoveredFun2))
+    val expr = withCoveredFun1.body.get
+    
+    val (res, ids) = coverage.markBranches(expr)
+    ids should have size 2
+    
+    res match {
+      case MatchExpr(funCall, Seq(
+            MatchCase(TuplePattern(None, Seq(WildcardPattern(Some(a1)), WildcardPattern(Some(b1)))), None,
+              MatchExpr(funCall2, Seq(
+                MatchCase(TuplePattern(None, Seq(WildcardPattern(Some(a2)), WildcardPattern(Some(b2)))), None,
+                  Tuple(Seq(BVPlus(Variable(ida1), Variable(ida2)), Or(Seq(Variable(idb1), Variable(idb2)))))
+            )
+          ))))) =>
+        withClue(res.toString) {
+          ida1 shouldEqual a1
+          ida2 shouldEqual a2
+          Set(idb1.uniqueName, idb2.uniqueName) shouldEqual Set(b1.uniqueName, b2.uniqueName)
+        }
+      case _ =>
+        fail(s"$res is not of type funCall() match { case (a1, b1) => funCall() match { case (a2, b2) => (a1 + a2, b1 || b2) } }")
+    }
+  }
+  
+  test("fundef composition-coverage should work"){ ctxprogram =>
+    implicit val (c, p) = ctxprogram
+    val withCoveredFun2 = funDef("InputCoverageSuite.withCoveredFun2")
+    val withCoveredFun3 = funDef("InputCoverageSuite.withCoveredFun3")
+    val coverage = new InputCoverage(withCoveredFun3, Set(withCoveredFun3, withCoveredFun2))
+    val expr = withCoveredFun3.body.get
+    
+    val (res, ids) = coverage.markBranches(expr)
+    ids should have size 2
+    res match {
+      case MatchExpr(funCall, Seq(
+            MatchCase(TuplePattern(None, Seq(WildcardPattern(Some(a)), WildcardPattern(Some(b1)))), None,
+              MatchExpr(FunctionInvocation(_, Seq(Variable(ida))), Seq(
+                MatchCase(TuplePattern(None, Seq(WildcardPattern(_), WildcardPattern(Some(b2)))), None,
+                  Tuple(Seq(p, Or(Seq(Variable(id1), Variable(id2)))))
+            )
+          ))))) if ida == a && id1 == b1 && id2 == b2 =>
+      case _ =>
+        fail(s"$res is not of type funCall() match { case (a, b1) => funCall(a) match { case (c, b2) => (c, b1 || b2) } }")
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/test/scala/leon/test/helpers/ExpressionsDSL.scala b/src/test/scala/leon/test/helpers/ExpressionsDSL.scala
index 63469ead59c6c4441ce12a92fc92c4349ae99d5b..91b77284cc16518a4b86e0bdcb5ad7e98230061f 100644
--- a/src/test/scala/leon/test/helpers/ExpressionsDSL.scala
+++ b/src/test/scala/leon/test/helpers/ExpressionsDSL.scala
@@ -9,6 +9,10 @@ import leon.purescala.Common._
 import leon.purescala.Types._
 import leon.purescala.Expressions._
 
+trait ExpressionsDSLVariables_a {
+  val a = FreshIdentifier("a", Int32Type).toVariable
+}
+
 trait ExpressionsDSLVariables {
   val F = BooleanLiteral(false)
   val T = BooleanLiteral(true)
@@ -18,7 +22,6 @@ trait ExpressionsDSLVariables {
   def i(x: Int)     = IntLiteral(x)
   def r(n: BigInt, d: BigInt)  = FractionalLiteral(n, d)
 
-  val a = FreshIdentifier("a", Int32Type).toVariable
   val b = FreshIdentifier("b", Int32Type).toVariable
   val c = FreshIdentifier("c", Int32Type).toVariable
 
@@ -97,7 +100,7 @@ self: Assertions =>
   }
 }
 
-trait ExpressionsDSL extends ExpressionsDSLVariables with ExpressionsDSLProgram {
+trait ExpressionsDSL extends ExpressionsDSLVariables with ExpressionsDSLProgram with ExpressionsDSLVariables_a {
   self: Assertions =>
   
 }