@@ -281,7 +281,10 @@ object Types {
281
281
}
282
282
283
283
/** Is this an alias TypeBounds? */
284
- 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
285
288
286
289
// ----- Higher-order combinators -----------------------------------
287
290
@@ -1226,18 +1229,6 @@ object Types {
1226
1229
case _ => TypeAlias (this )
1227
1230
}
1228
1231
1229
- /** The lower bound of a TypeBounds type, the type itself otherwise */
1230
- def loBound = this match {
1231
- case tp : TypeBounds => tp.lo
1232
- case _ => this
1233
- }
1234
-
1235
- /** The upper bound of a TypeBounds type, the type itself otherwise */
1236
- def hiBound = this match {
1237
- case tp : TypeBounds => tp.hi
1238
- case _ => this
1239
- }
1240
-
1241
1232
/** The type parameter with given `name`. This tries first `decls`
1242
1233
* in order not to provoke a cycle by forcing the info. If that yields
1243
1234
* no symbol it tries `member` as an alternative.
@@ -3733,16 +3724,15 @@ object Types {
3733
3724
case tp : NamedType =>
3734
3725
if (stopAtStatic && tp.symbol.isStatic) tp
3735
3726
else {
3736
- val prefix1 = tp.info match {
3737
- case info : TypeBounds if ! info.isAlias =>
3727
+ val prefix1 =
3728
+ if (tp. info.isRealTypeBounds) {
3738
3729
// prefix of an abstract type selection is non-variant, since a path
3739
3730
// cannot be legally widened to its underlying type, or any supertype.
3740
3731
val saved = variance
3741
3732
variance = 0
3742
3733
try this (tp.prefix) finally variance = saved
3743
- case _ =>
3744
- this (tp.prefix)
3745
- }
3734
+ }
3735
+ else this (tp.prefix)
3746
3736
derivedSelect(tp, prefix1)
3747
3737
}
3748
3738
case _ : ThisType
@@ -3872,6 +3862,11 @@ object Types {
3872
3862
def apply (tp : Type ) = tp
3873
3863
}
3874
3864
3865
+ case class Range (lo : Type , hi : Type ) extends UncachedGroundType {
3866
+ assert(! lo.isInstanceOf [Range ])
3867
+ assert(! hi.isInstanceOf [Range ])
3868
+ }
3869
+
3875
3870
/** A type map that approximates TypeBounds types depending on
3876
3871
* variance.
3877
3872
*
@@ -3880,74 +3875,124 @@ object Types {
3880
3875
* variance = 0 : propagate bounds to next outer level
3881
3876
*/
3882
3877
abstract class ApproximatingTypeMap (implicit ctx : Context ) extends TypeMap { thisMap =>
3878
+
3883
3879
def range (lo : Type = defn.NothingType , hi : Type = defn.AnyType ) =
3884
3880
if (variance > 0 ) hi
3885
3881
else if (variance < 0 ) lo
3886
- else TypeBounds (lo.loBound, hi.hiBound)
3882
+ else Range (loBound(lo), hiBound(hi))
3883
+
3884
+ def isRange (tp : Type ) = tp.isInstanceOf [Range ]
3885
+
3886
+ def loBound (tp : Type ) = tp match {
3887
+ case tp : Range => tp.lo
3888
+ case _ => tp
3889
+ }
3890
+
3891
+ /** The upper bound of a TypeBounds type, the type itself otherwise */
3892
+ def hiBound (tp : Type ) = tp match {
3893
+ case tp : Range => tp.hi
3894
+ case _ => tp
3895
+ }
3896
+
3897
+ def rangeToBounds (tp : Type ) = tp match {
3898
+ case Range (lo, hi) => TypeBounds (lo, hi)
3899
+ case _ => tp
3900
+ }
3887
3901
3888
3902
override protected def derivedSelect (tp : NamedType , pre : Type ) =
3889
3903
if (pre eq tp.prefix) tp
3890
3904
else pre match {
3891
- case TypeBounds (preLo, preHi) =>
3905
+ case Range (preLo, preHi) =>
3892
3906
tp.info match {
3893
3907
case TypeAlias (alias) => apply(alias)
3894
- case info @ TypeBounds (lo, hi) => apply( range(lo, hi))
3908
+ case TypeBounds (lo, hi) => range(apply(lo), apply( hi))
3895
3909
case _ => range(tp.derivedSelect(preLo), tp.derivedSelect(preHi))
3896
3910
}
3897
3911
case _ => tp.derivedSelect(pre)
3898
3912
}
3913
+
3899
3914
override protected def derivedRefinedType (tp : RefinedType , parent : Type , info : Type ) =
3900
3915
parent match {
3901
- case TypeBounds (parentLo, parentHi) =>
3916
+ case Range (parentLo, parentHi) =>
3902
3917
range(derivedRefinedType(tp, parentLo, info), derivedRefinedType(tp, parentHi, info))
3903
3918
case _ =>
3904
3919
if (parent.isBottomType) parent
3905
3920
else info match {
3906
- case TypeBounds (infoLo, infoHi) if tp.refinedName.isTermName =>
3921
+ case Range (infoLo, infoHi) if tp.refinedName.isTermName || variance <= 0 =>
3907
3922
range(derivedRefinedType(tp, parent, infoLo), derivedRefinedType(tp, parent, infoHi))
3908
3923
case _ =>
3909
- tp.derivedRefinedType(parent, tp.refinedName, info)
3924
+ tp.derivedRefinedType(parent, tp.refinedName, rangeToBounds( info) )
3910
3925
}
3911
3926
}
3912
3927
override protected def derivedRecType (tp : RecType , parent : Type ) =
3913
3928
parent match {
3914
- case TypeBounds (lo, hi) => range(tp.rebind(lo), tp.rebind(hi))
3929
+ case Range (lo, hi) => range(tp.rebind(lo), tp.rebind(hi))
3915
3930
case _ => tp.rebind(parent)
3916
3931
}
3917
3932
override protected def derivedTypeAlias (tp : TypeAlias , alias : Type ) =
3918
3933
alias match {
3919
- case bounds : TypeBounds => bounds
3934
+ case Range (lo, hi) =>
3935
+ if (variance > 0 ) TypeBounds (lo, hi)
3936
+ else range(TypeAlias (lo), TypeAlias (hi))
3920
3937
case _ => tp.derivedTypeAlias(alias)
3921
3938
}
3922
3939
override protected def derivedTypeBounds (tp : TypeBounds , lo : Type , hi : Type ) =
3923
- if ((lo eq tp.lo) && (hi eq tp.hi)) tp else range(lo, hi)
3940
+ if (isRange(lo) || isRange(hi))
3941
+ if (variance > 0 ) TypeBounds (loBound(lo), hiBound(hi))
3942
+ else range(TypeBounds (hiBound(lo), loBound(hi)), TypeBounds (loBound(lo), hiBound(hi)))
3943
+ else tp.derivedTypeBounds(lo, hi)
3924
3944
override protected def derivedSuperType (tp : SuperType , thistp : Type , supertp : Type ) =
3925
- if (thistp. isInstanceOf [ TypeBounds ] || supertp. isInstanceOf [ TypeBounds ] ) range()
3945
+ if (isRange( thistp) || isRange( supertp) ) range()
3926
3946
else tp.derivedSuperType(thistp, supertp)
3947
+
3927
3948
override protected def derivedAppliedType (tp : HKApply , tycon : Type , args : List [Type ]): Type =
3928
3949
tycon match {
3929
- case TypeBounds (tyconLo, tyconHi) =>
3930
- range(tp. derivedAppliedType(tyconLo, args), tp. derivedAppliedType(tyconHi, args))
3950
+ case Range (tyconLo, tyconHi) =>
3951
+ range(derivedAppliedType(tp, tyconLo, args), derivedAppliedType(tp, tyconHi, args))
3931
3952
case _ =>
3932
- tp.derivedAppliedType(tycon, args)
3953
+ if (args.exists(isRange))
3954
+ if (variance > 0 ) tp.derivedAppliedType(tycon, args.map(rangeToBounds))
3955
+ else {
3956
+ val loBuf, hiBuf = new mutable.ListBuffer [Type ]
3957
+ def distributeArgs (args : List [Type ], tparams : List [ParamInfo ]): Boolean = args match {
3958
+ case Range (lo, hi) :: args1 =>
3959
+ val v = tparams.head.paramVariance
3960
+ if (v == 0 ) false
3961
+ else if (v > 0 ) { loBuf += lo; hiBuf += hi }
3962
+ else { loBuf += hi; hiBuf += lo }
3963
+ distributeArgs(args1, tparams.tail)
3964
+ case arg :: args1 =>
3965
+ loBuf += arg; hiBuf += arg
3966
+ distributeArgs(args1, tparams.tail)
3967
+ case nil =>
3968
+ true
3969
+ }
3970
+ if (distributeArgs(args, tp.typeParams))
3971
+ range(tp.derivedAppliedType(tycon, loBuf.toList),
3972
+ tp.derivedAppliedType(tycon, hiBuf.toList))
3973
+ else range()
3974
+ }
3975
+ else tp.derivedAppliedType(tycon, args)
3933
3976
}
3977
+
3934
3978
override protected def derivedAndOrType (tp : AndOrType , tp1 : Type , tp2 : Type ) =
3935
- if (tp1.isInstanceOf [TypeBounds ] || tp2.isInstanceOf [TypeBounds ])
3936
- if (tp.isAnd) range(tp1. loBound & tp2. loBound, tp1. hiBound | tp1. hiBound)
3937
- else range(tp1. loBound | tp2. loBound, tp1. hiBound & tp1. hiBound)
3979
+ if (tp1.isInstanceOf [Range ] || tp2.isInstanceOf [Range ])
3980
+ if (tp.isAnd) range(loBound(tp1) & loBound(tp2), hiBound(tp1) & hiBound(tp2) )
3981
+ else range(loBound(tp1) | loBound(tp2), hiBound(tp1) | hiBound(tp2) )
3938
3982
else tp.derivedAndOrType(tp1, tp2)
3939
3983
override protected def derivedAnnotatedType (tp : AnnotatedType , underlying : Type , annot : Annotation ) =
3940
3984
underlying match {
3941
- case TypeBounds (lo, hi) =>
3985
+ case Range (lo, hi) =>
3942
3986
range(tp.derivedAnnotatedType(lo, annot), tp.derivedAnnotatedType(hi, annot))
3943
3987
case _ =>
3944
3988
if (underlying.isBottomType) underlying
3945
3989
else tp.derivedAnnotatedType(underlying, annot)
3946
3990
}
3947
- override protected def derivedWildcardType (tp : WildcardType , bounds : Type ) =
3948
- tp.derivedWildcardType(bounds)
3991
+ override protected def derivedWildcardType (tp : WildcardType , bounds : Type ) = {
3992
+ tp.derivedWildcardType(rangeToBounds(bounds))
3993
+ }
3949
3994
override protected def derivedClassInfo (tp : ClassInfo , pre : Type ): Type = {
3950
- assert(! pre.isInstanceOf [TypeBounds ])
3995
+ assert(! pre.isInstanceOf [Range ])
3951
3996
tp.derivedClassInfo(pre)
3952
3997
}
3953
3998
}
0 commit comments