@@ -139,6 +139,12 @@ object Types {
139139 case _ => false
140140 }
141141
142+ /** Is this type exactly Nothing (no vars, aliases, refinements etc allowed)? */
143+ def isBottomType (implicit ctx : Context ): Boolean = this match {
144+ case tp : TypeRef => tp.symbol eq defn.NothingClass
145+ case _ => false
146+ }
147+
142148 /** Is this type a (neither aliased nor applied) reference to class `sym`? */
143149 def isDirectRef (sym : Symbol )(implicit ctx : Context ): Boolean = stripTypeVar match {
144150 case this1 : TypeRef =>
@@ -278,7 +284,10 @@ object Types {
278284 }
279285
280286 /** Is this an alias TypeBounds? */
281- def isAlias : Boolean = this .isInstanceOf [TypeAlias ]
287+ final def isAlias : Boolean = this .isInstanceOf [TypeAlias ]
288+
289+ /** Is this a non-alias TypeBounds? */
290+ final def isRealTypeBounds = this .isInstanceOf [TypeBounds ] && ! isAlias
282291
283292// ----- Higher-order combinators -----------------------------------
284293
@@ -1223,6 +1232,18 @@ object Types {
12231232 case _ => TypeAlias (this )
12241233 }
12251234
1235+ /** The lower bound of a TypeBounds type, the type itself otherwise */
1236+ def loBound = this match {
1237+ case tp : TypeBounds => tp.lo
1238+ case _ => this
1239+ }
1240+
1241+ /** The upper bound of a TypeBounds type, the type itself otherwise */
1242+ def hiBound = this match {
1243+ case tp : TypeBounds => tp.hi
1244+ case _ => this
1245+ }
1246+
12261247 /** The type parameter with given `name`. This tries first `decls`
12271248 * in order not to provoke a cycle by forcing the info. If that yields
12281249 * no symbol it tries `member` as an alternative.
@@ -1769,6 +1790,7 @@ object Types {
17691790 */
17701791 def derivedSelect (prefix : Type )(implicit ctx : Context ): Type =
17711792 if (prefix eq this .prefix) this
1793+ else if (prefix.isBottomType) prefix
17721794 else if (isType) {
17731795 val res = prefix.lookupRefined(name)
17741796 if (res.exists) res
@@ -3725,6 +3747,18 @@ object Types {
37253747 // of `p`'s upper bound.
37263748 val prefix1 = this (tp.prefix)
37273749 variance = saved
3750+ /* was:
3751+ val prefix1 = tp.info match {
3752+ case info: TypeBounds if !info.isAlias =>
3753+ // prefix of an abstract type selection is non-variant, since a path
3754+ // cannot be legally widened to its underlying type, or any supertype.
3755+ val saved = variance
3756+ variance = 0
3757+ try this(tp.prefix) finally variance = saved
3758+ case _ =>
3759+ this(tp.prefix)
3760+ }
3761+ */
37283762 derivedSelect(tp, prefix1)
37293763 }
37303764 case _ : ThisType
@@ -3854,63 +3888,139 @@ object Types {
38543888 def apply (tp : Type ) = tp
38553889 }
38563890
3857- /** A type map that approximates NoTypes by upper or lower known bounds depending on
3891+ case class Range (lo : Type , hi : Type ) extends UncachedGroundType {
3892+ assert(! lo.isInstanceOf [Range ])
3893+ assert(! hi.isInstanceOf [Range ])
3894+ }
3895+
3896+ /** A type map that approximates TypeBounds types depending on
38583897 * variance.
38593898 *
38603899 * if variance > 0 : approximate by upper bound
38613900 * variance < 0 : approximate by lower bound
3862- * variance = 0 : propagate NoType to next outer level
3901+ * variance = 0 : propagate bounds to next outer level
38633902 */
38643903 abstract class ApproximatingTypeMap (implicit ctx : Context ) extends TypeMap { thisMap =>
3865- def approx (lo : Type = defn.NothingType , hi : Type = defn.AnyType ) =
3866- if (variance == 0 ) NoType
3867- else apply(if (variance < 0 ) lo else hi)
3904+
3905+ def range (lo : Type = defn.NothingType , hi : Type = defn.AnyType ) =
3906+ if (variance > 0 ) hi
3907+ else if (variance < 0 ) lo
3908+ else Range (loBound(lo), hiBound(hi))
3909+
3910+ def isRange (tp : Type ) = tp.isInstanceOf [Range ]
3911+
3912+ def loBound (tp : Type ) = tp match {
3913+ case tp : Range => tp.lo
3914+ case _ => tp
3915+ }
3916+
3917+ /** The upper bound of a TypeBounds type, the type itself otherwise */
3918+ def hiBound (tp : Type ) = tp match {
3919+ case tp : Range => tp.hi
3920+ case _ => tp
3921+ }
3922+
3923+ def rangeToBounds (tp : Type ) = tp match {
3924+ case Range (lo, hi) => TypeBounds (lo, hi)
3925+ case _ => tp
3926+ }
38683927
38693928 override protected def derivedSelect (tp : NamedType , pre : Type ) =
38703929 if (pre eq tp.prefix) tp
3871- else tp.info match {
3872- case TypeAlias (alias) => apply(alias) // try to heal by following aliases
3873- case _ =>
3874- if (pre.exists && ! pre.isRef(defn.NothingClass ) && variance > 0 ) tp.derivedSelect(pre)
3875- else tp.info match {
3876- case TypeBounds (lo, hi) => approx(lo, hi)
3877- case _ => approx()
3930+ else pre match {
3931+ case Range (preLo, preHi) =>
3932+ tp.info match {
3933+ case TypeAlias (alias) => apply(alias)
3934+ case TypeBounds (lo, hi) => range(apply(lo), apply(hi))
3935+ case _ => range(tp.derivedSelect(preLo), tp.derivedSelect(preHi))
38783936 }
3937+ case _ => tp.derivedSelect(pre)
38793938 }
3939+
38803940 override protected def derivedRefinedType (tp : RefinedType , parent : Type , info : Type ) =
3881- if (parent.exists && info.exists) tp.derivedRefinedType(parent, tp.refinedName, info)
3882- else approx(hi = parent)
3941+ parent match {
3942+ case Range (parentLo, parentHi) =>
3943+ range(derivedRefinedType(tp, parentLo, info), derivedRefinedType(tp, parentHi, info))
3944+ case _ =>
3945+ if (parent.isBottomType) parent
3946+ else info match {
3947+ case Range (infoLo, infoHi) if tp.refinedName.isTermName || variance <= 0 =>
3948+ range(derivedRefinedType(tp, parent, infoLo), derivedRefinedType(tp, parent, infoHi))
3949+ case _ =>
3950+ tp.derivedRefinedType(parent, tp.refinedName, rangeToBounds(info))
3951+ }
3952+ }
38833953 override protected def derivedRecType (tp : RecType , parent : Type ) =
3884- if (parent.exists) tp.rebind(parent)
3885- else approx()
3954+ parent match {
3955+ case Range (lo, hi) => range(tp.rebind(lo), tp.rebind(hi))
3956+ case _ => tp.rebind(parent)
3957+ }
38863958 override protected def derivedTypeAlias (tp : TypeAlias , alias : Type ) =
3887- if (alias.exists) tp.derivedTypeAlias(alias)
3888- else approx(NoType , TypeBounds .empty)
3959+ alias match {
3960+ case Range (lo, hi) =>
3961+ if (variance > 0 ) TypeBounds (lo, hi)
3962+ else range(TypeAlias (lo), TypeAlias (hi))
3963+ case _ => tp.derivedTypeAlias(alias)
3964+ }
38893965 override protected def derivedTypeBounds (tp : TypeBounds , lo : Type , hi : Type ) =
3890- if (lo.exists && hi.exists) tp.derivedTypeBounds(lo, hi)
3891- else approx(NoType ,
3892- if (lo.exists) TypeBounds .lower(lo)
3893- else if (hi.exists) TypeBounds .upper(hi)
3894- else TypeBounds .empty)
3966+ if (isRange(lo) || isRange(hi))
3967+ if (variance > 0 ) TypeBounds (loBound(lo), hiBound(hi))
3968+ else range(TypeBounds (hiBound(lo), loBound(hi)), TypeBounds (loBound(lo), hiBound(hi)))
3969+ else tp.derivedTypeBounds(lo, hi)
38953970 override protected def derivedSuperType (tp : SuperType , thistp : Type , supertp : Type ) =
3896- if (thistp.exists && supertp.exists) tp.derivedSuperType(thistp, supertp)
3897- else NoType
3971+ if (isRange(thistp) || isRange(supertp)) range()
3972+ else tp.derivedSuperType(thistp, supertp)
3973+
38983974 override protected def derivedAppliedType (tp : HKApply , tycon : Type , args : List [Type ]): Type =
3899- if (tycon.exists && args.forall(_.exists)) tp.derivedAppliedType(tycon, args)
3900- else approx() // This is rather coarse, but to do better is a bit complicated
3975+ tycon match {
3976+ case Range (tyconLo, tyconHi) =>
3977+ range(derivedAppliedType(tp, tyconLo, args), derivedAppliedType(tp, tyconHi, args))
3978+ case _ =>
3979+ if (args.exists(isRange))
3980+ if (variance > 0 ) tp.derivedAppliedType(tycon, args.map(rangeToBounds))
3981+ else {
3982+ val loBuf, hiBuf = new mutable.ListBuffer [Type ]
3983+ def distributeArgs (args : List [Type ], tparams : List [ParamInfo ]): Boolean = args match {
3984+ case Range (lo, hi) :: args1 =>
3985+ val v = tparams.head.paramVariance
3986+ if (v == 0 ) false
3987+ else if (v > 0 ) { loBuf += lo; hiBuf += hi }
3988+ else { loBuf += hi; hiBuf += lo }
3989+ distributeArgs(args1, tparams.tail)
3990+ case arg :: args1 =>
3991+ loBuf += arg; hiBuf += arg
3992+ distributeArgs(args1, tparams.tail)
3993+ case nil =>
3994+ true
3995+ }
3996+ if (distributeArgs(args, tp.typeParams))
3997+ range(tp.derivedAppliedType(tycon, loBuf.toList),
3998+ tp.derivedAppliedType(tycon, hiBuf.toList))
3999+ else range()
4000+ }
4001+ else tp.derivedAppliedType(tycon, args)
4002+ }
4003+
39014004 override protected def derivedAndOrType (tp : AndOrType , tp1 : Type , tp2 : Type ) =
3902- if (tp1.exists && tp2.exists) tp.derivedAndOrType(tp1, tp2)
3903- else if (tp.isAnd) approx(hi = tp1 & tp2) // if one of tp1d, tp2d exists, it is the result of tp1d & tp2d
3904- else approx(lo = tp1 & tp2)
4005+ if (tp1.isInstanceOf [Range ] || tp2.isInstanceOf [Range ])
4006+ if (tp.isAnd) range(loBound(tp1) & loBound(tp2), hiBound(tp1) & hiBound(tp2))
4007+ else range(loBound(tp1) | loBound(tp2), hiBound(tp1) | hiBound(tp2))
4008+ else tp.derivedAndOrType(tp1, tp2)
39054009 override protected def derivedAnnotatedType (tp : AnnotatedType , underlying : Type , annot : Annotation ) =
3906- if (underlying.exists) tp.derivedAnnotatedType(underlying, annot)
3907- else NoType
3908- override protected def derivedWildcardType (tp : WildcardType , bounds : Type ) =
3909- if (bounds.exists) tp.derivedWildcardType(bounds)
3910- else WildcardType
3911- override protected def derivedClassInfo (tp : ClassInfo , pre : Type ): Type =
3912- if (pre.exists) tp.derivedClassInfo(pre)
3913- else NoType
4010+ underlying match {
4011+ case Range (lo, hi) =>
4012+ range(tp.derivedAnnotatedType(lo, annot), tp.derivedAnnotatedType(hi, annot))
4013+ case _ =>
4014+ if (underlying.isBottomType) underlying
4015+ else tp.derivedAnnotatedType(underlying, annot)
4016+ }
4017+ override protected def derivedWildcardType (tp : WildcardType , bounds : Type ) = {
4018+ tp.derivedWildcardType(rangeToBounds(bounds))
4019+ }
4020+ override protected def derivedClassInfo (tp : ClassInfo , pre : Type ): Type = {
4021+ assert(! pre.isInstanceOf [Range ])
4022+ tp.derivedClassInfo(pre)
4023+ }
39144024 }
39154025
39164026 // ----- TypeAccumulators ----------------------------------------------------
0 commit comments