Skip to content

Commit 518448d

Browse files
committed
Add Inlined.inlinedFromOuterScope and refactor typedInlined
1 parent da16f43 commit 518448d

15 files changed

+45
-39
lines changed

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,9 @@ object Trees {
673673
*/
674674
case class Inlined[+T <: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit @constructorOnly src: SourceFile)
675675
extends Tree[T] {
676+
677+
def inlinedFromOuterScope: Boolean = call.isEmpty
678+
676679
type ThisTree[+T <: Untyped] = Inlined[T]
677680
override def isTerm = expansion.isTerm
678681
override def isType = expansion.isType
@@ -1479,7 +1482,7 @@ object Trees {
14791482
* innermost enclosing call for which the inlined version is currently
14801483
* processed.
14811484
*/
1482-
protected def inlineContext(call: tpd.Tree)(using Context): Context = ctx
1485+
protected def inlineContext(tree: Inlined)(using Context): Context = ctx
14831486

14841487
/** The context to use when mapping or accumulating over a tree */
14851488
def localCtx(tree: Tree)(using Context): Context
@@ -1549,8 +1552,8 @@ object Trees {
15491552
cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
15501553
case SeqLiteral(elems, elemtpt) =>
15511554
cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
1552-
case Inlined(call, bindings, expansion) =>
1553-
cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)(using inlineContext(call)))
1555+
case tree @ Inlined(call, bindings, expansion) =>
1556+
cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)(using inlineContext(tree)))
15541557
case TypeTree() =>
15551558
tree
15561559
case SingletonTypeTree(ref) =>
@@ -1693,8 +1696,8 @@ object Trees {
16931696
this(this(this(x, block), handler), finalizer)
16941697
case SeqLiteral(elems, elemtpt) =>
16951698
this(this(x, elems), elemtpt)
1696-
case Inlined(call, bindings, expansion) =>
1697-
this(this(x, bindings), expansion)(using inlineContext(call))
1699+
case tree @ Inlined(call, bindings, expansion) =>
1700+
this(this(x, bindings), expansion)(using inlineContext(tree))
16981701
case TypeTree() =>
16991702
x
17001703
case SingletonTypeTree(ref) =>

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,17 +1392,17 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
13921392
* EmptyTree calls (for parameters) cancel the next-enclosing call in the list instead of being added to it.
13931393
* We assume parameters are never nested inside parameters.
13941394
*/
1395-
override def inlineContext(call: Tree)(using Context): Context = {
1395+
override def inlineContext(tree: Inlined)(using Context): Context = {
13961396
// We assume enclosingInlineds is already normalized, and only process the new call with the head.
13971397
val oldIC = enclosingInlineds
13981398

13991399
val newIC =
1400-
if call.isEmpty then
1400+
if tree.inlinedFromOuterScope then
14011401
oldIC match
14021402
case t1 :: ts2 => ts2
14031403
case _ => oldIC
14041404
else
1405-
call :: oldIC
1405+
tree.call :: oldIC
14061406

14071407
val ctx1 = ctx.fresh.setProperty(InlinedCalls, newIC)
14081408
if oldIC.isEmpty then ctx1.setProperty(InlinedTrees, new Counter) else ctx1

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,12 +528,12 @@ class TreePickler(pickler: TastyPickler) {
528528
case SeqLiteral(elems, elemtpt) =>
529529
writeByte(REPEATED)
530530
withLength { pickleTree(elemtpt); elems.foreach(pickleTree) }
531-
case Inlined(call, bindings, expansion) =>
531+
case tree @ Inlined(call, bindings, expansion) =>
532532
writeByte(INLINED)
533533
bindings.foreach(preRegister)
534534
withLength {
535535
pickleTree(expansion)
536-
if (!call.isEmpty) pickleTree(call)
536+
if (!tree.inlinedFromOuterScope) pickleTree(call)
537537
bindings.foreach { b =>
538538
assert(b.isInstanceOf[DefDef] || b.isInstanceOf[ValDef])
539539
pickleTree(b)

compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,8 @@ class InlineReducer(inliner: Inliner)(using Context):
342342
}
343343
case Alternative(pats) =>
344344
pats.exists(reducePattern(caseBindingMap, scrut, _))
345-
case Inlined(EmptyTree, Nil, ipat) =>
346-
reducePattern(caseBindingMap, scrut, ipat)
345+
case tree: Inlined if tree.inlinedFromOuterScope =>
346+
reducePattern(caseBindingMap, scrut, tree.expansion)
347347
case _ => false
348348
}
349349
}

compiler/src/dotty/tools/dotc/inlines/Inliner.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ object Inliner:
129129
new InlinerMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo)
130130

131131
override def transformInlined(tree: Inlined)(using Context) =
132-
if tree.call.isEmpty then
132+
if tree.inlinedFromOuterScope then
133133
tree.expansion match
134134
case expansion: TypeTree => expansion
135135
case _ => tree
@@ -549,7 +549,7 @@ class Inliner(val call: tpd.Tree)(using Context):
549549

550550
val inlineTyper = new InlineTyper(ctx.reporter.errorCount)
551551

552-
val inlineCtx = inlineContext(call).fresh.setTyper(inlineTyper).setNewScope
552+
val inlineCtx = inlineContext(Inlined(call, Nil, ref(defn.Predef_undefined))).fresh.setTyper(inlineTyper).setNewScope
553553

554554
def inlinedFromOutside(tree: Tree)(span: Span): Tree =
555555
Inlined(EmptyTree, Nil, tree)(using ctx.withSource(inlinedMethod.topLevelClass.source)).withSpan(span)
@@ -1049,7 +1049,7 @@ class Inliner(val call: tpd.Tree)(using Context):
10491049
}
10501050
val inlinedNormalizer = new TreeMap {
10511051
override def transform(tree: tpd.Tree)(using Context): tpd.Tree = tree match {
1052-
case Inlined(EmptyTree, Nil, expr) if enclosingInlineds.isEmpty => transform(expr)
1052+
case tree @ Inlined(_, Nil, expr) if tree.inlinedFromOuterScope && enclosingInlineds.isEmpty => transform(expr)
10531053
case _ => super.transform(tree)
10541054
}
10551055
}

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
535535
case tree @ Inlined(call, bindings, body) =>
536536
val bodyText = if bindings.isEmpty then toText(body) else blockText(bindings :+ body)
537537
if homogenizedView || !ctx.settings.XprintInline.value then bodyText
538-
else if call.isEmpty then stringText("{{") ~ stringText("/* inlined from outside */") ~ bodyText ~ stringText("}}")
538+
else if tree.inlinedFromOuterScope then stringText("{{") ~ stringText("/* inlined from outside */") ~ bodyText ~ stringText("}}")
539539
else keywordText("{{") ~ keywordText("/* inlined from ") ~ toText(call) ~ keywordText(" */") ~ bodyText ~ keywordText("}}")
540540
case tpt: untpd.DerivedTypeTree =>
541541
"<derived typetree watching " ~ tpt.watched.showSummary() ~ ">"

compiler/src/dotty/tools/dotc/quoted/PickledQuotes.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@ object PickledQuotes {
8181

8282
/** Unpickle the tree contained in the TastyExpr */
8383
def unpickleTerm(pickled: String | List[String], typeHole: TypeHole, termHole: ExprHole)(using Context): Tree = {
84-
val unpickled = withMode(Mode.ReadPositions)(unpickle(pickled, isType = false))
85-
val Inlined(call, Nil, expansion) = unpickled: @unchecked
86-
val inlineCtx = inlineContext(call)
87-
val expansion1 = spliceTypes(expansion, typeHole)(using inlineCtx)
88-
val expansion2 = spliceTerms(expansion1, typeHole, termHole)(using inlineCtx)
89-
cpy.Inlined(unpickled)(call, Nil, expansion2)
84+
withMode(Mode.ReadPositions)(unpickle(pickled, isType = false)) match
85+
case tree @ Inlined(call, Nil, expansion) =>
86+
val inlineCtx = inlineContext(tree)
87+
val expansion1 = spliceTypes(expansion, typeHole)(using inlineCtx)
88+
val expansion2 = spliceTerms(expansion1, typeHole, termHole)(using inlineCtx)
89+
cpy.Inlined(tree)(call, Nil, expansion2)
9090
}
9191

9292

compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,10 +388,10 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT
388388
}
389389

390390
tree match {
391-
case Inlined(call, _, _) if !call.isEmpty =>
391+
case tree: Inlined if !tree.inlinedFromOuterScope =>
392392
// The inlined call is normally ignored by TreeTraverser but we need to
393393
// record it as a dependency
394-
traverse(call)
394+
traverse(tree.call)
395395
case vd: ValDef if vd.symbol.is(ModuleVal) =>
396396
// Don't visit module val
397397
case t: Template if t.symbol.owner.is(ModuleClass) =>

compiler/src/dotty/tools/dotc/transform/MegaPhase.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase {
396396
case tree: Inlined =>
397397
inContext(prepInlined(tree, start)(using outerCtx)) {
398398
val bindings = transformSpecificTrees(tree.bindings, start)
399-
val expansion = transformTree(tree.expansion, start)(using inlineContext(tree.call))
399+
val expansion = transformTree(tree.expansion, start)(using inlineContext(tree))
400400
goInlined(cpy.Inlined(tree)(tree.call, bindings, expansion), start)
401401
}
402402
case tree: Quote =>

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,12 +363,12 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
363363
case _ =>
364364
super.transform(tree1)
365365
}
366-
case Inlined(call, bindings, expansion) if !call.isEmpty =>
366+
case tree @ Inlined(call, bindings, expansion) if !tree.inlinedFromOuterScope =>
367367
val pos = call.sourcePos
368368
CrossVersionChecks.checkExperimentalRef(call.symbol, pos)
369369
withMode(Mode.InlinedCall)(transform(call))
370370
val callTrace = Inlines.inlineCallTrace(call.symbol, pos)(using ctx.withSource(pos.source))
371-
cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(using inlineContext(call)))
371+
cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(using inlineContext(tree)))
372372
case templ: Template =>
373373
withNoCheckNews(templ.parents.flatMap(newPart)) {
374374
forwardParamAccessors(templ)

compiler/src/dotty/tools/dotc/transform/Recheck.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ abstract class Recheck extends Phase, SymTransformer:
322322
recheckBlock(tree.stats, tree.expr, pt)
323323

324324
def recheckInlined(tree: Inlined, pt: Type)(using Context): Type =
325-
recheckBlock(tree.bindings, tree.expansion, pt)(using inlineContext(tree.call))
325+
recheckBlock(tree.bindings, tree.expansion, pt)(using inlineContext(tree))
326326

327327
def recheckIf(tree: If, pt: Type)(using Context): Type =
328328
recheck(tree.cond, defn.BooleanType)

compiler/src/dotty/tools/dotc/transform/Splicer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ object Splicer {
245245
case expr: Ident if expr.symbol.isAllOf(InlineByNameProxy) =>
246246
// inline proxy for by-name parameter
247247
expr.symbol.defTree.asInstanceOf[DefDef].rhs
248-
case Inlined(EmptyTree, _, body1) => body1
248+
case tree: Inlined if tree.inlinedFromOuterScope => tree.expansion
249249
case _ => body
250250
}
251251
new ExprImpl(Inlined(EmptyTree, Nil, QuoteUtils.changeOwnerOfTree(body1, ctx.owner)).withSpan(body1.span), SpliceScope.getCurrent)

compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,17 @@ class YCheckPositions extends Phase {
3838
// Recursivlely check children while keeping track of current source
3939
reporting.trace(i"check pos ${tree.getClass} ${tree.source} ${sources.head} $tree") {
4040
tree match {
41-
case Inlined(EmptyTree, bindings, expansion) =>
41+
case tree @ Inlined(_, bindings, expansion) if tree.inlinedFromOuterScope =>
4242
assert(bindings.isEmpty)
4343
val old = sources
4444
sources = old.tail
45-
traverse(expansion)(using inlineContext(EmptyTree).withSource(sources.head))
45+
traverse(expansion)(using inlineContext(tree).withSource(sources.head))
4646
sources = old
47-
case Inlined(call, bindings, expansion) =>
47+
case tree @ Inlined(call, bindings, expansion) =>
4848
// bindings.foreach(traverse(_)) // TODO check inline proxies (see tests/tun/lst)
4949
sources = call.symbol.topLevelClass.source :: sources
5050
if (!isMacro(call)) // FIXME macro implementations can drop Inlined nodes. We should reinsert them after macro expansion based on the positions of the trees
51-
traverse(expansion)(using inlineContext(call).withSource(sources.head))
51+
traverse(expansion)(using inlineContext(tree).withSource(sources.head))
5252
sources = sources.tail
5353
case _ => traverseChildren(tree)
5454
}

compiler/src/dotty/tools/dotc/typer/ReTyper.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking
9595
override def typedUnApply(tree: untpd.Apply, selType: Type)(using Context): Tree =
9696
typedApply(tree, selType)
9797

98+
override def typedInlined(tree: untpd.Inlined, pt: Type)(using Context): Tree = {
99+
val (bindings1, exprCtx) = typedBlockStats(tree.bindings)
100+
val expansion1 = typed(tree.expansion, pt)(using inlineContext(promote(tree))(using exprCtx))
101+
untpd.cpy.Inlined(tree)(tree.call, bindings1.asInstanceOf[List[MemberDef]], expansion1)
102+
.withType(avoidingType(expansion1, bindings1))
103+
}
104+
98105
override def typedQuote(tree: untpd.Quote, pt: Type)(using Context): Tree =
99106
assertTyped(tree)
100107
val body1 = typed(tree.body, promote(tree).bodyType)(using quoteContext)

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,12 +2092,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
20922092
}
20932093
}
20942094

2095-
def typedInlined(tree: untpd.Inlined, pt: Type)(using Context): Tree = {
2096-
val (bindings1, exprCtx) = typedBlockStats(tree.bindings)
2097-
val expansion1 = typed(tree.expansion, pt)(using inlineContext(tree.call)(using exprCtx))
2098-
assignType(cpy.Inlined(tree)(tree.call, bindings1.asInstanceOf[List[MemberDef]], expansion1),
2099-
bindings1, expansion1)
2100-
}
2095+
def typedInlined(tree: untpd.Inlined, pt: Type)(using Context): Tree =
2096+
throw new UnsupportedOperationException("cannot type check a Inlined node")
21012097

21022098
def completeTypeTree(tree: untpd.TypeTree, pt: Type, original: untpd.Tree)(using Context): TypeTree =
21032099
tree.withSpan(original.span).withAttachmentsFrom(original)

0 commit comments

Comments
 (0)