diff --git a/src/main/scala/leon/solvers/SolverFactory.scala b/src/main/scala/leon/solvers/SolverFactory.scala
index 2b838b68bb1e92cd442794c8e19532b910d97a42..5dd87da9acbe07cbddb9a32110ee877653e53a1c 100644
--- a/src/main/scala/leon/solvers/SolverFactory.scala
+++ b/src/main/scala/leon/solvers/SolverFactory.scala
@@ -40,10 +40,20 @@ object SolverFactory {
     }.mkString("")
 
   def getFromSettings(ctx: LeonContext, program: Program): SolverFactory[TimeoutSolver] = {
-    getFromName(ctx, program)(ctx.findOptionOrDefault(SharedOptions.optSelectedSolvers).toSeq : _*)
+    val names = ctx.findOptionOrDefault(SharedOptions.optSelectedSolvers)
+
+    if (((names contains "fairz3") || (names contains "unrollz3")) && !hasNativeZ3) {
+      if (!reported) {
+        ctx.reporter.warning("The Z3 native interface is not available, falling back to smt-based solver.")
+        reported = true
+      }
+      getFromName(ctx, program)("smt-z3")
+    } else {
+      getFromName(ctx, program)(names.toSeq : _*)
+    }
   }
 
-  def getFromName(ctx: LeonContext, program: Program)(names: String*): SolverFactory[TimeoutSolver] = {
+  private def getFromName(ctx: LeonContext, program: Program)(names: String*): SolverFactory[TimeoutSolver] = {
 
     def getSolver(name: String): SolverFactory[TimeoutSolver] = name match {
       case "fairz3" =>
@@ -95,9 +105,19 @@ object SolverFactory {
 
   // Solver qualifiers that get used internally:
 
+  private var reported = false
+
   // Fast solver used by simplifiactions, to discharge simple tautologies
   def uninterpreted(ctx: LeonContext, program: Program): SolverFactory[TimeoutSolver] = {
-    SolverFactory(() => new SMTLIBSolver(ctx, program) with SMTLIBZ3Target with TimeoutSolver)
+    if (hasNativeZ3) {
+      SolverFactory(() => new UninterpretedZ3Solver(ctx, program) with TimeoutSolver)
+    } else {
+      if (!reported) {
+        ctx.reporter.warning("The Z3 native interface is not available, falling back to smt-based solver.")
+        reported = true
+      }
+      SolverFactory(() => new SMTLIBSolver(ctx, program) with SMTLIBZ3Target with TimeoutSolver)
+    }
   }
 
   // Full featured solver used by default
@@ -105,4 +125,14 @@ object SolverFactory {
     getFromName(ctx, program)("fairz3")
   }
 
+  lazy val hasNativeZ3 = {
+    try {
+      new _root_.z3.scala.Z3Config
+      true
+    } catch {
+      case _: java.lang.UnsatisfiedLinkError =>
+        false
+    }
+  }
+
 }
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
index cfc0dee92025fc746b14c06c56a45e2e5df85935..7f8d4c3e432fc37c3ae8c99739330c540dd9898c 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
@@ -144,9 +144,12 @@ trait SMTLIBCVC4Target extends SMTLIBTarget {
       }
 
       m
+
     /**
      * ===== Set operations =====
      */
+
+
     case fs @ FiniteSet(elems) =>
       if (elems.isEmpty) {
         QualifiedIdentifier(SMTIdentifier(SSymbol("emptyset")), Some(declareSort(fs.getType)))
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
index fcfe4c801cf4334f90a051b0b361b9187964be18..7d694d10d03229d4037133986db922949e247898 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
@@ -57,12 +57,13 @@ trait SMTLIBTarget {
   def id2sym(id: Identifier): SSymbol = SSymbol(id.name+"!"+id.globalId)
 
   // metadata for CC, and variables
-  val constructors = new IncrementalBijection[TypeTree, SSymbol]()
-  val selectors    = new IncrementalBijection[(TypeTree, Int), SSymbol]()
-  val testers      = new IncrementalBijection[TypeTree, SSymbol]()
-  val variables    = new IncrementalBijection[Identifier, SSymbol]()
-  val sorts        = new IncrementalBijection[TypeTree, Sort]()
-  val functions    = new IncrementalBijection[TypedFunDef, SSymbol]()
+  val constructors  = new IncrementalBijection[TypeTree, SSymbol]()
+  val selectors     = new IncrementalBijection[(TypeTree, Int), SSymbol]()
+  val testers       = new IncrementalBijection[TypeTree, SSymbol]()
+  val variables     = new IncrementalBijection[Identifier, SSymbol]()
+  val genericValues = new IncrementalBijection[GenericValue, SSymbol]()
+  val sorts         = new IncrementalBijection[TypeTree, Sort]()
+  val functions     = new IncrementalBijection[TypedFunDef, SSymbol]()
 
   protected object OptionManager {
     lazy val leonOption = program.library.Option.get
@@ -151,7 +152,8 @@ trait SMTLIBTarget {
 
   def fromRawArray(r: RawArrayValue, tpe: TypeTree): Expr = tpe match {
     case SetType(base) =>
-      require(r.default == BooleanLiteral(false) && r.keyTpe == base)
+      require(r.default == BooleanLiteral(false), "Co-finite sets are not supported.")
+      require(r.keyTpe == base, s"Type error in solver model, expected $base, found ${r.keyTpe}")
 
       finiteSet(r.elems.keySet, base)
 
@@ -512,6 +514,12 @@ trait SMTLIBTarget {
       case m : MatchExpr =>
         toSMT(matchToIfThenElse(m))
 
+
+      case gv @ GenericValue(tpe, n) =>
+        genericValues.cachedB(gv) {
+          declareVariable(FreshIdentifier("gv"+n, tpe))
+        }
+
       /**
        * ===== Everything else =====
        */
@@ -582,7 +590,8 @@ trait SMTLIBTarget {
           case _ => reporter.fatalError("Unhandled nary "+e)
         }
 
-      case o => unsupported("Tree: " + o)
+      case o =>
+        unsupported("Tree: " + o)
     }
   }
 
@@ -731,6 +740,7 @@ trait SMTLIBTarget {
     selectors.push()
     testers.push()
     variables.push()
+    genericValues.push()
     sorts.push()
     functions.push()
 
@@ -744,6 +754,7 @@ trait SMTLIBTarget {
     selectors.pop()
     testers.pop()
     variables.pop()
+    genericValues.pop()
     sorts.pop()
     functions.pop()
 
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala
index 47088d817dfda6dfc9fe5cb4ef9e99118fd222b7..1574e990b44e6cd53312056fe34a4bdd576366dc 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala
@@ -41,6 +41,7 @@ trait SMTLIBZ3Target extends SMTLIBTarget {
     sorts.cachedB(tpe) {
       tpe match {
         case SetType(base) =>
+          super.declareSort(BooleanType)
           declareSetSort(base)
         case _ =>
           super.declareSort(t)
diff --git a/src/main/scala/leon/synthesis/Synthesizer.scala b/src/main/scala/leon/synthesis/Synthesizer.scala
index 9dabc12332e6f805b6a69d2308c169dc9c0d92f2..40e6b8bbcec93d4634f7048d9521d50163e51fea 100644
--- a/src/main/scala/leon/synthesis/Synthesizer.scala
+++ b/src/main/scala/leon/synthesis/Synthesizer.scala
@@ -73,7 +73,7 @@ class Synthesizer(val context : LeonContext,
 
     val (npr, fds) = solutionToProgram(sol)
 
-    val solverf = SolverFactory.getFromName(context, npr)("fairz3").withTimeout(timeout)
+    val solverf = SolverFactory.default(context, npr).withTimeout(timeout)
 
     val vctx = VerificationContext(context, npr, solverf, context.reporter)
     val vcs = generateVCs(vctx, Some(fds.map(_.id.name)))