Skip to content

Commit 3084b1a

Browse files
committed
Use EmptyTree for the cond of infinite WhileDo loops.
Such `WhileDo` node have type `Nothing` instead of `Unit`. This is used in the loops generated by `TailRec` in order not to need some spurious dead code.
1 parent b3b59d5 commit 3084b1a

File tree

5 files changed

+15
-11
lines changed

5 files changed

+15
-11
lines changed

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

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import reporting.diagnostic.messages.TailrecNotApplicable
3232
* {{{
3333
* var localForParam1: T1 = param1
3434
* ...
35-
* while (true) {
35+
* while (<empty>) {
3636
* tailResult[ResultType]: {
3737
* return {
3838
* // original rhs with tail recursive calls transformed (see below)
@@ -60,7 +60,7 @@ import reporting.diagnostic.messages.TailrecNotApplicable
6060
* def fact(n: Int, acc: Int): Int = {
6161
* var acc$tailLocal1: Int = acc
6262
* var n$tailLocal1: Int = n
63-
* while (true) {
63+
* while (<empty>) {
6464
* tailLabel1[Unit]: {
6565
* return {
6666
* if (n$tailLocal1 == 0)
@@ -75,7 +75,6 @@ import reporting.diagnostic.messages.TailrecNotApplicable
7575
* }
7676
* }
7777
* }
78-
* throw null // unreachable
7978
* }
8079
* }}}
8180
*
@@ -163,14 +162,12 @@ class TailRec extends MiniPhase {
163162
}
164163

165164
Block(
166-
initialVarDefs :::
167-
WhileDo(Literal(Constant(true)), {
165+
initialVarDefs,
166+
WhileDo(EmptyTree, {
168167
Labeled(transformer.continueLabel.asTerm, {
169168
Return(rhsFullyTransformed, origMeth)
170169
})
171-
}) ::
172-
Nil,
173-
Throw(Literal(Constant(null))) // unreachable code
170+
})
174171
)
175172
} else {
176173
if (mandatory) ctx.error(

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,11 @@ class TreeChecker extends Phase with SymTransformer {
452452
tree1
453453
}
454454

455+
override def typedWhileDo(tree: untpd.WhileDo)(implicit ctx: Context): Tree = {
456+
assert((tree.cond ne EmptyTree) || ctx.phase.refChecked, i"invalid empty condition in while at $tree")
457+
super.typedWhileDo(tree)
458+
}
459+
455460
override def ensureNoLocalRefs(tree: Tree, pt: Type, localSyms: => List[Symbol])(implicit ctx: Context): Tree =
456461
tree
457462

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ trait TypeAssigner {
486486
tree.withType(defn.NothingType)
487487

488488
def assignType(tree: untpd.WhileDo)(implicit ctx: Context): WhileDo =
489-
tree.withType(defn.UnitType)
489+
tree.withType(if (tree.cond eq EmptyTree) defn.NothingType else defn.UnitType)
490490

491491
def assignType(tree: untpd.Try, expr: Tree, cases: List[CaseDef])(implicit ctx: Context): Try =
492492
if (cases.isEmpty) tree.withType(expr.tpe)

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,9 @@ class Typer extends Namer
11271127
}
11281128

11291129
def typedWhileDo(tree: untpd.WhileDo)(implicit ctx: Context): Tree = track("typedWhileDo") {
1130-
val cond1 = typed(tree.cond, defn.BooleanType)
1130+
val cond1 =
1131+
if (tree.cond eq EmptyTree) EmptyTree
1132+
else typed(tree.cond, defn.BooleanType)
11311133
val body1 = typed(tree.body, defn.UnitType)
11321134
assignType(cpy.WhileDo(tree)(cond1, body1))
11331135
}

0 commit comments

Comments
 (0)