Skip to content

Commit 742575b

Browse files
committed
Always freeze GADTs when comparing type member infos
1 parent e560c2d commit 742575b

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,8 +1849,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
18491849
|| symInfo.isInstanceOf[MethodType]
18501850
&& symInfo.signature.consistentParams(info2.signature)
18511851

1852-
def tp1IsSingleton: Boolean = tp1.isInstanceOf[SingletonType]
1853-
18541852
// A relaxed version of isSubType, which compares method types
18551853
// under the standard arrow rule which is contravarient in the parameter types,
18561854
// but under the condition that signatures might have to match (see sigsOK)
@@ -1865,8 +1863,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
18651863
matchingMethodParams(info1, info2, precise = false)
18661864
&& isSubInfo(info1.resultType, info2.resultType.subst(info2, info1), symInfo1.resultType)
18671865
&& sigsOK(symInfo1, info2)
1868-
case _ => inFrozenGadtIf(tp1IsSingleton) { isSubType(info1, info2) }
1869-
case _ => inFrozenGadtIf(tp1IsSingleton) { isSubType(info1, info2) }
1866+
case _ => inFrozenGadt { isSubType(info1, info2) }
1867+
case _ => inFrozenGadt { isSubType(info1, info2) }
18701868

18711869
val info1 = m.info.widenExpr
18721870
isSubInfo(info1, tp2.refinedInfo.widenExpr, m.symbol.info.orElse(info1))

tests/neg/i15485.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
enum SUB[-A, +B]:
2+
case Refl[C]() extends SUB[C, C]
3+
4+
trait Tag { type T }
5+
6+
def foo[A, B, X <: Tag { type T <: A } ](
7+
e: SUB[X, Tag { type T <: B } ],
8+
x: A,
9+
): B = e match {
10+
case SUB.Refl() =>
11+
// unsound GADT constr because of approx state resetting:
12+
// A <: B
13+
x // error: Found: (x: A) Required: B
14+
}
15+
16+
def bad(x: Int): String =
17+
foo[Int, String, Tag { type T = Nothing } ](SUB.Refl(), x) // cast Int to String
18+
19+
object Test:
20+
def main(args: Array[String]): Unit = bad(1) // was: ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String

0 commit comments

Comments
 (0)