@@ -3923,20 +3923,27 @@ object Types {
3923
3923
case Range (parentLo, parentHi) =>
3924
3924
range(derivedRefinedType(tp, parentLo, info), derivedRefinedType(tp, parentHi, info))
3925
3925
case _ =>
3926
+ def propagate (lo : Type , hi : Type ) =
3927
+ range(derivedRefinedType(tp, parent, lo), derivedRefinedType(tp, parent, hi))
3926
3928
if (parent.isBottomType) parent
3927
3929
else info match {
3930
+ case Range (infoLo : TypeBounds , infoHi : TypeBounds ) =>
3931
+ assert(variance == 0 )
3932
+ val v1 = infoLo.variance
3933
+ val v2 = infoHi.variance
3934
+ // There's some weirdness coming from the way aliases can have variance
3935
+ // If infoLo and infoHi are both aliases with the same non-zero variance
3936
+ // we can propagate to a range of the refined types. If they are both
3937
+ // non-alias ranges we know that infoLo <:< infoHi and therefore we can
3938
+ // propagate to refined types with infoLo and infoHi as bounds.
3939
+ // In all other cases, Nothing..Any is the only interval that contains
3940
+ // the range. i966.scala is a test case.
3941
+ if (v1 > 0 && v2 > 0 ) propagate(infoLo, infoHi)
3942
+ else if (v1 < 0 && v2 < 0 ) propagate(infoHi, infoLo)
3943
+ else if (! infoLo.isAlias && ! infoHi.isAlias) propagate(infoLo, infoHi)
3944
+ else range(tp.bottomType, tp.topType)
3928
3945
case Range (infoLo, infoHi) =>
3929
- def propagate (lo : Type , hi : Type ) =
3930
- range(derivedRefinedType(tp, parent, lo), derivedRefinedType(tp, parent, hi))
3931
- tp.refinedInfo match {
3932
- case rinfo : TypeBounds =>
3933
- val v = if (rinfo.isAlias) rinfo.variance * variance else variance
3934
- if (v > 0 ) tp.derivedRefinedType(parent, tp.refinedName, rangeToBounds(info))
3935
- else if (v < 0 ) propagate(infoHi, infoLo)
3936
- else range(tp.bottomType, tp.topType)
3937
- case _ =>
3938
- propagate(infoLo, infoHi)
3939
- }
3946
+ propagate(infoLo, infoHi)
3940
3947
case _ =>
3941
3948
tp.derivedRefinedType(parent, tp.refinedName, info)
3942
3949
}
0 commit comments