@@ -154,24 +154,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
154154 case tp1 : NamedType =>
155155 val sym1 = tp1.symbol
156156 (if ((sym1 ne NoSymbol ) && (sym1 eq tp2.symbol))
157- ctx.erasedTypes || sym1.isStaticOwner ||
158- { // Implements: A # X <: B # X
159- // if either A =:= B (i.e. A <: B and B <: A), or the following three conditions hold:
160- // 1. X is a class type,
161- // 2. B is a class type without abstract type members.
162- // 3. A <: B.
163- // Dealiasing is taken care of elsewhere.
164- val pre1 = tp1.prefix
165- val pre2 = tp2.prefix
166- isSameType(pre1, pre2) ||
167- sym1.isClass &&
168- pre2.classSymbol.exists &&
169- pre2.abstractTypeMembers.isEmpty &&
170- isSubType(pre1, pre2)
171- }
157+ ctx.erasedTypes || sym1.isStaticOwner || isSubType(tp1.prefix, tp2.prefix)
172158 else
173159 (tp1.name eq tp2.name) &&
174- isSameType (tp1.prefix, tp2.prefix) &&
160+ isSubType (tp1.prefix, tp2.prefix) &&
175161 (tp1.signature == tp2.signature) &&
176162 ! tp1.isInstanceOf [WithFixedSym ] &&
177163 ! tp2.isInstanceOf [WithFixedSym ]
@@ -229,6 +215,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
229215 compareSuper
230216 case AndType (tp21, tp22) =>
231217 isSubType(tp1, tp21) && isSubType(tp1, tp22)
218+ case OrType (tp21, tp22) =>
219+ if (tp21.stripTypeVar eq tp22.stripTypeVar) isSubType(tp1, tp21)
220+ else secondTry(tp1, tp2)
232221 case TypeErasure .ErasedValueType (cls2, underlying2) =>
233222 def compareErasedValueType = tp1 match {
234223 case TypeErasure .ErasedValueType (cls1, underlying1) =>
@@ -291,6 +280,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
291280 isSubType(tp1.ref, tp2)
292281 case tp1 : AnnotatedType =>
293282 isSubType(tp1.tpe, tp2)
283+ case AndType (tp11, tp12) =>
284+ if (tp11.stripTypeVar eq tp12.stripTypeVar) isSubType(tp11, tp2)
285+ else thirdTry(tp1, tp2)
294286 case OrType (tp11, tp12) =>
295287 isSubType(tp11, tp2) && isSubType(tp12, tp2)
296288 case ErrorType =>
@@ -353,6 +345,21 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
353345 }
354346 compareRefined
355347 case OrType (tp21, tp22) =>
348+ // Rewrite T1 <: (T211 & T212) | T22 to T1 <: (T211 | T22) and T1 <: (T212 | T22)
349+ // and analogously for T1 <: T21 | (T221 & T222)
350+ // `|' types to the right of <: are problematic, because
351+ // we have to choose one constraint set or another, which might cut off
352+ // solutions. The rewriting delays the point where we have to choose.
353+ tp21 match {
354+ case AndType (tp211, tp212) =>
355+ return isSubType(tp1, OrType (tp211, tp22)) && isSubType(tp1, OrType (tp212, tp22))
356+ case _ =>
357+ }
358+ tp22 match {
359+ case AndType (tp221, tp222) =>
360+ return isSubType(tp1, OrType (tp21, tp221)) && isSubType(tp1, OrType (tp21, tp222))
361+ case _ =>
362+ }
356363 eitherIsSubType(tp1, tp21, tp1, tp22) || fourthTry(tp1, tp2)
357364 case tp2 @ MethodType (_, formals2) =>
358365 def compareMethod = tp1 match {
@@ -454,6 +461,21 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
454461 isNewSubType(tp1.parent, tp2) ||
455462 needsEtaLift(tp2, tp1) && tp2.testLifted(tp1.typeParams, isSubType(tp1, _), Nil )
456463 case AndType (tp11, tp12) =>
464+ // Rewrite (T111 | T112) & T12 <: T2 to (T111 & T12) <: T2 and (T112 | T12) <: T2
465+ // and analogously for T11 & (T121 | T122) & T12 <: T2
466+ // `&' types to the left of <: are problematic, because
467+ // we have to choose one constraint set or another, which might cut off
468+ // solutions. The rewriting delays the point where we have to choose.
469+ tp11 match {
470+ case OrType (tp111, tp112) =>
471+ return isSubType(AndType (tp111, tp12), tp2) && isSubType(AndType (tp112, tp12), tp2)
472+ case _ =>
473+ }
474+ tp12 match {
475+ case OrType (tp121, tp122) =>
476+ return isSubType(AndType (tp11, tp121), tp2) && isSubType(AndType (tp11, tp122), tp2)
477+ case _ =>
478+ }
457479 eitherIsSubType(tp11, tp2, tp12, tp2)
458480 case JavaArrayType (elem1) =>
459481 def compareJavaArray = tp2 match {
@@ -693,7 +715,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
693715 case formal1 :: rest1 =>
694716 formals2 match {
695717 case formal2 :: rest2 =>
696- (isSameType (formal1, formal2)
718+ (isSameTypeWhenFrozen (formal1, formal2)
697719 || isJava1 && (formal2 isRef ObjectClass ) && (formal1 isRef AnyClass )
698720 || isJava2 && (formal1 isRef ObjectClass ) && (formal2 isRef AnyClass )) &&
699721 matchingParams(rest1, rest2, isJava1, isJava2)
@@ -1067,7 +1089,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
10671089 case tp1 : ClassInfo =>
10681090 tp2 match {
10691091 case tp2 : ClassInfo =>
1070- isSubType (tp1.prefix, tp2.prefix) || (tp1.cls.owner derivesFrom tp2.cls.owner)
1092+ isSubTypeWhenFrozen (tp1.prefix, tp2.prefix) || (tp1.cls.owner derivesFrom tp2.cls.owner)
10711093 case _ =>
10721094 false
10731095 }
@@ -1083,7 +1105,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
10831105 tp2 match {
10841106 case tp2 : MethodType =>
10851107 def asGoodParams (formals1 : List [Type ], formals2 : List [Type ]) =
1086- (formals2 corresponds formals1)(isSubType )
1108+ (formals2 corresponds formals1)(isSubTypeWhenFrozen )
10871109 asGoodParams(tp1.paramTypes, tp2.paramTypes) &&
10881110 (! asGoodParams(tp2.paramTypes, tp1.paramTypes) ||
10891111 isAsGood(tp1.resultType, tp2.resultType))
0 commit comments