Skip to content

Commit

Permalink
Fix typing cases
Browse files Browse the repository at this point in the history
  • Loading branch information
noti0na1 committed Aug 28, 2024
1 parent ab9bb2d commit 1a628ff
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
8 changes: 5 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2195,7 +2195,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
}
val pat1 = indexPattern(tree).transform(pat)
val guard1 = typedExpr(tree.guard, defn.BooleanType)
var body1 = ensureNoLocalRefs(typedExpr(tree.body, pt1), pt1, ctx.scope.toList)
var body1 = ensureNoLocalRefs(
typedExpr(tree.body, pt1)(using ctx.addNotNullInfo(guard1.notNullInfoIf(true))),
pt1, ctx.scope.toList)
if ctx.gadt.isNarrowing then
// Store GADT constraint to later retrieve it (in PostTyper, for now).
// GADT constraints are necessary to correctly check bounds of type app,
Expand All @@ -2206,7 +2208,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
if pt1.isValueType then // insert a cast if body does not conform to expected type if we disregard gadt bounds
body1 = body1.ensureConforms(pt1)(using originalCtx)
val nni = pat1.notNullInfo
.seq(guard1.notNullInfoIf(false).alt(guard1.notNullInfoIf(true)))
.seq(guard1.notNullInfoIf(true))
.seq(body1.notNullInfo)
assignType(cpy.CaseDef(tree)(pat1, guard1, body1), pat1, body1).withNotNullInfo(nni)
}
Expand Down Expand Up @@ -2328,7 +2330,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
val cases2 = cases2x.asInstanceOf[List[CaseDef]]

var nni = expr2.notNullInfo.retractedInfo
if cases2.nonEmpty then nni = nni.seq(cases2.map(_.notNullInfo).reduce(_.alt(_)))
if cases2.nonEmpty then nni = nni.seq(cases2.map(_.notNullInfo.retractedInfo).reduce(_.alt(_)))
val finalizer1 = typed(tree.finalizer, defn.UnitType)(using ctx.addNotNullInfo(nni))
nni = nni.seq(finalizer1.notNullInfo)
assignType(cpy.Try(tree)(expr2, cases2, finalizer1), expr2, cases2).withNotNullInfo(nni)
Expand Down
9 changes: 8 additions & 1 deletion tests/explicit-nulls/neg/i21380b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@ def test2(i: Int) =
i match
case 1 => x = "1"
case _ => x = " "
x.replace("", "") // ok
x.replace("", "") // ok

def test3(i: Int) =
var x: String | Null = null
i match
case 1 if x != null => ()
case _ => x = " "
x.trim() // ok
13 changes: 12 additions & 1 deletion tests/explicit-nulls/neg/i21380c.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,15 @@ def test4: Int =
catch
case npe: NullPointerException => x = ""
case _ => x = ""
x.length // ok
x.length // error
// Although the catch block here is exhaustive,
// it is possible that the exception is thrown and not caught.
// Therefore, the code after the try block can only rely on the retracted info.

def test5: Int =
var x: String | Null = null
try
x = ""
throw new Exception()
catch
case npe: NullPointerException => val i: Int = x.length // error

0 comments on commit 1a628ff

Please sign in to comment.