diff --git a/doc/purescala.rst b/doc/purescala.rst
index 004d37a133f1a14c12cf77162247c605d9796406..f3c40b5fd57e5620fa33e2872ef51f7bfeb4583a 100644
--- a/doc/purescala.rst
+++ b/doc/purescala.rst
@@ -297,6 +297,10 @@ Map
  m isDefinedAt index
  m contains index
  m.updated(index, value)
+ m + (index -> value)
+ m + (value, index)
+ m.get(index)
+ m.getOrElse(index, value2)
 
 
 Function
diff --git a/library/lang/Map.scala b/library/lang/Map.scala
index bd186b721d7d7d62a194366fceedabd55b04986d..368c028abd1622c8236615121c3f324e54feffc6 100644
--- a/library/lang/Map.scala
+++ b/library/lang/Map.scala
@@ -12,10 +12,21 @@ object Map {
 }
 
 @ignore
-case class Map[A, B](val theMap: scala.collection.immutable.Map[A,B]) {
+case class Map[A, B] (theMap: scala.collection.immutable.Map[A,B]) {
   def apply(k: A): B = theMap.apply(k)
   def ++(b: Map[A, B]): Map[A,B] = new Map (theMap ++ b.theMap)
   def updated(k: A, v: B): Map[A,B] = new Map(theMap.updated(k, v))
   def contains(a: A): Boolean = theMap.contains(a)
   def isDefinedAt(a: A): Boolean = contains(a)
+
+  def +(kv: (A, B)): Map[A,B] = updated(kv._1, kv._2)
+  def +(k: A, v: B): Map[A,B] = updated(k, v)
+
+  def getOrElse(k: A, default: B): B = get(k).getOrElse(default)
+
+  def get(k: A): Option[B] = if (contains(k)) {
+    Some[B](apply(k))
+  } else {
+    None[B]()
+  }
 }
diff --git a/library/collection/Option.scala b/library/lang/Option.scala
similarity index 98%
rename from library/collection/Option.scala
rename to library/lang/Option.scala
index 56feffdc0fc5b017b8b8a5dc9862d1f3a06d5811..0d77ef74e34fca33a583b96d0a2b6e26af17d74c 100644
--- a/library/collection/Option.scala
+++ b/library/lang/Option.scala
@@ -1,6 +1,6 @@
 /* Copyright 2009-2015 EPFL, Lausanne */
 
-package leon.collection
+package leon.lang
 
 import leon.annotation._
 
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index b37b6672fe7c741e5c76e09408dd56bb2c55871d..2047200929bf3e3d9876e4e01f0ab5eefab34708 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -520,6 +520,7 @@ trait CodeExtraction extends ASTExtractors {
 
         parent.foreach(_.classDef.registerChildren(ccd))
 
+
         classesToClasses += sym -> ccd
 
         val fields = args.map { case (symbol, t) =>
@@ -1704,6 +1705,19 @@ trait CodeExtraction extends ASTExtractors {
             case (IsTyped(a1, MapType(_, vt)), "apply", List(a2)) =>
               MapGet(a1, a2)
 
+            case (IsTyped(a1, MapType(_, vt)), "get", List(a2)) =>
+              val someClass = CaseClassType(libraryCaseClass(sym.pos, "leon.lang.Some"), Seq(vt))
+              val noneClass = CaseClassType(libraryCaseClass(sym.pos, "leon.lang.None"), Seq(vt))
+
+              IfExpr(MapIsDefinedAt(a1, a2).setPos(current.pos),
+                CaseClass(someClass, Seq(MapGet(a1, a2).setPos(current.pos))).setPos(current.pos),
+                CaseClass(noneClass, Seq()).setPos(current.pos))
+
+            case (IsTyped(a1, MapType(_, vt)), "getOrElse", List(a2, a3)) =>
+              IfExpr(MapIsDefinedAt(a1, a2).setPos(current.pos),
+                MapGet(a1, a2).setPos(current.pos),
+                a3)
+
             case (IsTyped(a1, mt: MapType), "isDefinedAt", List(a2)) =>
               MapIsDefinedAt(a1, a2)
 
@@ -1713,6 +1727,17 @@ trait CodeExtraction extends ASTExtractors {
             case (IsTyped(a1, mt: MapType), "updated", List(k, v)) =>
               MapUnion(a1, FiniteMap(Seq((k, v)), mt.from, mt.to))
 
+            case (IsTyped(a1, mt: MapType), "+", List(k, v)) =>
+              MapUnion(a1, FiniteMap(Seq((k, v)), mt.from, mt.to))
+
+            case (IsTyped(a1, mt: MapType), "+", List(IsTyped(kv, TupleType(List(_, _))))) =>
+              kv match {
+                case Tuple(List(k, v)) =>
+                  MapUnion(a1, FiniteMap(Seq((k, v)), mt.from, mt.to))
+                case kv =>
+                  MapUnion(a1, FiniteMap(Seq((TupleSelect(kv, 1), TupleSelect(kv, 2))), mt.from, mt.to))
+              }
+
             case (IsTyped(a1, mt1: MapType), "++", List(IsTyped(a2, mt2: MapType)))  if mt1 == mt2 =>
               MapUnion(a1, a2)
 
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
index 3df3f89e57d809ba8d1ba6ef2785dbd078a71333..ae77673d813e66d10a0e0a75451f0a0ef3ba82d1 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
@@ -225,7 +225,12 @@ abstract class SMTLIBSolver(val context: LeonContext,
     case MapType(from, to) =>
       // We expect a RawArrayValue with keys in from and values in Option[to],
       // with default value == None
-      require(from == r.keyTpe && r.default == OptionManager.mkLeonNone(to))
+      if (r.default != OptionManager.mkLeonNone(to)) {
+        reporter.warning("Co-finite maps are not supported. (Default was "+r.default+")")
+        throw new IllegalArgumentException
+      }
+      require(r.keyTpe == from, s"Type error in solver model, expected $from, found ${r.keyTpe}")
+
       val elems = r.elems.flatMap {
         case (k, CaseClass(leonSome, Seq(x))) => Some(k -> x)
         case (k, _) => None
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Solver.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Solver.scala
index 37efdd120ba60bcafb27cc325ad7c84782d6c587..cc6e2161c3ee3d7c1ebd0ee27546a13dfe56f403 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Solver.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Solver.scala
@@ -156,6 +156,7 @@ class SMTLIBZ3Solver(context: LeonContext, program: Program) extends SMTLIBSolve
     case DefineFun(SMTFunDef(a, Seq(SortedVar(arg, akind)), rkind, body)) =>
       val (argTpe, retTpe) = tpe match {
         case SetType(base) => (base, BooleanType)
+        case MapType(from, to) => (from, OptionManager.leonOptionType(to))
         case ArrayType(base) => (Int32Type, base)
         case FunctionType(args, ret) => (tupleTypeWrap(args), ret)
         case RawArrayType(from, to) => (from, to)
diff --git a/src/main/scala/leon/utils/Library.scala b/src/main/scala/leon/utils/Library.scala
index f22169ba94f177f762fb114f8c3da7cf20880c43..e7c76c83165969a7cf12b32b6f96af12a1657010 100644
--- a/src/main/scala/leon/utils/Library.scala
+++ b/src/main/scala/leon/utils/Library.scala
@@ -11,9 +11,9 @@ case class Library(pgm: Program) {
   lazy val Cons = lookup("leon.collection.Cons") collect { case ccd : CaseClassDef => ccd }
   lazy val Nil  = lookup("leon.collection.Nil") collect { case ccd : CaseClassDef => ccd }
 
-  lazy val Option = lookup("leon.collection.Option") collect { case acd : AbstractClassDef => acd }
-  lazy val Some = lookup("leon.collection.Some") collect { case ccd : CaseClassDef => ccd }
-  lazy val None = lookup("leon.collection.None") collect { case ccd : CaseClassDef => ccd }
+  lazy val Option = lookup("leon.lang.Option") collect { case acd : AbstractClassDef => acd }
+  lazy val Some = lookup("leon.lang.Some") collect { case ccd : CaseClassDef => ccd }
+  lazy val None = lookup("leon.lang.None") collect { case ccd : CaseClassDef => ccd }
 
   lazy val String = lookup("leon.lang.string.String") collect { case ccd : CaseClassDef => ccd }
 
diff --git a/src/test/resources/regression/frontends/passing/ImplicitDefs2.scala b/src/test/resources/regression/frontends/passing/ImplicitDefs2.scala
index a157e5dd6bf437d11ae0d1ea51cca47d6d3723e0..9f4b1a83fbb7dd4c6e4600d1030d083335344b62 100644
--- a/src/test/resources/regression/frontends/passing/ImplicitDefs2.scala
+++ b/src/test/resources/regression/frontends/passing/ImplicitDefs2.scala
@@ -3,7 +3,6 @@ package leon.blup
 import leon._
 import leon.lang._
 import leon.annotation._
-import leon.collection.{Option,None,Some}
 //import leon.proof._
 
 // FIXME: the following should go into the leon.proof package object.
diff --git a/src/test/resources/regression/verification/purescala/valid/MapGetOrElse2.scala b/src/test/resources/regression/verification/purescala/valid/MapGetOrElse2.scala
new file mode 100644
index 0000000000000000000000000000000000000000..7b1e19418f09cdcf1df212934e7ca795780f4cf6
--- /dev/null
+++ b/src/test/resources/regression/verification/purescala/valid/MapGetOrElse2.scala
@@ -0,0 +1,17 @@
+import leon.lang._
+
+object MapGetOrElse2 {
+  def test1(a: Map[BigInt, BigInt]) = {
+    require(!(a contains 0))
+    a.get(0)
+  } ensuring {
+    _ == None[BigInt]()
+  }
+
+  def test2(a: Map[BigInt, BigInt]) = {
+    require(!(a contains 0))
+    a.getOrElse(0, 0)
+  } ensuring {
+    _ == 0
+  }
+}
diff --git a/src/test/resources/regression/verification/purescala/valid/MapPlus.scala b/src/test/resources/regression/verification/purescala/valid/MapPlus.scala
new file mode 100644
index 0000000000000000000000000000000000000000..86a3d6d22b15764f66be716052ab6737f63dda91
--- /dev/null
+++ b/src/test/resources/regression/verification/purescala/valid/MapPlus.scala
@@ -0,0 +1,18 @@
+import leon.lang._
+
+object MapGetPlus {
+  def test1(a: Map[BigInt, BigInt]) = {
+    require(!(a contains 0))
+    val b = a + (0, 1)
+    val c = a + (BigInt(0) -> BigInt(1))
+    b(0) == c(0)
+  }.holds
+
+  def test2(a: Map[BigInt, BigInt]) = {
+    require(!(a contains 0))
+    val t = (BigInt(0) -> BigInt(1))
+    val b = a + (0, 1)
+    val c = a + t
+    b(0) == c(0)
+  }.holds
+}
diff --git a/testcases/repair/Parser/Parser.scala b/testcases/repair/Parser/Parser.scala
index 876652d8e5c94bff65b3172b190efbd9e82c5893..8d838f470d63d8e8967f53cf88b2a6bcaf98061c 100644
--- a/testcases/repair/Parser/Parser.scala
+++ b/testcases/repair/Parser/Parser.scala
@@ -1,4 +1,5 @@
 import leon._
+import leon.lang._
 import leon.collection._
 
 object Parser {
diff --git a/testcases/repair/Parser/Parser1.scala b/testcases/repair/Parser/Parser1.scala
index 1a12b820cba019fb40ff3fe7ae8cc71849f1a85a..5fd18245f4cc6d62ecef9278ae29cfb9e8a16bd0 100644
--- a/testcases/repair/Parser/Parser1.scala
+++ b/testcases/repair/Parser/Parser1.scala
@@ -1,4 +1,5 @@
 import leon._
+import leon.lang._
 import leon.collection._
 
 object Parser {
diff --git a/testcases/repair/Parser/Parser2.scala b/testcases/repair/Parser/Parser2.scala
index 24fef56869854373c8367981fc38dea19af49218..919132e04b7fe97ac81b836b02140eb42fb57b77 100644
--- a/testcases/repair/Parser/Parser2.scala
+++ b/testcases/repair/Parser/Parser2.scala
@@ -1,4 +1,5 @@
 import leon._
+import leon.lang._
 import leon.collection._
 
 object Parser {
diff --git a/testcases/repair/Parser/Parser3.scala b/testcases/repair/Parser/Parser3.scala
index dcc8107f3e1e439e94c93083b5cb7370065678f5..cf11c4d3ff54ce42b6858f532e56a3f03e487fa0 100644
--- a/testcases/repair/Parser/Parser3.scala
+++ b/testcases/repair/Parser/Parser3.scala
@@ -1,4 +1,5 @@
 import leon._
+import leon.lang._
 import leon.collection._
 
 object Parser {
diff --git a/testcases/repair/Parser/Parser4.scala b/testcases/repair/Parser/Parser4.scala
index dcc8107f3e1e439e94c93083b5cb7370065678f5..cf11c4d3ff54ce42b6858f532e56a3f03e487fa0 100644
--- a/testcases/repair/Parser/Parser4.scala
+++ b/testcases/repair/Parser/Parser4.scala
@@ -1,4 +1,5 @@
 import leon._
+import leon.lang._
 import leon.collection._
 
 object Parser {
diff --git a/testcases/repair/Parser/Parser5.scala b/testcases/repair/Parser/Parser5.scala
index dcc8107f3e1e439e94c93083b5cb7370065678f5..cf11c4d3ff54ce42b6858f532e56a3f03e487fa0 100644
--- a/testcases/repair/Parser/Parser5.scala
+++ b/testcases/repair/Parser/Parser5.scala
@@ -1,4 +1,5 @@
 import leon._
+import leon.lang._
 import leon.collection._
 
 object Parser {