Skip to content

Commit 1a628ff

Browse files
committed
Fix typing cases
1 parent ab9bb2d commit 1a628ff

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

Diff for: compiler/src/dotty/tools/dotc/typer/Typer.scala

+5-3
Original file line numberDiff line numberDiff line change
@@ -2195,7 +2195,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
21952195
}
21962196
val pat1 = indexPattern(tree).transform(pat)
21972197
val guard1 = typedExpr(tree.guard, defn.BooleanType)
2198-
var body1 = ensureNoLocalRefs(typedExpr(tree.body, pt1), pt1, ctx.scope.toList)
2198+
var body1 = ensureNoLocalRefs(
2199+
typedExpr(tree.body, pt1)(using ctx.addNotNullInfo(guard1.notNullInfoIf(true))),
2200+
pt1, ctx.scope.toList)
21992201
if ctx.gadt.isNarrowing then
22002202
// Store GADT constraint to later retrieve it (in PostTyper, for now).
22012203
// GADT constraints are necessary to correctly check bounds of type app,
@@ -2206,7 +2208,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
22062208
if pt1.isValueType then // insert a cast if body does not conform to expected type if we disregard gadt bounds
22072209
body1 = body1.ensureConforms(pt1)(using originalCtx)
22082210
val nni = pat1.notNullInfo
2209-
.seq(guard1.notNullInfoIf(false).alt(guard1.notNullInfoIf(true)))
2211+
.seq(guard1.notNullInfoIf(true))
22102212
.seq(body1.notNullInfo)
22112213
assignType(cpy.CaseDef(tree)(pat1, guard1, body1), pat1, body1).withNotNullInfo(nni)
22122214
}
@@ -2328,7 +2330,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
23282330
val cases2 = cases2x.asInstanceOf[List[CaseDef]]
23292331

23302332
var nni = expr2.notNullInfo.retractedInfo
2331-
if cases2.nonEmpty then nni = nni.seq(cases2.map(_.notNullInfo).reduce(_.alt(_)))
2333+
if cases2.nonEmpty then nni = nni.seq(cases2.map(_.notNullInfo.retractedInfo).reduce(_.alt(_)))
23322334
val finalizer1 = typed(tree.finalizer, defn.UnitType)(using ctx.addNotNullInfo(nni))
23332335
nni = nni.seq(finalizer1.notNullInfo)
23342336
assignType(cpy.Try(tree)(expr2, cases2, finalizer1), expr2, cases2).withNotNullInfo(nni)

Diff for: 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

Diff for: 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)