@@ -300,8 +300,9 @@ trait ConstraintHandling[AbstractContext] {
300300 * (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint)
301301 * 2. If `inst` is a union type, approximate the union type from above by an intersection
302302 * 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`.
305306 *
306307 * Don't do these widenings if `bound` is a subtype of `scala.Singleton`.
307308 * Also, if the result of these widenings is a TypeRef to a module class,
@@ -313,21 +314,36 @@ trait ConstraintHandling[AbstractContext] {
313314 */
314315 def widenInferred (inst : Type , bound : Type )(implicit actx : AbstractContext ): Type =
315316
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
317336
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)
322341 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)
327344
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
331347
332348 def widenOr (tp : Type ) =
333349 val tpw = tp.widenUnion
@@ -343,10 +359,7 @@ trait ConstraintHandling[AbstractContext] {
343359
344360 val wideInst =
345361 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)))
350363 wideInst match
351364 case wideInst : TypeRef if wideInst.symbol.is(Module ) =>
352365 TermRef (wideInst.prefix, wideInst.symbol.sourceModule)
0 commit comments