Skip to content

Commit 7f0e259

Browse files
committed
Enhancement: Force all exception classes to be pure
Impure exceptions can't be thrown anyway since `throw` takes a pure `Throwable` as operand. The change avoids having to declare explicit pure self types for exception classes.
1 parent 4b97e1d commit 7f0e259

File tree

4 files changed

+30
-0
lines changed

4 files changed

+30
-0
lines changed

compiler/src/dotty/tools/dotc/cc/CaptureSet.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,11 @@ object CaptureSet:
326326
/** Used as a recursion brake */
327327
@sharable private[dotc] val Pending = Const(SimpleIdentitySet.empty)
328328

329+
/** The empty capture set with a description that says it's the elf type of an
330+
* exception class.
331+
*/
332+
val emptyOfException: CaptureSet.Const = Const(emptySet, "of an exception class")
333+
329334
def apply(elems: CaptureRef*)(using Context): CaptureSet.Const =
330335
if elems.isEmpty then empty
331336
else Const(SimpleIdentitySet(elems.map(_.normalizedRef)*))

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,8 @@ class CheckCaptures extends Recheck, SymTransformer:
504504
for param <- cls.paramGetters do
505505
if !param.hasAnnotation(defn.ConstructorOnlyAnnot) then
506506
checkSubset(param.termRef.captureSet, thisSet, param.srcPos) // (3)
507+
if cls.derivesFrom(defn.ThrowableClass) then
508+
checkSubset(thisSet, CaptureSet.emptyOfException, tree.srcPos)
507509
super.recheckClassDef(tree, impl, cls)
508510
finally
509511
curEnv = saved
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- Error: tests/neg-custom-args/captures/exception-definitions.scala:2:6 -----------------------------------------------
2+
2 |class Err extends Exception: // error
3+
|^
4+
|reference (scala.caps.* : Any) is not included in allowed capture set {} of an exception class
5+
3 | self: {*} Err =>
6+
-- Error: tests/neg-custom-args/captures/exception-definitions.scala:7:12 ----------------------------------------------
7+
7 | val x = c // error
8+
| ^
9+
| (c : {*} Any) cannot be referenced here; it is not included in the allowed capture set {} of an exception class
10+
-- Error: tests/neg-custom-args/captures/exception-definitions.scala:8:8 -----------------------------------------------
11+
8 | class Err3(c: {*} Any) extends Exception // error
12+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
| reference (Err3.this.c : {*} Any) is not included in allowed capture set {} of an exception class
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
class Err extends Exception: // error
3+
self: {*} Err =>
4+
5+
def test(c: {*} Any) =
6+
class Err2 extends Exception:
7+
val x = c // error
8+
class Err3(c: {*} Any) extends Exception // error
9+
10+

0 commit comments

Comments
 (0)