Skip to content

Commit c0ff503

Browse files
authored
Merge pull request #10109 from dotty-staging/fix-9533
Fix #9533: handle nested TypeParamRef in bounds
2 parents cf8fbd8 + f97d6de commit c0ff503

File tree

2 files changed

+32
-19
lines changed

2 files changed

+32
-19
lines changed

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

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ final class ProperGadtConstraint private(
173173
case null => null
174174
case tv =>
175175
fullBounds(tv.origin)
176-
.ensuring(containsNoInternalTypes(_))
176+
// .ensuring(containsNoInternalTypes(_))
177177
}
178178

179179
override def bounds(sym: Symbol)(using Context): TypeBounds =
@@ -223,24 +223,27 @@ final class ProperGadtConstraint private(
223223
override protected def isSub(tp1: Type, tp2: Type)(using Context): Boolean = TypeComparer.isSubType(tp1, tp2)
224224
override protected def isSame(tp1: Type, tp2: Type)(using Context): Boolean = TypeComparer.isSameType(tp1, tp2)
225225

226-
override def nonParamBounds(param: TypeParamRef)(using Context): TypeBounds =
227-
constraint.nonParamBounds(param) match {
228-
case TypeAlias(tpr: TypeParamRef) => TypeAlias(externalize(tpr))
229-
case tb => tb
230-
}
231-
232-
override def fullLowerBound(param: TypeParamRef)(using Context): Type =
233-
constraint.minLower(param).foldLeft(nonParamBounds(param).lo) {
234-
(t, u) => t | externalize(u)
235-
}
236-
237-
override def fullUpperBound(param: TypeParamRef)(using Context): Type =
238-
constraint.minUpper(param).foldLeft(nonParamBounds(param).hi) { (t, u) =>
239-
val eu = externalize(u)
240-
// Any as the upper bound means "no bound", but if F is higher-kinded,
241-
// Any & F = F[_]; this is wrong for us so we need to short-circuit
242-
if t.isAny then eu else t & eu
243-
}
226+
override def nonParamBounds(param: TypeParamRef)(using Context): TypeBounds =
227+
val externalizeMap = new TypeMap {
228+
def apply(tp: Type): Type = tp match {
229+
case tpr: TypeParamRef => externalize(tpr)
230+
case tp => mapOver(tp)
231+
}
232+
}
233+
externalizeMap(constraint.nonParamBounds(param)).bounds
234+
235+
override def fullLowerBound(param: TypeParamRef)(using Context): Type =
236+
constraint.minLower(param).foldLeft(nonParamBounds(param).lo) {
237+
(t, u) => t | externalize(u)
238+
}
239+
240+
override def fullUpperBound(param: TypeParamRef)(using Context): Type =
241+
constraint.minUpper(param).foldLeft(nonParamBounds(param).hi) { (t, u) =>
242+
val eu = externalize(u)
243+
// Any as the upper bound means "no bound", but if F is higher-kinded,
244+
// Any & F = F[_]; this is wrong for us so we need to short-circuit
245+
if t.isAny then eu else t & eu
246+
}
244247

245248
// ---- Private ----------------------------------------------------------
246249

tests/pos/i9533.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
object Test {
2+
sealed trait Base[-X]
3+
case class Child[X]() extends Base[X]
4+
5+
def apply[A, B](r: Base[A with B]): Unit = {
6+
r match {
7+
case Child() => ()
8+
}
9+
}
10+
}

0 commit comments

Comments
 (0)