@@ -136,6 +136,12 @@ object Types {
136
136
case _ => false
137
137
}
138
138
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
+
139
145
/** Is this type a (neither aliased nor applied) reference to class `sym`? */
140
146
def isDirectRef (sym : Symbol )(implicit ctx : Context ): Boolean = stripTypeVar match {
141
147
case this1 : TypeRef =>
@@ -275,7 +281,10 @@ object Types {
275
281
}
276
282
277
283
/** 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
279
288
280
289
// ----- Higher-order combinators -----------------------------------
281
290
@@ -1220,6 +1229,18 @@ object Types {
1220
1229
case _ => TypeAlias (this )
1221
1230
}
1222
1231
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
+
1223
1244
/** The type parameter with given `name`. This tries first `decls`
1224
1245
* in order not to provoke a cycle by forcing the info. If that yields
1225
1246
* no symbol it tries `member` as an alternative.
@@ -1766,6 +1787,7 @@ object Types {
1766
1787
*/
1767
1788
def derivedSelect (prefix : Type )(implicit ctx : Context ): Type =
1768
1789
if (prefix eq this .prefix) this
1790
+ else if (prefix.isBottomType) prefix
1769
1791
else if (isType) {
1770
1792
val res = prefix.lookupRefined(name)
1771
1793
if (res.exists) res
@@ -3724,6 +3746,18 @@ object Types {
3724
3746
// of `p`'s upper bound.
3725
3747
val prefix1 = this (tp.prefix)
3726
3748
variance = saved
3749
+ /* was:
3750
+ val prefix1 = tp.info match {
3751
+ case info: TypeBounds if !info.isAlias =>
3752
+ // prefix of an abstract type selection is non-variant, since a path
3753
+ // cannot be legally widened to its underlying type, or any supertype.
3754
+ val saved = variance
3755
+ variance = 0
3756
+ try this(tp.prefix) finally variance = saved
3757
+ case _ =>
3758
+ this(tp.prefix)
3759
+ }
3760
+ */
3727
3761
derivedSelect(tp, prefix1)
3728
3762
}
3729
3763
case _ : ThisType
@@ -3853,63 +3887,139 @@ object Types {
3853
3887
def apply (tp : Type ) = tp
3854
3888
}
3855
3889
3856
- /** A type map that approximates NoTypes by upper or lower known bounds depending on
3890
+ case class Range (lo : Type , hi : Type ) extends UncachedGroundType {
3891
+ assert(! lo.isInstanceOf [Range ])
3892
+ assert(! hi.isInstanceOf [Range ])
3893
+ }
3894
+
3895
+ /** A type map that approximates TypeBounds types depending on
3857
3896
* variance.
3858
3897
*
3859
3898
* if variance > 0 : approximate by upper bound
3860
3899
* variance < 0 : approximate by lower bound
3861
- * variance = 0 : propagate NoType to next outer level
3900
+ * variance = 0 : propagate bounds to next outer level
3862
3901
*/
3863
3902
abstract class ApproximatingTypeMap (implicit ctx : Context ) extends TypeMap { thisMap =>
3864
- def approx (lo : Type = defn.NothingType , hi : Type = defn.AnyType ) =
3865
- if (variance == 0 ) NoType
3866
- else apply(if (variance < 0 ) lo else hi)
3903
+
3904
+ def range (lo : Type = defn.NothingType , hi : Type = defn.AnyType ) =
3905
+ if (variance > 0 ) hi
3906
+ else if (variance < 0 ) lo
3907
+ else Range (loBound(lo), hiBound(hi))
3908
+
3909
+ def isRange (tp : Type ) = tp.isInstanceOf [Range ]
3910
+
3911
+ def loBound (tp : Type ) = tp match {
3912
+ case tp : Range => tp.lo
3913
+ case _ => tp
3914
+ }
3915
+
3916
+ /** The upper bound of a TypeBounds type, the type itself otherwise */
3917
+ def hiBound (tp : Type ) = tp match {
3918
+ case tp : Range => tp.hi
3919
+ case _ => tp
3920
+ }
3921
+
3922
+ def rangeToBounds (tp : Type ) = tp match {
3923
+ case Range (lo, hi) => TypeBounds (lo, hi)
3924
+ case _ => tp
3925
+ }
3867
3926
3868
3927
override protected def derivedSelect (tp : NamedType , pre : Type ) =
3869
3928
if (pre eq tp.prefix) tp
3870
- else tp.info match {
3871
- case TypeAlias (alias) => apply(alias) // try to heal by following aliases
3872
- case _ =>
3873
- if (pre.exists && ! pre.isRef(defn.NothingClass ) && variance > 0 ) tp.derivedSelect(pre)
3874
- else tp.info match {
3875
- case TypeBounds (lo, hi) => approx(lo, hi)
3876
- case _ => approx()
3929
+ else pre match {
3930
+ case Range (preLo, preHi) =>
3931
+ tp.info match {
3932
+ case TypeAlias (alias) => apply(alias)
3933
+ case TypeBounds (lo, hi) => range(apply(lo), apply(hi))
3934
+ case _ => range(tp.derivedSelect(preLo), tp.derivedSelect(preHi))
3877
3935
}
3936
+ case _ => tp.derivedSelect(pre)
3878
3937
}
3938
+
3879
3939
override protected def derivedRefinedType (tp : RefinedType , parent : Type , info : Type ) =
3880
- if (parent.exists && info.exists) tp.derivedRefinedType(parent, tp.refinedName, info)
3881
- else approx(hi = parent)
3940
+ parent match {
3941
+ case Range (parentLo, parentHi) =>
3942
+ range(derivedRefinedType(tp, parentLo, info), derivedRefinedType(tp, parentHi, info))
3943
+ case _ =>
3944
+ if (parent.isBottomType) parent
3945
+ else info match {
3946
+ case Range (infoLo, infoHi) if tp.refinedName.isTermName || variance <= 0 =>
3947
+ range(derivedRefinedType(tp, parent, infoLo), derivedRefinedType(tp, parent, infoHi))
3948
+ case _ =>
3949
+ tp.derivedRefinedType(parent, tp.refinedName, rangeToBounds(info))
3950
+ }
3951
+ }
3882
3952
override protected def derivedRecType (tp : RecType , parent : Type ) =
3883
- if (parent.exists) tp.rebind(parent)
3884
- else approx()
3953
+ parent match {
3954
+ case Range (lo, hi) => range(tp.rebind(lo), tp.rebind(hi))
3955
+ case _ => tp.rebind(parent)
3956
+ }
3885
3957
override protected def derivedTypeAlias (tp : TypeAlias , alias : Type ) =
3886
- if (alias.exists) tp.derivedTypeAlias(alias)
3887
- else approx(NoType , TypeBounds .empty)
3958
+ alias match {
3959
+ case Range (lo, hi) =>
3960
+ if (variance > 0 ) TypeBounds (lo, hi)
3961
+ else range(TypeAlias (lo), TypeAlias (hi))
3962
+ case _ => tp.derivedTypeAlias(alias)
3963
+ }
3888
3964
override protected def derivedTypeBounds (tp : TypeBounds , lo : Type , hi : Type ) =
3889
- if (lo.exists && hi.exists) tp.derivedTypeBounds(lo, hi)
3890
- else approx(NoType ,
3891
- if (lo.exists) TypeBounds .lower(lo)
3892
- else if (hi.exists) TypeBounds .upper(hi)
3893
- else TypeBounds .empty)
3965
+ if (isRange(lo) || isRange(hi))
3966
+ if (variance > 0 ) TypeBounds (loBound(lo), hiBound(hi))
3967
+ else range(TypeBounds (hiBound(lo), loBound(hi)), TypeBounds (loBound(lo), hiBound(hi)))
3968
+ else tp.derivedTypeBounds(lo, hi)
3894
3969
override protected def derivedSuperType (tp : SuperType , thistp : Type , supertp : Type ) =
3895
- if (thistp.exists && supertp.exists) tp.derivedSuperType(thistp, supertp)
3896
- else NoType
3970
+ if (isRange(thistp) || isRange(supertp)) range()
3971
+ else tp.derivedSuperType(thistp, supertp)
3972
+
3897
3973
override protected def derivedAppliedType (tp : HKApply , tycon : Type , args : List [Type ]): Type =
3898
- if (tycon.exists && args.forall(_.exists)) tp.derivedAppliedType(tycon, args)
3899
- else approx() // This is rather coarse, but to do better is a bit complicated
3974
+ tycon match {
3975
+ case Range (tyconLo, tyconHi) =>
3976
+ range(derivedAppliedType(tp, tyconLo, args), derivedAppliedType(tp, tyconHi, args))
3977
+ case _ =>
3978
+ if (args.exists(isRange))
3979
+ if (variance > 0 ) tp.derivedAppliedType(tycon, args.map(rangeToBounds))
3980
+ else {
3981
+ val loBuf, hiBuf = new mutable.ListBuffer [Type ]
3982
+ def distributeArgs (args : List [Type ], tparams : List [ParamInfo ]): Boolean = args match {
3983
+ case Range (lo, hi) :: args1 =>
3984
+ val v = tparams.head.paramVariance
3985
+ if (v == 0 ) false
3986
+ else if (v > 0 ) { loBuf += lo; hiBuf += hi }
3987
+ else { loBuf += hi; hiBuf += lo }
3988
+ distributeArgs(args1, tparams.tail)
3989
+ case arg :: args1 =>
3990
+ loBuf += arg; hiBuf += arg
3991
+ distributeArgs(args1, tparams.tail)
3992
+ case nil =>
3993
+ true
3994
+ }
3995
+ if (distributeArgs(args, tp.typeParams))
3996
+ range(tp.derivedAppliedType(tycon, loBuf.toList),
3997
+ tp.derivedAppliedType(tycon, hiBuf.toList))
3998
+ else range()
3999
+ }
4000
+ else tp.derivedAppliedType(tycon, args)
4001
+ }
4002
+
3900
4003
override protected def derivedAndOrType (tp : AndOrType , tp1 : Type , tp2 : Type ) =
3901
- if (tp1.exists && tp2.exists) tp.derivedAndOrType(tp1, tp2)
3902
- else if (tp.isAnd) approx(hi = tp1 & tp2) // if one of tp1d, tp2d exists, it is the result of tp1d & tp2d
3903
- else approx(lo = tp1 & tp2)
4004
+ if (tp1.isInstanceOf [Range ] || tp2.isInstanceOf [Range ])
4005
+ if (tp.isAnd) range(loBound(tp1) & loBound(tp2), hiBound(tp1) & hiBound(tp2))
4006
+ else range(loBound(tp1) | loBound(tp2), hiBound(tp1) | hiBound(tp2))
4007
+ else tp.derivedAndOrType(tp1, tp2)
3904
4008
override protected def derivedAnnotatedType (tp : AnnotatedType , underlying : Type , annot : Annotation ) =
3905
- if (underlying.exists) tp.derivedAnnotatedType(underlying, annot)
3906
- else NoType
3907
- override protected def derivedWildcardType (tp : WildcardType , bounds : Type ) =
3908
- if (bounds.exists) tp.derivedWildcardType(bounds)
3909
- else WildcardType
3910
- override protected def derivedClassInfo (tp : ClassInfo , pre : Type ): Type =
3911
- if (pre.exists) tp.derivedClassInfo(pre)
3912
- else NoType
4009
+ underlying match {
4010
+ case Range (lo, hi) =>
4011
+ range(tp.derivedAnnotatedType(lo, annot), tp.derivedAnnotatedType(hi, annot))
4012
+ case _ =>
4013
+ if (underlying.isBottomType) underlying
4014
+ else tp.derivedAnnotatedType(underlying, annot)
4015
+ }
4016
+ override protected def derivedWildcardType (tp : WildcardType , bounds : Type ) = {
4017
+ tp.derivedWildcardType(rangeToBounds(bounds))
4018
+ }
4019
+ override protected def derivedClassInfo (tp : ClassInfo , pre : Type ): Type = {
4020
+ assert(! pre.isInstanceOf [Range ])
4021
+ tp.derivedClassInfo(pre)
4022
+ }
3913
4023
}
3914
4024
3915
4025
// ----- TypeAccumulators ----------------------------------------------------
0 commit comments