@@ -1856,14 +1856,18 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1856
1856
case1
1857
1857
}
1858
1858
.asInstanceOf [List [CaseDef ]]
1859
- assignType(cpy.Match (tree)(sel, cases1), sel, cases1).cast(pt)
1859
+ var nni = sel.notNullInfo
1860
+ if cases1.nonEmpty then nni = nni.seq(cases1.map(_.notNullInfo).reduce(_.alt(_)))
1861
+ assignType(cpy.Match (tree)(sel, cases1), sel, cases1).cast(pt).withNotNullInfo(nni)
1860
1862
}
1861
1863
1862
1864
// Overridden in InlineTyper for inline matches
1863
1865
def typedMatchFinish (tree : untpd.Match , sel : Tree , wideSelType : Type , cases : List [untpd.CaseDef ], pt : Type )(using Context ): Tree = {
1864
1866
val cases1 = harmonic(harmonize, pt)(typedCases(cases, sel, wideSelType, pt.dropIfProto))
1865
1867
.asInstanceOf [List [CaseDef ]]
1866
- assignType(cpy.Match (tree)(sel, cases1), sel, cases1)
1868
+ var nni = sel.notNullInfo
1869
+ if cases1.nonEmpty then nni = nni.seq(cases1.map(_.notNullInfo).reduce(_.alt(_)))
1870
+ assignType(cpy.Match (tree)(sel, cases1), sel, cases1).withNotNullInfo(nni)
1867
1871
}
1868
1872
1869
1873
def typedCases (cases : List [untpd.CaseDef ], sel : Tree , wideSelType : Type , pt : Type )(using Context ): List [CaseDef ] =
@@ -1925,17 +1929,22 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1925
1929
}
1926
1930
val pat1 = indexPattern(tree).transform(pat)
1927
1931
val guard1 = typedExpr(tree.guard, defn.BooleanType )
1928
- var body1 = ensureNoLocalRefs(typedExpr(tree.body, pt1), pt1, ctx.scope.toList)
1932
+ var body1 = ensureNoLocalRefs(
1933
+ typedExpr(tree.body, pt1)(using ctx.addNotNullInfo(guard1.notNullInfoIf(true ))),
1934
+ pt1, ctx.scope.toList)
1929
1935
if ctx.gadt.isNarrowing then
1930
1936
// Store GADT constraint to later retrieve it (in PostTyper, for now).
1931
1937
// GADT constraints are necessary to correctly check bounds of type app,
1932
1938
// see tests/pos/i12226 and issue #12226. It might be possible that this
1933
1939
// will end up taking too much memory. If it does, we should just limit
1934
1940
// how much GADT constraints we infer - it's always sound to infer less.
1935
1941
pat1.putAttachment(InferredGadtConstraints , ctx.gadt)
1936
- if ( pt1.isValueType) // insert a cast if body does not conform to expected type if we disregard gadt bounds
1942
+ if pt1.isValueType then // insert a cast if body does not conform to expected type if we disregard gadt bounds
1937
1943
body1 = body1.ensureConforms(pt1)(using originalCtx)
1938
- assignType(cpy.CaseDef (tree)(pat1, guard1, body1), pat1, body1)
1944
+ val nni = pat1.notNullInfo
1945
+ .seq(guard1.notNullInfoIf(true ))
1946
+ .seq(body1.notNullInfo)
1947
+ assignType(cpy.CaseDef (tree)(pat1, guard1, body1), pat1, body1).withNotNullInfo(nni)
1939
1948
}
1940
1949
1941
1950
val pat1 = typedPattern(tree.pat, wideSelType)(using gadtCtx)
@@ -2040,13 +2049,27 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2040
2049
2041
2050
def typedTry (tree : untpd.Try , pt : Type )(using Context ): Try = {
2042
2051
val expr2 :: cases2x = harmonic(harmonize, pt) {
2043
- val cases1 = typedCases(tree.cases, EmptyTree , defn.ThrowableType , pt.dropIfProto)
2044
- val expr1 = typed(addCanThrowCapabilities(tree.expr, cases1), pt.dropIfProto)
2052
+ // We want to type check tree.expr first to comput NotNullInfo, but `addCanThrowCapabilities`
2053
+ // uses the types of patterns in `tree.cases` to determine the capabilities.
2054
+ // Hence, we create a copy of cases with empty body and type check that first, then type check
2055
+ // the rest of the tree in order.
2056
+ // It may seem that invalid references can be created if the type of the pattern contains
2057
+ // type binds, but this is not a valid `CanThrow` capability (checked by `addCanThrowCapabilities`),
2058
+ // so it is not a problem.
2059
+ val casesEmptyBody1 = tree.cases.mapconserve(cpy.CaseDef (_)(body = EmptyTree ))
2060
+ val casesEmptyBody2 = typedCases(casesEmptyBody1, EmptyTree , defn.ThrowableType , WildcardType )
2061
+ val expr1 = typed(addCanThrowCapabilities(tree.expr, casesEmptyBody2), pt.dropIfProto)
2062
+ val casesCtx = ctx.addNotNullInfo(expr1.notNullInfo.retractedInfo)
2063
+ val cases1 = typedCases(tree.cases, EmptyTree , defn.ThrowableType , pt.dropIfProto)(using casesCtx)
2045
2064
expr1 :: cases1
2046
2065
}: @ unchecked
2047
- val finalizer1 = typed(tree.finalizer, defn.UnitType )
2048
2066
val cases2 = cases2x.asInstanceOf [List [CaseDef ]]
2049
- assignType(cpy.Try (tree)(expr2, cases2, finalizer1), expr2, cases2)
2067
+
2068
+ var nni = expr2.notNullInfo.retractedInfo
2069
+ if cases2.nonEmpty then nni = nni.seq(cases2.map(_.notNullInfo.retractedInfo).reduce(_.alt(_)))
2070
+ val finalizer1 = typed(tree.finalizer, defn.UnitType )(using ctx.addNotNullInfo(nni))
2071
+ nni = nni.seq(finalizer1.notNullInfo)
2072
+ assignType(cpy.Try (tree)(expr2, cases2, finalizer1), expr2, cases2).withNotNullInfo(nni)
2050
2073
}
2051
2074
2052
2075
def typedTry (tree : untpd.ParsedTry , pt : Type )(using Context ): Try =
0 commit comments