@@ -14,6 +14,7 @@ import collection.mutable
14
14
import reporting .diagnostic .Message
15
15
import reporting .diagnostic .messages ._
16
16
import Checking .checkNoPrivateLeaks
17
+ import CheckRealizable ._
17
18
18
19
trait TypeAssigner {
19
20
import tpd ._
@@ -106,7 +107,7 @@ trait TypeAssigner {
106
107
case info : ClassInfo =>
107
108
range(defn.NothingType , apply(classBound(info)))
108
109
case _ =>
109
- range(defn. NothingType , defn. AnyType ) // should happen only in error cases
110
+ emptyRange // should happen only in error cases
110
111
}
111
112
case tp : ThisType if toAvoid(tp.cls) =>
112
113
range(defn.NothingType , apply(classBound(tp.cls.classInfo)))
@@ -337,13 +338,31 @@ trait TypeAssigner {
337
338
}
338
339
}
339
340
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
342
350
*/
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 ) = {
344
352
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
+ }
347
366
}
348
367
349
368
/** Substitute types of all arguments `args` for corresponding `params` in `tp`.
0 commit comments