Skip to content

Commit 5ab3c16

Browse files
committed
Warn trivial recursion with module prefix
1 parent 457a463 commit 5ab3c16

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ class TailRec extends MiniPhase {
196196
def isInfiniteRecCall(tree: Tree): Boolean = {
197197
def tailArgOrPureExpr(stat: Tree): Boolean = stat match {
198198
case stat: ValDef if stat.name.is(TailTempName) || !stat.symbol.is(Mutable) => tailArgOrPureExpr(stat.rhs)
199-
case Assign(lhs: Ident, rhs) if lhs.symbol.name.is(TailLocalName) => tailArgOrPureExpr(rhs)
199+
case Assign(lhs: Ident, rhs) if lhs.symbol.name.is(TailLocalName) =>
200+
tailArgOrPureExpr(rhs) || varForRewrittenThis.exists(_ == lhs.symbol && rhs.tpe.isStable)
200201
case Assign(lhs: Ident, rhs: Ident) => lhs.symbol == rhs.symbol
201202
case stat: Ident if stat.symbol.name.is(TailLocalName) => true
202203
case _ => tpd.isPureExpr(stat)
@@ -345,6 +346,9 @@ class TailRec extends MiniPhase {
345346
case prefix: This if prefix.symbol == enclosingClass =>
346347
// Avoid assigning `this = this`
347348
assignParamPairs
349+
case prefix if prefix.symbol.is(Module) && prefix.symbol.moduleClass == enclosingClass =>
350+
// Avoid assigning `this = MyObject`
351+
assignParamPairs
348352
case _ =>
349353
(getVarForRewrittenThis(), noTailTransform(prefix)) :: assignParamPairs
350354

tests/warn/i23277.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
enum Test:
3+
case One
4+
case Two(i: Int)
5+
6+
object Test:
7+
object Two:
8+
def apply(i: Int): Test.Two = Test.Two(i) // warn
9+
def apply(i: Int, j: Int): Test.Two = new Test.Two(i+j)
10+
def apply(): Test.Two = other.apply() // nowarn prefix is method call
11+
def other: this.type = this
12+
13+
object R extends Runnable:
14+
def r: this.type = this
15+
override def run() = r.run()
16+
17+
final class C(c: C):
18+
def f(i: Int): Int = c.f(i)
19+
20+
@main def main = println:
21+
Test.Two(1)

0 commit comments

Comments
 (0)