@@ -39,7 +39,8 @@ import annotation.tailrec
3939import Implicits ._
4040import util .Stats .record
4141import config .Printers .{gadts , typr , debug }
42- import config .Feature ._
42+ import config .Feature
43+ import config .Feature .{sourceVersion , migrateTo3 }
4344import config .SourceVersion ._
4445import rewrites .Rewrites .patch
4546import NavigateAST ._
@@ -712,7 +713,7 @@ class Typer extends Namer
712713 case Whole (16 ) => // cant parse hex literal as double
713714 case _ => return lit(doubleFromDigits(digits))
714715 }
715- else if genericNumberLiteralsEnabled
716+ else if Feature . genericNumberLiteralsEnabled
716717 && target.isValueType && isFullyDefined(target, ForceDegree .none)
717718 then
718719 // If expected type is defined with a FromDigits instance, use that one
@@ -1712,10 +1713,30 @@ class Typer extends Namer
17121713 .withNotNullInfo(body1.notNullInfo.retractedInfo.seq(cond1.notNullInfoIf(false )))
17131714 }
17141715
1716+ /** Add givens reflecting `CanThrow` capabilities for all checked exceptions matched
1717+ * by `cases`. The givens appear in nested blocks with earlier cases leading to
1718+ * more deeply nested givens. This way, given priority will be the same as pattern priority.
1719+ * The functionality is enabled if the experimental.saferExceptions language feature is enabled.
1720+ */
1721+ def addCanThrowCapabilities (expr : untpd.Tree , cases : List [CaseDef ])(using Context ): untpd.Tree =
1722+ def makeCanThrow (tp : Type ): untpd.Tree =
1723+ untpd.ValDef (
1724+ EvidenceParamName .fresh(),
1725+ untpd.TypeTree (defn.CanThrowClass .typeRef.appliedTo(tp)),
1726+ untpd.ref(defn.Predef_undefined ))
1727+ .withFlags(Given | Final | Lazy | Erased )
1728+ .withSpan(expr.span)
1729+ val caps =
1730+ for
1731+ CaseDef (pat, _, _) <- cases
1732+ if Feature .enabled(Feature .saferExceptions) && pat.tpe.widen.isCheckedException
1733+ yield makeCanThrow(pat.tpe.widen)
1734+ caps.foldLeft(expr)((e, g) => untpd.Block (g :: Nil , e))
1735+
17151736 def typedTry (tree : untpd.Try , pt : Type )(using Context ): Try = {
17161737 val expr2 :: cases2x = harmonic(harmonize, pt) {
1717- val expr1 = typed(tree.expr, pt.dropIfProto)
17181738 val cases1 = typedCases(tree.cases, EmptyTree , defn.ThrowableType , pt.dropIfProto)
1739+ val expr1 = typed(addCanThrowCapabilities(tree.expr, cases1), pt.dropIfProto)
17191740 expr1 :: cases1
17201741 }
17211742 val finalizer1 = typed(tree.finalizer, defn.UnitType )
@@ -1734,6 +1755,7 @@ class Typer extends Namer
17341755
17351756 def typedThrow (tree : untpd.Throw )(using Context ): Tree = {
17361757 val expr1 = typed(tree.expr, defn.ThrowableType )
1758+ checkCanThrow(expr1.tpe.widen, tree.span)
17371759 Throw (expr1).withSpan(tree.span)
17381760 }
17391761
@@ -1832,7 +1854,7 @@ class Typer extends Namer
18321854 def typedAppliedTypeTree (tree : untpd.AppliedTypeTree )(using Context ): Tree = {
18331855 tree.args match
18341856 case arg :: _ if arg.isTerm =>
1835- if dependentEnabled then
1857+ if Feature . dependentEnabled then
18361858 return errorTree(tree, i " Not yet implemented: T(...) " )
18371859 else
18381860 return errorTree(tree, dependentStr)
@@ -1928,7 +1950,7 @@ class Typer extends Namer
19281950 typeIndexedLambdaTypeTree(tree, tparams, body)
19291951
19301952 def typedTermLambdaTypeTree (tree : untpd.TermLambdaTypeTree )(using Context ): Tree =
1931- if dependentEnabled then
1953+ if Feature . dependentEnabled then
19321954 errorTree(tree, i " Not yet implemented: (...) =>> ... " )
19331955 else
19341956 errorTree(tree, dependentStr)
@@ -2399,7 +2421,7 @@ class Typer extends Namer
23992421 ctx.phase.isTyper &&
24002422 cdef1.symbol.ne(defn.DynamicClass ) &&
24012423 cdef1.tpe.derivesFrom(defn.DynamicClass ) &&
2402- ! dynamicsEnabled
2424+ ! Feature . dynamicsEnabled
24032425 if (reportDynamicInheritance) {
24042426 val isRequired = parents1.exists(_.tpe.isRef(defn.DynamicClass ))
24052427 report.featureWarning(nme.dynamics.toString, " extension of type scala.Dynamic" , cls, isRequired, cdef.srcPos)
@@ -2614,7 +2636,10 @@ class Typer extends Namer
26142636 val untpd .InfixOp (l, op, r) = tree
26152637 val result =
26162638 if (ctx.mode.is(Mode .Type ))
2617- typedAppliedTypeTree(cpy.AppliedTypeTree (tree)(op, l :: r :: Nil ))
2639+ typedAppliedTypeTree(
2640+ if op.name == tpnme.throws && Feature .enabled(Feature .saferExceptions)
2641+ then desugar.throws(l, op, r)
2642+ else cpy.AppliedTypeTree (tree)(op, l :: r :: Nil ))
26182643 else if (ctx.mode.is(Mode .Pattern ))
26192644 typedUnApply(cpy.Apply (tree)(op, l :: r :: Nil ), pt)
26202645 else {
@@ -3468,7 +3493,7 @@ class Typer extends Namer
34683493 def isAutoApplied (sym : Symbol ): Boolean =
34693494 sym.isConstructor
34703495 || sym.matchNullaryLoosely
3471- || warnOnMigration(MissingEmptyArgumentList (sym.show), tree.srcPos)
3496+ || Feature . warnOnMigration(MissingEmptyArgumentList (sym.show), tree.srcPos)
34723497 && { patch(tree.span.endPos, " ()" ); true }
34733498
34743499 // Reasons NOT to eta expand:
@@ -3819,7 +3844,7 @@ class Typer extends Namer
38193844 case ref : TermRef =>
38203845 pt match {
38213846 case pt : FunProto
3822- if needsTupledDual(ref, pt) && autoTuplingEnabled =>
3847+ if needsTupledDual(ref, pt) && Feature . autoTuplingEnabled =>
38233848 adapt(tree, pt.tupledDual, locked)
38243849 case _ =>
38253850 adaptOverloaded(ref)
0 commit comments