Skip to content

Commit 0c07ce5

Browse files
committed
Mitigate infinite recursion on canDirectlyPromote
1 parent be122d4 commit 0c07ce5

File tree

2 files changed

+13
-2
lines changed

2 files changed

+13
-2
lines changed

compiler/src/dotty/tools/dotc/transform/init/Checking.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,10 @@ object Checking {
270270
/// A potential can be (currently) directly promoted if and only if:
271271
/// - `pot == this` and all fields of this are initialized, or
272272
/// - `pot == Warm(C, outer)` where `outer` can be directly promoted.
273-
private def canDirectlyPromote(pot: Potential)(using state: State): Boolean = trace("checking direct promotion of " + pot.show, init) {
273+
private def canDirectlyPromote(pot: Potential, visited: Set[Potential] = Set.empty)(using state: State): Boolean = trace("checking direct promotion of " + pot.show, init) {
274274
if (state.safePromoted.contains(pot)) true
275+
// If this potential's promotion depends on itself, we cannot directly promote it.
276+
else if (visited.contains(pot)) false
275277
else pot match {
276278
case pot: ThisRef =>
277279
// If we have all fields initialized, then we can promote This to hot.
@@ -286,7 +288,7 @@ object Checking {
286288
val summary = expand(pot)
287289
if (!summary.effs.isEmpty)
288290
false // max depth of expansion reached
289-
else summary.pots.forall(canDirectlyPromote)
291+
else summary.pots.forall(canDirectlyPromote(_, visited + pot))
290292
}
291293
}
292294

tests/init/pos/early-promote.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,12 @@ class A { // checking A
2727
List(b) // Direct promotion works here
2828
val af = 42
2929
}
30+
31+
class RecursiveF {
32+
val a = f
33+
def f: RecursiveF = f
34+
class B(x: Int)
35+
36+
println(new a.B(5))
37+
val n = 10
38+
}

0 commit comments

Comments
 (0)