@@ -437,12 +437,19 @@ object Inferencing {
437
437
438
438
type VarianceMap = SimpleIdentityMap [TypeVar , Integer ]
439
439
440
- /** All occurrences of type vars in this type that satisfy predicate
441
- * `include` mapped to their variances (-1/0/1) in this type, where
440
+ /** All occurrences of type vars in `tp` that satisfy predicate
441
+ * `include` mapped to their variances (-1/0/1) in both `tp` and
442
+ * `pt.finalResultType`, where
442
443
* -1 means: only contravariant occurrences
443
444
* +1 means: only covariant occurrences
444
445
* 0 means: mixed or non-variant occurrences
445
446
*
447
+ * We need to take the occurences in `pt` into account because a type
448
+ * variable created when typing the current tree might only appear in the
449
+ * bounds of a type variable in the expected type, for example when
450
+ * `ConstraintHandling#addOneBound` creates type variables when approximating
451
+ * a bound.
452
+ *
446
453
* Note: We intentionally use a relaxed version of variance here,
447
454
* where the variance does not change under a prefix of a named type
448
455
* (the strict version makes prefixes invariant). This turns out to be
@@ -453,7 +460,7 @@ object Inferencing {
453
460
*
454
461
* we want to instantiate U to x.type right away. No need to wait further.
455
462
*/
456
- private def variances (tp : Type )(using Context ): VarianceMap = {
463
+ private def variances (tp : Type , pt : Type = WildcardType )(using Context ): VarianceMap = {
457
464
Stats .record(" variances" )
458
465
val constraint = ctx.typerState.constraint
459
466
@@ -486,21 +493,21 @@ object Inferencing {
486
493
def traverse (tp : Type ) = { vmap1 = accu(vmap1, tp) }
487
494
vmap.foreachBinding { (tvar, v) =>
488
495
val param = tvar.origin
489
- val e = constraint.entry(param)
490
- accu.setVariance(v)
491
- if (v >= 0 ) {
492
- traverse(e.bounds.lo)
493
- constraint.lower(param).foreach(p => traverse(constraint.typeVarOfParam(p)) )
494
- }
495
- if ( v <= 0 ) {
496
- traverse(e.bounds. hi)
497
- constraint.upper(param).foreach(p => traverse(constraint.typeVarOfParam(p)))
498
- }
496
+ constraint.entry(param) match
497
+ case TypeBounds (lo, hi) =>
498
+ accu.setVariance(v)
499
+ if v >= 0 then
500
+ traverse(lo )
501
+ constraint.lower(param).foreach(p => traverse(constraint.typeVarOfParam(p)))
502
+ if v <= 0 then
503
+ traverse(hi)
504
+ constraint.upper(param).foreach(p => traverse(constraint.typeVarOfParam(p)))
505
+ case _ =>
499
506
}
500
507
if (vmap1 eq vmap) vmap else propagate(vmap1)
501
508
}
502
509
503
- propagate(accu(SimpleIdentityMap .empty, tp))
510
+ propagate(accu(accu( SimpleIdentityMap .empty, tp), pt.finalResultType ))
504
511
}
505
512
506
513
/** Run the transformation after dealiasing but return the original type if it was a no-op. */
@@ -546,8 +553,8 @@ trait Inferencing { this: Typer =>
546
553
* @param locked the set of type variables of the current typer state that cannot be interpolated
547
554
* at the present time
548
555
* Eligible for interpolation are all type variables owned by the current typerstate
549
- * that are not in locked. Type variables occurring co- (respectively, contra-) variantly in the type
550
- * are minimized (respectvely, maximized). Non occurring type variables are minimized if they
556
+ * that are not in locked. Type variables occurring co- (respectively, contra-) variantly in the tree type
557
+ * or expected type are minimized (respectvely, maximized). Non occurring type variables are minimized if they
551
558
* have a lower bound different from Nothing, maximized otherwise. Type variables appearing
552
559
* non-variantly in the type are left untouched.
553
560
*
@@ -572,15 +579,15 @@ trait Inferencing { this: Typer =>
572
579
if ((ownedVars ne locked) && ! ownedVars.isEmpty) {
573
580
val qualifying = ownedVars -- locked
574
581
if (! qualifying.isEmpty) {
575
- typr.println(i " interpolate $tree: ${tree.tpe.widen} in $state, owned vars = ${state.ownedVars.toList}%, %, qualifying = ${qualifying.toList}%, %, previous = ${locked.toList}%, % / ${state.constraint}" )
582
+ typr.println(i " interpolate $tree: ${tree.tpe.widen} in $state, pt = $pt , owned vars = ${state.ownedVars.toList}%, %, qualifying = ${qualifying.toList}%, %, previous = ${locked.toList}%, % / ${state.constraint}" )
576
583
val resultAlreadyConstrained =
577
584
tree.isInstanceOf [Apply ] || tree.tpe.isInstanceOf [MethodOrPoly ]
578
585
if (! resultAlreadyConstrained)
579
586
constrainResult(tree.symbol, tree.tpe, pt)
580
587
// This is needed because it could establish singleton type upper bounds. See i2998.scala.
581
588
582
589
val tp = tree.tpe.widen
583
- val vs = variances(tp)
590
+ val vs = variances(tp, pt )
584
591
585
592
// Avoid interpolating variables occurring in tree's type if typerstate has unreported errors.
586
593
// Reason: The errors might reflect unsatisfiable constraints. In that
0 commit comments