Skip to content

Commit 41e7d95

Browse files
authored
Make safe init checker skip global objects (#18906)
Decouple the checking of classes and global objects. The `Ysafe-init-global` flag can be used for checking global objects instead.
2 parents 5fb2299 + 3fac025 commit 41e7d95

File tree

13 files changed

+51
-43
lines changed

13 files changed

+51
-43
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1140,7 +1140,7 @@ object Semantic:
11401140
*/
11411141
def checkClasses(classes: List[ClassSymbol])(using Context): Unit =
11421142
given Cache.Data()
1143-
for classSym <- classes if isConcreteClass(classSym) do
1143+
for classSym <- classes if isConcreteClass(classSym) && !classSym.isStaticObject do
11441144
checkClass(classSym)
11451145

11461146
// ----- Semantic definition --------------------------------

tests/init-global/neg/i15883.scala

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
val a = b // error
2+
val b = 1

tests/init/neg/apply2.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
object O:
1+
class O:
22
case class A(b: B):
33
println(n)
44

tests/init/neg/final-fields.scala

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ trait U {
1212
val f2: Int
1313
}
1414

15-
object Test0 extends U {
15+
class Test0 extends U {
1616
final val f1 = 1
1717
final val f2 = 2
1818
final val f3 = f1 + f2
1919
val f4: 3 = f3
2020
}
2121

22-
object Test1 extends U {
22+
class Test1 extends U {
2323
final val f1 = 1
2424
final val f3 = f1 + f2
2525
final val f2 = 2
@@ -28,7 +28,7 @@ object Test1 extends U {
2828

2929
}
3030

31-
object Test extends T {
31+
class Test extends T {
3232
override final val f1 = /*super.f1*/ 1 + f2 // error
3333
override final val f2 = 2 // error
3434
override final val f3 = {println(3); 3} // error
@@ -37,7 +37,7 @@ object Test extends T {
3737
def g: 3 = { println("g"); 3 }
3838
final val x = g + 1
3939
def main(args: Array[String]): Unit = {
40-
Test0
41-
Test1
40+
new Test0
41+
new Test1
4242
}
4343
}

tests/init/neg/i12544.scala

+15-10
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@ enum Enum:
22
case Case
33
case Case2(x: Int)
44

5-
def g(b: Enum.B): Int = b.foo()
5+
class Outer:
6+
val e = new Enum2
67

7-
object Enum:
8-
object nested:
9-
val a: Enum = Case
8+
class Enum2:
9+
class nested:
10+
val a: Enum = Enum.Case
1011

11-
val b: Enum = f(nested.a)
12+
val b: Enum = f((new nested).a)
1213

13-
def f(e: Enum): Enum = e
14+
def f(e: Enum): Enum = e
1415

15-
class B() { def foo() = n + 1 }
16-
g(new B()) // error
17-
val n: Int = 10
16+
class B() { def foo() = n + 1 }
17+
def g(b: B): Int = b.foo()
18+
g(new B()) // error
19+
val n: Int = 10
1820

19-
@main def main(): Unit = println(Enum.b)
21+
@main def main(): Unit = {
22+
val o = new Outer
23+
print(o.e.b)
24+
}

tests/init/neg/i15883.scala

-2
This file was deleted.

tests/init/neg/i4031.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
object App {
1+
class App {
22
trait A { type L >: Any}
33
def upcast(a: A, x: Any): a.L = x
44
val p: A { type L <: Nothing } = p // error

tests/init/neg/inner30.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
object Scanners {
1+
class Scanners {
22
enum IndentWidth {
33
case Run(ch: Char, n: Int)
44
case Conc(l: IndentWidth, r: Run)

tests/init/neg/inner9.scala

+17-14
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1-
object Flags {
2-
class Inner {
3-
println(b)
4-
}
1+
class Outer:
2+
val flags = new Flags // error
53

6-
new Flags.Inner
4+
class Flags {
5+
class Inner {
6+
println(b)
7+
}
78

8-
val a = this.b + 3
9-
val b = 5 // error
10-
}
9+
new flags.Inner
1110

12-
object Flags2 {
13-
class Inner {
14-
println(b)
11+
val a = this.b + 3
12+
val b = 5 // error
1513
}
1614

15+
class Flags2 {
16+
class Inner {
17+
println(b)
18+
}
19+
1720

18-
lazy val a = 3
19-
val b = 5
20-
}
21+
lazy val a = 3
22+
val b = 5
23+
}

tests/init/neg/leak-warm.check

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
19 | val l2 = l.map(_.m()) // error
33
| ^^^^^^^^^^^^
44
| Call method method map on an uninitialized (Cold) object. Calling trace:
5-
| ├── object leakWarm { [ leak-warm.scala:1 ]
5+
| ├── class leakWarm { [ leak-warm.scala:1 ]
66
| │ ^
77
| └── val l2 = l.map(_.m()) // error [ leak-warm.scala:19 ]
88
| ^^^^^^^^^^^^

tests/init/neg/leak-warm.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
object leakWarm {
1+
class leakWarm {
22
abstract class A(tag: Int) {
33
class B(x: Int) {
44
val y = x

tests/init/neg/t3273.check

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
-- Error: tests/init/neg/t3273.scala:4:42 ------------------------------------------------------------------------------
22
4 | val num1: LazyList[Int] = 1 #:: num1.map(_ + 1) // error
33
| ^^^^^^^^^^^^^^^
4-
|Could not verify that the method argument is transitively initialized (Hot). It was found to be a function where "this" is (the original object of type (object Test) where initialization checking started). Only transitively initialized arguments may be passed to methods (except constructors). Calling trace:
5-
|├── object Test { [ t3273.scala:3 ]
4+
|Could not verify that the method argument is transitively initialized (Hot). It was found to be a function where "this" is (the original object of type (class Test) where initialization checking started). Only transitively initialized arguments may be passed to methods (except constructors). Calling trace:
5+
|├── class Test { [ t3273.scala:3 ]
66
|│ ^
77
|└── val num1: LazyList[Int] = 1 #:: num1.map(_ + 1) // error [ t3273.scala:4 ]
88
| ^^^^^^^^^^^^^^^
@@ -14,13 +14,13 @@
1414
-- Error: tests/init/neg/t3273.scala:5:61 ------------------------------------------------------------------------------
1515
5 | val num2: LazyList[Int] = 1 #:: num2.iterator.map(_ + 1).to(LazyList) // error
1616
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17-
|Could not verify that the method argument is transitively initialized (Hot). It was found to be a function where "this" is (the original object of type (object Test) where initialization checking started). Only transitively initialized arguments may be passed to methods (except constructors). Calling trace:
18-
|├── object Test { [ t3273.scala:3 ]
17+
|Could not verify that the method argument is transitively initialized (Hot). It was found to be a function where "this" is (the original object of type (class Test) where initialization checking started). Only transitively initialized arguments may be passed to methods (except constructors). Calling trace:
18+
|├── class Test { [ t3273.scala:3 ]
1919
|│ ^
2020
|└── val num2: LazyList[Int] = 1 #:: num2.iterator.map(_ + 1).to(LazyList) // error [ t3273.scala:5 ]
2121
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2222
|
2323
|Promoting the value to transitively initialized (Hot) failed due to the following problem:
2424
|Access non-initialized value num2. Promotion trace:
2525
|└── val num2: LazyList[Int] = 1 #:: num2.iterator.map(_ + 1).to(LazyList) // error [ t3273.scala:5 ]
26-
| ^^^^
26+
| ^^^^

tests/init/neg/t3273.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import scala.language.implicitConversions
22

3-
object Test {
3+
class Test {
44
val num1: LazyList[Int] = 1 #:: num1.map(_ + 1) // error
55
val num2: LazyList[Int] = 1 #:: num2.iterator.map(_ + 1).to(LazyList) // error
66

0 commit comments

Comments
 (0)