Skip to content

Commit ec86d5e

Browse files
committed
Expand aliases when mapping explicit types in Setup
This is necessary because the compiler is free in previous phases to dealias or not. Therefore, capture checking should not depend on aliasing. The main difference is that now arguments to type aliases are not necessarily boxed. They are boxed only if they need boxing in the dealiased type.
1 parent ecf3428 commit ec86d5e

21 files changed

+102
-83
lines changed

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

-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ object ccConfig:
4949

5050
end ccConfig
5151

52-
5352
/** Are we at checkCaptures phase? */
5453
def isCaptureChecking(using Context): Boolean =
5554
ctx.phaseId == Phases.checkCapturesPhase.id

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
278278
paramInfos = tp.paramInfos.mapConserve(_.dropAllRetains.bounds),
279279
resType = this(tp.resType))
280280
case _ =>
281-
mapOver(tp)
281+
mapFollowingAliases(tp)
282282
addVar(addCaptureRefinements(normalizeCaptures(tp1)), ctx.owner)
283283
end apply
284284
end mapInferred
@@ -364,7 +364,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
364364
// Map references to capability classes C to C^
365365
if t.derivesFromCapability && !t.isSingleton && t.typeSymbol != defn.Caps_Exists
366366
then CapturingType(t, defn.universalCSImpliedByCapability, boxed = false)
367-
else normalizeCaptures(mapOver(t))
367+
else normalizeCaptures(mapFollowingAliases(t))
368368
end toCapturing
369369

370370
def fail(msg: Message) =
@@ -821,7 +821,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
821821
case tp @ OrType(tp1, tp2 @ CapturingType(parent2, refs2)) =>
822822
CapturingType(OrType(tp1, parent2, tp.isSoft), refs2, tp2.isBoxed)
823823
case tp @ AppliedType(tycon, args)
824-
if !defn.isFunctionClass(tp.dealias.typeSymbol) =>
824+
if !defn.isFunctionClass(tp.dealias.typeSymbol) && (tp.dealias eq tp) =>
825825
tp.derivedAppliedType(tycon, args.mapConserve(box))
826826
case tp: RealTypeBounds =>
827827
tp.derivedTypeBounds(tp.lo, box(tp.hi))

tests/neg-custom-args/captures/boundschecks2.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ object test {
88

99
val foo: C[Tree^] = ??? // error
1010
type T = C[Tree^] // error
11-
val bar: T -> T = ???
11+
//val bar: T -> T = ??? // --> boundschecks3.scala for what happens if we uncomment
1212
val baz: C[Tree^] -> Unit = ??? // error
1313
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Error: tests/neg-custom-args/captures/boundschecks3.scala:11:13 -----------------------------------------------------
2+
11 | val bar: T -> T = ??? // error, since `T` is expanded here. But the msg is not very good.
3+
| ^^^^^^
4+
| test.C[box test.Tree^] captures the root capability `cap` in invariant position
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
object test {
2+
3+
class Tree
4+
5+
def f[X <: Tree](x: X): Unit = ()
6+
7+
class C[X <: Tree](x: X)
8+
9+
val foo: C[Tree^] = ??? // hidden error
10+
type T = C[Tree^] // hidden error
11+
val bar: T -> T = ??? // error, since `T` is expanded here. But the msg is not very good.
12+
val baz: C[Tree^] -> Unit = ??? // hidden error
13+
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/box-adapt-cases.scala:14:4 -------------------------------
2-
14 | x(cap => cap.use()) // error
3-
| ^^^^^^^^^^^^^^^^
4-
| Found: (cap: box Cap^?) ->{io} Int
5-
| Required: (cap: box Cap^{io}) -> Int
1+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/box-adapt-cases.scala:14:10 ------------------------------
2+
14 | x.value(cap => cap.use()) // error
3+
| ^^^^^^^^^^^^^^^^
4+
| Found: (cap: box Cap^?) ->{io} Int
5+
| Required: (cap: box Cap^{io}) -> Int
66
|
77
| longer explanation available when compiling with `-explain`
8-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/box-adapt-cases.scala:28:4 -------------------------------
9-
28 | x(cap => cap.use()) // error
10-
| ^^^^^^^^^^^^^^^^
11-
| Found: (cap: box Cap^?) ->{io, fs} Int
12-
| Required: (cap: box Cap^{io, fs}) ->{io} Int
8+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/box-adapt-cases.scala:28:10 ------------------------------
9+
28 | x.value(cap => cap.use()) // error
10+
| ^^^^^^^^^^^^^^^^
11+
| Found: (cap: box Cap^?) ->{io, fs} Int
12+
| Required: (cap: box Cap^{io, fs}) ->{io} Int
1313
|
1414
| longer explanation available when compiling with `-explain`
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
trait Cap { def use(): Int }
22

33
def test1(): Unit = {
4-
type Id[X] = [T] -> (op: X => T) -> T
4+
class Id[X](val value: [T] -> (op: X => T) -> T)
55

66
val x: Id[Cap^] = ???
7-
x(cap => cap.use())
7+
x.value(cap => cap.use())
88
}
99

1010
def test2(io: Cap^): Unit = {
11-
type Id[X] = [T] -> (op: X -> T) -> T
11+
class Id[X](val value: [T] -> (op: X -> T) -> T)
1212

1313
val x: Id[Cap^{io}] = ???
14-
x(cap => cap.use()) // error
14+
x.value(cap => cap.use()) // error
1515
}
1616

1717
def test3(io: Cap^): Unit = {
18-
type Id[X] = [T] -> (op: X ->{io} T) -> T
18+
class Id[X](val value: [T] -> (op: X ->{io} T) -> T)
1919

2020
val x: Id[Cap^{io}] = ???
21-
x(cap => cap.use()) // ok
21+
x.value(cap => cap.use()) // ok
2222
}
2323

2424
def test4(io: Cap^, fs: Cap^): Unit = {
25-
type Id[X] = [T] -> (op: X ->{io} T) -> T
25+
class Id[X](val value: [T] -> (op: X ->{io} T) -> T)
2626

2727
val x: Id[Cap^{io, fs}] = ???
28-
x(cap => cap.use()) // error
28+
x.value(cap => cap.use()) // error
2929
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
trait Cap
22

33
def test1(io: Cap^) = {
4-
type Op[X] = [T] -> Unit -> X
4+
class Op[+X](val value: [T] -> Unit -> X)
55
val f: Op[Cap^{io}] = ???
6-
val x: [T] -> Unit -> Cap^{io} = f // error
6+
val x: [T] -> Unit -> Cap^{io} = f.value // error
77
}
88

99
def test2(io: Cap^) = {
10-
type Op[X] = [T] -> Unit -> X^{io}
10+
class Op[+X](val value: [T] -> Unit -> X^{io})
1111
val f: Op[Cap^{io}] = ???
12-
val x: Unit -> Cap^{io} = f[Unit] // error
13-
val x1: Unit ->{io} Cap^{io} = f[Unit] // ok
12+
val x: Unit -> Cap^{io} = f.value[Unit] // error
13+
val x1: Unit ->{io} Cap^{io} = f.value[Unit] // ok
1414
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
trait Cap { def use(): Int }
22

33
def test1(io: Cap^): Unit = {
4-
type Id[X] = [T] -> (op: X ->{io} T) -> T
4+
class Id[X](val value: [T] -> (op: X ->{io} T) -> T)
55

66
val x: Id[Cap]^{io} = ???
7-
x(cap => cap.use()) // ok
7+
x.value(cap => cap.use()) // ok
88
}
99

1010
def test2(io: Cap^): Unit = {
11-
type Id[X] = [T] -> (op: (x: X) ->{io} T) -> T
11+
class Id[X](val value: [T] -> (op: (x: X) ->{io} T) -> T)
1212

1313
val x: Id[Cap^{io}] = ???
14-
x(cap => cap.use())
14+
x.value(cap => cap.use())
1515
// should work when the expected type is a dependent function
1616
}
1717

1818
def test3(io: Cap^): Unit = {
19-
type Id[X] = [T] -> (op: (x: X) ->{} T) -> T
19+
class Id[X](val value: [T] -> (op: (x: X) ->{} T) -> T)
2020

2121
val x: Id[Cap^{io}] = ???
22-
x(cap => cap.use()) // error
22+
x.value(cap => cap.use()) // error
2323
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
trait Cap { def use(): Int }
22

33
def test1(io: Cap^): Unit = {
4-
type Op[X] = [T] -> X -> Unit
4+
class Op[X](val value: [T] -> X -> Unit)
55
val f: [T] -> (Cap^{io}) -> Unit = ???
6-
val op: Op[Cap^{io}] = f // error
6+
val op: Op[Cap^{io}] = Op(f) // was error, now ok
77
}
88

99
def test2(io: Cap^): Unit = {
10-
type Lazy[X] = [T] -> Unit -> X
10+
class Lazy[X](val value: [T] -> Unit -> X)
1111
val f: Lazy[Cap^{io}] = ???
12-
val test: [T] -> Unit -> (Cap^{io}) = f // error
12+
val test: [T] -> Unit -> (Cap^{io}) = f.value // error
1313
}

tests/neg-custom-args/captures/capt1.check

+6-6
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@
3636
-- Error: tests/neg-custom-args/captures/capt1.scala:34:16 -------------------------------------------------------------
3737
34 | val z2 = h[() -> Cap](() => x) // error // error
3838
| ^^^^^^^^^
39-
| Type variable X of method h cannot be instantiated to () -> box C^ since
40-
| the part box C^ of that type captures the root capability `cap`.
39+
| Type variable X of method h cannot be instantiated to () -> (ex$15: caps.Exists) -> C^{ex$15} since
40+
| the part C^{ex$15} of that type captures the root capability `cap`.
4141
-- Error: tests/neg-custom-args/captures/capt1.scala:34:30 -------------------------------------------------------------
4242
34 | val z2 = h[() -> Cap](() => x) // error // error
4343
| ^
44-
| reference (x : C^) is not included in the allowed capture set {}
45-
| of an enclosing function literal with expected type () -> box C^
44+
| reference (x : C^) is not included in the allowed capture set {}
45+
| of an enclosing function literal with expected type () -> (ex$15: caps.Exists) -> C^{ex$15}
4646
-- Error: tests/neg-custom-args/captures/capt1.scala:36:13 -------------------------------------------------------------
4747
36 | val z3 = h[(() -> Cap) @retains(x)](() => x)(() => C()) // error
4848
| ^^^^^^^^^^^^^^^^^^^^^^^
49-
| Type variable X of method h cannot be instantiated to box () ->{x} Cap since
50-
| the part Cap of that type captures the root capability `cap`.
49+
| Type variable X of method h cannot be instantiated to box () ->{x} (ex$20: caps.Exists) -> C^{ex$20} since
50+
| the part C^{ex$20} of that type captures the root capability `cap`.

tests/neg-custom-args/captures/cc-ex-conformance.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ def Test =
2121
val ex3: EX3 = ???
2222
val ex4: EX4 = ???
2323
val _: EX4 = ex3 // ok
24-
val _: EX4 = ex4
24+
val _: EX4 = ex4 // error (???) Probably since we also introduce existentials on expansion
2525
val _: EX3 = ex4 // error

tests/neg-custom-args/captures/existential-mapping.check

+12-12
Original file line numberDiff line numberDiff line change
@@ -33,56 +33,56 @@
3333
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:21:30 --------------------------
3434
21 | val _: A^ -> (x: C^) -> C = x5 // error
3535
| ^^
36-
| Found: (x5 : A^ -> (ex$27: caps.Exists) -> Fun[C^{ex$27}])
36+
| Found: (x5 : A^ -> (x: C^) -> (ex$27: caps.Exists) -> C^{ex$27})
3737
| Required: A^ -> (x: C^) -> C
3838
|
3939
| longer explanation available when compiling with `-explain`
4040
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:24:30 --------------------------
4141
24 | val _: A^ -> (x: C^) => C = x6 // error
4242
| ^^
43-
| Found: (x6 : A^ -> (ex$33: caps.Exists) -> IFun[C^{ex$33}])
44-
| Required: A^ -> (ex$36: caps.Exists) -> (x: C^) ->{ex$36} C
43+
| Found: (x6 : A^ -> (ex$36: caps.Exists) -> (x: C^) ->{ex$36} (ex$35: caps.Exists) -> C^{ex$35})
44+
| Required: A^ -> (ex$39: caps.Exists) -> (x: C^) ->{ex$39} C
4545
|
4646
| longer explanation available when compiling with `-explain`
4747
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:27:25 --------------------------
4848
27 | val _: (x: C^) => C = y1 // error
4949
| ^^
50-
| Found: (y1 : (x: C^) => (ex$38: caps.Exists) -> C^{ex$38})
50+
| Found: (y1 : (x: C^) => (ex$41: caps.Exists) -> C^{ex$41})
5151
| Required: (x: C^) => C
5252
|
5353
| longer explanation available when compiling with `-explain`
5454
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:30:20 --------------------------
5555
30 | val _: C^ => C = y2 // error
5656
| ^^
57-
| Found: (y2 : C^ => (ex$42: caps.Exists) -> C^{ex$42})
57+
| Found: (y2 : C^ => (ex$45: caps.Exists) -> C^{ex$45})
5858
| Required: C^ => C
5959
|
6060
| longer explanation available when compiling with `-explain`
6161
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:33:30 --------------------------
6262
33 | val _: A^ => (x: C^) => C = y3 // error
6363
| ^^
64-
| Found: (y3 : A^ => (ex$47: caps.Exists) -> (x: C^) ->{ex$47} (ex$46: caps.Exists) -> C^{ex$46})
65-
| Required: A^ => (ex$50: caps.Exists) -> (x: C^) ->{ex$50} C
64+
| Found: (y3 : A^ => (ex$50: caps.Exists) -> (x: C^) ->{ex$50} (ex$49: caps.Exists) -> C^{ex$49})
65+
| Required: A^ => (ex$53: caps.Exists) -> (x: C^) ->{ex$53} C
6666
|
6767
| longer explanation available when compiling with `-explain`
6868
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:36:25 --------------------------
6969
36 | val _: A^ => C^ => C = y4 // error
7070
| ^^
71-
| Found: (y4 : A^ => (ex$53: caps.Exists) -> C^ ->{ex$53} (ex$52: caps.Exists) -> C^{ex$52})
72-
| Required: A^ => (ex$56: caps.Exists) -> C^ ->{ex$56} C
71+
| Found: (y4 : A^ => (ex$56: caps.Exists) -> C^ ->{ex$56} (ex$55: caps.Exists) -> C^{ex$55})
72+
| Required: A^ => (ex$59: caps.Exists) -> C^ ->{ex$59} C
7373
|
7474
| longer explanation available when compiling with `-explain`
7575
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:39:30 --------------------------
7676
39 | val _: A^ => (x: C^) -> C = y5 // error
7777
| ^^
78-
| Found: (y5 : A^ => (ex$58: caps.Exists) -> Fun[C^{ex$58}])
78+
| Found: (y5 : A^ => (x: C^) -> (ex$61: caps.Exists) -> C^{ex$61})
7979
| Required: A^ => (x: C^) -> C
8080
|
8181
| longer explanation available when compiling with `-explain`
8282
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:42:30 --------------------------
8383
42 | val _: A^ => (x: C^) => C = y6 // error
8484
| ^^
85-
| Found: (y6 : A^ => (ex$64: caps.Exists) -> IFun[C^{ex$64}])
86-
| Required: A^ => (ex$67: caps.Exists) -> (x: C^) ->{ex$67} C
85+
| Found: (y6 : A^ => (ex$70: caps.Exists) -> (x: C^) ->{ex$70} (ex$69: caps.Exists) -> C^{ex$69})
86+
| Required: A^ => (ex$73: caps.Exists) -> (x: C^) ->{ex$73} C
8787
|
8888
| longer explanation available when compiling with `-explain`

tests/neg-custom-args/captures/i15922.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11

22

33
trait Cap { def use(): Int }
4-
type Id[X] = [T] -> (op: X => T) -> T
5-
def mkId[X](x: X): Id[X] = [T] => (op: X => T) => op(x)
4+
class Id[+X](val value: [T] -> (op: X => T) -> T)
5+
def mkId[X](x: X): Id[X] = Id([T] => (op: X => T) => op(x))
66

77
def withCap[X](op: (Cap^) => X): X = {
88
val cap: Cap^ = new Cap { def use() = { println("cap is used"); 0 } }

tests/neg-custom-args/captures/i16725.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ class IO extends caps.Capability:
33
def brewCoffee(): Unit = ???
44
def usingIO[T](op: IO => T): T = ???
55

6-
type Wrapper[T] = [R] -> (f: T => R) -> R
7-
def mk[T](x: T): Wrapper[T] = [R] => f => f(x)
6+
class Wrapper[T](val value: [R] -> (f: T => R) -> R)
7+
def mk[T](x: T): Wrapper[T] = Wrapper([R] => f => f(x))
88
def useWrappedIO(wrapper: Wrapper[IO]): () -> Unit =
99
() =>
10-
wrapper: io => // error
10+
wrapper.value: io => // error
1111
io.brewCoffee()
1212
def main(): Unit =
13-
val escaped = usingIO(io => useWrappedIO(mk(io)))
13+
val escaped = usingIO(io => useWrappedIO(mk(io))) // error
1414
escaped() // boom
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- Error: tests/neg-custom-args/captures/i19330.scala:15:29 ------------------------------------------------------------
2+
15 | val leaked = usingLogger[x.T]: l => // error
3+
| ^^^
4+
| Type variable T of method usingLogger cannot be instantiated to x.T since
5+
| the part () => Logger^ of that type captures the root capability `cap`.

tests/neg-custom-args/captures/i21401.check

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
-- Error: tests/neg-custom-args/captures/i21401.scala:16:66 ------------------------------------------------------------
1212
16 | val leaked: [R, X <: Boxed[IO^] -> R] -> (op: X) -> R = usingIO[Res](mkRes) // error
1313
| ^^^
14-
| Type variable R of method usingIO cannot be instantiated to Res since
15-
| the part box IO^ of that type captures the root capability `cap`.
14+
| Type variable R of method usingIO cannot be instantiated to [R, X <: Boxed[box IO^] -> R] => (op: X) -> R since
15+
| the part box IO^ of that type captures the root capability `cap`.
1616
-- Error: tests/neg-custom-args/captures/i21401.scala:17:29 ------------------------------------------------------------
1717
17 | val x: Boxed[IO^] = leaked[Boxed[IO^], Boxed[IO^] -> Boxed[IO^]](x => x) // error // error
1818
| ^^^^^^^^^^
@@ -21,8 +21,8 @@
2121
-- Error: tests/neg-custom-args/captures/i21401.scala:17:52 ------------------------------------------------------------
2222
17 | val x: Boxed[IO^] = leaked[Boxed[IO^], Boxed[IO^] -> Boxed[IO^]](x => x) // error // error
2323
| ^^^^^^^^^^^^^^^^^^^^^^^^
24-
|Type variable X of value leaked cannot be instantiated to Boxed[box IO^] -> (ex$18: caps.Exists) -> Boxed[box IO^{ex$18}] since
25-
|the part box IO^{ex$18} of that type captures the root capability `cap`.
24+
|Type variable X of value leaked cannot be instantiated to Boxed[box IO^] -> (ex$20: caps.Exists) -> Boxed[box IO^{ex$20}] since
25+
|the part box IO^{ex$20} of that type captures the root capability `cap`.
2626
-- Error: tests/neg-custom-args/captures/i21401.scala:18:21 ------------------------------------------------------------
2727
18 | val y: IO^{x*} = x.unbox // error
2828
| ^^^^^^^

tests/neg-custom-args/captures/outer-var.check

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/outer-var.scala:11:8 -------------------------------------
22
11 | x = q // error
33
| ^
4-
| Found: (q : Proc)
4+
| Found: (q : () => Unit)
55
| Required: () ->{p, q²} Unit
66
|
77
| where: q is a parameter in method inner
@@ -11,14 +11,14 @@
1111
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/outer-var.scala:12:9 -------------------------------------
1212
12 | x = (q: Proc) // error
1313
| ^^^^^^^
14-
| Found: Proc
14+
| Found: () => Unit
1515
| Required: () ->{p, q} Unit
1616
|
1717
| longer explanation available when compiling with `-explain`
1818
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/outer-var.scala:13:9 -------------------------------------
1919
13 | y = (q: Proc) // error
2020
| ^^^^^^^
21-
| Found: Proc
21+
| Found: () => Unit
2222
| Required: () ->{p} Unit
2323
|
2424
| Note that the universal capability `cap`
@@ -28,10 +28,10 @@
2828
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/outer-var.scala:14:8 -------------------------------------
2929
14 | y = q // error, was OK under unsealed
3030
| ^
31-
| Found: (q : Proc)
31+
| Found: (q : () => Unit)
3232
| Required: () ->{p} Unit
3333
|
34-
| Note that reference (q : Proc), defined in method inner
34+
| Note that reference (q : () => Unit), defined in method inner
3535
| cannot be included in outer capture set {p} of variable y
3636
|
3737
| longer explanation available when compiling with `-explain`

tests/neg-custom-args/captures/try.check

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
-- Error: tests/neg-custom-args/captures/try.scala:30:65 ---------------------------------------------------------------
77
30 | (x: CanThrow[Exception]) => () => raise(new Exception)(using x) // error
88
| ^
9-
| reference (x : CanThrow[Exception]) is not included in the allowed capture set {}
10-
| of an enclosing function literal with expected type () ->? Nothing
9+
| reference (x : CT[Exception]^) is not included in the allowed capture set {}
10+
| of an enclosing function literal with expected type () ->? Nothing
1111
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/try.scala:52:2 -------------------------------------------
1212
47 |val global: () -> Int = handle {
1313
48 | (x: CanThrow[Exception]) =>

0 commit comments

Comments
 (0)