@@ -286,18 +286,53 @@ trait ConstraintHandling {
286
286
}
287
287
}
288
288
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
+
289
329
/** Widen inferred type `inst` with upper `bound`, according to the following rules:
290
330
* 1. If `inst` is a singleton type, or a union containing some singleton types,
291
331
* widen (all) the singleton type(s), provided the result is a subtype of `bound`
292
332
* (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint)
293
333
* 2. If `inst` is a union type, approximate the union type from above by an intersection
294
334
* 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)
301
336
*
302
337
* Don't do these widenings if `bound` is a subtype of `scala.Singleton`.
303
338
* Also, if the result of these widenings is a TypeRef to a module class,
@@ -308,40 +343,6 @@ trait ConstraintHandling {
308
343
* as those could leak the annotation to users (see run/inferred-repeated-result).
309
344
*/
310
345
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
-
345
346
def widenOr (tp : Type ) =
346
347
val tpw = tp.widenUnion
347
348
if (tpw ne tp) && (tpw <:< bound) then tpw else tp
@@ -356,7 +357,7 @@ trait ConstraintHandling {
356
357
357
358
val wideInst =
358
359
if isSingleton(bound) then inst
359
- else dropSuperTraits(widenOr(widenSingle(inst)))
360
+ else dropSuperTraits(widenOr(widenSingle(inst)), bound )
360
361
wideInst match
361
362
case wideInst : TypeRef if wideInst.symbol.is(Module ) =>
362
363
TermRef (wideInst.prefix, wideInst.symbol.sourceModule)
0 commit comments