Skip to content

Commit 4598e8c

Browse files
committed
Address exhaustiveness warnings when matching on Trees.
- Introduce a marker trait for Tree[Nothing] nodes, and use this in TreeAccumulator. - seal GenericApply - Make the match demo plugin transformer @unchecked - Add tree checking for Try - Match on EmptyTree() rather than tpd.EmptyTree
1 parent 717f690 commit 4598e8c

File tree

3 files changed

+24
-9
lines changed

3 files changed

+24
-9
lines changed

src/dotty/tools/dotc/core/PluggableTransformers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ object PluggableTransformers {
7777
case _ => postProcess(tree, old, c, plugins)
7878
}
7979

80-
protected def postProcess(tree: Tree[T], old: Tree[T], c: Context, plugins: Plugins): Tree[T] = tree match {
80+
protected def postProcess(tree: Tree[T], old: Tree[T], c: Context, plugins: Plugins): Tree[T] = (tree: @unchecked) match {
8181
case tree: Ident[_] => finishIdent(tree, old, c, plugins)
8282
case tree: Select[_] => finishSelect(tree, old, c, plugins)
8383
}

src/dotty/tools/dotc/core/Trees.scala

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ object Trees {
206206
def forwardTo = qual
207207
}
208208

209-
abstract class GenericApply[T] extends ProxyTree[T] with TermTree[T] {
209+
sealed abstract class GenericApply[T] extends ProxyTree[T] with TermTree[T] {
210210
type ThisTree[T] <: GenericApply[T]
211211
val fun: Tree[T]
212212
val args: List[Tree[T]]
@@ -485,7 +485,7 @@ object Trees {
485485
}
486486

487487
/** A missing tree */
488-
abstract case class EmptyTree[T]()
488+
sealed abstract case class EmptyTree[T]()
489489
extends Tree[T] with AlwaysEmpty[T] {
490490
type ThisTree[T] = EmptyTree[T]
491491
}
@@ -496,7 +496,7 @@ object Trees {
496496
def apply[T]: EmptyTree[T] = theEmptyTree.asInstanceOf
497497
}
498498

499-
abstract class EmptyValDef[T] extends ValDef[T](
499+
sealed abstract class EmptyValDef[T] extends ValDef[T](
500500
Modifiers[T](Private), nme.WILDCARD, EmptyTree[T], EmptyTree[T])(NoPosition) with AlwaysEmpty[T]
501501

502502
private object theEmptyValDef extends EmptyValDef[Nothing]
@@ -506,7 +506,7 @@ object Trees {
506506
}
507507

508508
/** A tree that can be shared without its position
509-
* polluting containing trees. Accumulators and tranformers
509+
* polluting containing trees. Accumulators and transformers
510510
* memoize results of shared subtrees
511511
*/
512512
final case class Shared[T](shared: Tree[T]) extends Tree[T] {
@@ -518,20 +518,25 @@ object Trees {
518518

519519
// ----- Tree cases that exist in untyped form only ------------------
520520

521+
/** A marker trait for all Tree[Nothing] descendants. Useful for exhaustively pattern matching over Tree[U] */
522+
sealed trait UntypedTreeMarker {
523+
self: UntypedTree =>
524+
}
525+
521526
/** A typed subtree of an untyped tree needs to be wrapped in a TypedSlice */
522-
final class TypedSplice(tree: TypedTree) extends UntypedTree {
527+
final class TypedSplice(tree: TypedTree) extends UntypedTree with UntypedTreeMarker {
523528
val pos = tree.pos
524529
}
525530

526531
/** mods object name impl */
527532
final case class ModuleDef(mods: Modifiers[Nothing], name: TermName, impl: Template[Nothing])(implicit cpos: Position)
528-
extends DefTree[Nothing] {
533+
extends DefTree[Nothing] with UntypedTreeMarker {
529534
val pos = cpos union impl.pos
530535
}
531536

532537
/** (vparams) => body */
533538
final case class Function(vparams: List[ValDef[Nothing]], body: Tree[Nothing])(implicit cpos: Position)
534-
extends TermTree[Nothing] {
539+
extends TermTree[Nothing] with UntypedTreeMarker {
535540
val pos = unionPos(cpos union body.pos, vparams)
536541
}
537542

@@ -800,6 +805,8 @@ object Trees {
800805
tree1
801806
},
802807
tree, c, plugins)
808+
case _: UntypedTreeMarker =>
809+
tree // TODO should this abort?
803810
}
804811
def transform(trees: List[Tree[T]], c: C): List[Tree[T]] =
805812
trees mapConserve (transform(_, c))
@@ -948,6 +955,8 @@ object Trees {
948955
sharedMemo = sharedMemo.updated(tree, x1)
949956
x1
950957
}
958+
case _: UntypedTreeMarker =>
959+
x
951960
}
952961
}
953962
}

src/dotty/tools/dotc/core/TypedTrees.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,9 +573,15 @@ object TypedTrees {
573573
check(annot.symbol.isClassConstructor)
574574
check(annot.symbol.owner.isSubClass(defn.AnnotationClass))
575575
check(arg.isType || arg.isValue)
576-
case tpd.EmptyTree =>
577576
case Shared(shared) =>
578577
check(shared.isType || shared.isTerm)
578+
case Try(block, catches, finalizer) =>
579+
check(block.isTerm)
580+
check(finalizer.isTerm)
581+
def checkType(t: Tree[Type]) = check(t.tpe <:< tree.tpe)
582+
checkType(block)
583+
catches foreach checkType
584+
case EmptyTree() =>
579585
}
580586

581587
implicit class TreeInfo(val tree: tpd.Tree) extends AnyVal {

0 commit comments

Comments
 (0)