Skip to content

Commit 5274c48

Browse files
authored
Merge pull request #9665 from dotty-staging/fix-9664
Fix #9664: check outer of warm values
2 parents 733b57c + 78630f9 commit 5274c48

File tree

4 files changed

+35
-8
lines changed

4 files changed

+35
-8
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Checker extends MiniPhase {
4747
// A concrete class may not be instantiated if the self type is not satisfied
4848
if (instantiable) {
4949
implicit val state: Checking.State = Checking.State(
50-
visited = mutable.Set.empty,
50+
visited = Set.empty,
5151
path = Vector.empty,
5252
thisClass = cls,
5353
fieldsInited = mutable.Set.empty,

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

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,30 @@ object Checking {
3030
*
3131
*/
3232
case class State(
33-
visited: mutable.Set[Effect], // effects that have been checked
33+
private var visited: Set[Effect], // effects that have been checked
3434
path: Vector[Tree], // the path that leads to the current effect
3535
thisClass: ClassSymbol, // the concrete class of `this`
3636
fieldsInited: mutable.Set[Symbol],
3737
parentsInited: mutable.Set[ClassSymbol],
3838
env: Env
3939
) {
40+
4041
def withVisited(eff: Effect): State = {
41-
visited += eff
42+
visited = visited + eff
4243
copy(path = this.path :+ eff.source)
4344
}
4445

46+
def hasVisited(eff: Effect): Boolean =
47+
visited.contains(eff)
48+
4549
def withOwner(sym: Symbol): State = copy(env = env.withOwner(sym))
50+
51+
def test(op: State ?=> Errors): Errors = {
52+
val saved = visited
53+
val errors = op(using this)
54+
visited = saved
55+
errors
56+
}
4657
}
4758

4859
private implicit def theEnv(implicit state: State): Env = state.env
@@ -148,7 +159,7 @@ object Checking {
148159
}
149160

150161
private def check(eff: Effect)(implicit state: State): Errors =
151-
if (state.visited.contains(eff)) Errors.empty
162+
if (state.hasVisited(eff)) Errors.empty
152163
else trace("checking effect " + eff.show, init, errs => Errors.show(errs.asInstanceOf[Errors])) {
153164
implicit val state2: State = state.withVisited(eff)
154165

@@ -162,11 +173,13 @@ object Checking {
162173
PromoteCold(eff.source, state2.path).toErrors
163174

164175
case pot @ Warm(cls, outer) =>
165-
PromoteWarm(pot, eff.source, state2.path).toErrors
176+
val errors = state.test { check(Promote(outer)(eff.source)) }
177+
if (errors.isEmpty) Errors.empty
178+
else PromoteWarm(pot, eff.source, state2.path).toErrors
166179

167180
case Fun(pots, effs) =>
168-
val errs1 = effs.flatMap { check(_) }
169-
val errs2 = pots.flatMap { pot => check(Promote(pot)(eff.source))(state.copy(path = Vector.empty)) }
181+
val errs1 = state.test { effs.flatMap { check(_) } }
182+
val errs2 = state.test { pots.flatMap { pot => check(Promote(pot)(eff.source))(state.copy(path = Vector.empty)) } }
170183
if (errs1.nonEmpty || errs2.nonEmpty)
171184
UnsafePromotion(pot, eff.source, state2.path, errs1 ++ errs2).toErrors
172185
else

tests/init/neg/function1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class Foo {
44
val fun2: Int => Int = n => 1 + n + list.size
55
fun2(5)
66

7-
List(5, 9).map(n => 2 + n + list.size)
7+
List(5, 9).map(n => 2 + n + list.size) // error
88

99
final val list = List(1, 2, 3) // error
1010

tests/init/pos/i9664.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
object Wrap1 {
2+
class E
3+
object E {
4+
final val A = E()
5+
val $values = Array(A)
6+
}
7+
}
8+
object Wrap2 {
9+
class E
10+
object E {
11+
final val A = E()
12+
val ref = A
13+
}
14+
}

0 commit comments

Comments
 (0)