diff --git a/library/annotation/package.scala b/library/annotation/package.scala
index f5cd07d4172902aee5a63da9464dec2e3ffbc822..63bf384f24187a5ede39dcbdf39e90400803fccf 100644
--- a/library/annotation/package.scala
+++ b/library/annotation/package.scala
@@ -13,5 +13,7 @@ package object annotation {
   class ignore     extends StaticAnnotation
   @ignore
   class extern     extends StaticAnnotation
+  @ignore
+  class inline     extends StaticAnnotation
 }
 
diff --git a/library/lang/package.scala b/library/lang/package.scala
index 5902e46b15947f968d3ff383e6c1510a563f1c26..21535202b8cc2a5333a6372bde62a48b5fe52576 100644
--- a/library/lang/package.scala
+++ b/library/lang/package.scala
@@ -6,17 +6,30 @@ import leon.annotation._
 import scala.language.implicitConversions
 
 package object lang {
-  @ignore
+
   implicit class BooleanDecorations(val underlying: Boolean) {
+    @inline
     def holds : Boolean = {
-      assert(underlying)
       underlying
+    } ensuring {
+      _ == true
     }
+
+    @inline
     def ==> (that: Boolean): Boolean = {
       !underlying || that
     }
   }
 
+  implicit class SpecsDecorations[A](val underlying: A) {
+    @inline
+    def computes(target: A) = {
+      underlying
+    } ensuring {
+      res => res == target
+    }
+  }
+
   @ignore
   object InvariantFunction {
     def invariant(x: Boolean): Unit = ()
diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala
index 89dca4fcbae9866abb336e27bcadd97d2ad4ee60..79eb4d614ed6ff2ef3f2f5f80e71b2fc5308189f 100644
--- a/src/main/scala/leon/codegen/CodeGeneration.scala
+++ b/src/main/scala/leon/codegen/CodeGeneration.scala
@@ -450,7 +450,7 @@ trait CodeGeneration {
         // list
       
       // Static lazy fields/ functions
-      case FunctionInvocation(tfd, as) =>
+      case fi @ FunctionInvocation(tfd, as) =>
         val (cn, mn, ms) = leonFunDefToJVMInfo(tfd.fd).getOrElse {
           throw CompilationException("Unknown method : " + tfd.id)
         }
@@ -814,11 +814,9 @@ trait CodeGeneration {
         ch << InvokeStatic(GenericValuesClass, "get", "(I)Ljava/lang/Object;")
       
       case nt @ NoTree( tp@(Int32Type | BooleanType | UnitType | CharType)) =>
-        println("COMPILING "+nt+" TO "+simplestValue(tp))
         mkExpr(simplestValue(tp), ch)
         
       case nt @ NoTree(_) =>
-        println("COMPILING "+nt+" TO NULL")
         ch << ACONST_NULL
       
       case This(ct) =>
diff --git a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
index bee85f77dd6e619de01ed97ca5f09f1de813b0ca..211b7dfc072d7773d7166ddab14c831ada2739ff 100644
--- a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
+++ b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
@@ -20,6 +20,17 @@ trait ASTExtractors {
     rootMirror.getClassByName(newTermName(str))
   }
 
+  def annotationsOf(s: Symbol): Set[String] = {
+    val actualSymbol = s.accessedOrSelf
+
+    (for {
+      a <- actualSymbol.annotations ++ actualSymbol.owner.annotations
+      name = a.atp.safeToString.replaceAll("\\.package\\.", ".")
+      if (name startsWith "leon.annotation.")
+    } yield {
+      name.split("\\.", 3)(2)
+    }).toSet
+  }
 
   protected lazy val tuple2Sym          = classFromName("scala.Tuple2")
   protected lazy val tuple3Sym          = classFromName("scala.Tuple3")
@@ -295,9 +306,17 @@ trait ASTExtractors {
       }
     }
 
+    private def isCaseClass(cd: ClassDef): Boolean = {
+      cd.symbol.isCase && !cd.symbol.isAbstractClass && cd.impl.body.size >= 8
+    }
+
+    private def isImplicitClass(cd: ClassDef): Boolean = {
+      cd.symbol.isImplicit
+    }
+
     object ExCaseClass {
       def unapply(cd: ClassDef): Option[(String,Symbol,Seq[(Symbol,ValDef)], Template)] = cd match {
-        case ClassDef(_, name, tparams, impl) if cd.symbol.isCase && !cd.symbol.isAbstractClass && impl.body.size >= 8 => {
+        case ClassDef(_, name, tparams, impl) if isCaseClass(cd) || isImplicitClass(cd) => {
           val constructor: DefDef = impl.children.find {
             case ExConstructorDef() => true
             case _ => false
@@ -361,10 +380,19 @@ trait ASTExtractors {
         * and regardless of its visibility.
         */
       def unapply(dd: DefDef): Option[(Symbol, Seq[Symbol], Seq[ValDef], Type, Tree)] = dd match {
-        case DefDef(_, name, tparams, vparamss, tpt, rhs) if(
-           name != nme.CONSTRUCTOR && !dd.symbol.isSynthetic && !dd.symbol.isAccessor
-        ) =>
-          Some((dd.symbol, tparams.map(_.symbol), vparamss.flatten, tpt.tpe, rhs))
+        case DefDef(_, name, tparams, vparamss, tpt, rhs) if name != nme.CONSTRUCTOR && !dd.symbol.isAccessor =>
+          if (dd.symbol.isSynthetic && dd.symbol.isImplicit && dd.symbol.isMethod) {
+            // Check that the class it was generated from is not ignored
+            if (annotationsOf(tpt.symbol)("ignore")) {
+              None
+            } else {
+              Some((dd.symbol, tparams.map(_.symbol), vparamss.flatten, tpt.tpe, rhs))
+            }
+          } else if (!dd.symbol.isSynthetic) {
+            Some((dd.symbol, tparams.map(_.symbol), vparamss.flatten, tpt.tpe, rhs))
+          } else {
+            None
+          }
         case _ => None
       }
     }
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index 7a77450a7b41a8248b85fdddc3d19448588a9035..b159fdbdba34313cbe538767910750010456d45d 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -13,7 +13,6 @@ import Definitions.{
   ModuleDef   => LeonModuleDef,
   ValDef      => LeonValDef,
   Import      => LeonImport,
-  Annotation  => LeonAnnotation,
   _
 }
 
@@ -45,18 +44,6 @@ trait CodeExtraction extends ASTExtractors {
 
   val reporter = self.ctx.reporter
 
-  def annotationsOf(s: Symbol): Set[String] = {
-    val actualSymbol = s.accessedOrSelf
-
-    (for {
-      a <- actualSymbol.annotations ++ actualSymbol.owner.annotations
-      name = a.atp.safeToString.replaceAll("\\.package\\.", ".")
-      if (name startsWith "leon.annotation.")
-    } yield {
-      name.split("\\.", 3)(2)
-    }).toSet
-  }
-
   implicit def scalaPosToLeonPos(p: global.Position): LeonPosition = {
     if (p == NoPosition) {
       leon.utils.NoPosition
@@ -655,7 +642,11 @@ trait CodeExtraction extends ASTExtractors {
 
       fd.setPos(sym.pos)
 
-      fd.addFlag(annotationsOf(sym).toSeq.map(LeonAnnotation) : _*)
+      fd.addFlags(annotationsOf(sym).map(FunctionFlag.fromName))
+
+      if (sym.isImplicit) {
+        fd.addFlag(IsInlined)
+      }
 
       defsToDefs += sym -> fd
 
@@ -675,7 +666,7 @@ trait CodeExtraction extends ASTExtractors {
       fd.setPos(sym.pos)
       fd.addFlag(IsField(isLazy))
 
-      fd.addFlag(annotationsOf(sym).toSeq.map(LeonAnnotation) : _*)
+      fd.addFlags(annotationsOf(sym).map(FunctionFlag.fromName))
 
       defsToDefs += sym -> fd
 
@@ -1068,7 +1059,7 @@ trait CodeExtraction extends ASTExtractors {
 
           val tparamsMap = (tparams zip fd.tparams.map(_.tp)).toMap
 
-          fd.addFlag(annotationsOf(d.symbol).toSeq.map(LeonAnnotation) : _*)
+          fd.addFlags(annotationsOf(d.symbol).map(FunctionFlag.fromName))
 
           val newDctx = dctx.copy(tparams = dctx.tparams ++ tparamsMap)
 
diff --git a/src/main/scala/leon/purescala/DefOps.scala b/src/main/scala/leon/purescala/DefOps.scala
index 64a0dca50c0b66ceb685be331588fa703f2f62e3..7e4d216a32bbef4801936cb76f6bf8588820e52e 100644
--- a/src/main/scala/leon/purescala/DefOps.scala
+++ b/src/main/scala/leon/purescala/DefOps.scala
@@ -347,6 +347,20 @@ object DefOps {
     res
   }
 
+  // @Note: This function does not remove functions in classdefs
+  def removeDefs(p: Program, dds: Set[Definition]): Program = {
+    p.copy(units = for (u <- p.units if !dds(u)) yield {
+      u.copy(
+        defs = for (d <- u.defs if !dds(d)) yield d match {
+          case md: ModuleDef =>
+            md.copy(defs = md.defs.filterNot(dds))
+
+          case cd => cd 
+        }
+      )
+    })
+  }
+
   /**
    * Returns a call graph starting from the given sources, taking into account
    * instantiations of function type parameters,
diff --git a/src/main/scala/leon/purescala/Definitions.scala b/src/main/scala/leon/purescala/Definitions.scala
index 9f56f7ba1fcf3d190a5e9d37f529acdc580a44b2..127c562217fbb8d64329d87db3bbff969231405a 100644
--- a/src/main/scala/leon/purescala/Definitions.scala
+++ b/src/main/scala/leon/purescala/Definitions.scala
@@ -303,7 +303,15 @@ object Definitions {
   }
 
   // A class that represents flags that annotate a FunDef with different attributes
-  class FunctionFlag
+  sealed abstract class FunctionFlag
+
+  object FunctionFlag {
+    def fromName(name: String): FunctionFlag = name match {
+      case "inline" => IsInlined
+      case _ => Annotation(name)
+    }
+  }
+
   // Whether this FunDef was originally a (lazy) field
   case class IsField(isLazy: Boolean) extends FunctionFlag
   // Compiler annotations given in the source code as @annot
@@ -317,6 +325,8 @@ object Definitions {
   case object IsAbstract extends FunctionFlag
   // Currently, the only synthetic functions are those that calculate default values of parameters
   case object IsSynthetic extends FunctionFlag
+  // Is inlined
+  case object IsInlined extends FunctionFlag
 
   /** Functions
     *  This class represents methods or fields of objects. By "fields" we mean
@@ -376,20 +386,22 @@ object Definitions {
     
     def copyContentFrom(from : FunDef) {
       this.fullBody  = from.fullBody 
-      this.addFlag(from.flags.toSeq : _*)
+      this.addFlags(from.flags)
     }
 
     /* Flags */
 
-    private var flags_ : Set[FunctionFlag] = Set()
-    
-    def addFlag(flags: FunctionFlag*): FunDef = {
+    private[this] var flags_ : Set[FunctionFlag] = Set()
+
+    def addFlags(flags: Set[FunctionFlag]): FunDef = {
       this.flags_ ++= flags
       this
     }
-    
+
+    def addFlag(flag: FunctionFlag): FunDef = addFlags(Set(flag))
+
     def flags = flags_
-    
+
     def annotations: Set[String] = flags_ collect { case Annotation(s) => s }
     def canBeLazyField    = flags.contains(IsField(true))  && params.isEmpty && tparams.isEmpty
     def canBeStrictField  = flags.contains(IsField(false)) && params.isEmpty && tparams.isEmpty
diff --git a/src/main/scala/leon/purescala/ExprOps.scala b/src/main/scala/leon/purescala/ExprOps.scala
index b156a4bde8b102ee148dd2cbb4774868d7fc5480..66b1ed28a43b7849049d4a8bf726c8b49ab47c6d 100644
--- a/src/main/scala/leon/purescala/ExprOps.scala
+++ b/src/main/scala/leon/purescala/ExprOps.scala
@@ -472,6 +472,9 @@ object ExprOps {
       case TupleSelect(LetTuple(ids, v, b), ts) =>
         Some(letTuple(ids, v, tupleSelect(b, ts, true)))
 
+      case CaseClassSelector(cct, cc: CaseClass, id) =>
+        Some(CaseClassSelector(cct, cc, id))
+
       case IfExpr(c, thenn, elze) if (thenn == elze) && isDeterministic(e) =>
         Some(thenn)
 
diff --git a/src/main/scala/leon/utils/InliningPhase.scala b/src/main/scala/leon/utils/InliningPhase.scala
new file mode 100644
index 0000000000000000000000000000000000000000..5382275db54b3508a63aee57a11b5f229078f545
--- /dev/null
+++ b/src/main/scala/leon/utils/InliningPhase.scala
@@ -0,0 +1,51 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon.utils
+
+import leon._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.Types._
+import purescala.TypeOps._
+import purescala.ExprOps._
+import purescala.DefOps._
+
+object InliningPhase extends TransformationPhase {
+  
+  val name = "Inline @inline functions"
+  val description = "Inline functions marked as @inline and remove their definitions"
+  
+  def apply(ctx: LeonContext, p: Program): Program = {
+    val toInline = p.definedFunctions.filter(_.flags(IsInlined)).toSet
+
+    val substs = toInline.map { fd =>
+      fd -> { (tps: Seq[TypeTree], s: Seq[Expr]) => 
+        val newBody = replaceFromIDs(fd.params.map(_.id).zip(s).toMap, fd.fullBody)
+        instantiateType(newBody, (fd.tparams zip tps).toMap, Map())
+      }
+    }.toMap
+
+    def simplifyImplicitClass(e: Expr) = e match {
+      case CaseClassSelector(cct, cc: CaseClass, id) =>
+        Some(CaseClassSelector(cct, cc, id))
+
+      case _ =>
+        None
+    }
+
+    def simplify(e: Expr) = {
+      fixpoint(postMap(simplifyImplicitClass _))(e)
+    }
+
+    val (np, _) = replaceFunDefs(p)({fd => None}, {(fi, fd) => 
+      if (substs contains fd) {
+        Some(simplify(substs(fd)(fi.tfd.tps, fi.args)))
+      } else {
+        None
+      }
+    })
+
+    removeDefs(np, toInline.map { fd => (fd: Definition) })
+  }
+
+}
diff --git a/src/main/scala/leon/utils/PreprocessingPhase.scala b/src/main/scala/leon/utils/PreprocessingPhase.scala
index be022631ce3c1cb1095b321fcca6bdbd5c824bbe..8fdf84f8d733e5e476ed0b4f0688138f7bd9989e 100644
--- a/src/main/scala/leon/utils/PreprocessingPhase.scala
+++ b/src/main/scala/leon/utils/PreprocessingPhase.scala
@@ -23,7 +23,8 @@ object PreprocessingPhase extends TransformationPhase {
       ConvertHoles                  andThen
       CompleteAbstractDefinitions   andThen
       CheckADTFieldsTypes           andThen
-      InjectAsserts
+      InjectAsserts                 andThen
+      InliningPhase
 
 
     phases.run(ctx)(p)