diff --git a/src/main/scala/leon/Main.scala b/src/main/scala/leon/Main.scala
index 8278ca3396ab27ac4298881c678231fab122e5a2..a0d5c4830ffd69b47478593e823217960b2aa21d 100644
--- a/src/main/scala/leon/Main.scala
+++ b/src/main/scala/leon/Main.scala
@@ -11,7 +11,6 @@ object Main {
       frontends.scalac.ExtractionPhase,
       utils.TypingPhase,
       FileOutputPhase,
-      ScopingPhase,
       purescala.RestoreMethods,
       xlang.ArrayTransformation,
       xlang.EpsilonElimination,
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index eb010351db8a374196eef1582b3670b7cfe96d05..cbdf4a6e25302b719c32208cb03badceb4d55f4a 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -9,10 +9,11 @@ import scala.language.implicitConversions
 
 import purescala._
 import purescala.Definitions.{
-  ClassDef  => LeonClassDef, 
-  ModuleDef => LeonModuleDef, 
-  ValDef    => LeonValDef, 
-  Import    => LeonImport,
+  ClassDef    => LeonClassDef,
+  ModuleDef   => LeonModuleDef,
+  ValDef      => LeonValDef,
+  Import      => LeonImport,
+  Annotation  => LeonAnnotation,
   _
 }
 
@@ -287,7 +288,7 @@ trait CodeExtraction extends ASTExtractors {
             // Default value functions
             case ExDefaultValueFunction(sym, _, _, _ ,_ , _, _) =>
               val fd = defineFunDef(sym)(DefContext())
-              fd.addAnnotation("synthetic")
+              fd.addFlag(IsSynthetic)
 
               Some(fd)
 
@@ -578,7 +579,7 @@ trait CodeExtraction extends ASTExtractors {
         // Default values for parameters
         case t@ ExDefaultValueFunction(fsym, _, _, _, owner, index, _) =>
           val fd = defineFunDef(fsym)(defCtx)
-          fd.addAnnotation("synthetic")
+          fd.addFlag(IsSynthetic)
 
           isMethod += fsym
           methodToClass += fd -> cd
@@ -644,11 +645,11 @@ trait CodeExtraction extends ASTExtractors {
 
       val name = sym.name.toString
 
-      val fd = new FunDef(FreshIdentifier(name).setPos(sym.pos), tparamsDef, returnType, newParams, DefType.MethodDef)
+      val fd = new FunDef(FreshIdentifier(name).setPos(sym.pos), tparamsDef, returnType, newParams)
 
       fd.setPos(sym.pos)
 
-      fd.addAnnotation(annotationsOf(sym).toSeq : _*)
+      fd.addFlag(annotationsOf(sym).toSeq.map(LeonAnnotation) : _*)
 
       defsToDefs += sym -> fd
 
@@ -663,13 +664,12 @@ trait CodeExtraction extends ASTExtractors {
 
       val name = sym.name.toString
 
-      val fieldType = if (isLazy) DefType.LazyFieldDef else DefType.StrictFieldDef
-
-      val fd = new FunDef(FreshIdentifier(name).setPos(sym.pos), Seq(), returnType, Seq(), fieldType)
+      val fd = new FunDef(FreshIdentifier(name).setPos(sym.pos), Seq(), returnType, Seq())
 
       fd.setPos(sym.pos)
+      fd.addFlag(IsField(isLazy))
 
-      fd.addAnnotation(annotationsOf(sym).toSeq : _*)
+      fd.addFlag(annotationsOf(sym).toSeq.map(LeonAnnotation) : _*)
 
       defsToDefs += sym -> fd
 
@@ -768,7 +768,7 @@ trait CodeExtraction extends ASTExtractors {
 
       // If this is a lazy field definition, drop the assignment/ accessing
       val body = 
-        if (funDef.defType == DefType.LazyFieldDef) { body0 match {
+        if (funDef.flags.contains(IsField(true))) { body0 match {
           case Block(List(Assign(_, realBody)),_ ) => realBody
           case _ => outOfSubsetError(body0, "Wrong form of lazy accessor")
         }} else body0
@@ -799,7 +799,7 @@ trait CodeExtraction extends ASTExtractors {
             reporter.warning(funDef.getPos, "Function "+funDef.id.name+" is not fully unavailable to Leon.")
           }
 
-          funDef.addAnnotation("abstract")
+          funDef.addFlag(IsAbstract)
           NoTree(funDef.returnType)
       }
 
@@ -1062,7 +1062,7 @@ trait CodeExtraction extends ASTExtractors {
 
           val tparamsMap = (tparams zip fd.tparams.map(_.tp)).toMap
 
-          fd.addAnnotation(annotationsOf(d.symbol).toSeq : _*)
+          fd.addFlag(annotationsOf(d.symbol).toSeq.map(LeonAnnotation) : _*)
 
           val newDctx = dctx.copy(tparams = dctx.tparams ++ tparamsMap)
 
diff --git a/src/main/scala/leon/purescala/Definitions.scala b/src/main/scala/leon/purescala/Definitions.scala
index 439e5445c9b7f086d380faa862c00908ce64aee0..575939a8c7dfc0095df7134b3b158a024dbaff83 100644
--- a/src/main/scala/leon/purescala/Definitions.scala
+++ b/src/main/scala/leon/purescala/Definitions.scala
@@ -15,9 +15,7 @@ object Definitions {
   sealed abstract class Definition extends Tree {
     
     val id: Identifier
-    
-    var origOwner : Option[Definition] = None // The definition/scope enclosing this definition
-    
+
     def subDefinitions : Seq[Definition]      // The enclosed scopes/definitions by this definition
   
     def containsDef(df: Definition): Boolean = {
@@ -66,8 +64,6 @@ object Definitions {
   case class Program(units: List[UnitDef]) extends Definition {
     val id = FreshIdentifier("program")
 
-    origOwner = None
-
     lazy val library = Library(this)
 
     def subDefinitions = units
@@ -326,16 +322,21 @@ object Definitions {
     lazy val singleCaseClasses : Seq[CaseClassDef] = if (hasParent) Nil else Seq(this)
   }
 
- 
-  // Definition types (see below)
-  object DefType extends Enumeration {
-    type DefType = Value
-    val MethodDef      = Value("def")
-    val StrictFieldDef = Value("val")
-    val LazyFieldDef   = Value("lazy val")
-  } 
-  import DefType._
-  
+  // A class that represents flags that annotate a FunDef with different attributes
+  class FunctionFlag
+  // Whether this FunDef was originally a (lazy) field
+  case class IsField(isLazy: Boolean) extends FunctionFlag
+  // Compiler annotations provided with @annot
+  case class Annotation(annot: String) extends FunctionFlag
+  // If this class was a method. owner is the original owner of the method
+  case class IsMethod(owner: ClassDef) extends FunctionFlag
+  // If this function represents a loop that was there before XLangElimination
+  // Contains a copy of the original looping function
+  case class IsLoop(orig: FunDef) extends FunctionFlag
+  case object IsPrivate extends FunctionFlag
+  case object IsAbstract extends FunctionFlag
+  case object IsSynthetic extends FunctionFlag
+
   /** Functions
    *  This class represents methods or fields of objects (as specified by the defType field)
    *  that appear ONLY in the class/object's body (not the constructors)
@@ -349,13 +350,9 @@ object Definitions {
     val id: Identifier,
     val tparams: Seq[TypeParameterDef],
     val returnType: TypeTree,
-    val params: Seq[ValDef],
-    val defType: DefType
+    val params: Seq[ValDef]
   ) extends Definition {
-    
-    // A copy of the original function before Xlang elimination
-    var orig : Option[FunDef] = None
-    
+
     private var fullBody_ : Expr = NoTree(returnType)
     def fullBody = fullBody_
     def fullBody_= (e : Expr) {
@@ -382,41 +379,40 @@ object Definitions {
     def subDefinitions = params ++ tparams ++ nestedFuns.toList
 
     def duplicate: FunDef = {
-      val fd = new FunDef(id.freshen, tparams, returnType, params, defType)
+      val fd = new FunDef(id.freshen, tparams, returnType, params)
       fd.copyContentFrom(this)
       fd.copiedFrom(this)
     }
     
     def copyContentFrom(from : FunDef) {
       this.fullBody  = from.fullBody 
-      this.orig    = from.orig
-      this.origOwner = from.origOwner
-      this.addAnnotation(from.annotations.toSeq : _*)
+      this.addFlag(from.flags.toSeq : _*)
     }
 
     def hasBody                     = body.isDefined
     def hasPrecondition : Boolean   = precondition.isDefined
     def hasPostcondition : Boolean  = postcondition.isDefined
 
-    /**
-     * When this functions has been annotated as a (lazy) field 
-     * and has no arguments, it can be printed/compiled as a field 
-     */
-    def canBeLazyField   = defType == LazyFieldDef    && params.isEmpty && tparams.isEmpty
-    def canBeStrictField = defType == StrictFieldDef  && params.isEmpty && tparams.isEmpty
-    def canBeField       = canBeLazyField || canBeStrictField
-    def isRealFunction   = !canBeField
+    private var flags_ : Set[FunctionFlag] = Set()
 
-    def isSynthetic = annotations contains "synthetic"
-    
-    private var annots: Set[String] = Set.empty[String]
-    def addAnnotation(as: String*) : FunDef = {
-      annots = annots ++ as
+    def addFlag(flags: FunctionFlag*) : FunDef = {
+      this.flags_ ++= flags
       this
     }
-    def annotations : Set[String] = annots
+    def flags = flags_
+    def annotations : Set[String] = flags_ collect { case Annotation(s) => s }
 
-    def isPrivate : Boolean = annots.contains("private")
+    /**
+     * When this functions has been annotated as a (lazy) field
+     * and has no arguments, it can be printed/compiled as a field
+     */
+    def canBeLazyField   = flags.contains(IsField(true))  && params.isEmpty && tparams.isEmpty
+    def canBeStrictField = flags.contains(IsField(false)) && params.isEmpty && tparams.isEmpty
+    def canBeField       = canBeLazyField || canBeStrictField
+    def isRealFunction   = !canBeField
+    def isPrivate = flags contains IsPrivate
+    def isSynthetic = flags contains IsSynthetic
+    def methodOwner = flags collectFirst { case IsMethod(cd) => cd }
 
     def typed(tps: Seq[TypeTree]) = {
       assert(tps.size == tparams.size)
diff --git a/src/main/scala/leon/purescala/ExprOps.scala b/src/main/scala/leon/purescala/ExprOps.scala
index b043da9ac1fcdae8271419544e3aea9d3e192688..ad3216436a99594babc223f25b8b1bb4e539d2de 100644
--- a/src/main/scala/leon/purescala/ExprOps.scala
+++ b/src/main/scala/leon/purescala/ExprOps.scala
@@ -1918,7 +1918,7 @@ object ExprOps {
     import synthesis.Witnesses.Terminating
     val res1 = preMap({
       case LetDef(fd, b) =>
-        val nfd = new FunDef(fd.id.freshen, fd.tparams, fd.returnType, fd.params, fd.defType)
+        val nfd = new FunDef(fd.id.freshen, fd.tparams, fd.returnType, fd.params)
         nfd.copyContentFrom(fd)
         nfd.copiedFrom(fd)
 
diff --git a/src/main/scala/leon/purescala/FunctionClosure.scala b/src/main/scala/leon/purescala/FunctionClosure.scala
index 1eed1d4842d668231538e47aaf01d263823390a4..b91ca4e3f34e2b9ca81decc6fb36d928e1315973 100644
--- a/src/main/scala/leon/purescala/FunctionClosure.scala
+++ b/src/main/scala/leon/purescala/FunctionClosure.scala
@@ -60,10 +60,10 @@ object FunctionClosure extends TransformationPhase {
       val newBindedVars: Set[Identifier] = bindedVars ++ fd.params.map(_.id)
       val newFunId = FreshIdentifier(fd.id.uniqueName) //since we hoist this at the top level, we need to make it a unique name
 
-      val newFunDef = new FunDef(newFunId, fd.tparams, fd.returnType, newValDefs, fd.defType).copiedFrom(fd)
+      val newFunDef = new FunDef(newFunId, fd.tparams, fd.returnType, newValDefs).copiedFrom(fd)
       topLevelFuns += newFunDef
-      newFunDef.addAnnotation(fd.annotations.toSeq:_*) //TODO: this is still some dangerous side effects
-      newFunDef.orig = Some(fd)
+      newFunDef.copyContentFrom(fd) //TODO: this still has some dangerous side effects (?)
+      newFunDef.addFlag(IsLoop(fd))
 
       def introduceLets(expr: Expr, fd2FreshFd: Map[FunDef, (FunDef, Seq[Variable])]): Expr = {
         val (newExpr, _) = enclosingLets.foldLeft((expr, Map[Identifier, Identifier]()))((acc, p) => {
diff --git a/src/main/scala/leon/purescala/MethodLifting.scala b/src/main/scala/leon/purescala/MethodLifting.scala
index f033681b2937046213aa07ff75f4908870242bf2..f8a13009089ee6dc056b10bc3ed408025126c25c 100644
--- a/src/main/scala/leon/purescala/MethodLifting.scala
+++ b/src/main/scala/leon/purescala/MethodLifting.scala
@@ -41,9 +41,10 @@ object MethodLifting extends TransformationPhase {
 
         val receiver = FreshIdentifier("this", recType).setPos(cd.id)
 
-        val nfd = new FunDef(id, ctParams ++ fd.tparams, retType, ValDef(receiver) +: fdParams, fd.defType)
+        val nfd = new FunDef(id, ctParams ++ fd.tparams, retType, ValDef(receiver) +: fdParams)
         nfd.copyContentFrom(fd)
         nfd.setPos(fd)
+        nfd.addFlag(IsMethod(cd))
         nfd.fullBody = postMap{
           case This(ct) if ct.classDef == cd => Some(receiver.toVariable)
           case _ => None
diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index a1f9eb335f50c33442804fbfb4b681e9ffd369fc..7b6ccdcd60b89ac8d3351ff10159da689edd85e3 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -522,8 +522,11 @@ class PrettyPrinter(opts: PrinterOptions,
               |"""
         }
 
-        if (fd.canBeField) {
-          p"""|${fd.defType} ${fd.id} : ${fd.returnType} = {
+        if (fd.canBeStrictField) {
+          p"""|val ${fd.id} : ${fd.returnType} = {
+              |"""
+        } else if (fd.canBeLazyField) {
+          p"""|lazy val ${fd.id} : ${fd.returnType} = {
               |"""
         } else if (fd.tparams.nonEmpty) {
           p"""|def ${fd.id}[${nary(fd.tparams, ",")}](${fd.params}): ${fd.returnType} = {
@@ -572,23 +575,20 @@ class PrettyPrinter(opts: PrinterOptions,
 
   object FcallMethodInvocation {
     def unapply(fi: FunctionInvocation): Option[(Expr, FunDef, String, Seq[TypeTree], Seq[Expr])] = {
-        val FunctionInvocation(tfd, args) = fi
-        tfd.fd.origOwner match {
-          case Some(cd: ClassDef) =>
-            val (rec, rargs) = (args.head, args.tail)
+      val FunctionInvocation(tfd, args) = fi
+      tfd.fd.methodOwner.map { cd =>
+        val (rec, rargs) = (args.head, args.tail)
 
-            val fid = tfd.fd.id
+        val fid = tfd.fd.id
 
-            val fname = fid.name
+        val fname = fid.name
 
-            val decoded = scala.reflect.NameTransformer.decode(fname)
+        val decoded = scala.reflect.NameTransformer.decode(fname)
 
-            val realtps = tfd.tps.drop(cd.tparams.size)
+        val realtps = tfd.tps.drop(cd.tparams.size)
 
-            Some((rec, tfd.fd, decoded, realtps, rargs))
-          case _ =>
-            None
-        }
+        (rec, tfd.fd, decoded, realtps, rargs)
+      }
     }
   }
 
diff --git a/src/main/scala/leon/purescala/RestoreMethods.scala b/src/main/scala/leon/purescala/RestoreMethods.scala
index 74802b9aff126faf145feb687e7d88a55acd2bab..bd6a51cd00c082d363380f217faabe4a9226ff9b 100644
--- a/src/main/scala/leon/purescala/RestoreMethods.scala
+++ b/src/main/scala/leon/purescala/RestoreMethods.scala
@@ -18,7 +18,7 @@ object RestoreMethods extends TransformationPhase {
   // @TODO: This code probably needs fixing, but is mostly unused and completely untested.
   def apply(ctx: LeonContext, p: Program) = {
 
-    val classMethods = p.definedFunctions.groupBy(_.origOwner).collect {
+    val classMethods = p.definedFunctions.groupBy(_.methodOwner).collect {
       case (Some(cd: ClassDef), fds) => cd -> fds
     }
 
@@ -27,10 +27,11 @@ object RestoreMethods extends TransformationPhase {
         id = FreshIdentifier(fd.id.name),
         tparams = fd.tparams.drop(cd.tparams.size),
         params = fd.params.tail, // drop 'this'
-        returnType = fd.returnType,
-        defType = fd.defType
+        returnType = fd.returnType
       ).copiedFrom(fd)
 
+      md.copyContentFrom(fd)
+
       val thisArg  = fd.params.head
       val thisExpr = This(thisArg.getType.asInstanceOf[ClassType])
 
diff --git a/src/main/scala/leon/purescala/ScopeSimplifier.scala b/src/main/scala/leon/purescala/ScopeSimplifier.scala
index e15183d54e519876213bbfc80d6f84d5a0820f24..1bc8e9379f88f63bfbfe10bd80d8abab679e5f83 100644
--- a/src/main/scala/leon/purescala/ScopeSimplifier.scala
+++ b/src/main/scala/leon/purescala/ScopeSimplifier.scala
@@ -44,7 +44,8 @@ class ScopeSimplifier extends Transformer {
         ValDef(newArg, tpe)
       }
 
-      val newFd = new FunDef(newId, fd.tparams, fd.returnType, newArgs, fd.defType)
+      val newFd = new FunDef(newId, fd.tparams, fd.returnType, newArgs)
+      newFd.copyContentFrom(fd)
 
       newScope = newScope.registerFunDef(fd -> newFd)
 
diff --git a/src/main/scala/leon/solvers/templates/TemplateGenerator.scala b/src/main/scala/leon/solvers/templates/TemplateGenerator.scala
index 209c6c3ab0c617981d10c16febd3f027131dae17..61693206b0fcf55fdae8beec1814b56792563c5b 100644
--- a/src/main/scala/leon/solvers/templates/TemplateGenerator.scala
+++ b/src/main/scala/leon/solvers/templates/TemplateGenerator.scala
@@ -29,8 +29,7 @@ class TemplateGenerator[T](val encoder: TemplateEncoder[T],
     val fakeFunDef = new FunDef(FreshIdentifier("fake", alwaysShowUniqueID = true),
                                 Nil,
                                 body.getType,
-                                variablesOf(body).toSeq.map(ValDef(_)),
-                                DefType.MethodDef)
+                                variablesOf(body).toSeq.map(ValDef(_)))
 
     fakeFunDef.body = Some(body)
 
diff --git a/src/main/scala/leon/synthesis/rules/ADTInduction.scala b/src/main/scala/leon/synthesis/rules/ADTInduction.scala
index 90d60d4ebf5433f69f877f308275d3ff6409ec62..4578eab14eb9dcd7e70804f359a85c725bf1ec39 100644
--- a/src/main/scala/leon/synthesis/rules/ADTInduction.scala
+++ b/src/main/scala/leon/synthesis/rules/ADTInduction.scala
@@ -79,7 +79,7 @@ case object ADTInduction extends Rule("ADT Induction") {
           case sols =>
             var globalPre = List[Expr]()
 
-            val newFun = new FunDef(FreshIdentifier("rec", alwaysShowUniqueID = true), Nil, resType, ValDef(inductOn) +: residualArgDefs, DefType.MethodDef)
+            val newFun = new FunDef(FreshIdentifier("rec", alwaysShowUniqueID = true), Nil, resType, ValDef(inductOn) +: residualArgDefs)
 
             val cases = for ((sol, (problem, pre, cct, ids, calls)) <- sols zip subProblemsInfo) yield {
               globalPre ::= and(pre, sol.pre)
diff --git a/src/main/scala/leon/synthesis/rules/ADTLongInduction.scala b/src/main/scala/leon/synthesis/rules/ADTLongInduction.scala
index 663759335f8e126dabb0f09d1ab3bf66d1d93b34..bcafde3c54dd7ebadfab9eb8417a4c4c4ceb2406 100644
--- a/src/main/scala/leon/synthesis/rules/ADTLongInduction.scala
+++ b/src/main/scala/leon/synthesis/rules/ADTLongInduction.scala
@@ -129,7 +129,7 @@ case object ADTLongInduction extends Rule("ADT Long Induction") {
           case sols =>
             var globalPre = List[Expr]()
 
-            val newFun = new FunDef(FreshIdentifier("rec", alwaysShowUniqueID = true), Nil, resType, ValDef(inductOn) +: residualArgDefs, DefType.MethodDef)
+            val newFun = new FunDef(FreshIdentifier("rec", alwaysShowUniqueID = true), Nil, resType, ValDef(inductOn) +: residualArgDefs)
 
             val cases = for ((sol, (problem, pat, calls, pc)) <- sols zip subProblemsInfo) yield {
               globalPre ::= and(pc, sol.pre)
diff --git a/src/main/scala/leon/synthesis/rules/CEGISLike.scala b/src/main/scala/leon/synthesis/rules/CEGISLike.scala
index 0aab04f54277bb77fa41e9d95725e266dc3fc6b6..c97d14d1f0a983e46b8359b9299db076b254881d 100644
--- a/src/main/scala/leon/synthesis/rules/CEGISLike.scala
+++ b/src/main/scala/leon/synthesis/rules/CEGISLike.scala
@@ -236,19 +236,19 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) {
 
       private val bArrayId = FreshIdentifier("bArray", ArrayType(BooleanType), true)
 
-      private var cTreeFd = new FunDef(FreshIdentifier("cTree", alwaysShowUniqueID = true),
-                               Seq(),
-                               p.outType,
-                               p.as.map(id => ValDef(id)),
-                               DefType.MethodDef
-                             )
-
-      private var phiFd   = new FunDef(FreshIdentifier("phiFd", alwaysShowUniqueID = true),
-                               Seq(),
-                               BooleanType,
-                               p.as.map(id => ValDef(id)),
-                               DefType.MethodDef
-                             )
+      private var cTreeFd = new FunDef(
+        FreshIdentifier("cTree", alwaysShowUniqueID = true),
+        Seq(),
+        p.outType,
+        p.as.map(id => ValDef(id))
+      )
+
+      private var phiFd = new FunDef(
+        FreshIdentifier("phiFd", alwaysShowUniqueID = true),
+        Seq(),
+        BooleanType,
+        p.as.map(id => ValDef(id))
+      )
 
       private var programCTree: Program = _
 
@@ -280,11 +280,12 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) {
         val (prog2, fdMap2) = replaceFunDefs(prog1)({
           case fd if affected(fd) =>
             // Add the b array argument to all affected functions
-            val nfd = new FunDef(fd.id.freshen,
-                                 fd.tparams,
-                                 fd.returnType,
-                                 fd.params :+ ValDef(bArrayId),
-                                 fd.defType)
+            val nfd = new FunDef(
+              fd.id.freshen,
+              fd.tparams,
+              fd.returnType,
+              fd.params :+ ValDef(bArrayId)
+            )
             nfd.copyContentFrom(fd)
             nfd.copiedFrom(fd)
 
diff --git a/src/main/scala/leon/synthesis/rules/IntInduction.scala b/src/main/scala/leon/synthesis/rules/IntInduction.scala
index 58747ed6654385f10964a1aeded89de843626f2a..8f619667a9d8be318629c003984dcaa8147a8a77 100644
--- a/src/main/scala/leon/synthesis/rules/IntInduction.scala
+++ b/src/main/scala/leon/synthesis/rules/IntInduction.scala
@@ -45,7 +45,7 @@ case object IntInduction extends Rule("Int Induction") {
                              and(LessThan(Variable(inductOn), InfiniteIntegerLiteral(0)),    lt.pre))
               val preOut = subst(inductOn -> Variable(origId), preIn)
 
-              val newFun = new FunDef(FreshIdentifier("rec", alwaysShowUniqueID = true), Nil, tpe, Seq(ValDef(inductOn)),DefType.MethodDef)
+              val newFun = new FunDef(FreshIdentifier("rec", alwaysShowUniqueID = true), Nil, tpe, Seq(ValDef(inductOn)))
               val idPost = FreshIdentifier("res", tpe)
 
               newFun.precondition = Some(preIn)
diff --git a/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala b/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala
index ce20aee56f50e5e021164e2e56cf661a5c060951..9bd49fcebfc4f44ed4e874cfc1a7bf00bb0c0991 100644
--- a/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala
+++ b/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala
@@ -93,7 +93,7 @@ case object IntegerInequalities extends Rule("Integer Inequalities") {
 
       //define max function
       val maxValDefs: Seq[ValDef] = lowerBounds.map(_ => ValDef(FreshIdentifier("b", Int32Type)))
-      val maxFun = new FunDef(FreshIdentifier("max"), Nil, Int32Type, maxValDefs, DefType.MethodDef)
+      val maxFun = new FunDef(FreshIdentifier("max"), Nil, Int32Type, maxValDefs)
       def maxRec(bounds: List[Expr]): Expr = bounds match {
         case (x1 :: x2 :: xs) => {
           val v = FreshIdentifier("m", Int32Type)
@@ -107,7 +107,7 @@ case object IntegerInequalities extends Rule("Integer Inequalities") {
       def max(xs: Seq[Expr]): Expr = FunctionInvocation(maxFun.typed, xs)
       //define min function
       val minValDefs: Seq[ValDef] = upperBounds.map(_ => ValDef(FreshIdentifier("b", Int32Type)))
-      val minFun = new FunDef(FreshIdentifier("min"), Nil, Int32Type, minValDefs,DefType.MethodDef)
+      val minFun = new FunDef(FreshIdentifier("min"), Nil, Int32Type, minValDefs)
       def minRec(bounds: List[Expr]): Expr = bounds match {
         case (x1 :: x2 :: xs) => {
           val v = FreshIdentifier("m", Int32Type)
@@ -121,12 +121,10 @@ case object IntegerInequalities extends Rule("Integer Inequalities") {
       def min(xs: Seq[Expr]): Expr = FunctionInvocation(minFun.typed, xs)
       val floorFun = new FunDef(FreshIdentifier("floorDiv"), Nil, Int32Type, Seq(
                                   ValDef(FreshIdentifier("x", Int32Type)),
-                                  ValDef(FreshIdentifier("x", Int32Type))),
-                                  DefType.MethodDef)
+                                  ValDef(FreshIdentifier("x", Int32Type))))
       val ceilingFun = new FunDef(FreshIdentifier("ceilingDiv"), Nil, Int32Type, Seq(
                                   ValDef(FreshIdentifier("x", Int32Type)),
-                                  ValDef(FreshIdentifier("x", Int32Type))),
-                                  DefType.MethodDef)
+                                  ValDef(FreshIdentifier("x", Int32Type))))
       ceilingFun.body = Some(IntLiteral(0))
       def floorDiv(x: Expr, y: Expr): Expr = FunctionInvocation(floorFun.typed, Seq(x, y))
       def ceilingDiv(x: Expr, y: Expr): Expr = FunctionInvocation(ceilingFun.typed, Seq(x, y))
@@ -192,7 +190,7 @@ case object IntegerInequalities extends Rule("Integer Inequalities") {
               val concretePre = replace(Map(Variable(k) -> loopCounter), pre)
               val concreteTerm = replace(Map(Variable(k) -> loopCounter), term)
               val returnType = tupleTypeWrap(problem.xs.map(_.getType))
-              val funDef = new FunDef(FreshIdentifier("rec", alwaysShowUniqueID = true), Nil, returnType, Seq(ValDef(loopCounter.id)),DefType.MethodDef)
+              val funDef = new FunDef(FreshIdentifier("rec", alwaysShowUniqueID = true), Nil, returnType, Seq(ValDef(loopCounter.id)))
               val funBody = expandAndSimplifyArithmetic(IfExpr(
                 LessThan(loopCounter, IntLiteral(0)),
                 Error(returnType, "No solution exists"),
diff --git a/src/main/scala/leon/termination/StructuralSize.scala b/src/main/scala/leon/termination/StructuralSize.scala
index 11c2b6a66c34e7a3eb6baf9e4f3d0043e2202338..8656a2005ce10781ab219ee703a37d01f4073ba5 100644
--- a/src/main/scala/leon/termination/StructuralSize.scala
+++ b/src/main/scala/leon/termination/StructuralSize.scala
@@ -28,13 +28,13 @@ trait StructuralSize {
       FreshIdentifier(name, alwaysShowUniqueID = true),
       Seq(), // no type params 
       tp, // return type
-      Seq(ValDef(x)),
-      DefType.MethodDef
+      Seq(ValDef(x))
     )
     absFun.body = Some(IfExpr(
-        GreaterEquals(Variable(x), zero),
-        Variable(x),
-        uminus(Variable(x))))
+      GreaterEquals(Variable(x), zero),
+      Variable(x),
+      uminus(Variable(x))
+    ))
     TypedFunDef(absFun, Seq()) // Seq() because no generic type params
   }
   
@@ -56,7 +56,7 @@ trait StructuralSize {
         case None =>
           val argument = ValDef(FreshIdentifier("x", argumentType, true))
           val formalTParams = typeParams.map(TypeParameterDef)
-          val fd = new FunDef(FreshIdentifier("size", alwaysShowUniqueID = true), formalTParams, IntegerType, Seq(argument), DefType.MethodDef)
+          val fd = new FunDef(FreshIdentifier("size", alwaysShowUniqueID = true), formalTParams, IntegerType, Seq(argument))
           sizeCache(argumentType) = fd
 
           val body = simplifyLets(matchToIfThenElse(matchExpr(argument.toVariable, cases(argumentType))))
diff --git a/src/main/scala/leon/utils/PreprocessingPhase.scala b/src/main/scala/leon/utils/PreprocessingPhase.scala
index 60c2702485c3cdd55abab16e616dcca5d6952a80..be022631ce3c1cb1095b321fcca6bdbd5c824bbe 100644
--- a/src/main/scala/leon/utils/PreprocessingPhase.scala
+++ b/src/main/scala/leon/utils/PreprocessingPhase.scala
@@ -17,7 +17,6 @@ object PreprocessingPhase extends TransformationPhase {
   def apply(ctx: LeonContext, p: Program): Program = {
 
     val phases =
-      ScopingPhase                  andThen
       MethodLifting                 andThen
       TypingPhase                   andThen
       ConvertWithOracle             andThen
diff --git a/src/main/scala/leon/utils/ScopingPhase.scala b/src/main/scala/leon/utils/ScopingPhase.scala
deleted file mode 100644
index d45b7d4671a519d4eff66d661ef7ac9b32517efb..0000000000000000000000000000000000000000
--- a/src/main/scala/leon/utils/ScopingPhase.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Copyright 2009-2015 EPFL, Lausanne */
-
-package leon.utils
-
-import leon._
-import purescala.Definitions._
-
-object ScopingPhase extends UnitPhase[Program] {
-  
-  val name = "Scoping phase"
-  val description = "Insert scoping information to all definitions in the program"
-  
-  def apply(ctx: LeonContext, p: Program) {
-    insertScopingInformation(p, None)
-  }
-
-  private def insertScopingInformation(df : Definition , parent : Option[Definition]) {
-    df.origOwner = parent
-    for (sub <- df.subDefinitions){
-      insertScopingInformation(sub, Some(df))
-    }
-  }
-  
-}
\ No newline at end of file
diff --git a/src/main/scala/leon/utils/UnitElimination.scala b/src/main/scala/leon/utils/UnitElimination.scala
index 0af3318395d518743208ce3c7777c3c774354bea..0a487ef2842cc1b5da6e7aac77b585d4113e6335 100644
--- a/src/main/scala/leon/utils/UnitElimination.scala
+++ b/src/main/scala/leon/utils/UnitElimination.scala
@@ -26,8 +26,8 @@ object UnitElimination extends TransformationPhase {
         //first introduce new signatures without Unit parameters
         allFuns.foreach(fd => {
           if(fd.returnType != UnitType && fd.params.exists(vd => vd.getType == UnitType)) {
-            val freshFunDef = new FunDef(FreshIdentifier(fd.id.name), fd.tparams, fd.returnType, fd.params.filterNot(vd => vd.getType == UnitType), fd.defType).setPos(fd)
-            freshFunDef.addAnnotation(fd.annotations.toSeq:_*)
+            val freshFunDef = new FunDef(FreshIdentifier(fd.id.name), fd.tparams, fd.returnType, fd.params.filterNot(vd => vd.getType == UnitType)).setPos(fd)
+            freshFunDef.copyContentFrom(fd)
             fun2FreshFun += (fd -> freshFunDef)
           } else {
             fun2FreshFun += (fd -> fd) //this will make the next step simpler
@@ -97,8 +97,8 @@ object UnitElimination extends TransformationPhase {
           removeUnit(b)
         else {
           val (newFd, rest) = if(fd.params.exists(vd => vd.getType == UnitType)) {
-            val freshFunDef = new FunDef(FreshIdentifier(fd.id.name), fd.tparams, fd.returnType, fd.params.filterNot(vd => vd.getType == UnitType), fd.defType).setPos(fd)
-            freshFunDef.addAnnotation(fd.annotations.toSeq:_*)
+            val freshFunDef = new FunDef(FreshIdentifier(fd.id.name), fd.tparams, fd.returnType, fd.params.filterNot(vd => vd.getType == UnitType)).setPos(fd)
+            freshFunDef.copyContentFrom(fd)
             fun2FreshFun += (fd -> freshFunDef)
             freshFunDef.fullBody = removeUnit(fd.fullBody)
             val restRec = removeUnit(b)
diff --git a/src/main/scala/leon/xlang/EpsilonElimination.scala b/src/main/scala/leon/xlang/EpsilonElimination.scala
index 3b42be929f2aba4917509f054af463d0fc83a4e6..91b39ad5bf104583025e9791ea97196a517fc7d3 100644
--- a/src/main/scala/leon/xlang/EpsilonElimination.scala
+++ b/src/main/scala/leon/xlang/EpsilonElimination.scala
@@ -23,7 +23,7 @@ object EpsilonElimination extends UnitPhase[Program] {
       val newBody = postMap{
         case eps@Epsilon(pred, tpe) =>
           val freshName   = FreshIdentifier("epsilon")
-          val newFunDef   = new FunDef(freshName, Nil, tpe, Seq(), DefType.MethodDef)
+          val newFunDef   = new FunDef(freshName, Nil, tpe, Seq())
           val epsilonVar  = EpsilonVariable(eps.getPos, tpe)
           val resId       = FreshIdentifier("res", tpe)
           val postcondition = replace(Map(epsilonVar -> Variable(resId)), pred)
diff --git a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala
index a4d8b18c22db9b0bf47d045c52d08a50a76d91be..5abf808f41fb62b531a416f50345c94dc9a24439 100644
--- a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala
+++ b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala
@@ -152,7 +152,7 @@ object ImperativeCodeElimination extends LeonPhase[Program, (Program, Set[FunDef
           val modifiedVars2WhileFunVars = modifiedVars.zip(whileFunVars).toMap
           val whileFunValDefs = whileFunVars.map(ValDef(_))
           val whileFunReturnType = tupleTypeWrap(whileFunVars.map(_.getType))
-          val whileFunDef = new FunDef(FreshIdentifier(parent.id.name), Nil, whileFunReturnType, whileFunValDefs,DefType.MethodDef).setPos(wh)
+          val whileFunDef = new FunDef(FreshIdentifier(parent.id.name), Nil, whileFunReturnType, whileFunValDefs).setPos(wh)
           wasLoop += whileFunDef
           
           val whileFunCond = condScope(condRes)
diff --git a/src/main/scala/leon/xlang/XLangAnalysisPhase.scala b/src/main/scala/leon/xlang/XLangAnalysisPhase.scala
index 2828a220fbcee0c6ffd470cbc3d1431513c45c1c..1cd0961bc11f3f5f8e23fb99b598303476fffa3f 100644
--- a/src/main/scala/leon/xlang/XLangAnalysisPhase.scala
+++ b/src/main/scala/leon/xlang/XLangAnalysisPhase.scala
@@ -29,20 +29,13 @@ object XLangAnalysisPhase extends LeonPhase[Program, VerificationReport] {
       PrintTreePhase("Program after xlang transformations").run(ctx)(pgm2)
     }
 
-
-    def functionWasLoop(fd: FunDef): Boolean = fd.orig match {
+    def functionWasLoop(fd: FunDef): Boolean = fd.flags.collectFirst{ case IsLoop(fd) => fd } match {
       case Some(nested) => // could have been a LetDef originally
         wasLoop.contains(nested)
       case _ => false //meaning, this was a top level function
     }
 
-    var subFunctionsOf = Map[FunDef, Set[FunDef]]().withDefaultValue(Set())
-    //pgm2.definedFunctions.foreach { fd => fd.owner match {
-    //  case Some(p : FunDef) =>
-    //    subFunctionsOf += p -> (subFunctionsOf(p) + fd)
-    //  case _ =>
-    //}}
-
+    val subFunctionsOf = Map[FunDef, Set[FunDef]]().withDefaultValue(Set())
 
     val newOptions = ctx.options map {
       case LeonOption(SharedOptions.optFunctions, fs) => {
diff --git a/src/test/scala/leon/test/solvers/UnrollingSolverSuite.scala b/src/test/scala/leon/test/solvers/UnrollingSolverSuite.scala
index c6cfc68388636b381e696a01b59f002ffad492d8..d410aadfa6a1c5eb9222d2450057448808741d80 100644
--- a/src/test/scala/leon/test/solvers/UnrollingSolverSuite.scala
+++ b/src/test/scala/leon/test/solvers/UnrollingSolverSuite.scala
@@ -15,7 +15,7 @@ class UnrollingSolverSuite extends LeonTestSuite {
 
   private val fx   : Identifier = FreshIdentifier("x", IntegerType)
   private val fres : Identifier = FreshIdentifier("res", IntegerType)
-  private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx) :: Nil, DefType.MethodDef)
+  private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx) :: Nil)
   fDef.body = Some(IfExpr(GreaterThan(Variable(fx), InfiniteIntegerLiteral(0)),
     Plus(Variable(fx), FunctionInvocation(fDef.typed, Seq(Minus(Variable(fx), InfiniteIntegerLiteral(1))))),
     InfiniteIntegerLiteral(1)
diff --git a/src/test/scala/leon/test/solvers/z3/FairZ3SolverTests.scala b/src/test/scala/leon/test/solvers/z3/FairZ3SolverTests.scala
index 544d9cd4ae663bfcd5e102ef3464d26c49e37d26..3df66679b640e3d02a7904c91120f9ba8e584b56 100644
--- a/src/test/scala/leon/test/solvers/z3/FairZ3SolverTests.scala
+++ b/src/test/scala/leon/test/solvers/z3/FairZ3SolverTests.scala
@@ -38,7 +38,7 @@ class FairZ3SolverTests extends LeonTestSuite {
 
   // def f(fx : Int) : Int = fx + 1
   private val fx   : Identifier = FreshIdentifier("x", IntegerType)
-  private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx) :: Nil, DefType.MethodDef)
+  private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx) :: Nil)
   fDef.body = Some(Plus(Variable(fx), InfiniteIntegerLiteral(1)))
 
   private val minimalProgram = Program(
diff --git a/src/test/scala/leon/test/solvers/z3/FairZ3SolverTestsNewAPI.scala b/src/test/scala/leon/test/solvers/z3/FairZ3SolverTestsNewAPI.scala
index a6ae287369fdc5b7d1c540ec289c46dfa2b062db..9a5355348698e4ef030110655505cdf257625bd9 100644
--- a/src/test/scala/leon/test/solvers/z3/FairZ3SolverTestsNewAPI.scala
+++ b/src/test/scala/leon/test/solvers/z3/FairZ3SolverTestsNewAPI.scala
@@ -47,7 +47,7 @@ class FairZ3SolverTestsNewAPI extends LeonTestSuite {
 
   // def f(fx : Int) : Int = fx + 1
   private val fx   : Identifier = FreshIdentifier("x", IntegerType)
-  private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx) :: Nil, DefType.MethodDef)
+  private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx) :: Nil)
   fDef.body = Some(Plus(Variable(fx), InfiniteIntegerLiteral(1)))
 
   private val minimalProgram = Program(
diff --git a/src/test/scala/leon/test/solvers/z3/UninterpretedZ3SolverTests.scala b/src/test/scala/leon/test/solvers/z3/UninterpretedZ3SolverTests.scala
index b59e7437a89ef0a0befdf75a181cc50511c6ee49..99cd00bc9bd718076597310f9bf07e68a5e8ee4c 100644
--- a/src/test/scala/leon/test/solvers/z3/UninterpretedZ3SolverTests.scala
+++ b/src/test/scala/leon/test/solvers/z3/UninterpretedZ3SolverTests.scala
@@ -40,17 +40,17 @@ class UninterpretedZ3SolverTests extends LeonTestSuite {
 
   // def f(fx : Int) : Int = fx + 1
   private val fx   : Identifier = FreshIdentifier("x", IntegerType)
-  private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx) :: Nil, DefType.MethodDef)
+  private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx) :: Nil)
   fDef.body = Some(Plus(Variable(fx), InfiniteIntegerLiteral(1)))
 
   // g is a function that is not in the program (on purpose)
-  private val gDef : FunDef = new FunDef(FreshIdentifier("g"), Nil, IntegerType, ValDef(fx) :: Nil, DefType.MethodDef)
+  private val gDef : FunDef = new FunDef(FreshIdentifier("g"), Nil, IntegerType, ValDef(fx) :: Nil)
   gDef.body = Some(Plus(Variable(fx), InfiniteIntegerLiteral(1)))
 
   private val minimalProgram = Program(
     List(UnitDef(
-        FreshIdentifier("Minimal"),
-        List(ModuleDef(FreshIdentifier("Minimal"), Seq(fDef), false)
+      FreshIdentifier("Minimal"),
+      List(ModuleDef(FreshIdentifier("Minimal"), Seq(fDef), false)
     )))
   )