Skip to content

Safer exceptions with many cases in catch #13816

Closed
@prolativ

Description

@prolativ

Compiler version

3.1.1-RC1-bin-20211020-afaac17-NIGHTLY

Minimized code

import language.experimental.saferExceptions

class Ex1 extends Exception("Ex1")
class Ex2 extends Exception("Ex2")

def foo1(i: Int): Unit throws Ex1 throws Ex2 =
   if i > 0 then throw new Ex1 else throw new Ex2

def foo2(i: Int): Unit throws (Ex1 | Ex2) =
   if i > 0 then throw new Ex1 else throw new Ex2

def foo3(i: Int)(using CanThrow[Ex1], CanThrow[Ex2]) =
   if i > 0 then throw new Ex1 else throw new Ex2

def foo4(i: Int)(using CanThrow[Ex1])(using CanThrow[Ex2]) =
   if i > 0 then throw new Ex1 else throw new Ex2

def foo5(i: Int)(using CanThrow[Ex1 | Ex2]) =
   if i > 0 then throw new Ex1 else throw new Ex2

def test(): Unit =
  try {
    foo1(1)
    foo2(1) // error
    foo3(1)
    foo4(1)
    foo5(1) // error
  } catch {
    case _: Ex1 =>
    case _: Ex2 => 
  }

Output

[error] -- Error: /Users/mpalka/Projects/dotty-test/tmp/src/main/scala/test.scala:24:11 
[error] 24 |    foo2(1) // error
[error]    |           ^
[error]    |      The capability to throw exception Ex1 | Ex2 is missing.
[error]    |      The capability can be provided by one of the following:
[error]    |       - A using clause `(using CanThrow[Ex1 | Ex2])`
[error]    |       - A `throws` clause in a result type such as `X throws Ex1 | Ex2`
[error]    |       - an enclosing `try` that catches Ex1 | Ex2
[error]    |
[error]    |      The following import might fix the problem:
[error]    |
[error]    |        import unsafeExceptions.canThrowAny
[error]    |
[error] -- Error: /Users/mpalka/Projects/dotty-test/tmp/src/main/scala/test.scala:27:11 
[error] 27 |    foo5(1) // error
[error]    |           ^
[error]    |      The capability to throw exception Ex1 | Ex2 is missing.
[error]    |      The capability can be provided by one of the following:
[error]    |       - A using clause `(using CanThrow[Ex1 | Ex2])`
[error]    |       - A `throws` clause in a result type such as `X throws Ex1 | Ex2`
[error]    |       - an enclosing `try` that catches Ex1 | Ex2
[error]    |
[error]    |      The following import might fix the problem:
[error]    |
[error]    |        import unsafeExceptions.canThrowAny
[error]    |
[error] two errors found
[error] two errors found

Expectation

The compiler should be able to figure out that all the declared exceptions are handled. Interestingly adding case _: (Ex1 | Ex2) => inside catch makes the compiler stop complaining

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions