@@ -2436,29 +2436,36 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
24362436 val capabilityProof = caughtExceptions.reduce(OrType (_, _, true ))
24372437 untpd.Block (makeCanThrow(capabilityProof), expr)
24382438
2439- /** Graphic explaination of NotNullInfo logic:
2439+ /** Graphic explanation of NotNullInfo logic:
24402440 * Leftward exit indicates exceptional case
24412441 * Downward exit indicates normal case
24422442 *
2443- * ┌─────┐ α.retractedInfo
2443+ * ┌─────┐
24442444 * │ Try ├─────┬────────┬─────┐
24452445 * └──┬──┘ ▼ ▼ │
24462446 * │ ┌───────┐┌───────┐ │
2447- * α │ │ Catch ││ Catch ├─┤
2447+ * │ │ Catch ││ Catch ├─┤
24482448 * │ └───┬───┘└───┬───┘ │
2449- * │ β │ │ │
2450- * └──┬─────┴────────┘ │
2451- * │ γ = α.alt(β) │ ε = β.retractedInfo
2452- * ▼ ▼
2453- * ┌─────────┐ ┌─────────┐
2454- * δ = type(ε)│ Finally ├──────┐ │ Finally ├─────────┐
2455- * └────┬────┘ │ └────┬────┘ │
2456- * │ │ ▼ ▼
2457- * │ γ.seq(δ) └──────────────────────────►
2458- * ▼ ε.seq(δ)
2459- * We choose to use γ.seq(δ) as the NotNullInfo of the
2460- * overall tree if all the catch cases have NothingType,
2461- * otherwise we use ε.seq(δ).
2449+ * └─┬──────┴────────┘ │
2450+ * ▼ ▼
2451+ * ┌─────────┐ ┌─────────┐
2452+ * │ Finally ├──────┐ │ Finally ├──┐
2453+ * └────┬────┘ │ └────┬────┘ │
2454+ * ▼ └─────────┴───────┴─►
2455+ * α = tryEffect
2456+ * λ = α.retracted.seq.(catchEffects.reduce.alt)
2457+ * β = α.alt(λ)
2458+ * finallyCtx = β.retracted
2459+ * δ = finallyEffect
2460+ * resultNNInfo = β.seq(δ).alt(β.retracted.seq(δ).seq(empty.terminated))
2461+ *
2462+ * It is sufficient to type finally once provided that we type it in a context
2463+ * that considers all the paths before it that reach the finally. Since the NNinfo
2464+ * that we get from typing finally summarizes the effect of the finally, we can
2465+ * type the finally once and use the obtained NN info twice: once sequenced
2466+ * with β (normalNNInfo) and once sequenced with β.retractedInfo but post-sequenced
2467+ * by empty.terminated (to indicate that this path does not reach the code after
2468+ * the try-catch-finally).
24622469 */
24632470 def typedTry (tree : untpd.Try , pt : Type )(using Context ): Try =
24642471 val expr2 :: cases2x = harmonic(harmonize, pt) {
@@ -2478,25 +2485,21 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
24782485 expr1 :: cases1
24792486 }: @ unchecked
24802487 val cases2 = cases2x.asInstanceOf [List [CaseDef ]]
2481- val tryNNInfo = expr2.notNullInfo
2488+ val exprNNInfo = expr2.notNullInfo
24822489 // It is possible to have non-exhaustive cases, and some exceptions are thrown and not caught.
24832490 // Therefore, the code in the finalizer and after the try block can only rely on the retracted
24842491 // info from the cases' body.
2485- val catchNNInfo = if cases2.nonEmpty then
2486- tryNNInfo .seq(cases2.map(_.notNullInfo).reduce(_.alt(_)))
2492+ val casesNNInfo = if cases2.nonEmpty then
2493+ exprNNInfo.retractedInfo .seq(cases2.map(_.notNullInfo).reduce(_.alt(_)))
24872494 else
2488- NotNullInfo .empty
2489- val normalResolveNNInfo = tryNNInfo.alt(catchNNInfo)
2490- val exceptionalResolveNNInfo = catchNNInfo.retractedInfo
2491-
2492- val finalizer1 = typed(tree.finalizer, defn.UnitType )(using ctx.addNotNullInfo(exceptionalResolveNNInfo))
2493- val normalFinalNNInfo = normalResolveNNInfo.seq(finalizer1.notNullInfo)
2494- val exceptionalFinalNNInfo = exceptionalResolveNNInfo.seq(finalizer1.notNullInfo)
2495- val resNNInfo =
2496- if (cases2.forall(_.tpe == defn.NothingType )) then
2497- normalFinalNNInfo
2498- else
2499- exceptionalFinalNNInfo
2495+ NotNullInfo .empty.terminatedInfo
2496+ val catchSuccessNNInfo = exprNNInfo.alt(casesNNInfo)
2497+ val catchFailNNInfo = catchSuccessNNInfo.retractedInfo
2498+
2499+ val finalizer1 = typed(tree.finalizer, defn.UnitType )(using ctx.addNotNullInfo(catchFailNNInfo))
2500+ val normalFinalNNInfo = catchSuccessNNInfo.seq(finalizer1.notNullInfo)
2501+ val exceptionalFinalNNInfo = catchFailNNInfo.seq(finalizer1.notNullInfo)
2502+ val resNNInfo = normalFinalNNInfo.alt(exceptionalFinalNNInfo.seq(NotNullInfo .empty.terminatedInfo))
25002503 assignType(cpy.Try (tree)(expr2, cases2, finalizer1), expr2, cases2).withNotNullInfo(resNNInfo)
25012504
25022505 def typedTry (tree : untpd.ParsedTry , pt : Type )(using Context ): Try =
0 commit comments