From eae892085305d84dcde3415acf199fce64ac4473 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 23 Mar 2022 17:23:05 +0100 Subject: [PATCH 1/2] Keep correct kind when preparing constraint in stripParams Fixes #14760 --- .../dotty/tools/dotc/core/OrderingConstraint.scala | 2 +- .../dotty/tools/dotc/core/TypeApplications.scala | 13 +++++++++++++ tests/pos/i14760.scala | 5 +++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i14760.scala diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index d311f3d981d8..714383bafcd7 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -248,7 +248,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, NoType case tp: TypeBounds => val lo1 = stripParams(tp.lo, todos, !isUpper).orElse(defn.NothingType) - val hi1 = stripParams(tp.hi, todos, isUpper).orElse(defn.AnyKindType) + val hi1 = stripParams(tp.hi, todos, isUpper).orElse(tp.kind) tp.derivedTypeBounds(lo1, hi1) case tp: AndType if isUpper => val tp1 = stripParams(tp.tp1, todos, isUpper) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index da1817090d7a..4438b5550938 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -258,6 +258,19 @@ class TypeApplications(val self: Type) extends AnyVal { case _ => NoType } + /** The kind of a type is the largest type capturing the parameter shape + * of a type without looking at precise bounds. + * - The kind of single-kinded types is Any + * - A kind like (* -> *) -> * is represented as [X1 <: [X2] =>> Any] =>> Any + */ + def kind(using Context): Type = self.hkResult match + case NoType => defn.AnyType + case self: TypeRef if self.symbol == defn.AnyKindClass => self + case rt => + HKTypeLambda( + self.typeParams.map(tparam => TypeBounds.upper(tparam.paramInfo.hiBound.kind)), + rt.kind) + /** Do self and other have the same kinds (not counting bounds and variances)? * Note: An any-kinded type "has the same kind" as any other type. */ diff --git a/tests/pos/i14760.scala b/tests/pos/i14760.scala new file mode 100644 index 000000000000..a913361c83eb --- /dev/null +++ b/tests/pos/i14760.scala @@ -0,0 +1,5 @@ +enum SUB[-A, +B]: + case Refl[X]() extends SUB[X, X] + +def foo[C, A >: C <: C, B](e: SUB[B, A]) = e match + case SUB.Refl() => \ No newline at end of file From c2a7bf5095ec548dde78b4f45e46f90d443be107 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 23 Mar 2022 18:05:10 +0100 Subject: [PATCH 2/2] use topType instead of kind topType already does what we need here, and it is also correct for classes. --- .../tools/dotc/core/OrderingConstraint.scala | 2 +- .../tools/dotc/core/TypeApplications.scala | 19 +++++-------------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 714383bafcd7..6974f7f1b836 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -248,7 +248,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, NoType case tp: TypeBounds => val lo1 = stripParams(tp.lo, todos, !isUpper).orElse(defn.NothingType) - val hi1 = stripParams(tp.hi, todos, isUpper).orElse(tp.kind) + val hi1 = stripParams(tp.hi, todos, isUpper).orElse(tp.topType) tp.derivedTypeBounds(lo1, hi1) case tp: AndType if isUpper => val tp1 = stripParams(tp.tp1, todos, isUpper) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 4438b5550938..862e1b698a28 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -229,7 +229,11 @@ class TypeApplications(val self: Type) extends AnyVal { (alias ne self) && alias.hasSimpleKind } - /** The top type with the same kind as `self`. */ + /** The top type with the same kind as `self`. This is largest type capturing + * the parameter shape of a type without looking at precise bounds. + * - The top-type of simple-kinded types is Any + * - A kind like (* -> *) -> * is represented by the top type [X1 <: [X2] =>> Any] =>> Any + */ def topType(using Context): Type = if self.hasSimpleKind then defn.AnyType @@ -258,19 +262,6 @@ class TypeApplications(val self: Type) extends AnyVal { case _ => NoType } - /** The kind of a type is the largest type capturing the parameter shape - * of a type without looking at precise bounds. - * - The kind of single-kinded types is Any - * - A kind like (* -> *) -> * is represented as [X1 <: [X2] =>> Any] =>> Any - */ - def kind(using Context): Type = self.hkResult match - case NoType => defn.AnyType - case self: TypeRef if self.symbol == defn.AnyKindClass => self - case rt => - HKTypeLambda( - self.typeParams.map(tparam => TypeBounds.upper(tparam.paramInfo.hiBound.kind)), - rt.kind) - /** Do self and other have the same kinds (not counting bounds and variances)? * Note: An any-kinded type "has the same kind" as any other type. */