@@ -375,6 +375,87 @@ object Inferencing {
375
375
}
376
376
}
377
377
378
+ trait Inferencing { this : Typer =>
379
+ import Inferencing ._
380
+ import tpd ._
381
+
382
+ /** Interpolate those undetermined type variables in the widened type of this tree
383
+ * which are introduced by type application contained in the tree.
384
+ * If such a variable appears covariantly in type `tp` or does not appear at all,
385
+ * approximate it by its lower bound. Otherwise, if it appears contravariantly
386
+ * in type `tp` approximate it by its upper bound.
387
+ * @param ownedBy if it is different from NoSymbol, all type variables owned by
388
+ * `ownedBy` qualify, independent of position.
389
+ * Without that second condition, it can be that certain variables escape
390
+ * interpolation, for instance when their tree was eta-lifted, so
391
+ * the typechecked tree is no longer the tree in which the variable
392
+ * was declared. A concrete example of this phenomenon can be
393
+ * observed when compiling core.TypeOps#asSeenFrom.
394
+ */
395
+ def interpolateUndetVars (tree : Tree , ownedBy : Symbol , pt : Type )(implicit ctx : Context ): Unit = {
396
+ val constraint = ctx.typerState.constraint
397
+ val qualifies = (tvar : TypeVar ) =>
398
+ (tree contains tvar.bindingTree) || ownedBy.exists && tvar.owner == ownedBy
399
+ def interpolate () = Stats .track(" interpolateUndetVars" ) {
400
+ val tp = tree.tpe.widen
401
+ constr.println(s " interpolate undet vars in ${tp.show}, pos = ${tree.pos}, mode = ${ctx.mode}, undets = ${constraint.uninstVars map (tvar => s " ${tvar.show}@ ${tvar.bindingTree.pos}" )}" )
402
+ constr.println(s " qualifying undet vars: ${constraint.uninstVars filter qualifies map (tvar => s " $tvar / ${tvar.show}" )}, constraint: ${constraint.show}" )
403
+
404
+ val vs = variances(tp, qualifies)
405
+ val hasUnreportedErrors = ctx.typerState.reporter match {
406
+ case r : StoreReporter if r.hasErrors => true
407
+ case _ => false
408
+ }
409
+
410
+ var isConstrained = tree.isInstanceOf [Apply ] || tree.tpe.isInstanceOf [MethodOrPoly ]
411
+
412
+ def ensureConstrained () = if (! isConstrained) {
413
+ isConstrained = true
414
+ constrainResult(tree.tpe, pt)
415
+ }
416
+
417
+ // Avoid interpolating variables if typerstate has unreported errors.
418
+ // Reason: The errors might reflect unsatisfiable constraints. In that
419
+ // case interpolating without taking account the constraints risks producing
420
+ // nonsensical types that then in turn produce incomprehensible errors.
421
+ // An example is in neg/i1240.scala. Without the condition in the next code line
422
+ // we get for
423
+ //
424
+ // val y: List[List[String]] = List(List(1))
425
+ //
426
+ // i1430.scala:5: error: type mismatch:
427
+ // found : Int(1)
428
+ // required: Nothing
429
+ // val y: List[List[String]] = List(List(1))
430
+ // ^
431
+ // With the condition, we get the much more sensical:
432
+ //
433
+ // i1430.scala:5: error: type mismatch:
434
+ // found : Int(1)
435
+ // required: String
436
+ // val y: List[List[String]] = List(List(1))
437
+ if (! hasUnreportedErrors)
438
+ vs foreachBinding { (tvar, v) =>
439
+ if (v != 0 && ctx.typerState.constraint.contains(tvar)) {
440
+ // previous interpolations could have already instantiated `tvar`
441
+ // through unification, that's why we have to check again whether `tvar`
442
+ // is contained in the current constraint.
443
+ typr.println(s " interpolate ${if (v == 1 ) " co" else " contra" }variant ${tvar.show} in ${tp.show}" )
444
+ ensureConstrained()
445
+ tvar.instantiate(fromBelow = v == 1 )
446
+ }
447
+ }
448
+ for (tvar <- constraint.uninstVars)
449
+ if (! (vs contains tvar) && qualifies(tvar)) {
450
+ typr.println(s " instantiating non-occurring ${tvar.show} in ${tp.show} / $tp" )
451
+ ensureConstrained()
452
+ tvar.instantiate(fromBelow = true )
453
+ }
454
+ }
455
+ if (constraint.uninstVars exists qualifies) interpolate()
456
+ }
457
+ }
458
+
378
459
/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
379
460
@ sharable object ForceDegree {
380
461
class Value (val appliesTo : TypeVar => Boolean , val minimizeAll : Boolean )
0 commit comments