Skip to content

Union of three exceptions in throws clause does not compile #18168

Closed
@odersky

Description

@odersky

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:saferExceptionsscala.language.experimental.saferExceptionscc-experimentIntended to be merged with cc-experiment branch on originitype:bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions