diff options
author | Martin Odersky <odersky@gmail.com> | 2016-09-15 18:08:10 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-10-02 16:12:28 +0200 |
commit | 95e488eab2a686671b2a6ffd8fce05c043b3afab (patch) | |
tree | 397e7af116478809048f82b5469e6d7101b160ca /src/dotty/tools/dotc/core | |
parent | 5a46d19dde76b739f6672c9b6f57355cfd38159a (diff) | |
download | dotty-95e488eab2a686671b2a6ffd8fce05c043b3afab.tar.gz dotty-95e488eab2a686671b2a6ffd8fce05c043b3afab.tar.bz2 dotty-95e488eab2a686671b2a6ffd8fce05c043b3afab.zip |
Use BodyAnnot to indicate rhs of inline method
Since fundamental operations such as treeCopy have to know
about inline bodies, it seems better to represent this
information directly in an annotation.
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/Annotations.scala | 28 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreePickler.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 13 |
4 files changed, 41 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala index 5f96a60e6..fde41ef76 100644 --- a/src/dotty/tools/dotc/core/Annotations.scala +++ b/src/dotty/tools/dotc/core/Annotations.scala @@ -42,6 +42,34 @@ object Annotations { override def symbol(implicit ctx: Context): Symbol = sym } + /** An annotation indicating the body of a right-hand side, + * typically of an inline method. Treated specially in + * pickling/unpickling and treecopies + */ + abstract class BodyAnnotation extends Annotation { + override def symbol(implicit ctx: Context) = defn.BodyAnnot + override def derivedAnnotation(tree: Tree)(implicit ctx: Context) = + if (tree eq this.tree) this else ConcreteBodyAnnotation(tree) + override def arguments(implicit ctx: Context) = Nil + } + + case class ConcreteBodyAnnotation(body: Tree) extends BodyAnnotation { + def tree(implicit ctx: Context) = body + } + + case class LazyBodyAnnotation(bodyExpr: Context => Tree) extends BodyAnnotation { + private var evaluated = false + private var myBody: Tree = _ + def tree(implicit ctx: Context) = { + if (evaluated) assert(myBody != null) + else { + evaluated = true + myBody = bodyExpr(ctx) + } + myBody + } + } + object Annotation { def apply(tree: Tree) = ConcreteAnnotation(tree) diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 12677edb6..75b75d3d5 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -456,6 +456,8 @@ class Definitions { def AliasAnnot(implicit ctx: Context) = AliasAnnotType.symbol.asClass lazy val AnnotationDefaultAnnotType = ctx.requiredClassRef("dotty.annotation.internal.AnnotationDefault") def AnnotationDefaultAnnot(implicit ctx: Context) = AnnotationDefaultAnnotType.symbol.asClass + lazy val BodyAnnotType = ctx.requiredClassRef("dotty.annotation.internal.Body") + def BodyAnnot(implicit ctx: Context) = BodyAnnotType.symbol.asClass lazy val ChildAnnotType = ctx.requiredClassRef("dotty.annotation.internal.Child") def ChildAnnot(implicit ctx: Context) = ChildAnnotType.symbol.asClass lazy val CovariantBetweenAnnotType = ctx.requiredClassRef("dotty.annotation.internal.CovariantBetween") diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 99a3ff85c..b6f52c0ec 100644 --- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -565,10 +565,11 @@ class TreePickler(pickler: TastyPickler) { sym.annotations.foreach(pickleAnnotation) } - def pickleAnnotation(ann: Annotation)(implicit ctx: Context) = { - writeByte(ANNOTATION) - withLength { pickleType(ann.symbol.typeRef); pickleTree(ann.tree) } - } + def pickleAnnotation(ann: Annotation)(implicit ctx: Context) = + if (ann.symbol != defn.BodyAnnot) { // inline bodies are reconstituted automatically when unpickling + writeByte(ANNOTATION) + withLength { pickleType(ann.symbol.typeRef); pickleTree(ann.tree) } + } def pickle(trees: List[Tree])(implicit ctx: Context) = { trees.foreach(tree => if (!tree.isEmpty) pickleTree(tree)) diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 1b8434129..4a94e5d71 100644 --- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -488,13 +488,12 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle sym.completer.withDecls(newScope) forkAt(templateStart).indexTemplateParams()(localContext(sym)) } - else if (annots.exists(_.symbol == defn.InlineAnnot)) { - Inliner.registerInlineInfo( - sym, - implicit ctx => forkAt(rhsStart).readTerm(), - implicit ctx => localContext(sym).addMode(Mode.ReadPositions)) - // Previous line avoids space leaks because it does not capture the current context. - } + else if (annots.exists(_.symbol == defn.InlineAnnot)) + sym.addAnnotation(LazyBodyAnnotation { ctx0 => + implicit val ctx: Context = localContext(sym)(ctx0).addMode(Mode.ReadPositions) + // avoids space leaks by not capturing the current context + forkAt(rhsStart).readTerm() + }) goto(start) sym } |