diff options
Diffstat (limited to 'src/dotty')
-rw-r--r-- | src/dotty/tools/dotc/ast/TreeInfo.scala | 22 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Inliner.scala | 20 |
2 files changed, 31 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index 0d7ebc5e1..421ff5919 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -88,12 +88,6 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => case mp => mp } - /** If tree is a closure, it's body, otherwise tree itself */ - def closureBody(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match { - case Block((meth @ DefDef(nme.ANON_FUN, _, _, _, _)) :: Nil, Closure(_, _, _)) => meth.rhs - case _ => tree - } - /** If this is an application, its function part, stripping all * Apply nodes (but leaving TypeApply nodes in). Otherwise the tree itself. */ @@ -449,6 +443,22 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => (tree, Nil, Nil) } + /** An extractor for closures, either contained in a block or standalone. + */ + object closure { + def unapply(tree: Tree): Option[(List[Tree], Tree, Tree)] = tree match { + case Block(_, Closure(env, meth, tpt)) => Some(env, meth, tpt) + case Closure(env, meth, tpt) => Some(env, meth, tpt) + case _ => None + } + } + + /** If tree is a closure, it's body, otherwise tree itself */ + def closureBody(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match { + case Block((meth @ DefDef(nme.ANON_FUN, _, _, _, _)) :: Nil, Closure(_, _, _)) => meth.rhs + case _ => tree + } + /** The variables defined by a pattern, in reverse order of their appearance. */ def patVars(tree: Tree)(implicit ctx: Context): List[Symbol] = { val acc = new TreeAccumulator[List[Symbol]] { diff --git a/src/dotty/tools/dotc/typer/Inliner.scala b/src/dotty/tools/dotc/typer/Inliner.scala index 44946c37b..a78d1c029 100644 --- a/src/dotty/tools/dotc/typer/Inliner.scala +++ b/src/dotty/tools/dotc/typer/Inliner.scala @@ -505,13 +505,13 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { val expansion1 = InlineTyper.typed(expansion, pt)(inlineContext(call)) /** Does given definition bind a closure that will be inlined? */ - def bindsInlineableClosure(defn: ValOrDefDef) = Ident(defn.symbol.termRef) match { - case InlineableClosure(_) => true + def bindsDeadClosure(defn: ValOrDefDef) = Ident(defn.symbol.termRef) match { + case InlineableClosure(_) => !InlineTyper.retainedClosures.contains(defn.symbol) case _ => false } /** All bindings in `bindingsBuf` except bindings of inlineable closures */ - val bindings = bindingsBuf.toList.filterNot(bindsInlineableClosure).map(_.withPos(call.pos)) + val bindings = bindingsBuf.toList.filterNot(bindsDeadClosure).map(_.withPos(call.pos)) val result = tpd.Inlined(call, bindings, expansion1) inlining.println(i"inlined $call\n --> \n$result") @@ -524,8 +524,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { def unapply(tree: Ident)(implicit ctx: Context): Option[Tree] = if (paramProxies.contains(tree.tpe)) { bindingsBuf.find(_.name == tree.name).map(_.rhs) match { - case Some(Closure(_, meth, _)) if meth.symbol.isInlineMethod => Some(meth) - case Some(Block(_, Closure(_, meth, _))) if meth.symbol.isInlineMethod => Some(meth) + case Some(closure(_, meth, _)) if meth.symbol.isInlineMethod => Some(meth) case _ => None } } else None @@ -540,6 +539,17 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { */ private object InlineTyper extends ReTyper { + var retainedClosures = Set[Symbol]() + + override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context) = { + val tree1 = super.typedIdent(tree, pt) + tree1 match { + case InlineableClosure(_) => retainedClosures += tree.symbol + case _ => + } + tree1 + } + override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { val res = super.typedSelect(tree, pt) ensureAccessible(res.tpe, tree.qualifier.isInstanceOf[untpd.Super], tree.pos) |