@@ -39,7 +39,8 @@ import annotation.tailrec
39
39
import Implicits ._
40
40
import util .Stats .record
41
41
import config .Printers .{gadts , typr , debug }
42
- import config .Feature ._
42
+ import config .Feature
43
+ import config .Feature .{sourceVersion , migrateTo3 }
43
44
import config .SourceVersion ._
44
45
import rewrites .Rewrites .patch
45
46
import NavigateAST ._
@@ -712,7 +713,7 @@ class Typer extends Namer
712
713
case Whole (16 ) => // cant parse hex literal as double
713
714
case _ => return lit(doubleFromDigits(digits))
714
715
}
715
- else if genericNumberLiteralsEnabled
716
+ else if Feature . genericNumberLiteralsEnabled
716
717
&& target.isValueType && isFullyDefined(target, ForceDegree .none)
717
718
then
718
719
// If expected type is defined with a FromDigits instance, use that one
@@ -1712,10 +1713,30 @@ class Typer extends Namer
1712
1713
.withNotNullInfo(body1.notNullInfo.retractedInfo.seq(cond1.notNullInfoIf(false )))
1713
1714
}
1714
1715
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
+
1715
1736
def typedTry (tree : untpd.Try , pt : Type )(using Context ): Try = {
1716
1737
val expr2 :: cases2x = harmonic(harmonize, pt) {
1717
- val expr1 = typed(tree.expr, pt.dropIfProto)
1718
1738
val cases1 = typedCases(tree.cases, EmptyTree , defn.ThrowableType , pt.dropIfProto)
1739
+ val expr1 = typed(addCanThrowCapabilities(tree.expr, cases1), pt.dropIfProto)
1719
1740
expr1 :: cases1
1720
1741
}
1721
1742
val finalizer1 = typed(tree.finalizer, defn.UnitType )
@@ -1734,6 +1755,7 @@ class Typer extends Namer
1734
1755
1735
1756
def typedThrow (tree : untpd.Throw )(using Context ): Tree = {
1736
1757
val expr1 = typed(tree.expr, defn.ThrowableType )
1758
+ checkCanThrow(expr1.tpe.widen, tree.span)
1737
1759
Throw (expr1).withSpan(tree.span)
1738
1760
}
1739
1761
@@ -1832,7 +1854,7 @@ class Typer extends Namer
1832
1854
def typedAppliedTypeTree (tree : untpd.AppliedTypeTree )(using Context ): Tree = {
1833
1855
tree.args match
1834
1856
case arg :: _ if arg.isTerm =>
1835
- if dependentEnabled then
1857
+ if Feature . dependentEnabled then
1836
1858
return errorTree(tree, i " Not yet implemented: T(...) " )
1837
1859
else
1838
1860
return errorTree(tree, dependentStr)
@@ -1928,7 +1950,7 @@ class Typer extends Namer
1928
1950
typeIndexedLambdaTypeTree(tree, tparams, body)
1929
1951
1930
1952
def typedTermLambdaTypeTree (tree : untpd.TermLambdaTypeTree )(using Context ): Tree =
1931
- if dependentEnabled then
1953
+ if Feature . dependentEnabled then
1932
1954
errorTree(tree, i " Not yet implemented: (...) =>> ... " )
1933
1955
else
1934
1956
errorTree(tree, dependentStr)
@@ -2399,7 +2421,7 @@ class Typer extends Namer
2399
2421
ctx.phase.isTyper &&
2400
2422
cdef1.symbol.ne(defn.DynamicClass ) &&
2401
2423
cdef1.tpe.derivesFrom(defn.DynamicClass ) &&
2402
- ! dynamicsEnabled
2424
+ ! Feature . dynamicsEnabled
2403
2425
if (reportDynamicInheritance) {
2404
2426
val isRequired = parents1.exists(_.tpe.isRef(defn.DynamicClass ))
2405
2427
report.featureWarning(nme.dynamics.toString, " extension of type scala.Dynamic" , cls, isRequired, cdef.srcPos)
@@ -2614,7 +2636,10 @@ class Typer extends Namer
2614
2636
val untpd .InfixOp (l, op, r) = tree
2615
2637
val result =
2616
2638
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 ))
2618
2643
else if (ctx.mode.is(Mode .Pattern ))
2619
2644
typedUnApply(cpy.Apply (tree)(op, l :: r :: Nil ), pt)
2620
2645
else {
@@ -3468,7 +3493,7 @@ class Typer extends Namer
3468
3493
def isAutoApplied (sym : Symbol ): Boolean =
3469
3494
sym.isConstructor
3470
3495
|| sym.matchNullaryLoosely
3471
- || warnOnMigration(MissingEmptyArgumentList (sym.show), tree.srcPos)
3496
+ || Feature . warnOnMigration(MissingEmptyArgumentList (sym.show), tree.srcPos)
3472
3497
&& { patch(tree.span.endPos, " ()" ); true }
3473
3498
3474
3499
// Reasons NOT to eta expand:
@@ -3819,7 +3844,7 @@ class Typer extends Namer
3819
3844
case ref : TermRef =>
3820
3845
pt match {
3821
3846
case pt : FunProto
3822
- if needsTupledDual(ref, pt) && autoTuplingEnabled =>
3847
+ if needsTupledDual(ref, pt) && Feature . autoTuplingEnabled =>
3823
3848
adapt(tree, pt.tupledDual, locked)
3824
3849
case _ =>
3825
3850
adaptOverloaded(ref)
0 commit comments