@@ -446,8 +446,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
446446 case tp2 : HKTypeLambda =>
447447 def compareTypeLambda : Boolean = tp1.stripTypeVar match {
448448 case tp1 : HKTypeLambda =>
449- /* Don't compare bounds or variances of lambdas under language:Scala2.
450- * (1) If we compare bounds, t2994 will fail.
449+ /* Don't compare bounds of lambdas under language:Scala2, or t2994 will fail.
451450 * The issue is that, logically, bounds should compare contravariantly,
452451 * but that would invalidate a pattern exploited in t2994:
453452 *
@@ -459,32 +458,17 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
459458 *
460459 * Note: it would be nice if this could trigger a migration warning, but I
461460 * am not sure how, since the code is buried so deep in subtyping logic.
462- *
463- * (2) If we compare variances, compilation of scala.collection.mutable.Set wil fail.
464- * The issue is the following:
465- *
466- * Error overriding method companion in trait Iterable of type
467- * => scala.collection.generic.GenericCompanion[[+A] => scala.collection.Iterable[A]];
468- * method companion of type
469- * => scala.collection.generic.GenericCompanion[[A] => scala.collection.mutable.Set[A]]
470- * has incompatible type.
471- *
472- * Indeed, a non-variant Set is not a legal substitute for a covariant Iterable.
473- * Every instantiated Set is an Iterable, but the type constructor Iterable can be
474- * passed to a covariant type constructor CC[+X] whereas a non-variant Set cannot.
475461 */
476462 def boundsOK =
477463 ctx.scala2Mode ||
478464 tp1.typeParams.corresponds(tp2.typeParams)((tparam1, tparam2) =>
479465 isSubType(tparam2.paramInfo.subst(tp2, tp1), tparam1.paramInfo))
480- def variancesOK =
481- ctx.scala2Mode ||
482- variancesConform(tp1.typeParams, tp2.typeParams)
483466 val saved = comparedTypeLambdas
484467 comparedTypeLambdas += tp1
485468 comparedTypeLambdas += tp2
486469 try
487- variancesOK && boundsOK &&
470+ variancesConform(tp1.typeParams, tp2.typeParams) &&
471+ boundsOK &&
488472 isSubType(tp1.resType, tp2.resType.subst(tp2, tp1))
489473 finally comparedTypeLambdas = saved
490474 case _ =>
@@ -1014,7 +998,14 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
1014998 }
1015999 }
10161000
1017- isSubArg(args1.head, args2.head)
1001+ val arg1 = args1.head
1002+ val arg2 = args2.head
1003+ isSubArg(arg1, arg2) || {
1004+ // last effort: try to adapt variances of higher-kinded types if this is sound.
1005+ // TODO: Move this to eta-expansion?
1006+ val adapted2 = arg2.adaptHkVariances(tparam.paramInfo)
1007+ adapted2.ne(arg2) && isSubArg(arg1, adapted2)
1008+ }
10181009 } && isSubArgs(args1.tail, args2.tail, tp1, tparams.tail)
10191010
10201011 /** Test whether `tp1` has a base type of the form `B[T1, ..., Tn]` where
@@ -1186,6 +1177,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
11861177 def hasSubRefinement (tp1 : RefinedType , refine2 : Type ): Boolean = {
11871178 isSubType(tp1.refinedInfo, refine2) || {
11881179 // last effort: try to adapt variances of higher-kinded types if this is sound.
1180+ // TODO: Move this to eta-expansion?
11891181 val adapted2 = refine2.adaptHkVariances(tp1.parent.member(tp1.refinedName).symbol.info)
11901182 adapted2.ne(refine2) && hasSubRefinement(tp1, adapted2)
11911183 }
0 commit comments