@@ -14,6 +14,7 @@ import collection.mutable
1414import reporting .diagnostic .Message
1515import reporting .diagnostic .messages ._
1616import Checking .checkNoPrivateLeaks
17+ import CheckRealizable ._
1718
1819trait TypeAssigner {
1920 import tpd ._
@@ -106,7 +107,7 @@ trait TypeAssigner {
106107 case info : ClassInfo =>
107108 range(defn.NothingType , apply(classBound(info)))
108109 case _ =>
109- range(defn. NothingType , defn. AnyType ) // should happen only in error cases
110+ emptyRange // should happen only in error cases
110111 }
111112 case tp : ThisType if toAvoid(tp.cls) =>
112113 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 ) = {
354+ def safeSubstParam (tp : Type , pref : ParamRef , argType : Type , initVariance : Int = 1 )(implicit ctx : Context ) = {
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.isRealizable) 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