From ec75826f6ff78d0a04d3f93e6ca92bad9308f75d Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 20 Oct 2023 16:28:15 +0200 Subject: [PATCH 1/2] Fix callTrace if inlined methods We need to keep the reference to the called method, not only the symbol of the to level class. This is important for the traces of the `assert` method that is defined in a different file. This might also be useful for macro annotations. This is also a solution to the awkward Select vs. Ident distinction to identify macros in `YCheckPositions`. --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 5 +++-- .../src/dotty/tools/dotc/inlines/Inlines.scala | 14 -------------- .../dotty/tools/dotc/transform/PickleQuotes.scala | 2 +- .../src/dotty/tools/dotc/transform/PostTyper.scala | 2 +- .../tools/dotc/transform/YCheckPositions.scala | 12 ++++++------ 5 files changed, 11 insertions(+), 24 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 6941596e1c9b..230e35c5f070 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -31,7 +31,7 @@ object Trees { /** Property key for backquoted identifiers and definitions */ val Backquoted: Property.StickyKey[Unit] = Property.StickyKey() - + val SyntheticUnit: Property.StickyKey[Unit] = Property.StickyKey() /** Trees take a parameter indicating what the type of their `tpe` field @@ -661,7 +661,8 @@ object Trees { * * @param call Info about the original call that was inlined * Until PostTyper, this is the full call, afterwards only - * a reference to the toplevel class from which the call was inlined. + * a reference to the method or the top-level class from + * which the call was inlined. * @param bindings Bindings for proxies to be used in the inlined code * @param expansion The inlined tree, minus bindings. * diff --git a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala index 25e9b1480370..bef56374b6f0 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala @@ -299,20 +299,6 @@ object Inlines: (new Reposition).transform(tree) end reposition - /** Leave only a call trace consisting of - * - a reference to the top-level class from which the call was inlined, - * - the call's position - * in the call field of an Inlined node. - * The trace has enough info to completely reconstruct positions. - * Note: For macros it returns a Select and for other inline methods it returns an Ident (this distinction is only temporary to be able to run YCheckPositions) - */ - def inlineCallTrace(callSym: Symbol, pos: SourcePosition)(using Context): Tree = { - assert(ctx.source == pos.source) - val topLevelCls = callSym.topLevelClass - if (callSym.is(Macro)) ref(topLevelCls.owner).select(topLevelCls.name)(using ctx.withOwner(topLevelCls.owner)).withSpan(pos.span) - else Ident(topLevelCls.typeRef).withSpan(pos.span) - } - private object Intrinsics: import dotty.tools.dotc.reporting.Diagnostic.Error private enum ErrorKind: diff --git a/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala b/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala index b368e47bf0b3..01bb474cec35 100644 --- a/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala @@ -304,7 +304,7 @@ object PickleQuotes { def pickleAsTasty() = { val body1 = if body.isType then body - else Inlined(Inlines.inlineCallTrace(ctx.owner, quote.sourcePos), Nil, body) + else Inlined(ref(ctx.owner.topLevelClass.typeRef).withSpan(quote.span), Nil, body) val pickleQuote = PickledQuotes.pickleQuote(body1) val pickledQuoteStrings = pickleQuote match case x :: Nil => Literal(Constant(x)) diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index ff322dad9ab6..3b8376ab4970 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -367,7 +367,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase => val pos = call.sourcePos CrossVersionChecks.checkExperimentalRef(call.symbol, pos) withMode(Mode.InlinedCall)(transform(call)) - val callTrace = Inlines.inlineCallTrace(call.symbol, pos)(using ctx.withSource(pos.source)) + val callTrace = ref(call.symbol)(using ctx.withSource(pos.source)).withSpan(pos.span) cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(using inlineContext(tree))) case templ: Template => withNoCheckNews(templ.parents.flatMap(newPart)) { diff --git a/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala b/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala index 3cf74ee3fdb3..15adad47a3fc 100644 --- a/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala +++ b/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala @@ -35,7 +35,7 @@ class YCheckPositions extends Phase { val currentSource = sources.head 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 + // Recursively check children while keeping track of current source reporting.trace(i"check pos ${tree.getClass} ${tree.source} ${sources.head} $tree") { tree match { case tree @ Inlined(_, bindings, expansion) if tree.inlinedFromOuterScope => @@ -46,7 +46,7 @@ class YCheckPositions extends Phase { sources = old case tree @ Inlined(call, bindings, expansion) => // bindings.foreach(traverse(_)) // TODO check inline proxies (see tests/tun/lst) - sources = call.symbol.topLevelClass.source :: sources + sources = call.symbol.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(tree).withSource(sources.head)) sources = sources.tail @@ -61,10 +61,10 @@ class YCheckPositions extends Phase { private def isMacro(call: Tree)(using Context) = call.symbol.is(Macro) || - (call.symbol.isClass && call.tpe.derivesFrom(defn.MacroAnnotationClass)) || - // The call of a macro after typer is encoded as a Select while other inlines are Ident - // TODO remove this distinction once Inline nodes of expanded macros can be trusted (also in Inliner.inlineCallTrace) - (!(ctx.phase <= postTyperPhase) && call.isInstanceOf[Select]) + (call.symbol.isClass && call.tpe.derivesFrom(defn.MacroAnnotationClass)) || + // In 3.0-3.3, the call of a macro after typer is encoded as a Select while other inlines are Ident. + // In those versions we kept the reference to the top-level class instead of the methods. + (!(ctx.phase <= postTyperPhase) && call.symbol.isClass && call.isInstanceOf[Select]) } From eb0c408050a86934516a896ebfc035ea40807bcc Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 20 Oct 2023 16:41:04 +0200 Subject: [PATCH 2/2] Enable some tests using the Scala 2 library TASTy --- .github/workflows/ci.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index aae6ec8b9b0b..636b91084529 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -209,6 +209,10 @@ jobs: run: sbt ";dist/pack ;scala3-bootstrapped/compile ;scala3-bootstrapped/test" shell: cmd + - name: Test with Scala 2 library TASTy + run: sbt ";set ThisBuild/Build.useScala2LibraryTasty := true ;scala3-bootstrapped/testCompilation i5" # only test a subset of test to avoid doubling the CI execution time + shell: cmd + - name: Scala.js Test run: sbt ";sjsJUnitTests/test ;set sjsJUnitTests/scalaJSLinkerConfig ~= switchToESModules ;sjsJUnitTests/test ;sjsCompilerTests/test" shell: cmd