-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Type equality failure on pattern match with tuple types #15274
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
Comments
I think I've figured it out. The |
I tried to compile the code on the #14754 branch but it also fails. After inspecting the GADT traces, I found that the cause of the failure may lie in the upcasting logic of GADT constrainer (here): when upcasting the scrutinee type we do not take existing GADT upper bounds into consideration. In the minimal example below: enum Format[A]:
case Str[Next](next: Format[Next]) extends Format[(String, Next)]
def printf[A](format: Format[A], params: A): Unit = (format, params) match
case (Format.Str(next), (str, rest)) =>
val s: String = str // error To see why this limitation causes the compilation failure:
This is not necessarily related to pattern matching on tuples. We can decompose the tuple pattern matching into two steps, and the issue is still there: enum Format[A]:
case Str[Next](next: Format[Next]) extends Format[(String, Next)]
def printf[A](format: Format[A], params: A): Unit = format match
case Format.Str(next) => params match
case (str, rest) =>
val s: String = str Here is a straightforward fix for this issue: when upcasting the scrutinee type we also try the GADT upper bound. This allows the snippet to compile, and does not break tests on my machine. By principle upcasting the scrutinee will always be safe given that the upper bound is sound, but I am not 100% sure if this will cause soundness problems. Shall we go with this fix? |
Compiler version
3.1.2
Minimized code
Output
Compilation failure, the compiler cannot convince itself that, in the
Format.Str
branch, for example,A
is of type(String, ...)
(where...
is the right type to pass tonext
).Expectation
This should compile: the compiler already knows the right types. As shown by @smarter , the following code compiles (and runs as expected):
Note that the only difference is, instead of pattern matching on the tuple, this code explicitly calls
apply
on it, which somehow satisfies the compiler that everything is alright.The text was updated successfully, but these errors were encountered: