diff --git a/src/main/scala/inox/evaluators/SolvingEvaluator.scala b/src/main/scala/inox/evaluators/SolvingEvaluator.scala
index eb791cf360165c818cd31be39f7d46bbdc042b8f..09a479e94ef9d9a6d66fd53a6874d05b0afb278e 100644
--- a/src/main/scala/inox/evaluators/SolvingEvaluator.scala
+++ b/src/main/scala/inox/evaluators/SolvingEvaluator.scala
@@ -36,7 +36,7 @@ trait SolvingEvaluator extends Evaluator {
     import SolverResponses._
 
     solver.assertCnstr(body)
-    val res = solver.check(solver.Model)
+    val res = solver.check(Model)
     timer.stop()
 
     res match {
@@ -65,7 +65,7 @@ trait SolvingEvaluator extends Evaluator {
       import SolverResponses._
 
       solver.assertCnstr(Not(forall.body))
-      val res = solver.check(solver.Model)
+      val res = solver.check(Model)
       timer.stop()
 
       res match {
diff --git a/src/main/scala/inox/solvers/Solver.scala b/src/main/scala/inox/solvers/Solver.scala
index 97d46095a18fa8b6d5197caf1a004527279081f0..6c2ef90a933d09b22c07d27636caddf28d7b1102 100644
--- a/src/main/scala/inox/solvers/Solver.scala
+++ b/src/main/scala/inox/solvers/Solver.scala
@@ -30,11 +30,7 @@ trait AbstractSolver extends Interruptible {
   type Model
   type Cores
 
-  type Configuration = SolverResponses.Configuration[Model, Cores]
-  val Simple = SolverResponses.Simple
-  val Model  = SolverResponses.Model[Model]()
-  val Cores  = SolverResponses.Cores[Cores]()
-  val All    = SolverResponses.All[Model, Cores]()
+  import SolverResponses._
 
   lazy val reporter = program.ctx.reporter
 
@@ -43,10 +39,8 @@ trait AbstractSolver extends Interruptible {
 
   def assertCnstr(expression: Trees): Unit
 
-  def check[R](config: Configuration { type Response <: R }): R
-  def checkAssumptions[R](config: Configuration { type Response <: R })(assumptions: Set[Trees]): R
-
-  def getResultSolver: Option[Solver] = Some(this)
+  def check(config: Configuration): config.Response[Model, Cores]
+  def checkAssumptions(config: Configuration)(assumptions: Set[Trees]): config.Response[Model, Cores]
 
   def free(): Unit
 
@@ -63,6 +57,7 @@ trait AbstractSolver extends Interruptible {
 }
 
 trait Solver extends AbstractSolver {
+  import program._
   import program.trees._
 
   type Trees = Expr
@@ -78,6 +73,8 @@ trait Solver extends AbstractSolver {
   case class SolverUnsupportedError(t: Tree, reason: Option[String] = None)
     extends Unsupported(t, SolverUnsupportedError.msg(t,reason))
 
+  def getResultSolver: Option[Solver] = Some(this)
+
   protected def unsupported(t: Tree): Nothing = {
     val err = SolverUnsupportedError(t, None)
     reporter.warning(err.getMessage)
diff --git a/src/main/scala/inox/solvers/SolverResponses.scala b/src/main/scala/inox/solvers/SolverResponses.scala
index f4572e78d4503674e9d1bda0b2aba41d7e6619b1..006d2624fd14de9ce3da7018df5197e6fd16fb77 100644
--- a/src/main/scala/inox/solvers/SolverResponses.scala
+++ b/src/main/scala/inox/solvers/SolverResponses.scala
@@ -3,6 +3,9 @@
 package inox
 package solvers
 
+import scala.language.higherKinds
+import scala.language.implicitConversions
+
 object SolverResponses {
   sealed trait SolverResponse[+Model,+Cores]
 
@@ -43,63 +46,57 @@ object SolverResponses {
     }
   }
 
-  sealed trait Configuration[+Model, +Cores] {
-    type Response <: SolverResponse[Model, Cores]
-
-    def max[M >: Model,C >: Cores](that: Configuration[M, C]): Configuration[M, C] = (this, that) match {
-      case (All()  , _      ) => All()
-      case (_      , All()  ) => All()
-      case (Model(), Cores()) => All()
-      case (Cores(), Model()) => All()
-      case (Model(), _      ) => Model()
-      case (_      , Model()) => Model()
-      case (Cores(), _      ) => Cores()
-      case (_      , Cores()) => Cores()
-      case _                  => Simple
+  sealed trait Configuration {
+    type Response[+M,+C] <: SolverResponse[M,C]
+
+    def max(that: Configuration): Configuration = (this, that) match {
+      case (All  , _    ) => All
+      case (_    , All  ) => All
+      case (Model, Cores) => All
+      case (Cores, Model) => All
+      case (Model, _    ) => Model
+      case (_    , Model) => Model
+      case (Cores, _    ) => Cores
+      case (_    , Cores) => Cores
+      case _              => Simple
     }
 
-    def min[M >: Model, C >: Cores](that: Configuration[M, C]): Configuration[M, C] = (this, that) match {
+    def min(that: Configuration): Configuration = (this, that) match {
       case (o1, o2) if o1 == o2 => o1
       case (Simple, _) => Simple
       case (_, Simple) => Simple
-      case (Model(), Cores()) => Simple
-      case (Cores(), Model()) => Simple
-      case (All(), o) => o
-      case (o, All()) => o
+      case (Model, Cores) => Simple
+      case (Cores, Model) => Simple
+      case (All, o) => o
+      case (o, All) => o
     }
 
-    def cast[M <: Model, C <: Cores](resp: SolverResponse[M, C]): Response = ((this, resp) match {
+    def cast[M, C](resp: SolverResponse[M,C]): Response[M,C] = ((this, resp) match {
       case (_, Unknown)                               => Unknown
-      case (Simple  | Cores(), Sat)                   => Sat
-      case (Model() | All()  , s @ SatWithModel(_))   => s
-      case (Simple  | Model(), Unsat)                 => Unsat
-      case (Cores() | All()  , u @ UnsatWithCores(_)) => u
+      case (Simple | Cores, Sat)                   => Sat
+      case (Model  | All  , s @ SatWithModel(_))   => s
+      case (Simple | Model, Unsat)                 => Unsat
+      case (Cores  | All  , u @ UnsatWithCores(_)) => u
       case _ => throw FatalError("Unexpected response " + resp + " for configuration " + this)
-    }).asInstanceOf[Response]
+    }).asInstanceOf[Response[M,C]]
   }
 
   object Configuration {
-    def apply[M,C](model: Boolean = false, cores: Boolean = false): Configuration[M,C] =
-      if (model && cores) All()
-      else if (model) Model()
-      else if (cores) Cores()
+    def apply(model: Boolean = false, cores: Boolean = false): Configuration =
+      if (model && cores) All
+      else if (model) Model
+      else if (cores) Cores
       else Simple
   }
 
-  case object Simple extends Configuration[Nothing,Nothing] {
-    type Response = SimpleResponse
-  }
-
-  case class Model[Model]() extends Configuration[Model,Nothing] {
-    type Response = ResponseWithModel[Model]
-  }
-
-  case class Cores[Cores]() extends Configuration[Nothing,Cores] {
-    type Response = ResponseWithCores[Cores]
-  }
+  case object Simple extends Configuration { type Response[+M,+C] = SimpleResponse }
+  case object Model  extends Configuration { type Response[+M,+C] = ResponseWithModel[M] }
+  case object Cores  extends Configuration { type Response[+M,+C] = ResponseWithCores[C] }
+  case object All    extends Configuration { type Response[+M,+C] = ResponseWithModelAndCores[M, C] }
 
-  case class All[Model,Cores]() extends Configuration[Model,Cores] {
-    type Response = ResponseWithModelAndCores[Model, Cores]
+  implicit def wideningConfiguration[M,C](config: Configuration)
+                                         (resp: config.Response[M,C]): SolverResponse[M, C] = {
+    resp.asInstanceOf[SolverResponse[M, C]]
   }
 }
 
diff --git a/src/main/scala/inox/solvers/TimeoutSolver.scala b/src/main/scala/inox/solvers/TimeoutSolver.scala
index 3b0d516efa62b143d135511afe32ff9f16cab66c..17ae644b51c0f009d2efb8e91cb98bd2e1ed14e4 100644
--- a/src/main/scala/inox/solvers/TimeoutSolver.scala
+++ b/src/main/scala/inox/solvers/TimeoutSolver.scala
@@ -8,6 +8,7 @@ import scala.concurrent.duration._
 
 trait TimeoutSolver extends Solver {
   import program.trees._
+  import SolverResponses._
 
   val ti = new TimeoutFor(this)
 
@@ -23,7 +24,7 @@ trait TimeoutSolver extends Solver {
     this
   }
 
-  abstract override def check[R](config: Configuration { type Response <: R }): R = {
+  abstract override def check(config: Configuration) = {
     optTimeout match {
       case Some(to) =>
         ti.interruptAfter(to) {
@@ -34,8 +35,8 @@ trait TimeoutSolver extends Solver {
     }
   }
 
-  abstract override def checkAssumptions[R](config: Configuration { type Response <: R })
-                                           (assumptions: Set[Expr]): R = {
+  abstract override def checkAssumptions(config: Configuration)
+                                        (assumptions: Set[Expr]) = {
     optTimeout match {
       case Some(to) =>
         ti.interruptAfter(to) {
diff --git a/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala b/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala
index a5cc2f2d2676bb6f692a1ec270bde838c2902785..455729157b42647d4dfcef8a0b31a4d26c853c68 100644
--- a/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala
+++ b/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala
@@ -21,6 +21,8 @@ trait AbstractUnrollingSolver
   import program.trees._
   import program.symbols._
 
+  import SolverResponses._
+
   protected type Encoded
   protected implicit val printable: Encoded => Printable
 
@@ -36,9 +38,8 @@ trait AbstractUnrollingSolver
   }
 
   protected val underlying: AbstractSolver {
-    val program: AbstractUnrollingSolver.this.program.type
+    val program: AbstractUnrollingSolver.this.theories.targetProgram.type
     type Trees = Encoded
-    type Model = ModelWrapper
     type Cores = Set[Encoded]
   }
 
@@ -49,7 +50,7 @@ trait AbstractUnrollingSolver
   val assumePreHolds   = options.findOptionOrDefault(optAssumePre)
   val silentErrors     = options.findOptionOrDefault(optSilentErrors)
 
-  def check[R](config: Configuration { type Response <: R }): R =
+  def check(config: Configuration): config.Response[Model, Cores] =
     checkAssumptions(config)(Set.empty)
 
   private val constraints = new IncrementalSeq[Expr]()
@@ -99,49 +100,7 @@ trait AbstractUnrollingSolver
     }
   }
 
-  def solverAssert(cnstr: Encoded): Unit
-
-  /** Simpler version of [[Solver.SolverResponses]] used internally in
-    * [[AbstractUnrollingSolver]] and children.
-    *
-    * These enable optimizations for the native Z3 solver (such as avoiding
-    * full Z3 model extraction in certain cases).
-    */
-  protected sealed trait Response
-  protected case object Unknown extends Response
-  protected case class Unsat(cores: Option[Set[Encoded]]) extends Response
-  protected case class Sat(model: Option[ModelWrapper]) extends Response
-
-  /** Provides CPS solver.check call. CPS is necessary in order for calls that
-   *  depend on solver.getModel to be able to access the model BEFORE the call
-   *  to solver.pop() is issued.
-   *
-   *  The underlying solver therefore performs the following sequence of
-   *  solver calls:
-   *  {{{
-   *    solver.push()
-   *    for (cls <- clauses) solver.assertCnstr(cls)
-   *    val res = solver.check
-   *    block(res)
-   *    solver.pop()
-   *  }}}
-   *
-   *  This ordering guarantees that [[block]] can safely call solver.getModel.
-   *
-   *  This sequence of calls can also be used to mimic solver.checkAssumptions()
-   *  for solvers that don't support the construct natively.
-   */
-  def solverCheck[R](config: Configuration)
-                    (clauses: Seq[Encoded])
-                    (block: Response => R): R
-
-  /** We define solverCheckAssumptions in CPS in order for solvers that don't
-   *  support this feature to be able to use the provided [[solverCheck]] CPS
-   *  construction.
-   */
-  def solverCheckAssumptions[R](config: Configuration)
-                               (assumptions: Seq[Encoded])
-                               (block: Response => R): R = solverCheck(config)(assumptions)(block)
+  protected def wrapModel(model: underlying.Model): ModelWrapper
 
   trait ModelWrapper {
     def modelEval(elem: Encoded, tpe: Type): Option[Expr]
@@ -188,11 +147,13 @@ trait AbstractUnrollingSolver
     }
   }
 
-  private def extractSimpleModel(wrapper: ModelWrapper): Map[ValDef, Expr] = {
-    freeVars.toMap.map { case (v, _) => v.toVal -> wrapper.get(v).getOrElse(simplestValue(v.getType)) }
+  private def extractSimpleModel(model: underlying.Model): Map[ValDef, Expr] = {
+    val wrapped = wrapModel(model)
+    freeVars.toMap.map { case (v, _) => v.toVal -> wrapped.get(v).getOrElse(simplestValue(v.getType)) }
   }
 
-  private def extractTotalModel(wrapper: ModelWrapper): Map[ValDef, Expr] = {
+  private def extractTotalModel(model: underlying.Model): Map[ValDef, Expr] = {
+    val wrapped = wrapModel(model)
     def functionsOf(expr: Expr, selector: Expr): (Seq[(Expr, Expr)], Seq[Expr] => Expr) = {
       def reconstruct(subs: Seq[(Seq[(Expr, Expr)], Seq[Expr] => Expr)],
                       recons: Seq[Expr] => Expr): (Seq[(Expr, Expr)], Seq[Expr] => Expr) =
@@ -225,7 +186,7 @@ trait AbstractUnrollingSolver
 
     import templates.{QuantificationTypeMatcher => QTM}
     freeVars.toMap.map { case (v, idT) =>
-      val value = wrapper.get(v).getOrElse(simplestValue(v.getType))
+      val value = wrapped.get(v).getOrElse(simplestValue(v.getType))
       val (functions, recons) = functionsOf(value, v)
 
       v.toVal -> recons(functions.map { case (f, selector) =>
@@ -238,10 +199,10 @@ trait AbstractUnrollingSolver
           val app = templates.mkApplication(selector, params)
 
           val allImages = templates.getGroundInstantiations(encoded, tpe).flatMap { case (b, eArgs) =>
-            wrapper.eval(b, BooleanType).filter(_ == BooleanLiteral(true)).flatMap { _ =>
-              val optArgs = (eArgs zip from).map { case (arg, tpe) => wrapper.eval(arg, tpe) }
+            wrapped.eval(b, BooleanType).filter(_ == BooleanLiteral(true)).flatMap { _ =>
+              val optArgs = (eArgs zip from).map { case (arg, tpe) => wrapped.eval(arg, tpe) }
               val eApp = templates.mkEncoder(Map(v -> idT) ++ (params zip eArgs))(app)
-              val optResult = wrapper.eval(eApp, to)
+              val optResult = wrapped.eval(eApp, to)
 
               if (optArgs.forall(_.isDefined) && optResult.isDefined) {
                 val args = optArgs.map(_.get)
@@ -293,7 +254,7 @@ trait AbstractUnrollingSolver
     }
   }
 
-  def checkAssumptions[R](config: Configuration { type Response <: R })(assumptions: Set[Expr]): R = {
+  def checkAssumptions(config: Configuration)(assumptions: Set[Expr]): config.Response[Model, Cores] = {
 
     val assumptionsSeq       : Seq[Expr]          = assumptions.toSeq
     val encodedAssumptions   : Seq[Encoded]       = assumptionsSeq.map { expr =>
@@ -310,9 +271,11 @@ trait AbstractUnrollingSolver
       })
     }
 
+    import SolverResponses._
+
     sealed abstract class CheckState
-    class CheckResult(val response: config.Response) extends CheckState
-    case class Validate(model: Option[Map[ValDef, Expr]]) extends CheckState
+    class CheckResult(val response: config.Response[Model, Cores]) extends CheckState
+    case class Validate(model: Map[ValDef, Expr]) extends CheckState
     case object ModelCheck extends CheckState
     case object FiniteRangeCheck extends CheckState
     case object InstantiateQuantifiers extends CheckState
@@ -320,29 +283,29 @@ trait AbstractUnrollingSolver
     case object Unroll extends CheckState
 
     object CheckResult {
-      def apply(resp: config.Response) = new CheckResult(resp)
-
-      def apply(resp: Response): CheckResult = new CheckResult(config.cast(resp match {
-        case Unknown            => SolverResponses.Unknown
-        case Sat(None)          => SolverResponses.Sat
-        case Sat(Some(model))   => SolverResponses.SatWithModel(extractSimpleModel(model))
-        case Unsat(None)        => SolverResponses.Unsat
-        case Unsat(Some(cores)) => SolverResponses.UnsatWithCores(encodedCoreToCore(cores))
-        case _ => throw FatalError("Unexpected response " + resp + " for configuration " + config)
-      }))
-
-      def unapply(res: CheckResult): Option[config.Response] = Some(res.response)
+      def cast(resp: SolverResponse[underlying.Model, underlying.Cores]): CheckResult =
+        new CheckResult(config cast (resp match {
+          case Unknown               => Unknown
+          case Sat                   => Sat
+          case Unsat                 => Unsat
+          case SatWithModel(model)   => SatWithModel(extractSimpleModel(model))
+          case UnsatWithCores(cores) => UnsatWithCores(encodedCoreToCore(cores))
+          case _ => throw FatalError("Unexpected response " + resp + " for configuration " + config)
+        }))
+
+      def apply[M <: Model, C <: Cores](resp: config.Response[M, C]) = new CheckResult(resp)
+      def unapply(res: CheckResult): Option[config.Response[Model, Cores]] = Some(res.response)
     }
 
     object Abort {
-      def unapply(resp: Response): Boolean = resp == Unknown || interrupted
+      def unapply[A,B](resp: SolverResponse[A,B]): Boolean = resp == Unknown || interrupted
     }
 
     var currentState: CheckState = ModelCheck
     while (!currentState.isInstanceOf[CheckResult]) {
       currentState = currentState match {
         case _ if interrupted =>
-          CheckResult(Unknown)
+          CheckResult.cast(Unknown)
 
         case ModelCheck =>
           reporter.debug(" - Running search...")
@@ -352,82 +315,87 @@ trait AbstractUnrollingSolver
             .max(Configuration(model = false, cores = unrollUnsatCores))
 
           val timer = ctx.timers.solvers.check.start()
-          solverCheckAssumptions(checkConfig)(
-            encodedAssumptions.toSeq ++ templates.satisfactionAssumptions
-          ) { res =>
-            timer.stop()
-
-            reporter.debug(" - Finished search with blocked literals")
-
-            res match {
-              case Abort() =>
-                CheckResult(Unknown)
-
-              case sat: Sat =>
-                if (templates.requiresFiniteRangeCheck) {
-                  FiniteRangeCheck
-                } else {
-                  Validate(sat.model.map(extractSimpleModel))
-                }
-
-              case _: Unsat if !templates.canUnroll =>
-                CheckResult(res)
-
-              case Unsat(Some(cores)) if unrollUnsatCores =>
-                for (c <- cores) templates.extractNot(c) match {
-                  case Some(b) => templates.promoteBlocker(b)
-                  case None => reporter.fatalError("Unexpected blocker polarity for unsat core unrolling: " + c)
-                }
-                ProofCheck
-
-              case _ => 
-                ProofCheck
-            }
+          val res: SolverResponse[underlying.Model, underlying.Cores] =
+            underlying.checkAssumptions(checkConfig)(
+              encodedAssumptions.toSet ++ templates.satisfactionAssumptions
+            )
+          timer.stop()
+
+          reporter.debug(" - Finished search with blocked literals")
+
+          res match {
+            case Abort() =>
+              CheckResult.cast(Unknown)
+
+            case Sat if templates.requiresFiniteRangeCheck =>
+              FiniteRangeCheck
+
+            case Sat =>
+              CheckResult.cast(Sat)
+
+            case SatWithModel(model) =>
+              Validate(extractSimpleModel(model))
+
+            case _: Unsatisfiable if !templates.canUnroll =>
+              CheckResult.cast(res)
+
+            case UnsatWithCores(cores) if unrollUnsatCores =>
+              for (c <- cores) templates.extractNot(c) match {
+                case Some(b) => templates.promoteBlocker(b)
+                case None => reporter.fatalError("Unexpected blocker polarity for unsat core unrolling: " + c)
+              }
+              ProofCheck
+
+            case _ => 
+              ProofCheck
           }
 
         case FiniteRangeCheck =>
           reporter.debug(" - Verifying finite ranges")
 
           val clauses = templates.getFiniteRangeClauses
+
           val timer = ctx.timers.solvers.check.start()
-          solverCheck(config min Model)(
-            encodedAssumptions.toSeq ++ templates.satisfactionAssumptions ++ clauses
-          ) { res =>
-            timer.stop()
+          underlying.push()
+          for (cl <- encodedAssumptions.toSeq ++ templates.satisfactionAssumptions ++ clauses) {
+            underlying.assertCnstr(cl)
+          }
+          val res: SolverResponse[underlying.Model, underlying.Cores] = underlying.check(config min Model)
+          underlying.pop()
+          timer.stop()
 
-            reporter.debug(" - Finished checking finite ranges")
+          reporter.debug(" - Finished checking finite ranges")
 
-            res match {
-              case Abort() =>
-                CheckResult(Unknown)
+          res match {
+            case Abort() =>
+              CheckResult.cast(Unknown)
 
-              case Sat(optModel) =>
-                Validate(optModel.map(extractTotalModel))
+            case Sat =>
+              CheckResult.cast(Sat)
 
-              case _ =>
-                InstantiateQuantifiers
-            }
+            case SatWithModel(model) =>
+              Validate(extractTotalModel(model))
+
+            case _ =>
+              InstantiateQuantifiers
           }
 
-        case Validate(optModel) => optModel match {
-          case None => CheckResult(config cast SolverResponses.Sat)
-          case Some(model) =>
-            val valid = !checkModels || validateModel(model, assumptionsSeq, silenceErrors = silentErrors)
-            if (valid) {
-              CheckResult(config cast SolverResponses.SatWithModel(model))
-            } else {
-              reporter.error(
-                "Something went wrong. The model should have been valid, yet we got this: " +
-                model.toString +
-                " for formula " + andJoin(assumptionsSeq ++ constraints).asString)
-              CheckResult(Unknown)
-            }
-        }
+        case Validate(model) =>
+          val valid = !checkModels || validateModel(model, assumptionsSeq, silenceErrors = silentErrors)
+          if (valid) {
+            CheckResult(config cast SatWithModel(model))
+          } else {
+            reporter.error(
+              "Something went wrong. The model should have been valid, yet we got this: " +
+              model.toString +
+              " for formula " + andJoin(assumptionsSeq ++ constraints).asString)
+            CheckResult.cast(Unknown)
+          }
 
         case InstantiateQuantifiers =>
           if (!templates.quantificationsManager.unrollGeneration.isDefined) {
             reporter.error("Something went wrong. The model is not transitive yet we can't instantiate!?")
-            CheckResult(Unknown)
+            CheckResult.cast(Unknown)
           } else {
             templates.promoteQuantifications
             Unroll
@@ -441,36 +409,37 @@ trait AbstractUnrollingSolver
           }
 
           val timer = ctx.timers.solvers.check.start()
-          solverCheckAssumptions(config max Configuration(model = feelingLucky))(
-            encodedAssumptions.toSeq ++ templates.refutationAssumptions
-          ) { res =>
-            timer.stop()
-
-            reporter.debug(" - Finished search without blocked literals")
-
-            res match {
-              case Abort() =>
-                CheckResult(Unknown)
-
-              case _: Unsat =>
-                CheckResult(res)
-
-              case Sat(Some(model)) if feelingLucky =>
-                if (validateModel(extractSimpleModel(model), assumptionsSeq, silenceErrors = true)) {
-                  CheckResult(res)
-                } else {
-                  for {
-                    (inst, bs) <- templates.getInstantiationsWithBlockers
-                    if model.eval(inst, BooleanType) == Some(BooleanLiteral(false))
-                    b <- bs
-                  } templates.promoteBlocker(b, force = true)
-
-                  Unroll
-                }
-
-              case _ =>
+          val res: SolverResponse[underlying.Model, underlying.Cores] =
+            underlying.checkAssumptions(config max Configuration(model = feelingLucky))(
+              encodedAssumptions.toSet ++ templates.refutationAssumptions
+            )
+          timer.stop()
+
+          reporter.debug(" - Finished search without blocked literals")
+
+          res match {
+            case Abort() =>
+              CheckResult.cast(Unknown)
+
+            case _: Unsatisfiable =>
+              CheckResult.cast(res)
+
+            case SatWithModel(model) if feelingLucky =>
+              if (validateModel(extractSimpleModel(model), assumptionsSeq, silenceErrors = true)) {
+                CheckResult.cast(res)
+              } else {
+                val wrapped = wrapModel(model)
+                for {
+                  (inst, bs) <- templates.getInstantiationsWithBlockers
+                  if wrapped.eval(inst, BooleanType) == Some(BooleanLiteral(false))
+                  b <- bs
+                } templates.promoteBlocker(b, force = true)
+
                 Unroll
-            }
+              }
+
+            case _ =>
+              Unroll
           }
 
         case Unroll =>
@@ -481,7 +450,7 @@ trait AbstractUnrollingSolver
           for (i <- 1 to unfoldFactor.toInt) {
             val newClauses = templates.unroll
             for (ncl <- newClauses) {
-              solverAssert(ncl)
+              underlying.assertCnstr(ncl)
             }
           }
           timer.stop()
@@ -502,12 +471,17 @@ trait UnrollingSolver extends AbstractUnrollingSolver {
   import program.symbols._
 
   type Encoded = Expr
-  val solver: Solver { val program: theories.targetProgram.type }
+  val underlying: Solver {
+    val program: theories.targetProgram.type
+    type Trees = Expr
+    type Model = Map[ValDef, Expr]
+    type Cores = Set[Expr]
+  }
 
-  override val name = "U:"+solver.name
+  override val name = "U:"+underlying.name
 
   def free() {
-    solver.free()
+    underlying.free()
   }
 
   val printable = (e: Expr) => e
@@ -536,55 +510,35 @@ trait UnrollingSolver extends AbstractUnrollingSolver {
 
   def declareVariable(v: Variable): Variable = v
 
-  def solverAssert(cnstr: Expr): Unit = {
-    solver.assertCnstr(cnstr)
-  }
-
   case class ModelWrapper(model: Map[ValDef, Expr]) extends super.ModelWrapper {
     def modelEval(elem: Expr, tpe: Type): Option[Expr] = evaluator.eval(elem, model).result
     override def toString = model.mkString("\n")
   }
 
-  def solverCheck[R](config: Configuration)(clauses: Seq[Expr])(block: Response => R): R = {
-    solver.push()
-    for (cls <- clauses) solver.assertCnstr(cls)
-    import SolverResponses.{SolverResponse => SR}
-    val res = solver.check[SR[Map[ValDef, Expr], Set[Expr]]](config in solver) match {
-      case SolverResponses.Unknown               => Unknown
-      case SolverResponses.Unsat                 => Unsat(None)
-      case SolverResponses.UnsatWithCores(cores) => Unsat(Some(cores))
-      case SolverResponses.Sat                   => Sat(None)
-      case SolverResponses.SatWithModel(model)   => Sat(Some(ModelWrapper(model)))
-    }
-    val r = block(res)
-    solver.pop()
-    r
-  }
-
-  override def dbg(msg: => Any) = solver.dbg(msg)
+  override def dbg(msg: => Any) = underlying.dbg(msg)
 
   override def push(): Unit = {
     super.push()
-    solver.push()
+    underlying.push()
   }
 
   override def pop(): Unit = {
     super.pop()
-    solver.pop()
+    underlying.pop()
   }
 
   override def reset(): Unit = {
-    solver.reset()
+    underlying.reset()
     super.reset()
   }
 
   override def interrupt(): Unit = {
     super.interrupt()
-    solver.interrupt()
+    underlying.interrupt()
   }
 
   override def recoverInterrupt(): Unit = {
-    solver.recoverInterrupt()
+    underlying.recoverInterrupt()
     super.recoverInterrupt()
   }
 }