aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Inliner.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-09-15 15:39:57 +0200
committerMartin Odersky <odersky@gmail.com>2016-10-02 16:12:28 +0200
commit5a46d19dde76b739f6672c9b6f57355cfd38159a (patch)
tree57dc454cad17be45e71e9180bb283c7cd606920e /src/dotty/tools/dotc/typer/Inliner.scala
parentc9fa504161cc34ec979ae3c1b73db6798adc4872 (diff)
downloaddotty-5a46d19dde76b739f6672c9b6f57355cfd38159a.tar.gz
dotty-5a46d19dde76b739f6672c9b6f57355cfd38159a.tar.bz2
dotty-5a46d19dde76b739f6672c9b6f57355cfd38159a.zip
Handle inlining in inlining arguments
We got unbound symbols before because a TreeTypeMap would copy a tree of an inline DefDef but would not adapt the inline body stored in the @inline annotation of the DefDef to point to the updated tree.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Inliner.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Inliner.scala47
1 files changed, 31 insertions, 16 deletions
diff --git a/src/dotty/tools/dotc/typer/Inliner.scala b/src/dotty/tools/dotc/typer/Inliner.scala
index e9c054ff2..ef67384ff 100644
--- a/src/dotty/tools/dotc/typer/Inliner.scala
+++ b/src/dotty/tools/dotc/typer/Inliner.scala
@@ -214,17 +214,18 @@ object Inliner {
/** The accessor defs to non-public members which need to be defined
* together with the inline method
*/
- def removeAccessors(implicit ctx: Context): List[MemberDef] = {
+ def accessors(implicit ctx: Context): List[MemberDef] = {
ensureEvaluated()
- val res = myAccessors.toList
- myAccessors.clear()
- res
+ myAccessors.toList
}
}
/** A key to be used in an attachment for `@inline` annotations */
private val InlineInfo = new Property.Key[InlineInfo]
+ /** A key to be used in an attachment for `@inline` annotations */
+ private val InlineBody = new Property.Key[Tree]
+
/** A key to be used in a context property that tracks enclosing inlined calls */
private val InlinedCalls = new Property.Key[List[Tree]] // to be used in context
@@ -239,37 +240,51 @@ object Inliner {
*/
def registerInlineInfo(
sym: SymDenotation, treeExpr: Context => Tree, inlineCtxFn: Context => Context)(implicit ctx: Context): Unit = {
+ val inlineAnnotTree = sym.unforcedAnnotation(defn.InlineAnnot).get.tree
+ if (inlineAnnotTree.getAttachment(InlineBody).isEmpty)
+ inlineAnnotTree.getAttachment(InlineInfo) match {
+ case Some(inlineInfo) if inlineInfo.isEvaluated => // keep existing attachment
+ case _ =>
+ if (!ctx.isAfterTyper)
+ inlineAnnotTree.putAttachment(InlineInfo, new InlineInfo(treeExpr, inlineCtxFn))
+ }
+ }
+
+ /** Register an evaluated inline body for `sym` */
+ def updateInlineBody(sym: SymDenotation, body: Tree)(implicit ctx: Context): Unit = {
val inlineAnnot = sym.unforcedAnnotation(defn.InlineAnnot).get
- inlineAnnot.tree.getAttachment(InlineInfo) match {
- case Some(inlineInfo) if inlineInfo.isEvaluated => // keep existing attachment
- case _ =>
- if (!ctx.isAfterTyper)
- inlineAnnot.tree.putAttachment(InlineInfo, new InlineInfo(treeExpr, inlineCtxFn))
- }
+ assert(inlineAnnot.tree.putAttachment(InlineBody, body).isDefined)
}
/** Optionally, the inline info attached to the `@inline` annotation of `sym`. */
private def inlineInfo(sym: SymDenotation)(implicit ctx: Context): Option[InlineInfo] =
sym.getAnnotation(defn.InlineAnnot).get.tree.getAttachment(InlineInfo)
- /** Definition is an inline method with a known body to inline (note: definitions coming
+ /** Optionally, the inline body attached to the `@inline` annotation of `sym`. */
+ private def inlineBody(sym: SymDenotation)(implicit ctx: Context): Option[Tree] =
+ sym.getAnnotation(defn.InlineAnnot).get.tree.getAttachment(InlineBody)
+
+ /** Definition is an inline method with a known body to inline (note: definitions coming
* from Scala2x class files might be `@inline`, but still lack that body.
*/
def hasBodyToInline(sym: SymDenotation)(implicit ctx: Context): Boolean =
- sym.isInlineMethod && inlineInfo(sym).isDefined
+ sym.isInlineMethod && (inlineInfo(sym).isDefined || inlineBody(sym).isDefined)
/** The body to inline for method `sym`.
* @pre hasBodyToInline(sym)
*/
def bodyToInline(sym: SymDenotation)(implicit ctx: Context): Tree =
- inlineInfo(sym).get.body
+ inlineInfo(sym).map(_.body).getOrElse(inlineBody(sym).get)
/** The accessors to non-public members needed by the inlinable body of `sym`.
* @pre hasBodyToInline(sym)
*/
-
- def removeInlineAccessors(sym: SymDenotation)(implicit ctx: Context): List[MemberDef] =
- inlineInfo(sym).get.removeAccessors
+ def removeInlineAccessors(sym: SymDenotation)(implicit ctx: Context): List[MemberDef] = {
+ val inlineAnnotTree = sym.getAnnotation(defn.InlineAnnot).get.tree
+ val inlineInfo = inlineAnnotTree.removeAttachment(InlineInfo).get
+ inlineAnnotTree.putAttachment(InlineBody, inlineInfo.body)
+ inlineInfo.accessors
+ }
/** Try to inline a call to a `@inline` method. Fail with error if the maximal
* inline depth is exceeded.