@@ -300,9 +300,12 @@ trait ConstraintHandling[AbstractContext] {
300
300
* (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint)
301
301
* 2. If `inst` is a union type, approximate the union type from above by an intersection
302
302
* of all common base types, provided the result is a subtype of `bound`.
303
- * 3. If `inst` a super trait instance or an intersection with some super trait
304
- * parents, replace all super trait instances with AnyRef (or Any, if the trait
305
- * is a universal trait) as long as the result is a subtype of `bound`.
303
+ * 3. If `inst` an intersection such that some operands are super trait instances
304
+ * and others are not, replace as many super trait instances as possible with Any
305
+ * as long as the result is still a subtype of `bound`. But fall back to the
306
+ * original type if the resulting widened type is a supertype of all dropped
307
+ * types (since in this case the type was not a true intersection of super traits
308
+ * and other types to start with).
306
309
*
307
310
* Don't do these widenings if `bound` is a subtype of `scala.Singleton`.
308
311
* Also, if the result of these widenings is a TypeRef to a module class,
@@ -315,14 +318,14 @@ trait ConstraintHandling[AbstractContext] {
315
318
def widenInferred (inst : Type , bound : Type )(implicit actx : AbstractContext ): Type =
316
319
317
320
def dropSuperTraits (tp : Type ): Type =
318
- var keep : Set [Type ] = Set () // types to keep since otherwise bound would not fit
319
- var lastDropped : Type = NoType // the last type dropped in dropOneSuperTrait
321
+ var kept : Set [Type ] = Set () // types to keep since otherwise bound would not fit
322
+ var dropped : List [ Type ] = List () // the types dropped so far, last one on top
320
323
321
324
def dropOneSuperTrait (tp : Type ): Type =
322
325
val tpd = tp.dealias
323
- if tpd.typeSymbol.isSuperTrait && ! tpd.isLambdaSub && ! keep .contains(tpd) then
324
- lastDropped = tpd
325
- if tpd.derivesFrom(defn. ObjectClass ) then defn. ObjectType else defn.AnyType
326
+ if tpd.typeSymbol.isSuperTrait && ! tpd.isLambdaSub && ! kept .contains(tpd) then
327
+ dropped = tpd :: dropped
328
+ defn.AnyType
326
329
else tpd match
327
330
case AndType (tp1, tp2) =>
328
331
val tp1w = dropOneSuperTrait(tp1)
@@ -339,10 +342,12 @@ trait ConstraintHandling[AbstractContext] {
339
342
if tpw eq tp then tp
340
343
else if tpw <:< bound then recur(tpw)
341
344
else
342
- keep += lastDropped
345
+ kept += dropped.head
346
+ dropped = dropped.tail
343
347
recur(tp)
344
348
345
- recur(tp)
349
+ val tpw = recur(tp)
350
+ if (tpw eq tp) || dropped.forall(_ frozen_<:< tpw) then tp else tpw
346
351
end dropSuperTraits
347
352
348
353
def widenOr (tp : Type ) =
0 commit comments