@@ -222,72 +222,6 @@ object Inferencing {
222222 case _ => NoType
223223 }
224224
225- /** Interpolate those undetermined type variables in the widened type of this tree
226- * which are introduced by type application contained in the tree.
227- * If such a variable appears covariantly in type `tp` or does not appear at all,
228- * approximate it by its lower bound. Otherwise, if it appears contravariantly
229- * in type `tp` approximate it by its upper bound.
230- * @param ownedBy if it is different from NoSymbol, all type variables owned by
231- * `ownedBy` qualify, independent of position.
232- * Without that second condition, it can be that certain variables escape
233- * interpolation, for instance when their tree was eta-lifted, so
234- * the typechecked tree is no longer the tree in which the variable
235- * was declared. A concrete example of this phenomenon can be
236- * observed when compiling core.TypeOps#asSeenFrom.
237- */
238- def interpolateUndetVars (tree : Tree , ownedBy : Symbol )(implicit ctx : Context ): Unit = {
239- val constraint = ctx.typerState.constraint
240- val qualifies = (tvar : TypeVar ) =>
241- (tree contains tvar.bindingTree) || ownedBy.exists && tvar.owner == ownedBy
242- def interpolate () = Stats .track(" interpolateUndetVars" ) {
243- val tp = tree.tpe.widen
244- 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}" )}" )
245- constr.println(s " qualifying undet vars: ${constraint.uninstVars filter qualifies map (tvar => s " $tvar / ${tvar.show}" )}, constraint: ${constraint.show}" )
246-
247- val vs = variances(tp, qualifies)
248- val hasUnreportedErrors = ctx.typerState.reporter match {
249- case r : StoreReporter if r.hasErrors => true
250- case _ => false
251- }
252- // Avoid interpolating variables if typerstate has unreported errors.
253- // Reason: The errors might reflect unsatisfiable constraints. In that
254- // case interpolating without taking account the constraints risks producing
255- // nonsensical types that then in turn produce incomprehensible errors.
256- // An example is in neg/i1240.scala. Without the condition in the next code line
257- // we get for
258- //
259- // val y: List[List[String]] = List(List(1))
260- //
261- // i1430.scala:5: error: type mismatch:
262- // found : Int(1)
263- // required: Nothing
264- // val y: List[List[String]] = List(List(1))
265- // ^
266- // With the condition, we get the much more sensical:
267- //
268- // i1430.scala:5: error: type mismatch:
269- // found : Int(1)
270- // required: String
271- // val y: List[List[String]] = List(List(1))
272- if (! hasUnreportedErrors)
273- vs foreachBinding { (tvar, v) =>
274- if (v != 0 && ctx.typerState.constraint.contains(tvar)) {
275- // previous interpolations could have already instantiated `tvar`
276- // through unification, that's why we have to check again whether `tvar`
277- // is contained in the current constraint.
278- typr.println(s " interpolate ${if (v == 1 ) " co" else " contra" }variant ${tvar.show} in ${tp.show}" )
279- tvar.instantiate(fromBelow = v == 1 )
280- }
281- }
282- for (tvar <- constraint.uninstVars)
283- if (! (vs contains tvar) && qualifies(tvar)) {
284- typr.println(s " instantiating non-occurring ${tvar.show} in ${tp.show} / $tp" )
285- tvar.instantiate(fromBelow = true )
286- }
287- }
288- if (constraint.uninstVars exists qualifies) interpolate()
289- }
290-
291225 /** Instantiate undetermined type variables to that type `tp` is
292226 * maximized and return None. If this is not possible, because a non-variant
293227 * typevar is not uniquely determined, return that typevar in a Some.
@@ -375,6 +309,93 @@ object Inferencing {
375309 }
376310}
377311
312+ trait Inferencing { this : Typer =>
313+ import Inferencing ._
314+ import tpd ._
315+
316+ /** Interpolate those undetermined type variables in the widened type of this tree
317+ * which are introduced by type application contained in the tree.
318+ * If such a variable appears covariantly in type `tp` or does not appear at all,
319+ * approximate it by its lower bound. Otherwise, if it appears contravariantly
320+ * in type `tp` approximate it by its upper bound.
321+ * @param ownedBy if it is different from NoSymbol, all type variables owned by
322+ * `ownedBy` qualify, independent of position.
323+ * Without that second condition, it can be that certain variables escape
324+ * interpolation, for instance when their tree was eta-lifted, so
325+ * the typechecked tree is no longer the tree in which the variable
326+ * was declared. A concrete example of this phenomenon can be
327+ * observed when compiling core.TypeOps#asSeenFrom.
328+ */
329+ def interpolateUndetVars (tree : Tree , ownedBy : Symbol , pt : Type )(implicit ctx : Context ): Unit = {
330+ val constraint = ctx.typerState.constraint
331+ val qualifies = (tvar : TypeVar ) =>
332+ (tree contains tvar.bindingTree) || ownedBy.exists && tvar.owner == ownedBy
333+ def interpolate () = Stats .track(" interpolateUndetVars" ) {
334+ val tp = tree.tpe.widen
335+ 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}" )}" )
336+ constr.println(s " qualifying undet vars: ${constraint.uninstVars filter qualifies map (tvar => s " $tvar / ${tvar.show}" )}, constraint: ${constraint.show}" )
337+
338+ val vs = variances(tp, qualifies)
339+ val hasUnreportedErrors = ctx.typerState.reporter match {
340+ case r : StoreReporter if r.hasErrors => true
341+ case _ => false
342+ }
343+
344+ var isConstrained = false
345+ def ensureConstrained () =
346+ if (! isConstrained) {
347+ isConstrained = true
348+ tree match {
349+ case tree : Apply => // already constrained
350+ case _ => tree.tpe match {
351+ case _ : MethodOrPoly => // already constrained
352+ case tp => constrainResult(tp, pt)
353+ }
354+ }
355+ }
356+
357+ // Avoid interpolating variables if typerstate has unreported errors.
358+ // Reason: The errors might reflect unsatisfiable constraints. In that
359+ // case interpolating without taking account the constraints risks producing
360+ // nonsensical types that then in turn produce incomprehensible errors.
361+ // An example is in neg/i1240.scala. Without the condition in the next code line
362+ // we get for
363+ //
364+ // val y: List[List[String]] = List(List(1))
365+ //
366+ // i1430.scala:5: error: type mismatch:
367+ // found : Int(1)
368+ // required: Nothing
369+ // val y: List[List[String]] = List(List(1))
370+ // ^
371+ // With the condition, we get the much more sensical:
372+ //
373+ // i1430.scala:5: error: type mismatch:
374+ // found : Int(1)
375+ // required: String
376+ // val y: List[List[String]] = List(List(1))
377+ if (! hasUnreportedErrors)
378+ vs foreachBinding { (tvar, v) =>
379+ if (v != 0 && ctx.typerState.constraint.contains(tvar)) {
380+ // previous interpolations could have already instantiated `tvar`
381+ // through unification, that's why we have to check again whether `tvar`
382+ // is contained in the current constraint.
383+ typr.println(s " interpolate ${if (v == 1 ) " co" else " contra" }variant ${tvar.show} in ${tp.show}" )
384+ ensureConstrained()
385+ tvar.instantiate(fromBelow = v == 1 )
386+ }
387+ }
388+ for (tvar <- constraint.uninstVars)
389+ if (! (vs contains tvar) && qualifies(tvar)) {
390+ typr.println(s " instantiating non-occurring ${tvar.show} in ${tp.show} / $tp" )
391+ ensureConstrained()
392+ tvar.instantiate(fromBelow = true )
393+ }
394+ }
395+ if (constraint.uninstVars exists qualifies) interpolate()
396+ }
397+ }
398+
378399/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
379400@ sharable object ForceDegree {
380401 class Value (val appliesTo : TypeVar => Boolean , val minimizeAll : Boolean )
0 commit comments