From 52e0b4bdbdaa58e98c64272a7cc12194b1b6c050 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 8 May 2020 13:34:29 +0200 Subject: [PATCH] Fix #8892: Fix position adjustments in Inliner --- .../src/dotty/tools/dotc/ast/Positioned.scala | 1 + .../src/dotty/tools/dotc/ast/TreeInfo.scala | 7 +++++ compiler/src/dotty/tools/dotc/ast/Trees.scala | 2 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 17 ++++++----- tests/pos/i8892.scala | 28 +++++++++++++++++++ 5 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 tests/pos/i8892.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index bfefe9c829d5..66a75dca0110 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -119,6 +119,7 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Pro def cloneIn(src: SourceFile): this.type = { val newpd: this.type = clone.asInstanceOf[this.type] newpd.uniqueId = src.nextId + // assert(newpd.uniqueId != 2208, s"source = $this, ${this.uniqueId}, ${this.span}") newpd } diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 48671301cfea..657ce9fd0e94 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -8,6 +8,7 @@ import Names._, StdNames._, NameOps._, Symbols._ import typer.ConstFold import reporting.trace import dotty.tools.dotc.transform.SymUtils._ +import Decorators._ import scala.annotation.tailrec @@ -836,6 +837,12 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => } } + def assertAllPositioned(tree: Tree)(using Context): Unit = + tree.foreachSubTree { + case t: WithoutTypeOrPos[_] => + case t => assert(t.span.exists, i"$t") + } + /** Extractors for quotes */ object Quoted { /** Extracts the content of a quoted tree. diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 631168948121..4849991f60be 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1044,6 +1044,7 @@ object Trees { def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = tree match { case tree: Apply if (fun eq tree.fun) && (args eq tree.args) => tree case _ => finalize(tree, untpd.Apply(fun, args)(sourceFile(tree))) + //.ensuring(res => res.uniqueId != 2213, s"source = $tree, ${tree.uniqueId}, ${tree.span}") } def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = tree match { case tree: TypeApply if (fun eq tree.fun) && (args eq tree.args) => tree @@ -1060,7 +1061,6 @@ object Trees { def Typed(tree: Tree)(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed = tree match { case tree: Typed if (expr eq tree.expr) && (tpt eq tree.tpt) => tree case tree => finalize(tree, untpd.Typed(expr, tpt)(sourceFile(tree))) - //.ensuring(res => res.uniqueId != 1471, s"source = $tree, ${tree.uniqueId}") } def NamedArg(tree: Tree)(name: Name, arg: Tree)(implicit ctx: Context): NamedArg = tree match { case tree: NamedArg if (name == tree.name) && (arg eq tree.arg) => tree diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 4febbb96e3fc..d60123e510ab 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -75,14 +75,15 @@ object Inliner { * inlined call `call` to the position of `call`. This transform is necessary * when lifting bindings from the expansion to the outside of the call. */ - def liftFromInlined(call: Tree) = new TreeMap { + def liftFromInlined(call: Tree) = new TreeMap: override def transform(t: Tree)(using Context) = - t match { - case Inlined(t, Nil, expr) if t.isEmpty => expr - case _ if t.isEmpty => t - case _ => super.transform(t.withSpan(call.span)) - } - } + if call.span.exists then + t match + case Inlined(t, Nil, expr) if t.isEmpty => expr + case _ if t.isEmpty => t + case _ => super.transform(t.withSpan(call.span)) + else t + end liftFromInlined val bindings = new mutable.ListBuffer[Tree] @@ -108,6 +109,7 @@ object Inliner { tree } + // assertAllPositioned(tree) // debug val tree1 = liftBindings(tree, identity) if (bindings.nonEmpty) cpy.Block(tree)(bindings.toList, inlineCall(tree1)) @@ -590,6 +592,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { * itself, it has to be marked as an inlined argument. */ def integrate(tree: Tree, originalOwner: Symbol)(using Context): Tree = + // assertAllPositioned(tree) // debug tree.changeOwner(originalOwner, ctx.owner) def tryConstValue: Tree = diff --git a/tests/pos/i8892.scala b/tests/pos/i8892.scala new file mode 100644 index 000000000000..f08b12341d3b --- /dev/null +++ b/tests/pos/i8892.scala @@ -0,0 +1,28 @@ +trait Reporter: + def report(m: String): Unit + +class Dummy extends Reporter: + def report(m: String) = () + + object ABug { + sealed trait Nat { + inline def ++ : Succ[this.type] = Succ(this) + + transparent inline def +(inline that: Nat): Nat = + inline this match { + case Zero => that + case Succ(p) => p + that.++ + } + } + + case object Zero extends Nat + case class Succ[N <: Nat](p: N) extends Nat + + transparent inline def toIntg(inline n: Nat): Int = + inline n match { + case Zero => 0 + case Succ(p) => toIntg(p) + 1 + } + + val j31 = toIntg(Zero.++.++.++ + Zero.++) + } \ No newline at end of file