Skip to content

Commit

Permalink
Backport "Fix #19202: Passing NotNullInfos to a mutable field of a Co…
Browse files Browse the repository at this point in the history
…mpleter" to LTS (#20841)

Backports #19463 to the LTS branch.

PR submitted by the release tooling.
[skip ci]
  • Loading branch information
WojciechMazur authored Jun 28, 2024
2 parents 0fd4aae + da600b6 commit 2152d15
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 4 deletions.
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import parsing.JavaParsers.JavaParser
import parsing.Parsers.Parser
import Annotations.*
import Inferencing.*
import Nullables.*
import transform.ValueClasses.*
import TypeErasure.erasure
import reporting.*
Expand Down Expand Up @@ -781,12 +782,19 @@ class Namer { typer: Typer =>

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

/** Stores the latest NotNullInfos (updated by `setNotNullInfos`) */
private var myNotNullInfos: List[NotNullInfo] | Null = null

/** The context with which this completer was created */
given creationContext: Context = ictx
given creationContext[Dummy_so_its_a_def]: Context =
if myNotNullInfos == null then ictx else ictx.withNotNullInfos(myNotNullInfos.nn)

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

def setNotNullInfos(infos: List[NotNullInfo]): Unit =
myNotNullInfos = infos

protected def typeSig(sym: Symbol): Type = original match
case original: ValDef =>
if (sym.is(Module)) moduleValSig(sym)
Expand Down
5 changes: 2 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3297,12 +3297,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
mdef.getAttachment(SymOfTree) match {
case Some(sym) => sym.infoOrCompleter match {
case completer: Namer#Completer =>
if (completer.creationContext.notNullInfos ne ctx.notNullInfos)
if completer.creationContext.notNullInfos ne ctx.notNullInfos then
// The RHS of a val def should know about not null facts established
// in preceding statements (unless the DefTree is completed ahead of time,
// then it is impossible).
sym.info = Completer(completer.original)(
completer.creationContext.withNotNullInfos(ctx.notNullInfos))
completer.setNotNullInfos(ctx.notNullInfos)
true
case _ =>
// If it has been completed, then it must be because there is a forward reference
Expand Down
27 changes: 27 additions & 0 deletions tests/explicit-nulls/pos/i19202.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Test {
def test1(s: String | Null): Unit = {
if s == null then return

case class XXX()
}

def test2(s: String | Null): Unit = {
if s == "" then return

case class XXX()
}

def test3(s: String | Null): Unit = {
if s == null then return

case class XXX()
()
}

def test4(s: String | Null): String | Null = {
if s == null then return ""

case class XXX()
"xxx"
}
}
27 changes: 27 additions & 0 deletions tests/pos/i19202.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Test {
def test1(s: String): Unit = {
if s == null then return

case class XXX()
}

def test2(s: String): Unit = {
if s == "" then return

case class XXX()
}

def test3(s: String): Unit = {
if s == null then return

case class XXX()
()
}

def test4(s: String): String = {
if s == null then return ""

case class XXX()
"xxx"
}
}

0 comments on commit 2152d15

Please sign in to comment.