Skip to content

Commit a2974d9

Browse files
authored
Merge pull request #14728 from Linyxus/fix-gadt-sngl
Avoid unsound GADT constraints derived from subtyping relations between singletons and refined types
2 parents 18275ba + a64af57 commit a2974d9

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

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

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

1816+
def tp1IsSingleton: Boolean = tp1.isInstanceOf[SingletonType]
1817+
18161818
// A relaxed version of isSubType, which compares method types
18171819
// under the standard arrow rule which is contravarient in the parameter types,
18181820
// but under the condition that signatures might have to match (see sigsOK)
@@ -1827,8 +1829,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
18271829
matchingMethodParams(info1, info2, precise = false)
18281830
&& isSubInfo(info1.resultType, info2.resultType.subst(info2, info1), symInfo1.resultType)
18291831
&& sigsOK(symInfo1, info2)
1830-
case _ => isSubType(info1, info2)
1831-
case _ => isSubType(info1, info2)
1832+
case _ => inFrozenGadtIf(tp1IsSingleton) { isSubType(info1, info2) }
1833+
case _ => inFrozenGadtIf(tp1IsSingleton) { isSubType(info1, info2) }
18321834

18331835
val info1 = m.info.widenExpr
18341836
isSubInfo(info1, tp2.refinedInfo.widenExpr, m.symbol.info.orElse(info1))

tests/neg/gadt-sngl-refined.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
trait Foo {
2+
type A >: Nothing <: Any
3+
}
4+
5+
enum SUB[-A, +B]:
6+
case Refl[X]() extends SUB[X, X]
7+
8+
import SUB._
9+
10+
def test[X](foo: Foo, e: SUB[foo.type, Foo {type A <: X}], x: Any): X = e match
11+
case Refl() =>
12+
// From foo.type <:< Foo{type A <: X} we should not infer GADT constraints.
13+
x // error
14+
15+
val foo = new Foo { type A = Nothing }
16+
17+
def unsound(x: Any): Nothing =
18+
test[Nothing](foo, Refl(), x)

0 commit comments

Comments
 (0)