aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-09-04 18:18:57 +0200
committerMartin Odersky <odersky@gmail.com>2016-10-02 16:11:21 +0200
commita81070ca1af106688b03c46d96f4266934d8cfbb (patch)
treeec4520668276b45cf083e73f2a043a224325ce71
parentc1674dc461ee3f4bf38b7b895cfc9d7d6b41b53f (diff)
downloaddotty-a81070ca1af106688b03c46d96f4266934d8cfbb.tar.gz
dotty-a81070ca1af106688b03c46d96f4266934d8cfbb.tar.bz2
dotty-a81070ca1af106688b03c46d96f4266934d8cfbb.zip
Fix some problems in Inliner
1. Don't retypecheck the arguments of an inlined epressions. These might be very large (e.g. inlined track, or traceIndented in dotty)/ 2. Keep track of inlined calls in context instead of Inlined nodes. We only need the to compute the source file, the rest is irrelevant. 3. In Def bindings of inlined by-name parameters, change owner of right hand side. Otherwise we get incorrect owner chains. 4. In TreeTypeMap, treat Inlined in the same way as a block.
-rw-r--r--src/dotty/tools/dotc/ast/TreeTypeMap.scala4
-rw-r--r--src/dotty/tools/dotc/core/Decorators.scala8
-rw-r--r--src/dotty/tools/dotc/typer/Inliner.scala46
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala2
4 files changed, 33 insertions, 27 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/src/dotty/tools/dotc/ast/TreeTypeMap.scala
index a35fe2e8f..0593e8159 100644
--- a/src/dotty/tools/dotc/ast/TreeTypeMap.scala
+++ b/src/dotty/tools/dotc/ast/TreeTypeMap.scala
@@ -97,6 +97,10 @@ final class TreeTypeMap(
val (tmap1, stats1) = transformDefs(stats)
val expr1 = tmap1.transform(expr)
cpy.Block(blk)(stats1, expr1)
+ case inlined @ Inlined(call, bindings, expanded) =>
+ val (tmap1, bindings1) = transformDefs(bindings)
+ val expanded1 = tmap1.transform(expanded)
+ cpy.Inlined(inlined)(call, bindings1, expanded1)
case cdef @ CaseDef(pat, guard, rhs) =>
val tmap = withMappedSyms(patVars(pat))
val pat1 = tmap.transform(pat)
diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala
index cd4941c72..64f50173c 100644
--- a/src/dotty/tools/dotc/core/Decorators.scala
+++ b/src/dotty/tools/dotc/core/Decorators.scala
@@ -8,7 +8,7 @@ import util.Positions.Position, util.SourcePosition
import collection.mutable.ListBuffer
import dotty.tools.dotc.transform.TreeTransforms._
import typer.Inliner
-import ast.tpd.Inlined
+import ast.tpd.Tree
import scala.language.implicitConversions
import printing.Formatting._
@@ -151,9 +151,9 @@ object Decorators {
}
implicit def sourcePos(pos: Position)(implicit ctx: Context): SourcePosition = {
- def recur(inlineds: List[Inlined], pos: Position): SourcePosition = inlineds match {
- case inlined :: rest =>
- Inliner.sourceFile(inlined).atPos(pos).withOuter(recur(rest, inlined.call.pos))
+ def recur(inlinedCalls: List[Tree], pos: Position): SourcePosition = inlinedCalls match {
+ case inlinedCall :: rest =>
+ Inliner.sourceFile(inlinedCall).atPos(pos).withOuter(recur(rest, inlinedCall.pos))
case empty =>
ctx.source.atPos(pos)
}
diff --git a/src/dotty/tools/dotc/typer/Inliner.scala b/src/dotty/tools/dotc/typer/Inliner.scala
index 68bc55860..88d8b0de5 100644
--- a/src/dotty/tools/dotc/typer/Inliner.scala
+++ b/src/dotty/tools/dotc/typer/Inliner.scala
@@ -31,7 +31,7 @@ object Inliner {
private val InlinedBody = new Property.Key[InlinedBody] // to be used as attachment
- private val InlinedCall = new Property.Key[List[tpd.Inlined]] // to be used in context
+ private val InlinedCalls = new Property.Key[List[Tree]] // to be used in context
def attachBody(inlineAnnot: Annotation, tree: => Tree)(implicit ctx: Context): Unit =
inlineAnnot.tree.putAttachment(InlinedBody, new InlinedBody(tree))
@@ -71,16 +71,13 @@ object Inliner {
}
}
- def inlineCall(tree: Tree, pt: Type)(implicit ctx: Context): Tree = {
- if (enclosingInlineds.length < ctx.settings.xmaxInlines.value) {
- val rhs = inlinedBody(tree.symbol)
- val inlined = new Inliner(tree, rhs).inlined
- new Typer().typedUnadapted(inlined, pt)
- } else errorTree(tree,
+ def inlineCall(tree: Tree, pt: Type)(implicit ctx: Context): Tree =
+ if (enclosingInlineds.length < ctx.settings.xmaxInlines.value)
+ new Inliner(tree, inlinedBody(tree.symbol)).inlined(pt)
+ else errorTree(tree,
i"""Maximal number of successive inlines (${ctx.settings.xmaxInlines.value}) exceeded,
| Maybe this is caused by a recursive inline method?
| You can use -Xmax:inlines to change the limit.""")
- }
def dropInlined(inlined: tpd.Inlined)(implicit ctx: Context): Tree = {
val reposition = new TreeMap {
@@ -90,20 +87,21 @@ object Inliner {
tpd.seq(inlined.bindings, reposition.transform(inlined.expansion))
}
- def inlineContext(tree: untpd.Inlined)(implicit ctx: Context): Context =
- ctx.fresh.setProperty(InlinedCall, tree :: enclosingInlineds)
+ def inlineContext(call: Tree)(implicit ctx: Context): Context =
+ ctx.fresh.setProperty(InlinedCalls, call :: enclosingInlineds)
- def enclosingInlineds(implicit ctx: Context): List[Inlined] =
- ctx.property(InlinedCall).getOrElse(Nil)
+ def enclosingInlineds(implicit ctx: Context): List[Tree] =
+ ctx.property(InlinedCalls).getOrElse(Nil)
- def sourceFile(inlined: Inlined)(implicit ctx: Context) = {
- val file = inlined.call.symbol.sourceFile
+ def sourceFile(call: Tree)(implicit ctx: Context) = {
+ val file = call.symbol.sourceFile
if (file.exists) new SourceFile(file) else NoSource
}
}
class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
import tpd._
+ import Inliner._
private def decomposeCall(tree: Tree): (Tree, List[Tree], List[List[Tree]]) = tree match {
case Apply(fn, args) =>
@@ -154,10 +152,12 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
case argtpe =>
val (bindingFlags, bindingType) =
if (isByName) (Method, ExprType(argtpe.widen)) else (EmptyFlags, argtpe.widen)
- val binding = newSym(name, bindingFlags, bindingType).asTerm
- bindingsBuf +=
- (if (isByName) DefDef(binding, arg) else ValDef(binding, arg))
- binding.termRef
+ val boundSym = newSym(name, bindingFlags, bindingType).asTerm
+ val binding =
+ if (isByName) DefDef(boundSym, arg.changeOwner(ctx.owner, boundSym))
+ else ValDef(boundSym, arg)
+ bindingsBuf += binding
+ boundSym.termRef
}
}
computeParamBindings(tp.resultType, targs, argss.tail)
@@ -192,7 +192,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
private def outerLevel(sym: Symbol) = sym.name.drop(nme.SELF.length).toString.toInt
- val inlined = {
+ def inlined(pt: Type) = {
rhs.foreachSubTree(registerLeaf)
val accessedSelfSyms =
@@ -236,9 +236,11 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
}
val inliner = new TreeTypeMap(typeMap, treeMap, meth :: Nil, ctx.owner :: Nil)
- val Block(bindings: List[MemberDef], expansion) =
- inliner(Block(bindingsBuf.toList, rhs)).withPos(call.pos)
- val result = tpd.Inlined(call, bindings, expansion)
+ val bindings = bindingsBuf.toList.map(_.withPos(call.pos))
+ val expansion = inliner(rhs.withPos(call.pos))
+
+ val expansion1 = new Typer().typed(expansion, pt)(inlineContext(call))
+ val result = tpd.Inlined(call, bindings, expansion1)
inlining.println(i"inlining $call\n --> \n$result")
result
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index e809605f4..09259b361 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -947,7 +947,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedInlined(tree: untpd.Inlined, pt: Type)(implicit ctx: Context): Inlined = {
val (exprCtx, bindings1) = typedBlockStats(tree.bindings)
- val expansion1 = typed(tree.expansion, pt)(Inliner.inlineContext(tree)(exprCtx))
+ val expansion1 = typed(tree.expansion, pt)(Inliner.inlineContext(tree.call)(exprCtx))
cpy.Inlined(tree)(tree.call, bindings1.asInstanceOf[List[MemberDef]], expansion1)
.withType(expansion1.tpe)
}