@@ -286,18 +286,53 @@ trait ConstraintHandling {
286286 }
287287 }
288288
289+ /** If `tp` is an intersection such that some operands are super trait instances
290+ * and others are not, replace as many super trait instances as possible with Any
291+ * as long as the result is still a subtype of `bound`. But fall back to the
292+ * original type if the resulting widened type is a supertype of all dropped
293+ * types (since in this case the type was not a true intersection of super traits
294+ * and other types to start with).
295+ */
296+ def dropSuperTraits (tp : Type , bound : Type )(using Context ): Type =
297+ var kept : Set [Type ] = Set () // types to keep since otherwise bound would not fit
298+ var dropped : List [Type ] = List () // the types dropped so far, last one on top
299+
300+ def dropOneSuperTrait (tp : Type ): Type =
301+ val tpd = tp.dealias
302+ if tpd.typeSymbol.isSuperTrait && ! tpd.isLambdaSub && ! kept.contains(tpd) then
303+ dropped = tpd :: dropped
304+ defn.AnyType
305+ else tpd match
306+ case AndType (tp1, tp2) =>
307+ val tp1w = dropOneSuperTrait(tp1)
308+ if tp1w ne tp1 then tp1w & tp2
309+ else
310+ val tp2w = dropOneSuperTrait(tp2)
311+ if tp2w ne tp2 then tp1 & tp2w
312+ else tpd
313+ case _ =>
314+ tp
315+
316+ def recur (tp : Type ): Type =
317+ val tpw = dropOneSuperTrait(tp)
318+ if tpw eq tp then tp
319+ else if tpw <:< bound then recur(tpw)
320+ else
321+ kept += dropped.head
322+ dropped = dropped.tail
323+ recur(tp)
324+
325+ val tpw = recur(tp)
326+ if (tpw eq tp) || dropped.forall(_ frozen_<:< tpw) then tp else tpw
327+ end dropSuperTraits
328+
289329 /** Widen inferred type `inst` with upper `bound`, according to the following rules:
290330 * 1. If `inst` is a singleton type, or a union containing some singleton types,
291331 * widen (all) the singleton type(s), provided the result is a subtype of `bound`
292332 * (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint)
293333 * 2. If `inst` is a union type, approximate the union type from above by an intersection
294334 * of all common base types, provided the result is a subtype of `bound`.
295- * 3. If `inst` is an intersection such that some operands are super trait instances
296- * and others are not, replace as many super trait instances as possible with Any
297- * as long as the result is still a subtype of `bound`. But fall back to the
298- * original type if the resulting widened type is a supertype of all dropped
299- * types (since in this case the type was not a true intersection of super traits
300- * and other types to start with).
335+ * 3. drop super traits from intersections (see @dropSuperTraits)
301336 *
302337 * Don't do these widenings if `bound` is a subtype of `scala.Singleton`.
303338 * Also, if the result of these widenings is a TypeRef to a module class,
@@ -308,40 +343,6 @@ trait ConstraintHandling {
308343 * as those could leak the annotation to users (see run/inferred-repeated-result).
309344 */
310345 def widenInferred (inst : Type , bound : Type )(using Context ): Type =
311-
312- def dropSuperTraits (tp : Type ): Type =
313- var kept : Set [Type ] = Set () // types to keep since otherwise bound would not fit
314- var dropped : List [Type ] = List () // the types dropped so far, last one on top
315-
316- def dropOneSuperTrait (tp : Type ): Type =
317- val tpd = tp.dealias
318- if tpd.typeSymbol.isSuperTrait && ! tpd.isLambdaSub && ! kept.contains(tpd) then
319- dropped = tpd :: dropped
320- defn.AnyType
321- else tpd match
322- case AndType (tp1, tp2) =>
323- val tp1w = dropOneSuperTrait(tp1)
324- if tp1w ne tp1 then tp1w & tp2
325- else
326- val tp2w = dropOneSuperTrait(tp2)
327- if tp2w ne tp2 then tp1 & tp2w
328- else tpd
329- case _ =>
330- tp
331-
332- def recur (tp : Type ): Type =
333- val tpw = dropOneSuperTrait(tp)
334- if tpw eq tp then tp
335- else if tpw <:< bound then recur(tpw)
336- else
337- kept += dropped.head
338- dropped = dropped.tail
339- recur(tp)
340-
341- val tpw = recur(tp)
342- if (tpw eq tp) || dropped.forall(_ frozen_<:< tpw) then tp else tpw
343- end dropSuperTraits
344-
345346 def widenOr (tp : Type ) =
346347 val tpw = tp.widenUnion
347348 if (tpw ne tp) && (tpw <:< bound) then tpw else tp
@@ -356,7 +357,7 @@ trait ConstraintHandling {
356357
357358 val wideInst =
358359 if isSingleton(bound) then inst
359- else dropSuperTraits(widenOr(widenSingle(inst)))
360+ else dropSuperTraits(widenOr(widenSingle(inst)), bound )
360361 wideInst match
361362 case wideInst : TypeRef if wideInst.symbol.is(Module ) =>
362363 TermRef (wideInst.prefix, wideInst.symbol.sourceModule)
0 commit comments