From 29ac57669cde00a221f3e9680edcc341b5efd5a2 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 14 Dec 2023 16:36:03 +0100 Subject: [PATCH] Revert "Fix callTrace if inlined methods" This reverts commit ec75826f6ff78d0a04d3f93e6ca92bad9308f75d. The previous encoding of INLINE nodes in TASTy assumed that the callTrace was a type. We cannot make it a term, or we would not be able to unpickle this tree properly. We need another solution to be able to pickle this correctly. For now we revert the change to avoid generating invalid TASTy. --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 3 +-- .../dotty/tools/dotc/inlines/Inlines.scala | 14 ++++++++++++++ .../tools/dotc/transform/PickleQuotes.scala | 2 +- .../tools/dotc/transform/PostTyper.scala | 2 +- .../dotc/transform/YCheckPositions.scala | 19 +++++++++++++------ 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 8345416a7386..4ec41b95a90b 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -661,8 +661,7 @@ 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 method or the top-level class from - * which the call was inlined. + * a reference to the toplevel 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 c040c15f5d60..4860913bdc63 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala @@ -299,6 +299,20 @@ 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 1f51f17ab91e..624ec9628d87 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(ref(ctx.owner.topLevelClass.typeRef).withSpan(quote.span), Nil, body) + else Inlined(Inlines.inlineCallTrace(ctx.owner, quote.sourcePos), 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 3b6c3f9bff96..effbc1dba69a 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.NoInline)(transform(call)) - val callTrace = ref(call.symbol)(using ctx.withSource(pos.source)).withSpan(pos.span) + val callTrace = Inlines.inlineCallTrace(call.symbol, pos)(using ctx.withSource(pos.source)) cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(using inlineContext(tree))) case templ: Template => Checking.checkPolyFunctionExtension(templ) diff --git a/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala b/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala index 88d3e384213c..222f3fec24dc 100644 --- a/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala +++ b/compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala @@ -46,8 +46,10 @@ 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.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 + 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 + && !isBootstrappedPredefWithPatchedMethods(call) // FIXME The patched symbol has a different source as the definition of Predef. Solution: define them directly in `Predef`s TASTy and do not patch (see #19231). + then traverse(expansion)(using inlineContext(tree).withSource(sources.head)) sources = sources.tail case _ => traverseChildren(tree) @@ -59,12 +61,17 @@ class YCheckPositions extends Phase { case _ => } + private def isBootstrappedPredefWithPatchedMethods(call: Tree)(using Context) = + val sym = call.symbol + (sym.is(Inline) && sym.owner == defn.ScalaPredefModuleClass && sym.owner.is(Scala2Tasty)) + || (sym == defn.ScalaPredefModuleClass && sym.is(Scala2Tasty)) + private def isMacro(call: Tree)(using Context) = call.symbol.is(Macro) || - (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]) + (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]) }