@@ -2135,14 +2135,18 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
21352135 case1
21362136 }
21372137 .asInstanceOf [List [CaseDef ]]
2138- assignType(cpy.Match (tree)(sel, cases1), sel, cases1).cast(pt)
2138+ var nni = sel.notNullInfo
2139+ if cases1.nonEmpty then nni = nni.seq(cases1.map(_.notNullInfo).reduce(_.alt(_)))
2140+ assignType(cpy.Match (tree)(sel, cases1), sel, cases1).cast(pt).withNotNullInfo(nni)
21392141 }
21402142
21412143 // Overridden in InlineTyper for inline matches
21422144 def typedMatchFinish (tree : untpd.Match , sel : Tree , wideSelType : Type , cases : List [untpd.CaseDef ], pt : Type )(using Context ): Tree = {
21432145 val cases1 = harmonic(harmonize, pt)(typedCases(cases, sel, wideSelType, pt.dropIfProto))
21442146 .asInstanceOf [List [CaseDef ]]
2145- assignType(cpy.Match (tree)(sel, cases1), sel, cases1)
2147+ var nni = sel.notNullInfo
2148+ if cases1.nonEmpty then nni = nni.seq(cases1.map(_.notNullInfo).reduce(_.alt(_)))
2149+ assignType(cpy.Match (tree)(sel, cases1), sel, cases1).withNotNullInfo(nni)
21462150 }
21472151
21482152 def typedCases (cases : List [untpd.CaseDef ], sel : Tree , wideSelType0 : Type , pt : Type )(using Context ): List [CaseDef ] =
@@ -2206,17 +2210,22 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
22062210 }
22072211 val pat1 = indexPattern(tree).transform(pat)
22082212 val guard1 = typedExpr(tree.guard, defn.BooleanType )
2209- 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)
22102216 if ctx.gadt.isNarrowing then
22112217 // Store GADT constraint to later retrieve it (in PostTyper, for now).
22122218 // GADT constraints are necessary to correctly check bounds of type app,
22132219 // see tests/pos/i12226 and issue #12226. It might be possible that this
22142220 // will end up taking too much memory. If it does, we should just limit
22152221 // how much GADT constraints we infer - it's always sound to infer less.
22162222 pat1.putAttachment(InferredGadtConstraints , ctx.gadt)
2217- if ( pt1.isValueType) // insert a cast if body does not conform to expected type if we disregard gadt bounds
2223+ if pt1.isValueType then // insert a cast if body does not conform to expected type if we disregard gadt bounds
22182224 body1 = body1.ensureConforms(pt1)(using originalCtx)
2219- assignType(cpy.CaseDef (tree)(pat1, guard1, body1), pat1, body1)
2225+ val nni = pat1.notNullInfo
2226+ .seq(guard1.notNullInfoIf(true ))
2227+ .seq(body1.notNullInfo)
2228+ assignType(cpy.CaseDef (tree)(pat1, guard1, body1), pat1, body1).withNotNullInfo(nni)
22202229 }
22212230
22222231 val pat1 = typedPattern(tree.pat, wideSelType)(using gadtCtx)
@@ -2321,13 +2330,27 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
23212330
23222331 def typedTry (tree : untpd.Try , pt : Type )(using Context ): Try = {
23232332 val expr2 :: cases2x = harmonic(harmonize, pt) {
2324- val cases1 = typedCases(tree.cases, EmptyTree , defn.ThrowableType , pt.dropIfProto)
2325- val expr1 = typed(addCanThrowCapabilities(tree.expr, cases1), pt.dropIfProto)
2333+ // We want to type check tree.expr first to comput NotNullInfo, but `addCanThrowCapabilities`
2334+ // uses the types of patterns in `tree.cases` to determine the capabilities.
2335+ // Hence, we create a copy of cases with empty body and type check that first, then type check
2336+ // the rest of the tree in order.
2337+ // It may seem that invalid references can be created if the type of the pattern contains
2338+ // type binds, but this is not a valid `CanThrow` capability (checked by `addCanThrowCapabilities`),
2339+ // so it is not a problem.
2340+ val casesEmptyBody1 = tree.cases.mapconserve(cpy.CaseDef (_)(body = EmptyTree ))
2341+ val casesEmptyBody2 = typedCases(casesEmptyBody1, EmptyTree , defn.ThrowableType , WildcardType )
2342+ val expr1 = typed(addCanThrowCapabilities(tree.expr, casesEmptyBody2), pt.dropIfProto)
2343+ val casesCtx = ctx.addNotNullInfo(expr1.notNullInfo.retractedInfo)
2344+ val cases1 = typedCases(tree.cases, EmptyTree , defn.ThrowableType , pt.dropIfProto)(using casesCtx)
23262345 expr1 :: cases1
23272346 }: @ unchecked
2328- val finalizer1 = typed(tree.finalizer, defn.UnitType )
23292347 val cases2 = cases2x.asInstanceOf [List [CaseDef ]]
2330- assignType(cpy.Try (tree)(expr2, cases2, finalizer1), expr2, cases2)
2348+
2349+ var nni = expr2.notNullInfo.retractedInfo
2350+ if cases2.nonEmpty then nni = nni.seq(cases2.map(_.notNullInfo.retractedInfo).reduce(_.alt(_)))
2351+ val finalizer1 = typed(tree.finalizer, defn.UnitType )(using ctx.addNotNullInfo(nni))
2352+ nni = nni.seq(finalizer1.notNullInfo)
2353+ assignType(cpy.Try (tree)(expr2, cases2, finalizer1), expr2, cases2).withNotNullInfo(nni)
23312354 }
23322355
23332356 def typedTry (tree : untpd.ParsedTry , pt : Type )(using Context ): Try =
0 commit comments