Skip to content

Refactor the abstract domain of global init checker to compile http4s #22179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
386 changes: 288 additions & 98 deletions compiler/src/dotty/tools/dotc/transform/init/Objects.scala

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
## See #18882
patmat.scala
t9312.scala
unapplySeq-implicit-arg.scala
unapplySeq-implicit-arg2.scala
unapplySeq-implicit-arg3.scala
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our goal is to move all tests shown here to warn-tasty since they rely on tasty, but they also trigger some warnings in scala2 library which is hard to document

ScalaCheck.scala
mutable-read8.scala
TypeCast.scala
Expand Down
4 changes: 4 additions & 0 deletions compiler/test/dotty/tools/dotc/CompilationTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ class CompilationTests {
implicit val testGroup: TestGroup = TestGroup("checkInitGlobal")
compileFilesInDir("tests/init-global/warn", defaultOptions.and("-Ysafe-init-global"), FileFilter.exclude(TestSources.negInitGlobalScala2LibraryTastyExcludelisted)).checkWarnings()
compileFilesInDir("tests/init-global/pos", defaultOptions.and("-Ysafe-init-global", "-Xfatal-warnings"), FileFilter.exclude(TestSources.posInitGlobalScala2LibraryTastyExcludelisted)).checkCompile()
if Properties.usingScalaLibraryTasty && !Properties.usingScalaLibraryCCTasty then
compileFilesInDir("tests/init-global/warn-tasty", defaultOptions.and("-Ysafe-init-global"), FileFilter.exclude(TestSources.negInitGlobalScala2LibraryTastyExcludelisted)).checkWarnings()
compileFilesInDir("tests/init-global/pos-tasty", defaultOptions.and("-Ysafe-init-global", "-Xfatal-warnings"), FileFilter.exclude(TestSources.posInitGlobalScala2LibraryTastyExcludelisted)).checkCompile()
end if
}

// initialization tests
Expand Down
5 changes: 5 additions & 0 deletions tests/init-global/pos/arithmetic.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object A:
val a = f(10)
val b = -a
val c = b.toDouble
def f(x: Int) = x * 2 + 5
16 changes: 16 additions & 0 deletions tests/init-global/pos/packageObjectStringInterpolator.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package p
package object a {
val b = 10
implicit class CI(s: StringContext) {
def ci(args: Any*) = 10
}
}

import p.a._

object A:
val f = b // p.a(ObjectRef(p.a)).b
def foo(s: String): String = s
val f1 = ci"a" // => p.a(Package(p).select(a)).CI(StringContext"a").ci()


Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-- Warning: tests/init-global/warn/unapplySeq-implicit-arg.scala:11:20 -------------------------------------------------
-- Warning: tests/init-global/warn-tasty/unapplySeq-implicit-arg.scala:11:20 -------------------------------------------
11 | val i2: Int = Seq(i2) match // warn
| ^^
| Access uninitialized field value i2. Calling trace:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-- Warning: tests/init-global/warn/unapplySeq-implicit-arg2.scala:4:9 --------------------------------------------------
-- Warning: tests/init-global/warn-tasty/unapplySeq-implicit-arg2.scala:4:9 --------------------------------------------
4 | Some(i1 +: seqi) // warn
| ^^
|Access uninitialized field value i1. Calling trace:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-- Warning: tests/init-global/warn/unapplySeq-implicit-arg3.scala:3:27 -------------------------------------------------
-- Warning: tests/init-global/warn-tasty/unapplySeq-implicit-arg3.scala:3:27 -------------------------------------------
3 | def m(seq: Seq[Int]) = i1 +: seq // warn
| ^^
|Access uninitialized field value i1. Calling trace:
Expand Down
6 changes: 3 additions & 3 deletions tests/init-global/warn/mutable-array.check
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
-- Warning: tests/init-global/warn/mutable-array.scala:8:19 ------------------------------------------------------------
8 | val x: Int = box.value // warn
-- Warning: tests/init-global/warn/mutable-array.scala:9:19 ------------------------------------------------------------
9 | val x: Int = box.value // warn
| ^^^^^^^^^
|Reading mutable state of object A during initialization of object B.
|Reading mutable state of other static objects is forbidden as it breaks initialization-time irrelevance. Calling trace:
|├── object B: [ mutable-array.scala:5 ]
|│ ^
|└── val x: Int = box.value // warn [ mutable-array.scala:8 ]
|└── val x: Int = box.value // warn [ mutable-array.scala:9 ]
| ^^^^^^^^^
|The mutable state is created through:
|├── object A: [ mutable-array.scala:1 ]
Expand Down
3 changes: 2 additions & 1 deletion tests/init-global/warn/mutable-array.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ object A:
val box: Box = new Box(0)

object B:
val boxes: Array[A.Box] = Array(A.box)
val boxes = new Array[A.Box](2)
boxes(0) = A.box
val box: A.Box = boxes(0)
val x: Int = box.value // warn
20 changes: 20 additions & 0 deletions tests/init-global/warn/widen.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- Warning: tests/init-global/warn/widen.scala:13:13 -------------------------------------------------------------------
13 | t.foo() // warn
| ^^^^^^^
| Value is unknown to the checker due to widening. Calling trace:
| ├── object O: [ widen.scala:9 ]
| │ ^
| ├── val a = bar(new C) [ widen.scala:20 ]
| │ ^^^^^^^^^^
| ├── def bar(t: T) = { [ widen.scala:10 ]
| │ ^
| ├── new A [ widen.scala:18 ]
| │ ^^^^^
| ├── class A { [ widen.scala:11 ]
| │ ^
| ├── val b = new B [ widen.scala:16 ]
| │ ^^^^^
| ├── class B { [ widen.scala:12 ]
| │ ^
| └── t.foo() // warn [ widen.scala:13 ]
| ^^^^^^^
20 changes: 20 additions & 0 deletions tests/init-global/warn/widen.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
trait T {
def foo(): Unit
}

class C extends T {
def foo(): Unit = println("Calling foo on an instance of C!")
}

object O:
def bar(t: T) = {
class A {
class B {
t.foo() // warn
}

val b = new B
}
new A
}
val a = bar(new C)
Loading