Skip to content

Commit 9d5e90a

Browse files
committed
Record ordering constraint between HK type variables
If `?F <: [X] => ?G[X]`, then the ordering part of the constraint should record `?F <: ?G`, otherwise constraints won't be propagated correctly. It's not clear to me if we should make a similar change in `stripParams` but note that doing so would require being a bit careful: since we use the upper bound of a type variable to determine its kind, we can't just replace it by `[X] => ?G[X]` by `AnyKind`. Fixes #9676.
1 parent 8c94870 commit 9d5e90a

File tree

4 files changed

+22
-6
lines changed

4 files changed

+22
-6
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools
22
package dotc
33
package core
44

5-
import Types._, Contexts._, Symbols._, Decorators._
5+
import Types._, Contexts._, Symbols._, Decorators._, TypeApplications._
66
import util.SimpleIdentityMap
77
import collection.mutable
88
import printing.Printer
@@ -360,13 +360,15 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
360360
* Q <: tp implies Q <: P and isUpper = true, or
361361
* tp <: Q implies P <: Q and isUpper = false
362362
*/
363-
private def dependentParams(tp: Type, isUpper: Boolean): List[TypeParamRef] = tp match
363+
private def dependentParams(tp: Type, isUpper: Boolean)(using Context): List[TypeParamRef] = tp match
364364
case param: TypeParamRef if contains(param) =>
365365
param :: (if (isUpper) upper(param) else lower(param))
366366
case tp: AndType if isUpper =>
367367
dependentParams(tp.tp1, isUpper) | (dependentParams(tp.tp2, isUpper))
368368
case tp: OrType if !isUpper =>
369369
dependentParams(tp.tp1, isUpper).intersect(dependentParams(tp.tp2, isUpper))
370+
case EtaExpansion(tycon) =>
371+
dependentParams(tycon, isUpper)
370372
case _ =>
371373
Nil
372374

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ object TypeApplications {
3939
tycon.EtaExpand(tycon.typeParamSymbols)
4040
}
4141

42-
def unapply(tp: Type)(using Context): Option[TypeRef] = tp match {
43-
case tp @ HKTypeLambda(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.paramRef)) => Some(fn)
42+
def unapply(tp: Type)(using Context): Option[Type] = tp match {
43+
case tp @ HKTypeLambda(tparams, AppliedType(fn: Type, args))
44+
if args.lazyZip(tparams).forall((arg, tparam) => arg == tparam.paramRef) => Some(fn)
4445
case _ => None
4546
}
4647
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
605605
if (tparams1.nonEmpty)
606606
return recur(tp1.EtaExpand(tparams1), tp2) || fourthTry
607607
tp2 match {
608-
case EtaExpansion(tycon2) if tycon2.symbol.isClass && tycon2.symbol.is(JavaDefined) =>
608+
case EtaExpansion(tycon2: TypeRef) if tycon2.typeSymbol.isClass && tycon2.symbol.is(JavaDefined) =>
609609
recur(tp1, tycon2) || fourthTry
610610
case _ =>
611611
fourthTry
@@ -769,7 +769,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
769769
isNewSubType(tp1.parent)
770770
case tp1: HKTypeLambda =>
771771
def compareHKLambda = tp1 match {
772-
case EtaExpansion(tycon1) if tycon1.symbol.isClass && tycon1.symbol.is(JavaDefined) =>
772+
case EtaExpansion(tycon1: TypeRef) if tycon1.symbol.isClass && tycon1.symbol.is(JavaDefined) =>
773773
// It's a raw type that was mistakenly eta-expanded to a hk-type.
774774
// This can happen because we do not cook types coming from Java sources
775775
recur(tycon1, tp2)

tests/pos/i9676.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
trait SubtypeOf[A[_], B[_]]
2+
3+
object Test1 {
4+
def instance[F[_], G[a] >: F[a]]: SubtypeOf[F, G] = new SubtypeOf[F, G] {}
5+
6+
val x: SubtypeOf[List, Seq] = instance
7+
}
8+
9+
object Test2 {
10+
def instance[G[_], F[a] <: G[a]]: SubtypeOf[F, G] = new SubtypeOf[F, G] {}
11+
12+
val x: SubtypeOf[List, Seq] = instance
13+
}

0 commit comments

Comments
 (0)