@@ -1201,7 +1201,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
12011201 untpd.unsplice(tree.expr).putAttachment(AscribedToUnit , ())
12021202 typed(tree.expr, underlyingTreeTpe.tpe.widenSkolem)
12031203 assignType(cpy.Typed (tree)(expr1, tpt), underlyingTreeTpe)
1204- .withNotNullInfo(expr1.notNullInfo)
12051204 }
12061205
12071206 if (untpd.isWildcardStarArg(tree)) {
@@ -1551,11 +1550,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
15511550
15521551 def thenPathInfo = cond1.notNullInfoIf(true ).seq(result.thenp.notNullInfo)
15531552 def elsePathInfo = cond1.notNullInfoIf(false ).seq(result.elsep.notNullInfo)
1554- result.withNotNullInfo(
1555- if result.thenp.tpe.isRef(defn.NothingClass ) then elsePathInfo
1556- else if result.elsep.tpe.isRef(defn.NothingClass ) then thenPathInfo
1557- else thenPathInfo.alt(elsePathInfo)
1558- )
1553+ result.withNotNullInfo(thenPathInfo.alt(elsePathInfo))
15591554 end typedIf
15601555
15611556 /** Decompose function prototype into a list of parameter prototypes and a result
@@ -2139,20 +2134,25 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
21392134 case1
21402135 }
21412136 .asInstanceOf [List [CaseDef ]]
2142- var nni = sel.notNullInfo
2143- if cases1.nonEmpty then nni = nni.seq(cases1.map(_.notNullInfo).reduce(_.alt(_)))
2144- assignType(cpy.Match (tree)(sel, cases1), sel, cases1).cast(pt).withNotNullInfo(nni)
2137+ assignType(cpy.Match (tree)(sel, cases1), sel, cases1).cast(pt)
2138+ .withNotNullInfo(notNullInfoFromCases(sel.notNullInfo, cases1))
21452139 }
21462140
21472141 // Overridden in InlineTyper for inline matches
21482142 def typedMatchFinish (tree : untpd.Match , sel : Tree , wideSelType : Type , cases : List [untpd.CaseDef ], pt : Type )(using Context ): Tree = {
21492143 val cases1 = harmonic(harmonize, pt)(typedCases(cases, sel, wideSelType, pt.dropIfProto))
21502144 .asInstanceOf [List [CaseDef ]]
2151- var nni = sel.notNullInfo
2152- if cases1.nonEmpty then nni = nni.seq(cases1.map(_.notNullInfo).reduce(_.alt(_)))
2153- assignType(cpy.Match (tree)(sel, cases1), sel, cases1).withNotNullInfo(nni)
2145+ assignType(cpy.Match (tree)(sel, cases1), sel, cases1)
2146+ .withNotNullInfo(notNullInfoFromCases(sel.notNullInfo, cases1))
21542147 }
21552148
2149+ private def notNullInfoFromCases (initInfo : NotNullInfo , cases : List [CaseDef ])(using Context ): NotNullInfo =
2150+ if cases.isEmpty then
2151+ // Empty cases is not allowed for match tree in the source code,
2152+ // but it can be generated by inlining: `tests/pos/i19198.scala`.
2153+ initInfo
2154+ else cases.map(_.notNullInfo).reduce(_.alt(_))
2155+
21562156 def typedCases (cases : List [untpd.CaseDef ], sel : Tree , wideSelType0 : Type , pt : Type )(using Context ): List [CaseDef ] =
21572157 var caseCtx = ctx
21582158 var wideSelType = wideSelType0
@@ -2241,7 +2241,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
22412241 def typedLabeled (tree : untpd.Labeled )(using Context ): Labeled = {
22422242 val bind1 = typedBind(tree.bind, WildcardType ).asInstanceOf [Bind ]
22432243 val expr1 = typed(tree.expr, bind1.symbol.info)
2244- assignType(cpy.Labeled (tree)(bind1, expr1))
2244+ assignType(cpy.Labeled (tree)(bind1, expr1)).withNotNullInfo(expr1.notNullInfo.retractedInfo)
22452245 }
22462246
22472247 /** Type a case of a type match */
@@ -2291,7 +2291,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
22912291 // Hence no adaptation is possible, and we assume WildcardType as prototype.
22922292 (from, proto)
22932293 val expr1 = typedExpr(tree.expr orElse untpd.syntheticUnitLiteral.withSpan(tree.span), proto)
2294- assignType(cpy.Return (tree)(expr1, from))
2294+ assignType(cpy.Return (tree)(expr1, from)).withNotNullInfo(expr1.notNullInfo.terminatedInfo)
22952295 end typedReturn
22962296
22972297 def typedWhileDo (tree : untpd.WhileDo )(using Context ): Tree =
@@ -2332,7 +2332,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
23322332 val capabilityProof = caughtExceptions.reduce(OrType (_, _, true ))
23332333 untpd.Block (makeCanThrow(capabilityProof), expr)
23342334
2335- def typedTry (tree : untpd.Try , pt : Type )(using Context ): Try = {
2335+ def typedTry (tree : untpd.Try , pt : Type )(using Context ): Try =
2336+ var nnInfo = NotNullInfo .empty
23362337 val expr2 :: cases2x = harmonic(harmonize, pt) {
23372338 // We want to type check tree.expr first to comput NotNullInfo, but `addCanThrowCapabilities`
23382339 // uses the types of patterns in `tree.cases` to determine the capabilities.
@@ -2344,18 +2345,26 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
23442345 val casesEmptyBody1 = tree.cases.mapconserve(cpy.CaseDef (_)(body = EmptyTree ))
23452346 val casesEmptyBody2 = typedCases(casesEmptyBody1, EmptyTree , defn.ThrowableType , WildcardType )
23462347 val expr1 = typed(addCanThrowCapabilities(tree.expr, casesEmptyBody2), pt.dropIfProto)
2347- val casesCtx = ctx.addNotNullInfo(expr1.notNullInfo.retractedInfo)
2348+
2349+ // Since we don't know at which point the the exception is thrown in the body,
2350+ // we have to collect any reference that is once retracted.
2351+ nnInfo = expr1.notNullInfo.retractedInfo
2352+
2353+ val casesCtx = ctx.addNotNullInfo(nnInfo)
23482354 val cases1 = typedCases(tree.cases, EmptyTree , defn.ThrowableType , pt.dropIfProto)(using casesCtx)
23492355 expr1 :: cases1
23502356 }: @ unchecked
23512357 val cases2 = cases2x.asInstanceOf [List [CaseDef ]]
23522358
2353- var nni = expr2.notNullInfo.retractedInfo
2354- if cases2.nonEmpty then nni = nni.seq(cases2.map(_.notNullInfo.retractedInfo).reduce(_.alt(_)))
2355- val finalizer1 = typed(tree.finalizer, defn.UnitType )(using ctx.addNotNullInfo(nni))
2356- nni = nni.seq(finalizer1.notNullInfo)
2357- assignType(cpy.Try (tree)(expr2, cases2, finalizer1), expr2, cases2).withNotNullInfo(nni)
2358- }
2359+ // It is possible to have non-exhaustive cases, and some exceptions are thrown and not caught.
2360+ // Therefore, the code in the finalizer and after the try block can only rely on the retracted
2361+ // info from the cases' body.
2362+ if cases2.nonEmpty then
2363+ nnInfo = nnInfo.seq(cases2.map(_.notNullInfo.retractedInfo).reduce(_.alt(_)))
2364+
2365+ val finalizer1 = typed(tree.finalizer, defn.UnitType )(using ctx.addNotNullInfo(nnInfo))
2366+ nnInfo = nnInfo.seq(finalizer1.notNullInfo)
2367+ assignType(cpy.Try (tree)(expr2, cases2, finalizer1), expr2, cases2).withNotNullInfo(nnInfo)
23592368
23602369 def typedTry (tree : untpd.ParsedTry , pt : Type )(using Context ): Try =
23612370 val cases : List [untpd.CaseDef ] = tree.handler match
@@ -2369,15 +2378,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
23692378 def typedThrow (tree : untpd.Throw )(using Context ): Tree =
23702379 val expr1 = typed(tree.expr, defn.ThrowableType )
23712380 val cap = checkCanThrow(expr1.tpe.widen, tree.span)
2372- val res = Throw (expr1).withSpan(tree.span)
2381+ var res = Throw (expr1).withSpan(tree.span)
23732382 if Feature .ccEnabled && ! cap.isEmpty && ! ctx.isAfterTyper then
23742383 // Record access to the CanThrow capabulity recovered in `cap` by wrapping
23752384 // the type of the `throw` (i.e. Nothing) in a `@requiresCapability` annotation.
2376- Typed (res,
2385+ res = Typed (res,
23772386 TypeTree (
23782387 AnnotatedType (res.tpe,
23792388 Annotation (defn.RequiresCapabilityAnnot , cap, tree.span))))
2380- else res
2389+ res.withNotNullInfo(expr1.notNullInfo.terminatedInfo)
23812390
23822391 def typedSeqLiteral (tree : untpd.SeqLiteral , pt : Type )(using Context ): SeqLiteral = {
23832392 val elemProto = pt.stripNull().elemType match {
@@ -2842,6 +2851,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
28422851 val vdef1 = assignType(cpy.ValDef (vdef)(name, tpt1, rhs1), sym)
28432852 postProcessInfo(vdef1, sym)
28442853 vdef1.setDefTree
2854+ val nnInfo = rhs1.notNullInfo
2855+ vdef1.withNotNullInfo(if sym.is(Lazy ) then nnInfo.retractedInfo else nnInfo)
28452856 }
28462857
28472858 private def retractDefDef (sym : Symbol )(using Context ): Tree =
0 commit comments