@@ -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)))
@@ -337,13 +338,31 @@ trait TypeAssigner {
337338 }
338339 }
339340
340- /** Substitute argument type `argType` for parameter `pref` in type `tp`,
341- * skolemizing the argument type if it is not stable and `pref` occurs in `tp`.
341+ /** Substitute argument type `argType` for parameter `pref` in type `tp`, but
342+ * take special measures if the argument is not realizable:
343+ * 1. If the widened argument type is known to have good bounds,
344+ * substitute the skolemized argument type.
345+ * 2. If the widened argument type is not known to have good bounds, eliminate all references
346+ * to the parameter in `tp`.
347+ * (2) is necessary since even with a skolemized type we might break subtyping if
348+ * bounds are bad. This could lead to errors not being detected. A test case is the second
349+ * failure in neg/i4031.scala
342350 */
343- def safeSubstParam (tp : Type , pref : ParamRef , argType : Type )(implicit ctx : Context ) = {
351+ def safeSubstParam (tp : Type , pref : ParamRef , argType : Type , initVariance : Int = 1 )(implicit ctx : Context ) = {
344352 val tp1 = tp.substParam(pref, argType)
345- if ((tp1 eq tp) || argType.isStable) tp1
346- else tp.substParam(pref, SkolemType (argType.widen))
353+ if ((tp1 eq tp) || argType.isRealizable) tp1
354+ else {
355+ val widenedArgType = argType.widen
356+ if (realizability(widenedArgType) == Realizable )
357+ tp.substParam(pref, SkolemType (widenedArgType))
358+ else {
359+ val avoidParam = new ApproximatingTypeMap {
360+ variance = initVariance
361+ def apply (t : Type ) = if (t `eq` pref) emptyRange else mapOver(t)
362+ }
363+ avoidParam(tp)
364+ }
365+ }
347366 }
348367
349368 /** Substitute types of all arguments `args` for corresponding `params` in `tp`.
0 commit comments