Skip to content

Commit a4594dd

Browse files
committed
Fix #1515: Don't narrow gadt bounds when frozen
Fixes #1515. Review by @smarter.
1 parent 8bfaada commit a4594dd

File tree

2 files changed

+38
-21
lines changed

2 files changed

+38
-21
lines changed

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

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -965,28 +965,29 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
965965
* Test that the resulting bounds are still satisfiable.
966966
*/
967967
private def narrowGADTBounds(tr: NamedType, bound: Type, isUpper: Boolean): Boolean =
968-
ctx.mode.is(Mode.GADTflexible) && {
969-
val tparam = tr.symbol
970-
typr.println(i"narrow gadt bound of $tparam: ${tparam.info} from ${if (isUpper) "above" else "below"} to $bound ${bound.isRef(tparam)}")
971-
if (bound.isRef(tparam)) false
972-
else bound match {
973-
case bound: TypeRef
974-
if bound.symbol.is(BindDefinedType) && ctx.gadt.bounds.contains(bound.symbol) &&
975-
!tr.symbol.is(BindDefinedType) =>
976-
// Avoid having pattern-bound types in gadt bounds,
977-
// as these might be eliminated once the pattern is typechecked.
978-
// Pattern-bound type symbols should be narrowed first, only if that fails
979-
// should symbols in the environment be constrained.
980-
narrowGADTBounds(bound, tr, !isUpper)
981-
case _ =>
982-
val oldBounds = ctx.gadt.bounds(tparam)
983-
val newBounds =
984-
if (isUpper) TypeBounds(oldBounds.lo, oldBounds.hi & bound)
985-
else TypeBounds(oldBounds.lo | bound, oldBounds.hi)
986-
isSubType(newBounds.lo, newBounds.hi) &&
987-
{ ctx.gadt.setBounds(tparam, newBounds); true }
968+
ctx.mode.is(Mode.GADTflexible) && !frozenConstraint && {
969+
val tparam = tr.symbol
970+
typr.println(i"narrow gadt bound of $tparam: ${tparam.info} from ${if (isUpper) "above" else "below"} to $bound ${bound.isRef(tparam)}")
971+
if (bound.isRef(tparam)) false
972+
else bound match {
973+
case bound: TypeRef
974+
if bound.symbol.is(BindDefinedType) &&
975+
ctx.gadt.bounds.contains(bound.symbol) &&
976+
!tr.symbol.is(BindDefinedType) =>
977+
// Avoid having pattern-bound types in gadt bounds,
978+
// as these might be eliminated once the pattern is typechecked.
979+
// Pattern-bound type symbols should be narrowed first, only if that fails
980+
// should symbols in the environment be constrained.
981+
narrowGADTBounds(bound, tr, !isUpper)
982+
case _ =>
983+
val oldBounds = ctx.gadt.bounds(tparam)
984+
val newBounds =
985+
if (isUpper) TypeBounds(oldBounds.lo, oldBounds.hi & bound)
986+
else TypeBounds(oldBounds.lo | bound, oldBounds.hi)
987+
isSubType(newBounds.lo, newBounds.hi) &&
988+
{ ctx.gadt.setBounds(tparam, newBounds); true }
989+
}
988990
}
989-
}
990991

991992
// Tests around `matches`
992993

tests/pos/i1515.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sealed trait Trait[T]
2+
3+
final case class Case[T](e: T) extends Trait[T]
4+
5+
object Demo {
6+
def main(args: Array[String]): Unit = {
7+
8+
def f[H](t: Trait[H]): Unit =
9+
t match {
10+
case Case(e) => println(Some(e))
11+
}
12+
13+
f(Case(1))
14+
15+
}
16+
}

0 commit comments

Comments
 (0)