Skip to content

Commit

Permalink
Consider cases with Nothing type
Browse files Browse the repository at this point in the history
  • Loading branch information
noti0na1 committed Oct 11, 2024
1 parent 273c867 commit 0a319be
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 8 deletions.
24 changes: 16 additions & 8 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1543,9 +1543,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
def thenPathInfo = cond1.notNullInfoIf(true).seq(result.thenp.notNullInfo)
def elsePathInfo = cond1.notNullInfoIf(false).seq(result.elsep.notNullInfo)
result.withNotNullInfo(
if result.thenp.tpe.isRef(defn.NothingClass) then
if result.thenp.tpe.isNothingType then
elsePathInfo.withRetracted(thenPathInfo)
else if result.elsep.tpe.isRef(defn.NothingClass) then
else if result.elsep.tpe.isNothingType then
thenPathInfo.withRetracted(elsePathInfo)
else thenPathInfo.alt(elsePathInfo)
)
Expand Down Expand Up @@ -2134,20 +2134,28 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
case1
}
.asInstanceOf[List[CaseDef]]
var nni = sel.notNullInfo
if cases1.nonEmpty then nni = nni.seq(cases1.map(_.notNullInfo).reduce(_.alt(_)))
assignType(cpy.Match(tree)(sel, cases1), sel, cases1).cast(pt).withNotNullInfo(nni)
assignType(cpy.Match(tree)(sel, cases1), sel, cases1).cast(pt)
.withNotNullInfo(notNullInfoFromCases(sel.notNullInfo, cases1))
}

// Overridden in InlineTyper for inline matches
def typedMatchFinish(tree: untpd.Match, sel: Tree, wideSelType: Type, cases: List[untpd.CaseDef], pt: Type)(using Context): Tree = {
val cases1 = harmonic(harmonize, pt)(typedCases(cases, sel, wideSelType, pt.dropIfProto))
.asInstanceOf[List[CaseDef]]
var nnInfo = sel.notNullInfo
if cases1.nonEmpty then nnInfo = nnInfo.seq(cases1.map(_.notNullInfo).reduce(_.alt(_)))
assignType(cpy.Match(tree)(sel, cases1), sel, cases1).withNotNullInfo(nnInfo)
assignType(cpy.Match(tree)(sel, cases1), sel, cases1)
.withNotNullInfo(notNullInfoFromCases(sel.notNullInfo, cases1))
}

private def notNullInfoFromCases(initInfo: NotNullInfo, cases: List[CaseDef])(using Context): NotNullInfo =
var nnInfo = initInfo
if cases.nonEmpty then
val (nothingCases, normalCases) = cases.partition(_.body.tpe.isNothingType)
nnInfo = nothingCases.foldLeft(nnInfo):
(nni, c) => nni.withRetracted(c.notNullInfo)
if normalCases.nonEmpty then
nnInfo = nnInfo.seq(normalCases.map(_.notNullInfo).reduce(_.alt(_)))
nnInfo

def typedCases(cases: List[untpd.CaseDef], sel: Tree, wideSelType0: Type, pt: Type)(using Context): List[CaseDef] =
var caseCtx = ctx
var wideSelType = wideSelType0
Expand Down
18 changes: 18 additions & 0 deletions tests/explicit-nulls/neg/i21380b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,22 @@ def test3(i: Int) =
i match
case 1 if x != null => ()
case _ => x = " "
x.trim() // ok

def test4(i: Int) =
var x: String | Null = null
var y: String | Null = null
i match
case 1 => x = "1"
case _ => y = " "
x.trim() // error

def test5(i: Int): String =
var x: String | Null = null
var y: String | Null = null
i match
case 1 => x = "1"
case _ =>
y = " "
return y
x.trim() // ok

0 comments on commit 0a319be

Please sign in to comment.