Skip to content

Commit

Permalink
Revert "Fix callTrace if inlined methods" (#19273)
Browse files Browse the repository at this point in the history
This reverts commit ec75826.

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.
  • Loading branch information
nicolasstucki authored Dec 19, 2023
2 parents 9af39e3 + 29ac576 commit eb4962b
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 10 deletions.
3 changes: 1 addition & 2 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
14 changes: 14 additions & 0 deletions compiler/src/dotty/tools/dotc/inlines/Inlines.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,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)
Expand Down
19 changes: 13 additions & 6 deletions compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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])

}

Expand Down

0 comments on commit eb4962b

Please sign in to comment.