Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
odersky opened this issue Jul 7, 2023 · 3 comments
Closed

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

odersky opened this issue Jul 7, 2023 · 3 comments
Labels
area:saferExceptions scala.language.experimental.saferExceptions cc-experiment Intended to be merged with cc-experiment branch on origin itype:bug

Comments

@odersky
Copy link
Contributor

odersky commented Jul 7, 2023

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.

@odersky odersky added stat:needs triage Every issue needs to have an "area" and "itype" label cc-experiment Intended to be merged with cc-experiment branch on origin area:saferExceptions scala.language.experimental.saferExceptions itype:bug and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Jul 7, 2023
@Linyxus
Copy link
Contributor

Linyxus commented Jul 10, 2023

I looked into this issue a bit and it seems to have different causes on the main branch and on the branch of #18131.

  • On the main branch, it is a bug in expandAbbreviations. The capture sets will not be pushed to the right transitively in curried functions: (x1: CT^) -> (x2: CT^) -> (x3: CT^) -> Unit will be (x1: CT^) -> (x2: CT^) ->{x1} (x3: CT^) ->{x2} Unit but not (x1: CT^) -> (x2: CT^) ->{x1} (x3: CT^) ->{x1, x2} Unit.

  • But expandAbbreviation has been dropped in Change handling of curried function types in capture checking #18131, so it is irrelevant. I traced down the suspicious capture set, and noticed that at this line, we enter the specialized method comparison logic for CC only when RHS is a normal function, but not when it is an erased one. After taking erased functions into account (as in this commit), the error is fixed.

@odersky
Copy link
Contributor Author

odersky commented Jul 11, 2023

Great analysis!

odersky added a commit to dotty-staging/dotty that referenced this issue Jul 13, 2023
@odersky
Copy link
Contributor Author

odersky commented Jul 13, 2023

I noted that this works now after the isFunctionType refactoring. I added the test to tests/pos/i13816.scala, where it was disabled before.

@odersky odersky closed this as completed Jul 13, 2023
odersky added a commit to dotty-staging/dotty that referenced this issue Jul 14, 2023
odersky added a commit to dotty-staging/dotty that referenced this issue Jul 16, 2023
olhotak pushed a commit to dotty-staging/dotty that referenced this issue Jul 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:saferExceptions scala.language.experimental.saferExceptions cc-experiment Intended to be merged with cc-experiment branch on origin itype:bug
Projects
None yet
Development

No branches or pull requests

2 participants