Skip to content

Commit dcf176b

Browse files
authored
Fix existing GADT constraints with introduced pattern-bound symbols (#22928)
Fixes #22879
2 parents 7976598 + 9173814 commit dcf176b

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

Diff for: compiler/src/dotty/tools/dotc/core/GadtConstraint.scala

+15
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ class GadtConstraint private (
3333
reverseMapping = reverseMapping.updated(tv.origin, sym),
3434
)
3535

36+
def replace(param: TypeParamRef, tp: Type)(using Context) =
37+
var constr = constraint
38+
for
39+
poly <- constraint.domainLambdas
40+
paramRef <- poly.paramRefs
41+
do
42+
val entry0 = constr.entry(paramRef)
43+
val entry1 = entry0.substParam(param, tp)
44+
if entry1 ne entry0 then
45+
constr = constr.updateEntry(paramRef, entry1)
46+
withConstraint(constr)
47+
3648
/** Is `sym1` ordered to be less than `sym2`? */
3749
def isLess(sym1: Symbol, sym2: Symbol)(using Context): Boolean =
3850
constraint.isLess(tvarOrError(sym1).origin, tvarOrError(sym2).origin)
@@ -245,6 +257,9 @@ sealed trait GadtState {
245257
result
246258
}
247259

260+
def replace(param: TypeParamRef, tp: Type)(using Context) =
261+
gadt = gadt.replace(param, tp)
262+
248263
/** See [[ConstraintHandling.approximation]] */
249264
def approximation(sym: Symbol, fromBelow: Boolean, maxLevel: Int = Int.MaxValue)(using Context): Type = {
250265
approximation(gadt.tvarOrError(sym).origin, fromBelow, maxLevel).match

Diff for: compiler/src/dotty/tools/dotc/typer/Inferencing.scala

+6-1
Original file line numberDiff line numberDiff line change
@@ -509,10 +509,15 @@ object Inferencing {
509509
}
510510
}
511511
}
512-
val res = patternBindings.toList.map { (boundSym, _) =>
512+
val res = patternBindings.toList.map { (boundSym, origin) =>
513513
// substitute bounds of pattern bound variables to deal with possible F-bounds
514514
for (wildCard, param) <- patternBindings do
515515
boundSym.info = boundSym.info.substParam(param, wildCard.typeRef)
516+
517+
// also substitute in any GADT bounds
518+
// e.g. in i22879, replace the `T` in `X <: Iterable[T]` with the pattern bound `T$1`
519+
ctx.gadtState.replace(origin, boundSym.typeRef)
520+
516521
boundSym
517522
}
518523

Diff for: tests/pos/i22879.scala

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
sealed trait E[S]
2+
final case class I[T, U <: Iterable[T]]() extends E[U]
3+
class Test {
4+
def test[X](a: E[X]): Unit = {
5+
a match {
6+
case I() => ???
7+
}
8+
}
9+
}

0 commit comments

Comments
 (0)