Closed
Description
Compiler version
3.3.1
Minimized example
import language.experimental.saferExceptions
class Ex1 extends Exception("Ex1")
class Ex2 extends Exception("Ex2")
class Ex3 extends Exception("Ex3")
def foo9(i: Int): Unit throws Ex1 | Ex2 | Ex3 = // error
if i > 0 then throw new Ex1
else if i < 0 then throw new Ex2
else throw new Ex3
// The following manual expansion works, however:
def foo(i: Int): (ex1: CanThrow[Ex1]) -> (ex2: CanThrow[Ex2]) -> (ex3: CanThrow[Ex3]) ->{ex1, ex2} Unit =
(ex1: CanThrow[Ex1]) =>
(ex2: CanThrow[Ex2]) =>
(ex3: CanThrow[Ex3]) =>
given CanThrow[Ex1] = ex1
given CanThrow[Ex2] = ex2
given CanThrow[Ex3] = ex3
if i > 0 then throw new Ex1
else if i < 0 then throw new Ex2
else throw new Ex3
Output
-- [E007] Type Mismatch Error: cc-triple-curried.scala:19:2 --------------------
19 | if i > 0 then throw new Ex1
| ^
|Found: (erased evidence$1: CanThrow[Ex3]) ?->?
| (erased x$0: CanThrow[Ex2]) ?->?
| (erased x$1: CanThrow[Ex1]) ?->{x$0², evidence$1, x$0} Unit
|Required: (erased x$0: CanThrow[Ex3]) ?-> (erased x$1: CanThrow[Ex2]) ?->
| (erased x$2: CanThrow[Ex1]) ?->{x$1, x$0} Unit
|
|where: x$0 is a reference to a value parameter
| x$0² is a reference to a value parameter
20 | else if i < 0 then throw new Ex2
21 | else throw new Ex3
|
| longer explanation available when compiling with `-explain`
1 error found
Expectation
Should compile. There's a dubious capture set with three members in the error message: {x$0², evidence$1, x$0}
. I guess the two x$0 should map to the same reference.
The $throws clause expands to roughly the code in the second foo
method. The main difference is that $throws
clauses generate context functions. But we cannot write dependent context functions as a result type, that hits an implementation restriction. I therefore wrote them as normal functions, with embedded given clauses. But that change makes the error go away.