Skip to content

Keep inlined nodes until the backend phase #18230

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import dotty.tools.dotc.core.Contexts._
import dotty.tools.dotc.core.Phases._
import dotty.tools.dotc.core.Decorators.em
import dotty.tools.dotc.report
import dotty.tools.dotc.inlines.Inlines

/*
*
Expand Down Expand Up @@ -479,6 +480,10 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
case t: TypeApply => // dotty specific
generatedType = genTypeApply(t)

case inlined @ Inlined(_, _, _) =>
genLoadTo(Inlines.dropInlined(inlined) , expectedType, dest)
generatedDest = dest

case _ => abort(s"Unexpected tree in genLoad: $tree/${tree.getClass} at: ${tree.span}")
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import dotty.tools.dotc.transform.sjs.JSSymUtils._

import JSEncoding._
import ScopedVar.withScopedVars
import dotty.tools.dotc.inlines.Inlines

/** Main codegen for Scala.js IR.
*
Expand Down Expand Up @@ -1930,6 +1931,9 @@ class JSCodeGen()(using genCtx: Context) {
case EmptyTree =>
js.Skip()

case inlined @ Inlined(_, _, _) =>
genStatOrExpr(Inlines.dropInlined(inlined), isStat)

case _ =>
throw new FatalError("Unexpected tree in genExpr: " +
tree + "/" + tree.getClass + " at: " + (tree.span: Position))
Expand Down
17 changes: 12 additions & 5 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1341,10 +1341,17 @@ object Trees {
case tree: SeqLiteral if (elems eq tree.elems) && (elemtpt eq tree.elemtpt) => tree
case _ => finalize(tree, untpd.SeqLiteral(elems, elemtpt)(sourceFile(tree)))
}
def Inlined(tree: Tree)(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(using Context): Inlined = tree match {
case tree: Inlined if (call eq tree.call) && (bindings eq tree.bindings) && (expansion eq tree.expansion) => tree
case _ => finalize(tree, untpd.Inlined(call, bindings, expansion)(sourceFile(tree)))
}
// Positions of trees are automatically pushed down except when we reach an Inlined tree. Therefore, we
// make sure the new expansion has a position by copying the one of the original Inlined tree.
def Inlined(tree: Inlined)(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(using Context): Inlined =
if (call eq tree.call) && (bindings eq tree.bindings) && (expansion eq tree.expansion) then tree
else
// Copy the span from the original Inlined tree if the new expansion doesn't have a span.
val expansionWithSpan =
if expansion.span.exists then expansion
else expansion.withSpan(tree.expansion.span)
finalize(tree, untpd.Inlined(call, bindings, expansionWithSpan)(sourceFile(tree)))

def Quote(tree: Tree)(body: Tree, tags: List[Tree])(using Context): Quote = tree match {
case tree: Quote if (body eq tree.body) && (tags eq tree.tags) => tree
case _ => finalize(tree, untpd.Quote(body, tags)(sourceFile(tree)))
Expand Down Expand Up @@ -1549,7 +1556,7 @@ object Trees {
cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
case SeqLiteral(elems, elemtpt) =>
cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
case Inlined(call, bindings, expansion) =>
case tree @ Inlined(call, bindings, expansion) =>
cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)(using inlineContext(call)))
case TypeTree() =>
tree
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}

override def Inlined(tree: Tree)(call: Tree, bindings: List[MemberDef], expansion: Tree)(using Context): Inlined = {
override def Inlined(tree: Inlined)(call: Tree, bindings: List[MemberDef], expansion: Tree)(using Context): Inlined = {
val tree1 = untpdCpy.Inlined(tree)(call, bindings, expansion)
tree match {
case tree: Inlined if sameTypes(bindings, tree.bindings) && (expansion.tpe eq tree.expansion.tpe) =>
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/inlines/Inlines.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ object Inlines:
case Block(stats, expr) =>
bindings ++= stats.map(liftPos)
liftBindings(expr, liftPos)
case Inlined(call, stats, expr) =>
case tree @ Inlined(call, stats, expr) =>
bindings ++= stats.map(liftPos)
val lifter = liftFromInlined(call)
cpy.Inlined(tree)(call, Nil, liftBindings(expr, liftFromInlined(call).transform(_)))
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/quoted/PickledQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ object PickledQuotes {

/** Unpickle the tree contained in the TastyExpr */
def unpickleTerm(pickled: String | List[String], typeHole: TypeHole, termHole: ExprHole)(using Context): Tree = {
val unpickled = withMode(Mode.ReadPositions)(unpickle(pickled, isType = false))
val unpickled = withMode(Mode.ReadPositions)(unpickle(pickled, isType = false)).asInstanceOf[Inlined]
val Inlined(call, Nil, expansion) = unpickled: @unchecked
val inlineCtx = inlineContext(call)
val expansion1 = spliceTypes(expansion, typeHole)(using inlineCtx)
Expand Down
43 changes: 31 additions & 12 deletions compiler/src/dotty/tools/dotc/transform/ArrayApply.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import dotty.tools.dotc.ast.tpd
*
* Transforms `scala.Array.apply([....])` and `scala.Array.apply(..., [....])` into `[...]`
*/
class ArrayApply extends MiniPhase {
class ArrayApply extends MiniPhase:
import tpd._

override def phaseName: String = ArrayApply.name
Expand All @@ -25,14 +25,18 @@ class ArrayApply extends MiniPhase {
override def transformApply(tree: tpd.Apply)(using Context): tpd.Tree =
if isArrayModuleApply(tree.symbol) then
tree.args match {
case StripAscription(Apply(wrapRefArrayMeth, (seqLit: tpd.JavaSeqLiteral) :: Nil)) :: ct :: Nil
if defn.WrapArrayMethods().contains(wrapRefArrayMeth.symbol) && elideClassTag(ct) =>
case AppliedLiterals(seqLit) :: ct :: Nil if elideClassTag(ct) =>
seqLit

case elem0 :: StripAscription(Apply(wrapRefArrayMeth, (seqLit: tpd.JavaSeqLiteral) :: Nil)) :: Nil
if defn.WrapArrayMethods().contains(wrapRefArrayMeth.symbol) =>
case InlinedSplice(inlined, seqLit) :: ct :: Nil if elideClassTag(ct) =>
tpd.cpy.Inlined(inlined)(inlined.call, inlined.bindings, seqLit)

case elem0 :: AppliedLiterals(seqLit) :: Nil =>
tpd.JavaSeqLiteral(elem0 :: seqLit.elems, seqLit.elemtpt)

case elem0 :: InlinedSplice(inlined, seqLit) :: Nil =>
tpd.cpy.Inlined(inlined)(inlined.call, inlined.bindings, tpd.JavaSeqLiteral(elem0 :: seqLit.elems, seqLit.elemtpt))

case _ =>
tree
}
Expand All @@ -49,6 +53,7 @@ class ArrayApply extends MiniPhase {
* - `ClassTag.XYZ` for primitive types
*/
private def elideClassTag(ct: Tree)(using Context): Boolean = ct match {
case Inlined(_, _, expansion) => elideClassTag(expansion)
case Apply(_, rc :: Nil) if ct.symbol == defn.ClassTagModule_apply =>
rc match {
case _: Literal => true // ClassTag.apply(classOf[XYZ])
Expand All @@ -63,13 +68,27 @@ class ArrayApply extends MiniPhase {
case _ => false
}

object StripAscription {
def unapply(tree: Tree)(using Context): Some[Tree] = tree match {
case Typed(expr, _) => unapply(expr)
case _ => Some(tree)
}
}
}
// Match a sequence of literal arguments passed to an Array constructor
private object AppliedLiterals:

def unapply(tree: Tree)(using Context): Option[tpd.JavaSeqLiteral] = tree match
case Apply(wrapRefArrayMeth, (seqLit: tpd.JavaSeqLiteral) :: Nil)
if defn.WrapArrayMethods().contains(wrapRefArrayMeth.symbol) =>
Some(seqLit)
case _ => None

end AppliedLiterals

// Match an inlined sequence splice
private object InlinedSplice:
def unapply(tree: Tree)(using Context): Option[(Inlined, tpd.JavaSeqLiteral)] = tree match
case inlined @ Inlined(_, _, Typed(AppliedLiterals(seqLit), _)) =>
Some((inlined, seqLit))
case _ => None

end InlinedSplice

end ArrayApply

object ArrayApply:
val name: String = "arrayApply"
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/BetaReduce.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ object BetaReduce:
case _ => None
case Block(stats, expr) if stats.forall(isPureBinding) =>
recur(expr, argss).map(cpy.Block(fn)(stats, _))
case Inlined(call, bindings, expr) if bindings.forall(isPureBinding) =>
case fn @ Inlined(call, bindings, expr) if bindings.forall(isPureBinding) =>
recur(expr, argss).map(cpy.Inlined(fn)(call, bindings, _))
case Typed(expr, tpt) =>
recur(expr, argss)
Expand Down
5 changes: 0 additions & 5 deletions compiler/src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -895,11 +895,6 @@ object Erasure {
tree.typeOpt
else valueErasure(tree.typeOpt)

override def typedInlined(tree: untpd.Inlined, pt: Type)(using Context): Tree =
super.typedInlined(tree, pt) match {
case tree: Inlined => Inlines.dropInlined(tree)
}

override def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree =
if (sym.isEffectivelyErased) erasedDef(sym)
else
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/Mixin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Names._
import NameKinds._
import NameOps._
import ast.Trees._
import dotty.tools.dotc.inlines.Inlines

object Mixin {
val name: String = "mixin"
Expand Down Expand Up @@ -221,6 +222,7 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
case _ =>
}
(scall, stats ::: inits, args)
case inlined @ Inlined(_, _, _) => transformConstructor(Inlines.dropInlined(inlined) )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this one needed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newClassExtendsClassParams was finding an unexpected inlined node while transforming the constructor

case _ =>
val Apply(sel @ Select(New(_), nme.CONSTRUCTOR), args) = tree: @unchecked
val (callArgs, initArgs) = if (tree.symbol.owner.is(Trait)) (Nil, args) else (args, Nil)
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 @@ -115,7 +115,7 @@ class PickleQuotes extends MacroTransform {
holeContents += content
val holeType = getPicklableHoleType(tree.tpe, stagedClasses)
val hole = untpd.cpy.Hole(tree)(content = EmptyTree).withType(holeType)
cpy.Inlined(tree)(EmptyTree, Nil, hole)
Inlined(EmptyTree, Nil, hole).withSpan(tree.span)
case tree: DefTree =>
if tree.symbol.isClass then
stagedClasses += tree.symbol
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>

private object dropInlines extends TreeMap {
override def transform(tree: Tree)(using Context): Tree = tree match {
case Inlined(call, _, expansion) =>
case tree @ Inlined(call, _, expansion) =>
val newExpansion = PruneErasedDefs.trivialErasedTree(tree)
cpy.Inlined(tree)(call, Nil, newExpansion)
case _ => super.transform(tree)
Expand Down Expand Up @@ -363,7 +363,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
case _ =>
super.transform(tree1)
}
case Inlined(call, bindings, expansion) if !call.isEmpty =>
case tree @ Inlined(call, bindings, expansion) if !call.isEmpty =>
val pos = call.sourcePos
CrossVersionChecks.checkExperimentalRef(call.symbol, pos)
withMode(Mode.InlinedCall)(transform(call))
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
def apply(call: Option[Tree], bindings: List[Definition], expansion: Term): Inlined =
withDefaultPos(tpd.Inlined(call.getOrElse(tpd.EmptyTree), bindings.map { case b: tpd.MemberDef => b }, xCheckMacroValidExpr(expansion)))
def copy(original: Tree)(call: Option[Tree], bindings: List[Definition], expansion: Term): Inlined =
tpd.cpy.Inlined(original)(call.getOrElse(tpd.EmptyTree), bindings.asInstanceOf[List[tpd.MemberDef]], xCheckMacroValidExpr(expansion))
tpd.cpy.Inlined(original.asInstanceOf[Inlined])(call.getOrElse(tpd.EmptyTree), bindings.asInstanceOf[List[tpd.MemberDef]], xCheckMacroValidExpr(expansion))
def unapply(x: Inlined): (Option[Tree /* Term | TypeTree */], List[Definition], Term) =
(optional(x.call), x.bindings, x.body)
end Inlined
Expand Down