Skip to content

Commit 4be1482

Browse files
authored
Merge pull request #15527 from dotty-staging/init-inner-first
Make sure inner classes are checked first
2 parents 16ded76 + 1ff85dc commit 4be1482

File tree

6 files changed

+49
-43
lines changed

6 files changed

+49
-43
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,10 +1143,10 @@ object Semantic:
11431143
case class Task(value: ThisRef)
11441144

11451145
class WorkList private[Semantic]():
1146-
private var pendingTasks: List[Task] = Nil
1146+
private val pendingTasks: mutable.ArrayBuffer[Task] = new mutable.ArrayBuffer
11471147

11481148
def addTask(task: Task): Unit =
1149-
if !pendingTasks.contains(task) then pendingTasks = task :: pendingTasks
1149+
if !pendingTasks.contains(task) then pendingTasks.append(task)
11501150

11511151
/** Process the worklist until done */
11521152
final def work()(using Cache, Context): Unit =

tests/init/neg/cycle-structure.check

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
1-
-- Error: tests/init/neg/cycle-structure.scala:9:13 --------------------------------------------------------------------
2-
9 | val x = A(this) // error
1+
-- Error: tests/init/neg/cycle-structure.scala:3:13 --------------------------------------------------------------------
2+
3 | val x = B(this) // error
33
| ^^^^^^^
44
| Problematic object instantiation: arg 1 is not fully initialized. Calling trace:
5-
| -> case class B(a: A) { [ cycle-structure.scala:7 ]
5+
| -> case class A(b: B) { [ cycle-structure.scala:1 ]
66
| ^
7-
| -> val x = A(this) // error [ cycle-structure.scala:9 ]
7+
| -> val x = B(this) // error [ cycle-structure.scala:3 ]
88
| ^^^^^^^
99
|
1010
| It leads to the following error during object initialization:
1111
| Access field on a value with an unknown initialization status. Calling trace:
12-
| -> case class A(b: B) { [ cycle-structure.scala:1 ]
12+
| -> case class B(a: A) { [ cycle-structure.scala:7 ]
1313
| ^
14-
| -> val x1 = b.x [ cycle-structure.scala:2 ]
14+
| -> val x1 = a.x [ cycle-structure.scala:8 ]
1515
| ^^^
16-
-- Error: tests/init/neg/cycle-structure.scala:3:13 --------------------------------------------------------------------
17-
3 | val x = B(this) // error
16+
-- Error: tests/init/neg/cycle-structure.scala:9:13 --------------------------------------------------------------------
17+
9 | val x = A(this) // error
1818
| ^^^^^^^
1919
| Problematic object instantiation: arg 1 is not fully initialized. Calling trace:
20-
| -> case class A(b: B) { [ cycle-structure.scala:1 ]
20+
| -> case class B(a: A) { [ cycle-structure.scala:7 ]
2121
| ^
22-
| -> val x = B(this) // error [ cycle-structure.scala:3 ]
22+
| -> val x = A(this) // error [ cycle-structure.scala:9 ]
2323
| ^^^^^^^
2424
|
2525
| It leads to the following error during object initialization:
2626
| Access field on a value with an unknown initialization status. Calling trace:
27-
| -> case class B(a: A) { [ cycle-structure.scala:7 ]
27+
| -> case class A(b: B) { [ cycle-structure.scala:1 ]
2828
| ^
29-
| -> val x1 = a.x [ cycle-structure.scala:8 ]
29+
| -> val x1 = b.x [ cycle-structure.scala:2 ]
3030
| ^^^

tests/init/neg/inherit-non-hot.check

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22
6 | if b == null then b = new B(this) // error
33
| ^^^^^^^^^^^
44
| The RHS of reassignment must be fully initialized. Calling trace:
5-
| -> object Foo { [ inherit-non-hot.scala:2 ]
6-
| ^
7-
| -> val c = new C [ inherit-non-hot.scala:19 ]
8-
| ^^^^^
95
| -> class C extends A { [ inherit-non-hot.scala:15 ]
106
| ^
117
| -> val bAgain = toB.getBAgain [ inherit-non-hot.scala:16 ]

tests/init/neg/inner-first.check

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- Error: tests/init/neg/inner-first.scala:3:12 ------------------------------------------------------------------------
2+
3 | println(this) // error
3+
| ^^^^
4+
| Cannot prove the argument is fully initialized. Only fully initialized values are safe to leak.
5+
| Non initialized field(s): value n. Calling trace:
6+
| -> class B: [ inner-first.scala:2 ]
7+
| ^
8+
| -> println(this) // error [ inner-first.scala:3 ]
9+
| ^^^^

tests/init/neg/inner-first.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class A:
2+
class B:
3+
println(this) // error
4+
val n = 10
5+
def foo() = println(m)
6+
new B
7+
val m = 20

tests/init/neg/secondary-ctor4.check

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,26 @@
11
-- Error: tests/init/neg/secondary-ctor4.scala:54:14 -------------------------------------------------------------------
22
54 | val c = new C(b, 5) // error
33
| ^^^^^^^^^^^
4-
| Problematic object instantiation: the outer M.this and arg 1 are not fully initialized. Calling trace:
5-
| -> class N(d: D) extends M(d) { [ secondary-ctor4.scala:59 ]
6-
| ^
7-
| -> def this(d: D) = { [ secondary-ctor4.scala:7 ]
8-
| ^
9-
| -> new A(new B(new D)) // error [ secondary-ctor4.scala:42 ]
10-
| ^^^^^
11-
| -> class D { [ secondary-ctor4.scala:52 ]
12-
| ^
13-
| -> val c = new C(b, 5) // error [ secondary-ctor4.scala:54 ]
14-
| ^^^^^^^^^^^
4+
| Problematic object instantiation: arg 1 is not fully initialized. Calling trace:
5+
| -> class D { [ secondary-ctor4.scala:52 ]
6+
| ^
7+
| -> val c = new C(b, 5) // error [ secondary-ctor4.scala:54 ]
8+
| ^^^^^^^^^^^
159
|
16-
| It leads to the following error during object initialization:
17-
| Access field on a value with an unknown initialization status. Calling trace:
18-
| -> def this(b: B, x: Int) = this(b) [ secondary-ctor4.scala:49 ]
19-
| ^^^^^^^
20-
| -> class C(b: B) extends A(b) with T { [ secondary-ctor4.scala:48 ]
21-
| ^
22-
| -> def this(b: B) = { [ secondary-ctor4.scala:17 ]
23-
| ^
24-
| -> Inner().foo() [ secondary-ctor4.scala:26 ]
25-
| ^^^^^^^
26-
| -> class Inner() { [ secondary-ctor4.scala:21 ]
27-
| ^
28-
| -> println(b.n) [ secondary-ctor4.scala:23 ]
29-
| ^^^
10+
| It leads to the following error during object initialization:
11+
| Access field on a value with an unknown initialization status. Calling trace:
12+
| -> def this(b: B, x: Int) = this(b) [ secondary-ctor4.scala:49 ]
13+
| ^^^^^^^
14+
| -> class C(b: B) extends A(b) with T { [ secondary-ctor4.scala:48 ]
15+
| ^
16+
| -> def this(b: B) = { [ secondary-ctor4.scala:17 ]
17+
| ^
18+
| -> Inner().foo() [ secondary-ctor4.scala:26 ]
19+
| ^^^^^^^
20+
| -> class Inner() { [ secondary-ctor4.scala:21 ]
21+
| ^
22+
| -> println(b.n) [ secondary-ctor4.scala:23 ]
23+
| ^^^
3024
-- Error: tests/init/neg/secondary-ctor4.scala:42:4 --------------------------------------------------------------------
3125
42 | new A(new B(new D)) // error
3226
| ^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)