@@ -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 =>
@@ -1220,6 +1226,18 @@ object Types {
1220
1226
case _ => TypeAlias (this )
1221
1227
}
1222
1228
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
+
1223
1241
/** The type parameter with given `name`. This tries first `decls`
1224
1242
* in order not to provoke a cycle by forcing the info. If that yields
1225
1243
* no symbol it tries `member` as an alternative.
@@ -1766,6 +1784,7 @@ object Types {
1766
1784
*/
1767
1785
def derivedSelect (prefix : Type )(implicit ctx : Context ): Type =
1768
1786
if (prefix eq this .prefix) this
1787
+ else if (prefix.isBottomType) prefix
1769
1788
else if (isType) {
1770
1789
val res = prefix.lookupRefined(name)
1771
1790
if (res.exists) res
@@ -3713,8 +3732,19 @@ object Types {
3713
3732
tp match {
3714
3733
case tp : NamedType =>
3715
3734
if (stopAtStatic && tp.symbol.isStatic) tp
3716
- else derivedSelect(tp, this (tp.prefix))
3717
-
3735
+ else {
3736
+ val prefix1 = tp.info match {
3737
+ case info : TypeBounds if ! info.isAlias =>
3738
+ // prefix of an abstract type selection is non-variant, since a path
3739
+ // cannot be legally widened to its underlying type, or any supertype.
3740
+ val saved = variance
3741
+ variance = 0
3742
+ try this (tp.prefix) finally variance = saved
3743
+ case _ =>
3744
+ this (tp.prefix)
3745
+ }
3746
+ derivedSelect(tp, prefix1)
3747
+ }
3718
3748
case _ : ThisType
3719
3749
| _ : BoundType
3720
3750
| NoPrefix => tp
@@ -3842,63 +3872,84 @@ object Types {
3842
3872
def apply (tp : Type ) = tp
3843
3873
}
3844
3874
3845
- /** A type map that approximates NoTypes by upper or lower known bounds depending on
3875
+ /** A type map that approximates TypeBounds types depending on
3846
3876
* variance.
3847
3877
*
3848
3878
* if variance > 0 : approximate by upper bound
3849
3879
* variance < 0 : approximate by lower bound
3850
- * variance = 0 : propagate NoType to next outer level
3880
+ * variance = 0 : propagate bounds to next outer level
3851
3881
*/
3852
3882
abstract class ApproximatingTypeMap (implicit ctx : Context ) extends TypeMap { thisMap =>
3853
- def approx (lo : Type = defn.NothingType , hi : Type = defn.AnyType ) =
3854
- if (variance == 0 ) NoType
3855
- else apply(if (variance < 0 ) lo else hi)
3883
+ def range (lo : Type = defn.NothingType , hi : Type = defn.AnyType ) =
3884
+ if (variance > 0 ) hi
3885
+ else if (variance < 0 ) lo
3886
+ else TypeBounds (lo.loBound, hi.hiBound)
3856
3887
3857
3888
override protected def derivedSelect (tp : NamedType , pre : Type ) =
3858
3889
if (pre eq tp.prefix) tp
3859
- else tp.info match {
3860
- case TypeAlias (alias) => apply(alias) // try to heal by following aliases
3861
- case _ =>
3862
- if (pre.exists && ! pre.isRef(defn.NothingClass ) && variance > 0 ) tp.derivedSelect(pre)
3863
- else tp.info match {
3864
- case TypeBounds (lo, hi) => approx(lo, hi)
3865
- case _ => approx()
3890
+ else pre match {
3891
+ case TypeBounds (preLo, preHi) =>
3892
+ tp.info match {
3893
+ case TypeAlias (alias) => apply(alias)
3894
+ case info @ TypeBounds (lo, hi) => apply(range(lo, hi))
3895
+ case _ => range(tp.derivedSelect(preLo), tp.derivedSelect(preHi))
3866
3896
}
3897
+ case _ => tp.derivedSelect(pre)
3867
3898
}
3868
3899
override protected def derivedRefinedType (tp : RefinedType , parent : Type , info : Type ) =
3869
- if (parent.exists && info.exists) tp.derivedRefinedType(parent, tp.refinedName, info)
3870
- else approx(hi = parent)
3900
+ parent match {
3901
+ case TypeBounds (parentLo, parentHi) =>
3902
+ range(derivedRefinedType(tp, parentLo, info), derivedRefinedType(tp, parentHi, info))
3903
+ case _ =>
3904
+ if (parent.isBottomType) parent
3905
+ else info match {
3906
+ case TypeBounds (infoLo, infoHi) if tp.refinedName.isTermName =>
3907
+ range(derivedRefinedType(tp, parent, infoLo), derivedRefinedType(tp, parent, infoHi))
3908
+ case _ =>
3909
+ tp.derivedRefinedType(parent, tp.refinedName, info)
3910
+ }
3911
+ }
3871
3912
override protected def derivedRecType (tp : RecType , parent : Type ) =
3872
- if (parent.exists) tp.rebind(parent)
3873
- else approx()
3913
+ parent match {
3914
+ case TypeBounds (lo, hi) => range(tp.rebind(lo), tp.rebind(hi))
3915
+ case _ => tp.rebind(parent)
3916
+ }
3874
3917
override protected def derivedTypeAlias (tp : TypeAlias , alias : Type ) =
3875
- if (alias.exists) tp.derivedTypeAlias(alias)
3876
- else approx(NoType , TypeBounds .empty)
3918
+ alias match {
3919
+ case bounds : TypeBounds => bounds
3920
+ case _ => tp.derivedTypeAlias(alias)
3921
+ }
3877
3922
override protected def derivedTypeBounds (tp : TypeBounds , lo : Type , hi : Type ) =
3878
- if (lo.exists && hi.exists) tp.derivedTypeBounds(lo, hi)
3879
- else approx(NoType ,
3880
- if (lo.exists) TypeBounds .lower(lo)
3881
- else if (hi.exists) TypeBounds .upper(hi)
3882
- else TypeBounds .empty)
3923
+ if ((lo eq tp.lo) && (hi eq tp.hi)) tp else range(lo, hi)
3883
3924
override protected def derivedSuperType (tp : SuperType , thistp : Type , supertp : Type ) =
3884
- if (thistp.exists && supertp.exists) tp.derivedSuperType(thistp, supertp )
3885
- else NoType
3925
+ if (thistp.isInstanceOf [ TypeBounds ] || supertp.isInstanceOf [ TypeBounds ]) range( )
3926
+ else tp.derivedSuperType(thistp, supertp)
3886
3927
override protected def derivedAppliedType (tp : HKApply , tycon : Type , args : List [Type ]): Type =
3887
- if (tycon.exists && args.forall(_.exists)) tp.derivedAppliedType(tycon, args)
3888
- else approx() // This is rather coarse, but to do better is a bit complicated
3928
+ tycon match {
3929
+ case TypeBounds (tyconLo, tyconHi) =>
3930
+ range(tp.derivedAppliedType(tyconLo, args), tp.derivedAppliedType(tyconHi, args))
3931
+ case _ =>
3932
+ tp.derivedAppliedType(tycon, args)
3933
+ }
3889
3934
override protected def derivedAndOrType (tp : AndOrType , tp1 : Type , tp2 : Type ) =
3890
- if (tp1.exists && tp2.exists) tp.derivedAndOrType(tp1, tp2)
3891
- else if (tp.isAnd) approx(hi = tp1 & tp2) // if one of tp1d, tp2d exists, it is the result of tp1d & tp2d
3892
- else approx(lo = tp1 & tp2)
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)
3938
+ else tp.derivedAndOrType(tp1, tp2)
3893
3939
override protected def derivedAnnotatedType (tp : AnnotatedType , underlying : Type , annot : Annotation ) =
3894
- if (underlying.exists) tp.derivedAnnotatedType(underlying, annot)
3895
- else NoType
3940
+ underlying match {
3941
+ case TypeBounds (lo, hi) =>
3942
+ range(tp.derivedAnnotatedType(lo, annot), tp.derivedAnnotatedType(hi, annot))
3943
+ case _ =>
3944
+ if (underlying.isBottomType) underlying
3945
+ else tp.derivedAnnotatedType(underlying, annot)
3946
+ }
3896
3947
override protected def derivedWildcardType (tp : WildcardType , bounds : Type ) =
3897
- if (bounds.exists) tp.derivedWildcardType(bounds)
3898
- else WildcardType
3899
- override protected def derivedClassInfo ( tp : ClassInfo , pre : Type ) : Type =
3900
- if (pre.exists) tp.derivedClassInfo(pre)
3901
- else NoType
3948
+ tp.derivedWildcardType(bounds)
3949
+ override protected def derivedClassInfo ( tp : ClassInfo , pre : Type ) : Type = {
3950
+ assert( ! pre. isInstanceOf [ TypeBounds ])
3951
+ tp.derivedClassInfo(pre)
3952
+ }
3902
3953
}
3903
3954
3904
3955
// ----- TypeAccumulators ----------------------------------------------------
0 commit comments