-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix a case of MT reduction using abstract types #18243
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
Conversation
The original motivation wasn't with a test case. And reproducing it is not convincing. So I'd rather revert and fix this issue.
The new match type spec refuses to reduce here, like I think this is actually unsound, but I'm having a hard time actually causing a crash. My best attempt so far is final class Box[T](var value: T)
type TupleIndex[T <: Tuple, A, I <: Int] <: (Any, Int) = T match
case A *: _ => (A, I)
case _ *: t => TupleIndex[t, A, S[I]]
def tupleIndex[T <: Tuple, A](box: Box[Tuple.Elem[TupleIndex[T, A, 0], 1]]): Unit = box.value = 5
def test(): Unit =
summon[TupleIndex[(String, String), String, 0] =:= (String, 0)]
summon[Tuple.Elem[TupleIndex[(String, String), String, 0], 1] =:= 0] // proof that it reduces to 0
val box: Box[0] = new Box(0)
tupleIndex[(String, String), String](box) // error here
val zero: 0 = box.value
println(zero) but I still get
However, at this point So it's only by chance that this snippet does not compile, once this commit is applied. |
To better illustrate the "random"/"by chance" aspect of the above consider this variant: import compiletime.ops.int.*
final class Box[T](var value: T)
type TupleIndex[T <: Tuple, A, I <: Int] <: (Any, Int) = T match
case A *: _ => (A, I)
case _ *: t => TupleIndex[t, A, S[I]]
class Container:
type A
type T <: Tuple
type TheIndex = TupleIndex[T, A, 0]
def tupleIndex(box: Box[Tuple.Elem[TheIndex, 1]]): Unit = box.value = 5 // LINE 13
class Child extends Container:
type A = String
type T = (String, String)
type TheIndex = (String, 0)
def test(): Unit =
val box: Box[0] = new Box(0)
val child = new Child
child.tupleIndex(box) // LINE 23
val zero: 0 = box.value
println(zero) which gives the following error:
but if we replace, on LINE 13,
On |
@sjrd thanks for your thoughts! I'd like the understand better why/how this could be unsound, though it's a bit out of my wheelhouse so please excuse my ignorance 😄
Even if you don't have a code sample for it, what kind of crash do you think might be possible? From #18202 (comment)
I don't fully follow this, but I think my understanding might be off -- I thought that if |
In this case I expect the
Implicit resolution has nothing to do with this example. We're type-checking the body of the method, in which we already have the value at our disposal. It is only a matter of reduction. The fact that your body previously typechecked shows that reduction of |
Perhaps it's easier to get the exception with a class Foo and subclass Foo1, rather than Int and 0. |
I don't think it's unsound, and the fact that it doesn't compile is because it's right not to.
Sure, when
I don't understand why that changes, but the ultimate error on line 23 is still right. |
That's not how match types work. Match types have to follow a stronger property:
Concretely, that means that type captures cannot be instantiated to some
We reduced to
Imagine that in version 1 of a library I define it with That's the problem with the "it reduces by chance". The presence of type aliases in the middle of the path should never alter what a match type reduces to. |
The original motivation wasn't with a test case. And reproducing it
is not convincing. So I'd rather revert and fix this issue.