Skip to content

Commit df62cc3

Browse files
committed
More robust scheme for untyped splices
- extend scheme to accumulators - no need anymore to define special tpd versions of maps and accumulators - no extra `typeMap` field needed in typeMap; instead the UntypedSplice case is handled directly.
1 parent c9cb5df commit df62cc3

File tree

4 files changed

+59
-41
lines changed

4 files changed

+59
-41
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class TreeTypeMap(
3838
val oldOwners: List[Symbol] = Nil,
3939
val newOwners: List[Symbol] = Nil,
4040
val substFrom: List[Symbol] = Nil,
41-
val substTo: List[Symbol] = Nil)(implicit ctx: Context) extends tpd.TypedTreeMap {
41+
val substTo: List[Symbol] = Nil)(implicit ctx: Context) extends tpd.TreeMap {
4242
import tpd._
4343

4444
/** If `sym` is one of `oldOwners`, replace by corresponding symbol in `newOwners` */

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

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,10 @@ object Trees {
11091109
case tree: Annotated if (arg eq tree.arg) && (annot eq tree.annot) => tree
11101110
case _ => finalize(tree, untpd.Annotated(arg, annot))
11111111
}
1112+
def UntypedSplice(tree: Tree)(splice: untpd.Tree) = tree match {
1113+
case tree: tpd.UntypedSplice if tree.splice `eq` splice => tree
1114+
case _ => finalize(tree, tpd.UntypedSplice(splice))
1115+
}
11121116
def Thicket(tree: Tree)(trees: List[Tree]): Thicket = tree match {
11131117
case tree: Thicket if trees eq tree.trees => tree
11141118
case _ => finalize(tree, untpd.Thicket(trees))
@@ -1146,10 +1150,7 @@ object Trees {
11461150
*/
11471151
protected def inlineContext(call: Tree)(implicit ctx: Context): Context = ctx
11481152

1149-
abstract class TreeMap(val cpy: TreeCopier = inst.cpy) {
1150-
1151-
protected def handleMoreCases(tree: Tree)(implicit ctx: Context): Tree =
1152-
if (ctx.reporter.errorsReported) tree else throw new MatchError(tree)
1153+
abstract class TreeMap(val cpy: TreeCopier = inst.cpy) { self =>
11531154

11541155
def transform(tree: Tree)(implicit ctx: Context): Tree = {
11551156
Stats.record(s"TreeMap.transform $getClass")
@@ -1249,7 +1250,7 @@ object Trees {
12491250
val trees1 = transform(trees)
12501251
if (trees1 eq trees) tree else Thicket(trees1)
12511252
case _ =>
1252-
handleMoreCases(tree)
1253+
transformMoreCases(tree)
12531254
}
12541255
}
12551256

@@ -1261,9 +1262,26 @@ object Trees {
12611262
transform(tree).asInstanceOf[Tr]
12621263
def transformSub[Tr <: Tree](trees: List[Tr])(implicit ctx: Context): List[Tr] =
12631264
transform(trees).asInstanceOf[List[Tr]]
1265+
1266+
protected def transformMoreCases(tree: Tree)(implicit ctx: Context): Tree = tree match {
1267+
case tpd.UntypedSplice(usplice) =>
1268+
// For a typed tree map: homomorphism on the untyped part with
1269+
// recursive mapping of typed splices.
1270+
// The case is overridden in UntypedTreeMap.##
1271+
val untpdMap = new untpd.UntypedTreeMap {
1272+
override def transform(tree: untpd.Tree)(implicit ctx: Context): untpd.Tree = tree match {
1273+
case untpd.TypedSplice(tsplice) =>
1274+
untpd.cpy.TypedSplice(tree)(self.transform(tsplice).asInstanceOf[tpd.Tree])
1275+
// the cast is safe, since the UntypedSplice case is overridden in UntypedTreeMap.
1276+
case _ => super.transform(tree)
1277+
}
1278+
}
1279+
cpy.UntypedSplice(tree)(untpdMap.transform(usplice))
1280+
case _ if ctx.reporter.errorsReported => tree
1281+
}
12641282
}
12651283

1266-
abstract class TreeAccumulator[X] {
1284+
abstract class TreeAccumulator[X] { self =>
12671285
// Ties the knot of the traversal: call `foldOver(x, tree))` to dive in the `tree` node.
12681286
def apply(x: X, tree: Tree)(implicit ctx: Context): X
12691287

@@ -1358,14 +1376,29 @@ object Trees {
13581376
this(this(x, arg), annot)
13591377
case Thicket(ts) =>
13601378
this(x, ts)
1361-
case _ if ctx.reporter.errorsReported || ctx.mode.is(Mode.Interactive) =>
1362-
// In interactive mode, errors might come from previous runs.
1363-
// In case of errors it may be that typed trees point to untyped ones.
1364-
// The IDE can still traverse inside such trees, either in the run where errors
1365-
// are reported, or in subsequent ones.
1366-
x
1379+
case _ =>
1380+
foldMoreCases(x, tree)
13671381
}
13681382
}
1383+
1384+
def foldMoreCases(x: X, tree: Tree)(implicit ctx: Context): X = tree match {
1385+
case tpd.UntypedSplice(usplice) =>
1386+
// For a typed tree accumulator: skip the untyped part and fold all typed splices.
1387+
// The case is overridden in UntypedTreeAccumulator.
1388+
val untpdAcc = new untpd.UntypedTreeAccumulator[X] {
1389+
override def apply(x: X, tree: untpd.Tree)(implicit ctx: Context): X = tree match {
1390+
case untpd.TypedSplice(tsplice) => self(x, tsplice)
1391+
case _ => foldOver(x, tree)
1392+
}
1393+
}
1394+
untpdAcc(x, usplice)
1395+
case _ if ctx.reporter.errorsReported || ctx.mode.is(Mode.Interactive) =>
1396+
// In interactive mode, errors might come from previous runs.
1397+
// In case of errors it may be that typed trees point to untyped ones.
1398+
// The IDE can still traverse inside such trees, either in the run where errors
1399+
// are reported, or in subsequent ones.
1400+
x
1401+
}
13691402
}
13701403

13711404
abstract class TreeTraverser extends TreeAccumulator[Unit] {

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

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -611,11 +611,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
611611
}
612612
}
613613

614-
def UntypedSplice(tree: Tree)(splice: untpd.Tree) = tree match {
615-
case tree: tpd.UntypedSplice if tree.splice `eq` splice => tree
616-
case _ => finalize(tree, tpd.UntypedSplice(splice))
617-
}
618-
619614
override def If(tree: If)(cond: Tree = tree.cond, thenp: Tree = tree.thenp, elsep: Tree = tree.elsep)(implicit ctx: Context): If =
620615
If(tree: Tree)(cond, thenp, elsep)
621616
override def Closure(tree: Closure)(env: List[Tree] = tree.env, meth: Tree = tree.meth, tpt: Tree = tree.tpt)(implicit ctx: Context): Closure =
@@ -645,18 +640,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
645640
Closure(tree: Tree)(env, meth, tpt)
646641
}
647642

648-
class TypedTreeMap(cpy: TypedTreeCopier = tpd.cpy) extends TreeMap(cpy) { self =>
649-
override def handleMoreCases(tree: Tree)(implicit ctx: Context) = tree match {
650-
case UntypedSplice(utree) =>
651-
val umap = new untpd.UntypedTreeMap() {
652-
override def typedMap = self.transform(_)
653-
}
654-
cpy.UntypedSplice(tree)(umap.transform(utree))
655-
case _ =>
656-
super.handleMoreCases(tree)
657-
}
658-
}
659-
660643
override def skipTransform(tree: Tree)(implicit ctx: Context) = tree.tpe.isError
661644

662645
implicit class TreeOps[ThisTree <: tpd.Tree](val tree: ThisTree) extends AnyVal {

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -503,9 +503,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
503503
}
504504

505505
abstract class UntypedTreeMap(cpy: UntypedTreeCopier = untpd.cpy) extends TreeMap(cpy) {
506-
protected def typedMap: tpd.Tree => tpd.Tree = identity
507-
508-
override def handleMoreCases(tree: Tree)(implicit ctx: Context): Tree = tree match {
506+
override def transformMoreCases(tree: Tree)(implicit ctx: Context): Tree = tree match {
509507
case ModuleDef(name, impl) =>
510508
cpy.ModuleDef(tree)(name, transformSub(impl))
511509
case ParsedTry(expr, handler, finalizer) =>
@@ -546,15 +544,17 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
546544
cpy.ContextBounds(tree)(transformSub(bounds), transform(cxBounds))
547545
case PatDef(mods, pats, tpt, rhs) =>
548546
cpy.PatDef(tree)(mods, transform(pats), transform(tpt), transform(rhs))
549-
case TypedSplice(splice) =>
550-
cpy.TypedSplice(tree)(typedMap(splice))
547+
case tpd.UntypedSplice(splice) =>
548+
cpy.UntypedSplice(tree)(transform(splice))
549+
case TypedSplice(_) =>
550+
tree
551551
case _ =>
552-
super.handleMoreCases(tree)
552+
super.transformMoreCases(tree)
553553
}
554554
}
555555

556-
abstract class UntypedTreeAccumulator[X] extends TreeAccumulator[X] {
557-
override def foldOver(x: X, tree: Tree)(implicit ctx: Context): X = tree match {
556+
abstract class UntypedTreeAccumulator[X] extends TreeAccumulator[X] { self =>
557+
override def foldMoreCases(x: X, tree: Tree)(implicit ctx: Context): X = tree match {
558558
case ModuleDef(name, impl) =>
559559
this(x, impl)
560560
case ParsedTry(expr, handler, finalizer) =>
@@ -595,10 +595,12 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
595595
this(this(x, bounds), cxBounds)
596596
case PatDef(mods, pats, tpt, rhs) =>
597597
this(this(this(x, pats), tpt), rhs)
598-
case TypedSplice(tree) =>
599-
this(x, tree)
598+
case TypedSplice(splice) =>
599+
this(x, splice)
600+
case tpd.UntypedSplice(splice) =>
601+
this(x, splice)
600602
case _ =>
601-
super.foldOver(x, tree)
603+
super.foldMoreCases(x, tree)
602604
}
603605
}
604606

0 commit comments

Comments
 (0)