-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Open
Labels
area:pattern-matchingarea:union-typesIssues tied to union types.Issues tied to union types.itype:bugitype:soundnessSoundness bug (it lets us compile code that crashes at runtime with a ClassCastException)Soundness bug (it lets us compile code that crashes at runtime with a ClassCastException)
Description
Compiler version
scala 3.7.1
Minimized code
case class Id1[A](val x: A)
case class Id2[A](val y: A)
type IdAll[A] = Id1[A] | Id2[A]
sealed trait Adt[A]
case class Con1[B >: Id1[A], A](x: A) extends Adt[B]
case class Con2[B >: Id2[A], A](x: A) extends Adt[B]
def test[A, T >: IdAll[A]](expr: Adt[T]): A = {
expr match
case Con1(x) => x
case Con2(x) => x
}
val result = test[Int, IdAll[Int] | Id2[String]](Con2(""))
print(result)
Output
java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer
Expectation
Compiler error, because the lower bound of IdAll[A]
does not guarantee that type T
will not contain any Id2[B]
, which results in a bounds conflict.
Metadata
Metadata
Assignees
Labels
area:pattern-matchingarea:union-typesIssues tied to union types.Issues tied to union types.itype:bugitype:soundnessSoundness bug (it lets us compile code that crashes at runtime with a ClassCastException)Soundness bug (it lets us compile code that crashes at runtime with a ClassCastException)
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
Alex1005a commentedon Jun 13, 2025
Not surprisingly, replacing union types with intersection types, and lower bounds with upper bounds, the issue remains.
noti0na1 commentedon Jun 16, 2025
I agree. Since we can create
Adt[Any]
for anyCon*
, the pattern case should not have any information aboutx
.I think this is related to GADT. cc @Linyxus
Linyxus commentedon Jul 11, 2025
This does not seem to be solely a GADT problem; it is related to type inference as well. The typed tree: