@@ -460,66 +460,36 @@ trait ConstraintHandling[AbstractContext] {
460
460
if (fromBelow) isSubType(bound, tp) else isSubType(tp, bound)
461
461
}
462
462
463
- /** Drop all constrained parameters that occur at the toplevel in `bound` and
464
- * handle them by `addLess` calls.
465
- * The preconditions make sure that such parameters occur only
466
- * in one of two ways:
463
+ /** Normalize the bound `bnd` in the following ways:
467
464
*
468
- * 1.
465
+ * 1. Any toplevel occurrences of the compared parameter `param` are
466
+ * replaced by `Nothing` if bound is from below or `Any` otherwise.
467
+ * 2. Toplevel occurrences of TypeVars over TypeRefs in the current
468
+ * constraint are dereferenced.
469
+ * 3. Toplevel occurrences of TypeRefs that are instantiated in the current
470
+ * constraint are also referenced.
471
+ * 4. Toplevel occurrences of ExprTypes lead to a `NoType` return, which
472
+ * causes the addConstraint operation to fail.
469
473
*
470
- * P <: Ts1 | ... | Tsm (m > 0)
471
- * Tsi = T1 & ... Tn (n >= 0)
472
- * Some of the Ti are constrained parameters
473
- *
474
- * 2.
475
- *
476
- * Ts1 & ... & Tsm <: P (m > 0)
477
- * Tsi = T1 | ... | Tn (n >= 0)
478
- * Some of the Ti are constrained parameters
479
- *
480
- * In each case we cannot leave the parameter in place,
481
- * because that would risk making a parameter later a subtype or supertype
482
- * of a bound where the parameter occurs again at toplevel, which leads to cycles
483
- * in the subtyping test. So we intentionally narrow the constraint by
484
- * recording an isLess relationship instead (even though this is not implied
485
- * by the bound).
486
- *
487
- * Normally, narrowing a constraint is better than widening it, because
488
- * narrowing leads to incompleteness (which we face anyway, see for
489
- * instance `TypeComparer#either`) but widening leads to unsoundness,
490
- * but note the special handling in `ConstrainResult` mode below.
491
- *
492
- * A test case that demonstrates the problem is i864.scala.
493
- * Turn Config.checkConstraintsSeparated on to get an accurate diagnostic
494
- * of the cycle when it is created.
495
- *
496
- * @return The pruned type if all `addLess` calls succeed, `NoType` otherwise.
474
+ * An occurrence is toplevel if it is the bound itself,
475
+ * or the bound is a union or intersection, and the ocurrence is
476
+ * toplevel in one of the operands of the `&` or `|`.
497
477
*/
498
- def prune (bnd : Type ): Type = bnd match {
499
- case bnd : AndType if ! fromBelow =>
478
+ def prune (bnd : Type ): Type = bnd match
479
+ case bnd : AndOrType =>
500
480
val p1 = prune(bnd.tp1)
501
481
val p2 = prune(bnd.tp2)
502
- if (p1.exists && p2.exists) bnd.derivedAndType (p1, p2)
482
+ if (p1.exists && p2.exists) bnd.derivedAndOrType (p1, p2)
503
483
else NoType
504
- case bnd : OrType if fromBelow =>
505
- val p1 = prune(bnd.tp1)
506
- val p2 = prune(bnd.tp2)
507
- if (p1.exists && p2.exists) bnd.derivedOrType(p1, p2)
508
- else NoType
509
- case bnd : TypeVar if constraint contains bnd.origin =>
484
+ case bnd : TypeVar if constraint contains bnd.origin => // (2)
510
485
prune(bnd.underlying)
511
- case bnd : TypeParamRef if bnd ne param =>
512
- constraint.entry(bnd) match {
513
- case NoType => pruneLambdaParams(bnd)
514
- case _ : TypeBounds =>
515
- assertFail(i " pruning $param $bound $fromBelow $bnd" )
516
- if (! addParamBound(bnd)) NoType
517
- else if (fromBelow) defn.NothingType
518
- else defn.AnyType
519
- case inst =>
520
- prune(inst)
521
- }
522
- case bnd : ExprType =>
486
+ case bnd : TypeParamRef =>
487
+ if bnd eq param then // (1)
488
+ if fromBelow then defn.NothingType else defn.AnyType
489
+ else constraint.entry(bnd) match
490
+ case _ : TypeBounds => bnd
491
+ case inst => prune(inst) // (3)
492
+ case bnd : ExprType => // (4)
523
493
// ExprTypes are not value types, so type parameters should not
524
494
// be instantiated to ExprTypes. A scenario where such an attempted
525
495
// instantiation can happen is if we unify (=> T) => () with A => ()
@@ -531,8 +501,7 @@ trait ConstraintHandling[AbstractContext] {
531
501
// the resulting types down) and is largely unknown terrain.
532
502
NoType
533
503
case _ =>
534
- pruneLambdaParams(bnd)
535
- }
504
+ bnd
536
505
537
506
def kindCompatible (tp1 : Type , tp2 : Type ): Boolean =
538
507
val tparams1 = tp1.typeParams
@@ -547,7 +516,8 @@ trait ConstraintHandling[AbstractContext] {
547
516
addParamBound(bound)
548
517
case _ =>
549
518
val savedConstraint = constraint
550
- val pbound = prune(bound)
519
+ val pbound = prune(pruneLambdaParams(bound))
520
+ assert(constraint eq savedConstraint)
551
521
val constraintsNarrowed = constraint ne savedConstraint
552
522
553
523
val res =
0 commit comments