@@ -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
@@ -3722,6 +3744,18 @@ object Types {
3722
3744
// of `p`'s upper bound.
3723
3745
val prefix1 = this (tp.prefix)
3724
3746
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
+ */
3725
3759
derivedSelect(tp, prefix1)
3726
3760
}
3727
3761
case _ : ThisType
@@ -3851,63 +3885,139 @@ object Types {
3851
3885
def apply (tp : Type ) = tp
3852
3886
}
3853
3887
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
3855
3894
* variance.
3856
3895
*
3857
3896
* if variance > 0 : approximate by upper bound
3858
3897
* variance < 0 : approximate by lower bound
3859
- * variance = 0 : propagate NoType to next outer level
3898
+ * variance = 0 : propagate bounds to next outer level
3860
3899
*/
3861
3900
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
+ }
3865
3924
3866
3925
override protected def derivedSelect (tp : NamedType , pre : Type ) =
3867
3926
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))
3875
3933
}
3934
+ case _ => tp.derivedSelect(pre)
3876
3935
}
3936
+
3877
3937
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
+ }
3880
3950
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
+ }
3883
3955
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
+ }
3886
3962
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)
3892
3967
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
+
3895
3971
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
+
3898
4001
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)
3902
4006
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
+ }
3911
4021
}
3912
4022
3913
4023
// ----- TypeAccumulators ----------------------------------------------------
0 commit comments