@@ -136,6 +136,12 @@ object Types {
136136 case _ => false
137137 }
138138
139+ /** Is this type exactly Nothing (no vars, aliases, refinements etc allowed)? */
140+ def isBottomType (implicit ctx : Context ): Boolean = this match {
141+ case tp : TypeRef => tp.symbol eq defn.NothingClass
142+ case _ => false
143+ }
144+
139145 /** Is this type a (neither aliased nor applied) reference to class `sym`? */
140146 def isDirectRef (sym : Symbol )(implicit ctx : Context ): Boolean = stripTypeVar match {
141147 case this1 : TypeRef =>
@@ -275,7 +281,10 @@ object Types {
275281 }
276282
277283 /** Is this an alias TypeBounds? */
278- def isAlias : Boolean = this .isInstanceOf [TypeAlias ]
284+ final def isAlias : Boolean = this .isInstanceOf [TypeAlias ]
285+
286+ /** Is this a non-alias TypeBounds? */
287+ final def isRealTypeBounds = this .isInstanceOf [TypeBounds ] && ! isAlias
279288
280289// ----- Higher-order combinators -----------------------------------
281290
@@ -1220,6 +1229,18 @@ object Types {
12201229 case _ => TypeAlias (this )
12211230 }
12221231
1232+ /** The lower bound of a TypeBounds type, the type itself otherwise */
1233+ def loBound = this match {
1234+ case tp : TypeBounds => tp.lo
1235+ case _ => this
1236+ }
1237+
1238+ /** The upper bound of a TypeBounds type, the type itself otherwise */
1239+ def hiBound = this match {
1240+ case tp : TypeBounds => tp.hi
1241+ case _ => this
1242+ }
1243+
12231244 /** The type parameter with given `name`. This tries first `decls`
12241245 * in order not to provoke a cycle by forcing the info. If that yields
12251246 * no symbol it tries `member` as an alternative.
@@ -1766,6 +1787,7 @@ object Types {
17661787 */
17671788 def derivedSelect (prefix : Type )(implicit ctx : Context ): Type =
17681789 if (prefix eq this .prefix) this
1790+ else if (prefix.isBottomType) prefix
17691791 else if (isType) {
17701792 val res = prefix.lookupRefined(name)
17711793 if (res.exists) res
@@ -3722,6 +3744,18 @@ object Types {
37223744 // of `p`'s upper bound.
37233745 val prefix1 = this (tp.prefix)
37243746 variance = saved
3747+ /* was:
3748+ val prefix1 = tp.info match {
3749+ case info: TypeBounds if !info.isAlias =>
3750+ // prefix of an abstract type selection is non-variant, since a path
3751+ // cannot be legally widened to its underlying type, or any supertype.
3752+ val saved = variance
3753+ variance = 0
3754+ try this(tp.prefix) finally variance = saved
3755+ case _ =>
3756+ this(tp.prefix)
3757+ }
3758+ */
37253759 derivedSelect(tp, prefix1)
37263760 }
37273761 case _ : ThisType
@@ -3851,63 +3885,139 @@ object Types {
38513885 def apply (tp : Type ) = tp
38523886 }
38533887
3854- /** A type map that approximates NoTypes by upper or lower known bounds depending on
3888+ case class Range (lo : Type , hi : Type ) extends UncachedGroundType {
3889+ assert(! lo.isInstanceOf [Range ])
3890+ assert(! hi.isInstanceOf [Range ])
3891+ }
3892+
3893+ /** A type map that approximates TypeBounds types depending on
38553894 * variance.
38563895 *
38573896 * if variance > 0 : approximate by upper bound
38583897 * variance < 0 : approximate by lower bound
3859- * variance = 0 : propagate NoType to next outer level
3898+ * variance = 0 : propagate bounds to next outer level
38603899 */
38613900 abstract class ApproximatingTypeMap (implicit ctx : Context ) extends TypeMap { thisMap =>
3862- def approx (lo : Type = defn.NothingType , hi : Type = defn.AnyType ) =
3863- if (variance == 0 ) NoType
3864- else apply(if (variance < 0 ) lo else hi)
3901+
3902+ def range (lo : Type = defn.NothingType , hi : Type = defn.AnyType ) =
3903+ if (variance > 0 ) hi
3904+ else if (variance < 0 ) lo
3905+ else Range (loBound(lo), hiBound(hi))
3906+
3907+ def isRange (tp : Type ) = tp.isInstanceOf [Range ]
3908+
3909+ def loBound (tp : Type ) = tp match {
3910+ case tp : Range => tp.lo
3911+ case _ => tp
3912+ }
3913+
3914+ /** The upper bound of a TypeBounds type, the type itself otherwise */
3915+ def hiBound (tp : Type ) = tp match {
3916+ case tp : Range => tp.hi
3917+ case _ => tp
3918+ }
3919+
3920+ def rangeToBounds (tp : Type ) = tp match {
3921+ case Range (lo, hi) => TypeBounds (lo, hi)
3922+ case _ => tp
3923+ }
38653924
38663925 override protected def derivedSelect (tp : NamedType , pre : Type ) =
38673926 if (pre eq tp.prefix) tp
3868- else tp.info match {
3869- case TypeAlias (alias) => apply(alias) // try to heal by following aliases
3870- case _ =>
3871- if (pre.exists && ! pre.isRef(defn.NothingClass ) && variance > 0 ) tp.derivedSelect(pre)
3872- else tp.info match {
3873- case TypeBounds (lo, hi) => approx(lo, hi)
3874- case _ => approx()
3927+ else pre match {
3928+ case Range (preLo, preHi) =>
3929+ tp.info match {
3930+ case TypeAlias (alias) => apply(alias)
3931+ case TypeBounds (lo, hi) => range(apply(lo), apply(hi))
3932+ case _ => range(tp.derivedSelect(preLo), tp.derivedSelect(preHi))
38753933 }
3934+ case _ => tp.derivedSelect(pre)
38763935 }
3936+
38773937 override protected def derivedRefinedType (tp : RefinedType , parent : Type , info : Type ) =
3878- if (parent.exists && info.exists) tp.derivedRefinedType(parent, tp.refinedName, info)
3879- else approx(hi = parent)
3938+ parent match {
3939+ case Range (parentLo, parentHi) =>
3940+ range(derivedRefinedType(tp, parentLo, info), derivedRefinedType(tp, parentHi, info))
3941+ case _ =>
3942+ if (parent.isBottomType) parent
3943+ else info match {
3944+ case Range (infoLo, infoHi) if tp.refinedName.isTermName || variance <= 0 =>
3945+ range(derivedRefinedType(tp, parent, infoLo), derivedRefinedType(tp, parent, infoHi))
3946+ case _ =>
3947+ tp.derivedRefinedType(parent, tp.refinedName, rangeToBounds(info))
3948+ }
3949+ }
38803950 override protected def derivedRecType (tp : RecType , parent : Type ) =
3881- if (parent.exists) tp.rebind(parent)
3882- else approx()
3951+ parent match {
3952+ case Range (lo, hi) => range(tp.rebind(lo), tp.rebind(hi))
3953+ case _ => tp.rebind(parent)
3954+ }
38833955 override protected def derivedTypeAlias (tp : TypeAlias , alias : Type ) =
3884- if (alias.exists) tp.derivedTypeAlias(alias)
3885- else approx(NoType , TypeBounds .empty)
3956+ alias match {
3957+ case Range (lo, hi) =>
3958+ if (variance > 0 ) TypeBounds (lo, hi)
3959+ else range(TypeAlias (lo), TypeAlias (hi))
3960+ case _ => tp.derivedTypeAlias(alias)
3961+ }
38863962 override protected def derivedTypeBounds (tp : TypeBounds , lo : Type , hi : Type ) =
3887- if (lo.exists && hi.exists) tp.derivedTypeBounds(lo, hi)
3888- else approx(NoType ,
3889- if (lo.exists) TypeBounds .lower(lo)
3890- else if (hi.exists) TypeBounds .upper(hi)
3891- else TypeBounds .empty)
3963+ if (isRange(lo) || isRange(hi))
3964+ if (variance > 0 ) TypeBounds (loBound(lo), hiBound(hi))
3965+ else range(TypeBounds (hiBound(lo), loBound(hi)), TypeBounds (loBound(lo), hiBound(hi)))
3966+ else tp.derivedTypeBounds(lo, hi)
38923967 override protected def derivedSuperType (tp : SuperType , thistp : Type , supertp : Type ) =
3893- if (thistp.exists && supertp.exists) tp.derivedSuperType(thistp, supertp)
3894- else NoType
3968+ if (isRange(thistp) || isRange(supertp)) range()
3969+ else tp.derivedSuperType(thistp, supertp)
3970+
38953971 override protected def derivedAppliedType (tp : HKApply , tycon : Type , args : List [Type ]): Type =
3896- if (tycon.exists && args.forall(_.exists)) tp.derivedAppliedType(tycon, args)
3897- else approx() // This is rather coarse, but to do better is a bit complicated
3972+ tycon match {
3973+ case Range (tyconLo, tyconHi) =>
3974+ range(derivedAppliedType(tp, tyconLo, args), derivedAppliedType(tp, tyconHi, args))
3975+ case _ =>
3976+ if (args.exists(isRange))
3977+ if (variance > 0 ) tp.derivedAppliedType(tycon, args.map(rangeToBounds))
3978+ else {
3979+ val loBuf, hiBuf = new mutable.ListBuffer [Type ]
3980+ def distributeArgs (args : List [Type ], tparams : List [ParamInfo ]): Boolean = args match {
3981+ case Range (lo, hi) :: args1 =>
3982+ val v = tparams.head.paramVariance
3983+ if (v == 0 ) false
3984+ else if (v > 0 ) { loBuf += lo; hiBuf += hi }
3985+ else { loBuf += hi; hiBuf += lo }
3986+ distributeArgs(args1, tparams.tail)
3987+ case arg :: args1 =>
3988+ loBuf += arg; hiBuf += arg
3989+ distributeArgs(args1, tparams.tail)
3990+ case nil =>
3991+ true
3992+ }
3993+ if (distributeArgs(args, tp.typeParams))
3994+ range(tp.derivedAppliedType(tycon, loBuf.toList),
3995+ tp.derivedAppliedType(tycon, hiBuf.toList))
3996+ else range()
3997+ }
3998+ else tp.derivedAppliedType(tycon, args)
3999+ }
4000+
38984001 override protected def derivedAndOrType (tp : AndOrType , tp1 : Type , tp2 : Type ) =
3899- if (tp1.exists && tp2.exists) tp.derivedAndOrType(tp1, tp2)
3900- else if (tp.isAnd) approx(hi = tp1 & tp2) // if one of tp1d, tp2d exists, it is the result of tp1d & tp2d
3901- else approx(lo = tp1 & tp2)
4002+ if (tp1.isInstanceOf [Range ] || tp2.isInstanceOf [Range ])
4003+ if (tp.isAnd) range(loBound(tp1) & loBound(tp2), hiBound(tp1) & hiBound(tp2))
4004+ else range(loBound(tp1) | loBound(tp2), hiBound(tp1) | hiBound(tp2))
4005+ else tp.derivedAndOrType(tp1, tp2)
39024006 override protected def derivedAnnotatedType (tp : AnnotatedType , underlying : Type , annot : Annotation ) =
3903- if (underlying.exists) tp.derivedAnnotatedType(underlying, annot)
3904- else NoType
3905- override protected def derivedWildcardType (tp : WildcardType , bounds : Type ) =
3906- if (bounds.exists) tp.derivedWildcardType(bounds)
3907- else WildcardType
3908- override protected def derivedClassInfo (tp : ClassInfo , pre : Type ): Type =
3909- if (pre.exists) tp.derivedClassInfo(pre)
3910- else NoType
4007+ underlying match {
4008+ case Range (lo, hi) =>
4009+ range(tp.derivedAnnotatedType(lo, annot), tp.derivedAnnotatedType(hi, annot))
4010+ case _ =>
4011+ if (underlying.isBottomType) underlying
4012+ else tp.derivedAnnotatedType(underlying, annot)
4013+ }
4014+ override protected def derivedWildcardType (tp : WildcardType , bounds : Type ) = {
4015+ tp.derivedWildcardType(rangeToBounds(bounds))
4016+ }
4017+ override protected def derivedClassInfo (tp : ClassInfo , pre : Type ): Type = {
4018+ assert(! pre.isInstanceOf [Range ])
4019+ tp.derivedClassInfo(pre)
4020+ }
39114021 }
39124022
39134023 // ----- TypeAccumulators ----------------------------------------------------
0 commit comments