Skip to content

Wrongly synthesized CanThrow for exceptions with an invariant type parameter #13864

Closed
@prolativ

Description

@prolativ

Compiler version

3.1.2-RC1-bin-20211101-49b6c08-NIGHTLY

Minimized code

import language.experimental.saferExceptions

case class Ex[A](a: A) extends Exception(s"Ex: $a")

def foo[A](a: A): Unit throws Ex[A] = throw new Ex(a)

def test(): Unit =
  try
    foo(1)
  catch
    case Ex(i: Int) => println("Caught an Int")

Output

[error] The capability can be provided by one of the following:
[error]  - A using clause `(using CanThrow[Ex[Int]])`
[error]  - A `throws` clause in a result type such as `X throws Ex[Int]`
[error]  - an enclosing `try` that catches Ex[Int]
[error] 
[error] The following import might fix the problem:
[error] 
[error]   import unsafeExceptions.canThrowAny
[error] 
[error]     foo(1)
[error]

Expectation

This should compile successfully.
If one tries to compile this code with -Xprint:typer one can see that the entire try/catch block gets desugared to

      try 
        {
          final lazy given erased val evidence$2: CanThrow[Ex[A$1]] = ???
          foo[Int](1).apply(/* missing */summon[CanThrow[Ex[Int]]])
        }
       catch 
        {
          case Ex.unapply[A$1 @ A$1](i @ _:Int):Ex[A$1] => 
            println("Caught an Int")
        }

where A$1 does not get substituted with Int as expected.
Interestingly, the error does not occur if we define case class Ex[+A](a: A) with a covariant type parameter

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions