Skip to content

Commit 0b7a785

Browse files
authored
Fix #19202: Passing latest NotNullInfos to a mutable field of a Completer (#19463)
Fix #19202 by passing latest `NotNullInfos` to a mutable field of a `Completer`. Completing a `Def` requires the new NotNullInfos from previous statements. Originally, we created a new Completer with the new creation ctx in `adaptCreationContext`. However, we should not create a regular Completer for `TypeDef`s. This PR fixes the issue by creating a mutable field for NotNullInfos in Completer, and the field is updated in `adaptCreationContext` now.
2 parents eb41221 + 44e63a1 commit 0b7a785

File tree

4 files changed

+65
-4
lines changed

4 files changed

+65
-4
lines changed

compiler/src/dotty/tools/dotc/typer/Namer.scala

+9-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import parsing.JavaParsers.JavaParser
2222
import parsing.Parsers.Parser
2323
import Annotations.*
2424
import Inferencing.*
25+
import Nullables.*
2526
import transform.ValueClasses.*
2627
import TypeErasure.erasure
2728
import reporting.*
@@ -784,12 +785,19 @@ class Namer { typer: Typer =>
784785

785786
protected def localContext(owner: Symbol): FreshContext = ctx.fresh.setOwner(owner).setTree(original)
786787

788+
/** Stores the latest NotNullInfos (updated by `setNotNullInfos`) */
789+
private var myNotNullInfos: List[NotNullInfo] | Null = null
790+
787791
/** The context with which this completer was created */
788-
given creationContext: Context = ictx
792+
given creationContext[Dummy_so_its_a_def]: Context =
793+
if myNotNullInfos == null then ictx else ictx.withNotNullInfos(myNotNullInfos.nn)
789794

790795
// make sure testing contexts are not captured by completers
791796
assert(!ictx.reporter.isInstanceOf[ExploringReporter])
792797

798+
def setNotNullInfos(infos: List[NotNullInfo]): Unit =
799+
myNotNullInfos = infos
800+
793801
protected def typeSig(sym: Symbol): Type = original match
794802
case original: ValDef =>
795803
if (sym.is(Module)) moduleValSig(sym)

compiler/src/dotty/tools/dotc/typer/Typer.scala

+2-3
Original file line numberDiff line numberDiff line change
@@ -3361,12 +3361,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
33613361
mdef.getAttachment(SymOfTree) match {
33623362
case Some(sym) => sym.infoOrCompleter match {
33633363
case completer: Namer#Completer =>
3364-
if (completer.creationContext.notNullInfos ne ctx.notNullInfos)
3364+
if completer.creationContext.notNullInfos ne ctx.notNullInfos then
33653365
// The RHS of a val def should know about not null facts established
33663366
// in preceding statements (unless the DefTree is completed ahead of time,
33673367
// then it is impossible).
3368-
sym.info = Completer(completer.original)(
3369-
completer.creationContext.withNotNullInfos(ctx.notNullInfos))
3368+
completer.setNotNullInfos(ctx.notNullInfos)
33703369
true
33713370
case _ =>
33723371
// If it has been completed, then it must be because there is a forward reference

tests/explicit-nulls/pos/i19202.scala

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class Test {
2+
def test1(s: String | Null): Unit = {
3+
if s == null then return
4+
5+
case class XXX()
6+
}
7+
8+
def test2(s: String | Null): Unit = {
9+
if s == "" then return
10+
11+
case class XXX()
12+
}
13+
14+
def test3(s: String | Null): Unit = {
15+
if s == null then return
16+
17+
case class XXX()
18+
()
19+
}
20+
21+
def test4(s: String | Null): String | Null = {
22+
if s == null then return ""
23+
24+
case class XXX()
25+
"xxx"
26+
}
27+
}

tests/pos/i19202.scala

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class Test {
2+
def test1(s: String): Unit = {
3+
if s == null then return
4+
5+
case class XXX()
6+
}
7+
8+
def test2(s: String): Unit = {
9+
if s == "" then return
10+
11+
case class XXX()
12+
}
13+
14+
def test3(s: String): Unit = {
15+
if s == null then return
16+
17+
case class XXX()
18+
()
19+
}
20+
21+
def test4(s: String): String = {
22+
if s == null then return ""
23+
24+
case class XXX()
25+
"xxx"
26+
}
27+
}

0 commit comments

Comments
 (0)