@@ -139,6 +139,12 @@ object Types {
139
139
case _ => false
140
140
}
141
141
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
+
142
148
/** Is this type a (neither aliased nor applied) reference to class `sym`? */
143
149
def isDirectRef (sym : Symbol )(implicit ctx : Context ): Boolean = stripTypeVar match {
144
150
case this1 : TypeRef =>
@@ -278,7 +284,10 @@ object Types {
278
284
}
279
285
280
286
/** 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
282
291
283
292
// ----- Higher-order combinators -----------------------------------
284
293
@@ -1223,6 +1232,18 @@ object Types {
1223
1232
case _ => TypeAlias (this )
1224
1233
}
1225
1234
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
+
1226
1247
/** The type parameter with given `name`. This tries first `decls`
1227
1248
* in order not to provoke a cycle by forcing the info. If that yields
1228
1249
* no symbol it tries `member` as an alternative.
@@ -1769,6 +1790,7 @@ object Types {
1769
1790
*/
1770
1791
def derivedSelect (prefix : Type )(implicit ctx : Context ): Type =
1771
1792
if (prefix eq this .prefix) this
1793
+ else if (prefix.isBottomType) prefix
1772
1794
else if (isType) {
1773
1795
val res = prefix.lookupRefined(name)
1774
1796
if (res.exists) res
@@ -3725,6 +3747,18 @@ object Types {
3725
3747
// of `p`'s upper bound.
3726
3748
val prefix1 = this (tp.prefix)
3727
3749
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
+ */
3728
3762
derivedSelect(tp, prefix1)
3729
3763
}
3730
3764
case _ : ThisType
@@ -3854,63 +3888,139 @@ object Types {
3854
3888
def apply (tp : Type ) = tp
3855
3889
}
3856
3890
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
3858
3897
* variance.
3859
3898
*
3860
3899
* if variance > 0 : approximate by upper bound
3861
3900
* variance < 0 : approximate by lower bound
3862
- * variance = 0 : propagate NoType to next outer level
3901
+ * variance = 0 : propagate bounds to next outer level
3863
3902
*/
3864
3903
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
+ }
3868
3927
3869
3928
override protected def derivedSelect (tp : NamedType , pre : Type ) =
3870
3929
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))
3878
3936
}
3937
+ case _ => tp.derivedSelect(pre)
3879
3938
}
3939
+
3880
3940
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
+ }
3883
3953
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
+ }
3886
3958
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
+ }
3889
3965
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)
3895
3970
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
+
3898
3974
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
+
3901
4004
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)
3905
4009
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
+ }
3914
4024
}
3915
4025
3916
4026
// ----- TypeAccumulators ----------------------------------------------------
0 commit comments