@@ -13,6 +13,7 @@ import NameOps._
1313import collection .mutable
1414import reporting .diagnostic .messages ._
1515import Checking .checkNoPrivateLeaks
16+ import CheckRealizable ._
1617
1718trait TypeAssigner {
1819 import tpd ._
@@ -105,7 +106,7 @@ trait TypeAssigner {
105106 case info : ClassInfo =>
106107 range(defn.NothingType , apply(classBound(info)))
107108 case _ =>
108- range(defn. NothingType , defn. AnyType ) // should happen only in error cases
109+ emptyRange // should happen only in error cases
109110 }
110111 case tp : ThisType if toAvoid(tp.cls) =>
111112 range(defn.NothingType , apply(classBound(tp.cls.classInfo)))
@@ -340,13 +341,31 @@ trait TypeAssigner {
340341 }
341342 }
342343
343- /** Substitute argument type `argType` for parameter `pref` in type `tp`,
344- * skolemizing the argument type if it is not stable and `pref` occurs in `tp`.
344+ /** Substitute argument type `argType` for parameter `pref` in type `tp`, but
345+ * take special measures if the argument is not realizable:
346+ * 1. If the widened argument type is known to have good bounds,
347+ * substitute the skolemized argument type.
348+ * 2. If the widened argument type is not known to have good bounds, eliminate all references
349+ * to the parameter in `tp`.
350+ * (2) is necessary since even with a skolemized type we might break subtyping if
351+ * bounds are bad. This could lead to errors not being detected. A test case is the second
352+ * failure in neg/i4031.scala
345353 */
346- def safeSubstParam (tp : Type , pref : ParamRef , argType : Type )(implicit ctx : Context ): Type = {
354+ def safeSubstParam (tp : Type , pref : ParamRef , argType : Type , initVariance : Int = 1 )(implicit ctx : Context ): Type = {
347355 val tp1 = tp.substParam(pref, argType)
348- if ((tp1 eq tp) || argType.isStable) tp1
349- else tp.substParam(pref, SkolemType (argType.widen))
356+ if ((tp1 eq tp) || argType.isStableRealizable) tp1
357+ else {
358+ val widenedArgType = argType.widen
359+ if (realizability(widenedArgType) == Realizable )
360+ tp.substParam(pref, SkolemType (widenedArgType))
361+ else {
362+ val avoidParam = new ApproximatingTypeMap {
363+ variance = initVariance
364+ def apply (t : Type ) = if (t `eq` pref) emptyRange else mapOver(t)
365+ }
366+ avoidParam(tp)
367+ }
368+ }
350369 }
351370
352371 /** Substitute types of all arguments `args` for corresponding `params` in `tp`.
0 commit comments