Skip to content

Commit 7f92b53

Browse files
committed
Fix typing cases
1 parent 7674fef commit 7f92b53

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -2210,7 +2210,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
22102210
}
22112211
val pat1 = indexPattern(tree).transform(pat)
22122212
val guard1 = typedExpr(tree.guard, defn.BooleanType)
2213-
var body1 = ensureNoLocalRefs(typedExpr(tree.body, pt1), pt1, ctx.scope.toList)
2213+
var body1 = ensureNoLocalRefs(
2214+
typedExpr(tree.body, pt1)(using ctx.addNotNullInfo(guard1.notNullInfoIf(true))),
2215+
pt1, ctx.scope.toList)
22142216
if ctx.gadt.isNarrowing then
22152217
// Store GADT constraint to later retrieve it (in PostTyper, for now).
22162218
// GADT constraints are necessary to correctly check bounds of type app,
@@ -2221,7 +2223,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
22212223
if pt1.isValueType then // insert a cast if body does not conform to expected type if we disregard gadt bounds
22222224
body1 = body1.ensureConforms(pt1)(using originalCtx)
22232225
val nni = pat1.notNullInfo
2224-
.seq(guard1.notNullInfoIf(false).alt(guard1.notNullInfoIf(true)))
2226+
.seq(guard1.notNullInfoIf(true))
22252227
.seq(body1.notNullInfo)
22262228
assignType(cpy.CaseDef(tree)(pat1, guard1, body1), pat1, body1).withNotNullInfo(nni)
22272229
}
@@ -2343,7 +2345,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
23432345
val cases2 = cases2x.asInstanceOf[List[CaseDef]]
23442346

23452347
var nni = expr2.notNullInfo.retractedInfo
2346-
if cases2.nonEmpty then nni = nni.seq(cases2.map(_.notNullInfo).reduce(_.alt(_)))
2348+
if cases2.nonEmpty then nni = nni.seq(cases2.map(_.notNullInfo.retractedInfo).reduce(_.alt(_)))
23472349
val finalizer1 = typed(tree.finalizer, defn.UnitType)(using ctx.addNotNullInfo(nni))
23482350
nni = nni.seq(finalizer1.notNullInfo)
23492351
assignType(cpy.Try(tree)(expr2, cases2, finalizer1), expr2, cases2).withNotNullInfo(nni)

tests/explicit-nulls/neg/i21380b.scala

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,11 @@ def test2(i: Int) =
1111
i match
1212
case 1 => x = "1"
1313
case _ => x = " "
14-
x.replace("", "") // ok
14+
x.replace("", "") // ok
15+
16+
def test3(i: Int) =
17+
var x: String | Null = null
18+
i match
19+
case 1 if x != null => ()
20+
case _ => x = " "
21+
x.trim() // ok

tests/explicit-nulls/neg/i21380c.scala

+12-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,15 @@ def test4: Int =
3131
catch
3232
case npe: NullPointerException => x = ""
3333
case _ => x = ""
34-
x.length // ok
34+
x.length // error
35+
// Although the catch block here is exhaustive,
36+
// it is possible that the exception is thrown and not caught.
37+
// Therefore, the code after the try block can only rely on the retracted info.
38+
39+
def test5: Int =
40+
var x: String | Null = null
41+
try
42+
x = ""
43+
throw new Exception()
44+
catch
45+
case npe: NullPointerException => val i: Int = x.length // error

0 commit comments

Comments
 (0)