From 512028279fda5a855eb1d9b85faef8b8c62c6ed5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 25 Feb 2022 14:40:56 +0100 Subject: [PATCH] Handle ownership changes in InlineTyper Fixes a part of #13334 which now works for `transparent inline`. --- .../dotc/transform/YCheckPositions.scala | 35 ++++++++++--------- .../src/dotty/tools/dotc/typer/Inliner.scala | 10 +++++- tests/pos/i13334.scala | 23 ++++++++++++ 3 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 tests/pos/i13334.scala diff --git a/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala b/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala index b3634e7cc07a..ba42d826fe82 100644 --- a/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala +++ b/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala @@ -22,7 +22,7 @@ class YCheckPositions extends Phase { override def checkPostCondition(tree: Tree)(using Context): Unit = tree match { case PackageDef(pid, _) if tree.symbol.owner == defn.RootClass => - new TreeTraverser { + val checker = new TreeTraverser { private var sources: List[SourceFile] = ctx.source :: Nil def traverse(tree: tpd.Tree)(using Context): Unit = { @@ -36,23 +36,26 @@ class YCheckPositions extends Phase { assert(tree.source == currentSource, i"wrong source set for $tree # ${tree.uniqueId} of ${tree.getClass}, set to ${tree.source} but context had $currentSource\n ${tree.symbol.flagsString}") // Recursivlely check children while keeping track of current source - tree match { - case Inlined(EmptyTree, bindings, expansion) => - assert(bindings.isEmpty) - val old = sources - sources = old.tail - traverse(expansion)(using inlineContext(EmptyTree).withSource(sources.head)) - sources = old - case Inlined(call, bindings, expansion) => - // bindings.foreach(traverse(_)) // TODO check inline proxies (see tests/tun/lst) - sources = call.symbol.topLevelClass.source :: sources - if (!isMacro(call)) // FIXME macro implementations can drop Inlined nodes. We should reinsert them after macro expansion based on the positions of the trees - traverse(expansion)(using inlineContext(call).withSource(sources.head)) - sources = sources.tail - case _ => traverseChildren(tree) + reporting.trace(i"check pos ${tree.getClass} ${tree.source} ${sources.head} $tree") { + tree match { + case Inlined(EmptyTree, bindings, expansion) => + assert(bindings.isEmpty) + val old = sources + sources = old.tail + traverse(expansion)(using inlineContext(EmptyTree).withSource(sources.head)) + sources = old + case Inlined(call, bindings, expansion) => + // bindings.foreach(traverse(_)) // TODO check inline proxies (see tests/tun/lst) + sources = call.symbol.topLevelClass.source :: sources + if (!isMacro(call)) // FIXME macro implementations can drop Inlined nodes. We should reinsert them after macro expansion based on the positions of the trees + traverse(expansion)(using inlineContext(call).withSource(sources.head)) + sources = sources.tail + case _ => traverseChildren(tree) + } } } - }.traverse(tree) + } + checker.traverse(tree) case _ => } diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index f73f37c48e03..043c1b6919f0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -1540,7 +1540,15 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { ctx override def typedIdent(tree: untpd.Ident, pt: Type)(using Context): Tree = - inlineIfNeeded(tryInlineArg(tree.asInstanceOf[tpd.Tree]) `orElse` super.typedIdent(tree, pt)) + val tree1 = inlineIfNeeded( + tryInlineArg(tree.asInstanceOf[tpd.Tree]) `orElse` super.typedIdent(tree, pt) + ) + tree1 match + case id: Ident if tpd.needsSelect(id.tpe) => + inlining.println(i"expanding $id to selection") + ref(id.tpe.asInstanceOf[TermRef]).withSpan(id.span) + case _ => + tree1 override def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = { val qual1 = typed(tree.qualifier, shallowSelectionProto(tree.name, pt, this)) diff --git a/tests/pos/i13334.scala b/tests/pos/i13334.scala new file mode 100644 index 000000000000..d7767125673c --- /dev/null +++ b/tests/pos/i13334.scala @@ -0,0 +1,23 @@ +class Bar + +transparent inline def bar(i: Int): Bar = + new Bar: + def j = i + +class Foo(x: Int): + def foo = bar(x) + +trait DFC +given DFC = new DFC {} + +trait TC +object TC: + def foo()(using DFC): Unit = {} + + transparent inline given (using DFC): TC = new TC: + foo() + +class Baz(using DFC): + summon[TC] + +val top = new Baz