Skip to content

Commit 8d5640a

Browse files
committed
Mitigate infinite recursion on canDirectlyPromote
1 parent e24d76a commit 8d5640a

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
@@ -260,8 +260,10 @@ object Checking {
260260
/// A potential can be (currently) directly promoted if and only if:
261261
/// - `pot == this` and all fields of this are initialized, or
262262
/// - `pot == Warm(C, outer)` where `outer` can be directly promoted.
263-
private def canDirectlyPromote(pot: Potential)(using state: State): Boolean = trace("checking direct promotion of " + pot.show, init) {
263+
private def canDirectlyPromote(pot: Potential, visited: Set[Potential] = Set.empty)(using state: State): Boolean = trace("checking direct promotion of " + pot.show, init) {
264264
if (state.safePromoted.contains(pot)) true
265+
// If this potential's promotion depends on itself, we cannot directly promote it.
266+
else if (visited.contains(pot)) false
265267
else pot match {
266268
case pot: ThisRef =>
267269
// If we have all fields initialized, then we can promote This to hot.
@@ -276,7 +278,7 @@ object Checking {
276278
val summary = expand(pot)
277279
if (!summary.effs.isEmpty)
278280
false // max depth of expansion reached
279-
else summary.pots.forall(canDirectlyPromote)
281+
else summary.pots.forall(canDirectlyPromote(_, visited + pot))
280282
}
281283
}
282284

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)