@@ -1000,7 +1000,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
10001000 untpd.unsplice(tree.expr).putAttachment(AscribedToUnit , ())
10011001 typed(tree.expr, underlyingTreeTpe.tpe.widenSkolem)
10021002 assignType(cpy.Typed (tree)(expr1, tpt), underlyingTreeTpe)
1003- .withNotNullInfo(expr1.notNullInfo)
10041003 }
10051004
10061005 if (untpd.isWildcardStarArg(tree)) {
@@ -1333,11 +1332,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
13331332
13341333 def thenPathInfo = cond1.notNullInfoIf(true ).seq(result.thenp.notNullInfo)
13351334 def elsePathInfo = cond1.notNullInfoIf(false ).seq(result.elsep.notNullInfo)
1336- result.withNotNullInfo(
1337- if result.thenp.tpe.isRef(defn.NothingClass ) then elsePathInfo
1338- else if result.elsep.tpe.isRef(defn.NothingClass ) then thenPathInfo
1339- else thenPathInfo.alt(elsePathInfo)
1340- )
1335+ result.withNotNullInfo(thenPathInfo.alt(elsePathInfo))
13411336 end typedIf
13421337
13431338 /** Decompose function prototype into a list of parameter prototypes and a result
@@ -1860,20 +1855,25 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
18601855 case1
18611856 }
18621857 .asInstanceOf [List [CaseDef ]]
1863- var nni = sel.notNullInfo
1864- if cases1.nonEmpty then nni = nni.seq(cases1.map(_.notNullInfo).reduce(_.alt(_)))
1865- assignType(cpy.Match (tree)(sel, cases1), sel, cases1).cast(pt).withNotNullInfo(nni)
1858+ assignType(cpy.Match (tree)(sel, cases1), sel, cases1).cast(pt)
1859+ .withNotNullInfo(notNullInfoFromCases(sel.notNullInfo, cases1))
18661860 }
18671861
18681862 // Overridden in InlineTyper for inline matches
18691863 def typedMatchFinish (tree : untpd.Match , sel : Tree , wideSelType : Type , cases : List [untpd.CaseDef ], pt : Type )(using Context ): Tree = {
18701864 val cases1 = harmonic(harmonize, pt)(typedCases(cases, sel, wideSelType, pt.dropIfProto))
18711865 .asInstanceOf [List [CaseDef ]]
1872- var nni = sel.notNullInfo
1873- if cases1.nonEmpty then nni = nni.seq(cases1.map(_.notNullInfo).reduce(_.alt(_)))
1874- assignType(cpy.Match (tree)(sel, cases1), sel, cases1).withNotNullInfo(nni)
1866+ assignType(cpy.Match (tree)(sel, cases1), sel, cases1)
1867+ .withNotNullInfo(notNullInfoFromCases(sel.notNullInfo, cases1))
18751868 }
18761869
1870+ private def notNullInfoFromCases (initInfo : NotNullInfo , cases : List [CaseDef ])(using Context ): NotNullInfo =
1871+ if cases.isEmpty then
1872+ // Empty cases is not allowed for match tree in the source code,
1873+ // but it can be generated by inlining: `tests/pos/i19198.scala`.
1874+ initInfo
1875+ else cases.map(_.notNullInfo).reduce(_.alt(_))
1876+
18771877 def typedCases (cases : List [untpd.CaseDef ], sel : Tree , wideSelType : Type , pt : Type )(using Context ): List [CaseDef ] =
18781878 var caseCtx = ctx
18791879 cases.mapconserve { cas =>
@@ -1960,7 +1960,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
19601960 def typedLabeled (tree : untpd.Labeled )(using Context ): Labeled = {
19611961 val bind1 = typedBind(tree.bind, WildcardType ).asInstanceOf [Bind ]
19621962 val expr1 = typed(tree.expr, bind1.symbol.info)
1963- assignType(cpy.Labeled (tree)(bind1, expr1))
1963+ assignType(cpy.Labeled (tree)(bind1, expr1)).withNotNullInfo(expr1.notNullInfo.retractedInfo)
19641964 }
19651965
19661966 /** Type a case of a type match */
@@ -2010,7 +2010,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
20102010 // Hence no adaptation is possible, and we assume WildcardType as prototype.
20112011 (from, proto)
20122012 val expr1 = typedExpr(tree.expr orElse untpd.syntheticUnitLiteral.withSpan(tree.span), proto)
2013- assignType(cpy.Return (tree)(expr1, from))
2013+ assignType(cpy.Return (tree)(expr1, from)).withNotNullInfo(expr1.notNullInfo.terminatedInfo)
20142014 end typedReturn
20152015
20162016 def typedWhileDo (tree : untpd.WhileDo )(using Context ): Tree =
@@ -2051,7 +2051,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
20512051 val capabilityProof = caughtExceptions.reduce(OrType (_, _, true ))
20522052 untpd.Block (makeCanThrow(capabilityProof), expr)
20532053
2054- def typedTry (tree : untpd.Try , pt : Type )(using Context ): Try = {
2054+ def typedTry (tree : untpd.Try , pt : Type )(using Context ): Try =
2055+ var nnInfo = NotNullInfo .empty
20552056 val expr2 :: cases2x = harmonic(harmonize, pt) {
20562057 // We want to type check tree.expr first to comput NotNullInfo, but `addCanThrowCapabilities`
20572058 // uses the types of patterns in `tree.cases` to determine the capabilities.
@@ -2063,18 +2064,26 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
20632064 val casesEmptyBody1 = tree.cases.mapconserve(cpy.CaseDef (_)(body = EmptyTree ))
20642065 val casesEmptyBody2 = typedCases(casesEmptyBody1, EmptyTree , defn.ThrowableType , WildcardType )
20652066 val expr1 = typed(addCanThrowCapabilities(tree.expr, casesEmptyBody2), pt.dropIfProto)
2066- val casesCtx = ctx.addNotNullInfo(expr1.notNullInfo.retractedInfo)
2067+
2068+ // Since we don't know at which point the the exception is thrown in the body,
2069+ // we have to collect any reference that is once retracted.
2070+ nnInfo = expr1.notNullInfo.retractedInfo
2071+
2072+ val casesCtx = ctx.addNotNullInfo(nnInfo)
20672073 val cases1 = typedCases(tree.cases, EmptyTree , defn.ThrowableType , pt.dropIfProto)(using casesCtx)
20682074 expr1 :: cases1
20692075 }: @ unchecked
20702076 val cases2 = cases2x.asInstanceOf [List [CaseDef ]]
20712077
2072- var nni = expr2.notNullInfo.retractedInfo
2073- if cases2.nonEmpty then nni = nni.seq(cases2.map(_.notNullInfo.retractedInfo).reduce(_.alt(_)))
2074- val finalizer1 = typed(tree.finalizer, defn.UnitType )(using ctx.addNotNullInfo(nni))
2075- nni = nni.seq(finalizer1.notNullInfo)
2076- assignType(cpy.Try (tree)(expr2, cases2, finalizer1), expr2, cases2).withNotNullInfo(nni)
2077- }
2078+ // It is possible to have non-exhaustive cases, and some exceptions are thrown and not caught.
2079+ // Therefore, the code in the finalizer and after the try block can only rely on the retracted
2080+ // info from the cases' body.
2081+ if cases2.nonEmpty then
2082+ nnInfo = nnInfo.seq(cases2.map(_.notNullInfo.retractedInfo).reduce(_.alt(_)))
2083+
2084+ val finalizer1 = typed(tree.finalizer, defn.UnitType )(using ctx.addNotNullInfo(nnInfo))
2085+ nnInfo = nnInfo.seq(finalizer1.notNullInfo)
2086+ assignType(cpy.Try (tree)(expr2, cases2, finalizer1), expr2, cases2).withNotNullInfo(nnInfo)
20782087
20792088 def typedTry (tree : untpd.ParsedTry , pt : Type )(using Context ): Try =
20802089 val cases : List [untpd.CaseDef ] = tree.handler match
@@ -2088,15 +2097,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
20882097 def typedThrow (tree : untpd.Throw )(using Context ): Tree =
20892098 val expr1 = typed(tree.expr, defn.ThrowableType )
20902099 val cap = checkCanThrow(expr1.tpe.widen, tree.span)
2091- val res = Throw (expr1).withSpan(tree.span)
2100+ var res = Throw (expr1).withSpan(tree.span)
20922101 if Feature .ccEnabled && ! cap.isEmpty && ! ctx.isAfterTyper then
20932102 // Record access to the CanThrow capabulity recovered in `cap` by wrapping
2094- // the type of the `throw` (i.e. Nothing) in a `@requiresCapability` annotatoon .
2095- Typed (res,
2103+ // the type of the `throw` (i.e. Nothing) in a `@requiresCapability` annotation .
2104+ res = Typed (res,
20962105 TypeTree (
20972106 AnnotatedType (res.tpe,
20982107 Annotation (defn.RequiresCapabilityAnnot , cap, tree.span))))
2099- else res
2108+ res.withNotNullInfo(expr1.notNullInfo.terminatedInfo)
21002109
21012110 def typedSeqLiteral (tree : untpd.SeqLiteral , pt : Type )(using Context ): SeqLiteral = {
21022111 val elemProto = pt.stripNull.elemType match {
@@ -2507,6 +2516,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
25072516 val vdef1 = assignType(cpy.ValDef (vdef)(name, tpt1, rhs1), sym)
25082517 postProcessInfo(vdef1, sym)
25092518 vdef1.setDefTree
2519+ val nnInfo = rhs1.notNullInfo
2520+ vdef1.withNotNullInfo(if sym.is(Lazy ) then nnInfo.retractedInfo else nnInfo)
25102521 }
25112522
25122523 private def retractDefDef (sym : Symbol )(using Context ): Tree =
0 commit comments