@@ -300,8 +300,9 @@ 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. (currently not enabled, see #9028) If `inst` is an intersection with some restricted base types, drop
304
- * the restricted base types from the intersection, 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`.
305
306
*
306
307
* Don't do these widenings if `bound` is a subtype of `scala.Singleton`.
307
308
* Also, if the result of these widenings is a TypeRef to a module class,
@@ -313,21 +314,36 @@ trait ConstraintHandling[AbstractContext] {
313
314
*/
314
315
def widenInferred (inst : Type , bound : Type )(implicit actx : AbstractContext ): Type =
315
316
316
- def isRestricted (tp : Type ) = tp.typeSymbol == defn.EnumValueClass // for now, to be generalized later
317
+ 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
320
+
321
+ def dropOneSuperTrait (tp : Type ): Type =
322
+ 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
+ else tpd match
327
+ case AndType (tp1, tp2) =>
328
+ val tp1w = dropOneSuperTrait(tp1)
329
+ if tp1w ne tp1 then tp1w & tp2
330
+ else
331
+ val tp2w = dropOneSuperTrait(tp2)
332
+ if tp2w ne tp2 then tp1 & tp2w
333
+ else tpd
334
+ case _ =>
335
+ tp
317
336
318
- def dropRestricted (tp : Type ): Type = tp.dealias match
319
- case tpd @ AndType (tp1, tp2) =>
320
- if isRestricted(tp1) then tp2
321
- else if isRestricted(tp2) then tp1
337
+ def recur (tp : Type ): Type =
338
+ val tpw = dropOneSuperTrait(tp)
339
+ if tpw eq tp then tp
340
+ else if tpw <:< bound then recur(tpw)
322
341
else
323
- val tpw = tpd.derivedAndType(dropRestricted(tp1), dropRestricted(tp2))
324
- if tpw ne tpd then tpw else tp
325
- case _ =>
326
- tp
342
+ keep += lastDropped
343
+ recur(tp)
327
344
328
- def widenRestricted (tp : Type ) =
329
- val tpw = dropRestricted(tp)
330
- if (tpw ne tp) && (tpw <:< bound) then tpw else tp
345
+ recur(tp)
346
+ end dropSuperTraits
331
347
332
348
def widenOr (tp : Type ) =
333
349
val tpw = tp.widenUnion
@@ -343,10 +359,7 @@ trait ConstraintHandling[AbstractContext] {
343
359
344
360
val wideInst =
345
361
if isSingleton(bound) then inst
346
- else /* widenRestricted*/ (widenOr(widenSingle(inst)))
347
- // widenRestricted is currently not called since it's special cased in `dropEnumValue`
348
- // in `Namer`. It's left in here in case we want to generalize the scheme to other
349
- // "protected inheritance" classes.
362
+ else dropSuperTraits(widenOr(widenSingle(inst)))
350
363
wideInst match
351
364
case wideInst : TypeRef if wideInst.symbol.is(Module ) =>
352
365
TermRef (wideInst.prefix, wideInst.symbol.sourceModule)
0 commit comments