@@ -3676,14 +3676,26 @@ object Types {
3676
3676
3677
3677
// ----- TypeMaps --------------------------------------------------------------------
3678
3678
3679
- abstract class TypeMap (implicit protected val ctx : Context ) extends (Type => Type ) { thisMap =>
3679
+ /** Common base class of TypeMap and TypeAccumulator */
3680
+ abstract class VariantTraversal {
3681
+ protected [core] var variance = 1
3682
+
3683
+ @ inline protected def atVariance [T ](v : Int )(op : => T ): T = {
3684
+ val saved = variance
3685
+ variance = v
3686
+ val res = op
3687
+ variance = saved
3688
+ res
3689
+ }
3690
+ }
3691
+
3692
+ abstract class TypeMap (implicit protected val ctx : Context )
3693
+ extends VariantTraversal with (Type => Type ) { thisMap =>
3680
3694
3681
3695
protected def stopAtStatic = true
3682
3696
3683
3697
def apply (tp : Type ): Type
3684
3698
3685
- protected [core] var variance = 1
3686
-
3687
3699
protected def derivedSelect (tp : NamedType , pre : Type ): Type =
3688
3700
tp.derivedSelect(pre)
3689
3701
protected def derivedRefinedType (tp : RefinedType , parent : Type , info : Type ): Type =
@@ -3721,16 +3733,13 @@ object Types {
3721
3733
case tp : NamedType =>
3722
3734
if (stopAtStatic && tp.symbol.isStatic) tp
3723
3735
else {
3724
- val saved = variance
3725
- variance = variance max 0
3736
+ val prefix1 = atVariance(variance max 0 )(this (tp.prefix))
3726
3737
// A prefix is never contravariant. Even if say `p.A` is used in a contravariant
3727
3738
// context, we cannot assume contravariance for `p` because `p`'s lower
3728
3739
// bound might not have a binding for `A` (e.g. the lower bound could be `Nothing`).
3729
3740
// By contrast, covariance does translate to the prefix, since we have that
3730
3741
// if `p <: q` then `p.A <: q.A`, and well-formedness requires that `A` is a member
3731
3742
// of `p`'s upper bound.
3732
- val prefix1 = this (tp.prefix)
3733
- variance = saved
3734
3743
derivedSelect(tp, prefix1)
3735
3744
}
3736
3745
case _ : ThisType
@@ -3741,11 +3750,7 @@ object Types {
3741
3750
derivedRefinedType(tp, this (tp.parent), this (tp.refinedInfo))
3742
3751
3743
3752
case tp : TypeAlias =>
3744
- val saved = variance
3745
- variance *= tp.variance
3746
- val alias1 = this (tp.alias)
3747
- variance = saved
3748
- derivedTypeAlias(tp, alias1)
3753
+ derivedTypeAlias(tp, atVariance(variance * tp.variance)(this (tp.alias)))
3749
3754
3750
3755
case tp : TypeBounds =>
3751
3756
variance = - variance
@@ -3761,12 +3766,8 @@ object Types {
3761
3766
if (inst.exists) apply(inst) else tp
3762
3767
3763
3768
case tp : HKApply =>
3764
- def mapArg (arg : Type , tparam : ParamInfo ): Type = {
3765
- val saved = variance
3766
- variance *= tparam.paramVariance
3767
- try this (arg)
3768
- finally variance = saved
3769
- }
3769
+ def mapArg (arg : Type , tparam : ParamInfo ): Type =
3770
+ atVariance(variance * tparam.paramVariance)(this (arg))
3770
3771
derivedAppliedType(tp, this (tp.tycon),
3771
3772
tp.args.zipWithConserve(tp.typeParams)(mapArg))
3772
3773
@@ -3891,12 +3892,6 @@ object Types {
3891
3892
case _ => tp
3892
3893
}
3893
3894
3894
- protected def atVariance [T ](v : Int )(op : => T ): T = {
3895
- val saved = variance
3896
- variance = v
3897
- try op finally variance = saved
3898
- }
3899
-
3900
3895
/** Derived selection.
3901
3896
* @pre the (upper bound of) prefix `pre` has a member named `tp.name`.
3902
3897
*/
@@ -4051,23 +4046,17 @@ object Types {
4051
4046
4052
4047
// ----- TypeAccumulators ----------------------------------------------------
4053
4048
4054
- abstract class TypeAccumulator [T ](implicit protected val ctx : Context ) extends ((T , Type ) => T ) {
4049
+ abstract class TypeAccumulator [T ](implicit protected val ctx : Context )
4050
+ extends VariantTraversal with ((T , Type ) => T ) {
4055
4051
4056
4052
protected def stopAtStatic = true
4057
4053
4058
4054
def apply (x : T , tp : Type ): T
4059
4055
4060
4056
protected def applyToAnnot (x : T , annot : Annotation ): T = x // don't go into annotations
4061
4057
4062
- protected var variance = 1
4063
-
4064
- protected final def applyToPrefix (x : T , tp : NamedType ) = {
4065
- val saved = variance
4066
- variance = variance max 0 // see remark on NamedType case in TypeMap
4067
- val result = this (x, tp.prefix)
4068
- variance = saved
4069
- result
4070
- }
4058
+ protected final def applyToPrefix (x : T , tp : NamedType ) =
4059
+ atVariance(variance max 0 )(this (x, tp.prefix)) // see remark on NamedType case in TypeMap
4071
4060
4072
4061
def foldOver (x : T , tp : Type ): T = tp match {
4073
4062
case tp : TypeRef =>
@@ -4088,13 +4077,7 @@ object Types {
4088
4077
this (this (x, tp.parent), tp.refinedInfo)
4089
4078
4090
4079
case bounds @ TypeBounds (lo, hi) =>
4091
- if (lo eq hi) {
4092
- val saved = variance
4093
- variance = variance * bounds.variance
4094
- val result = this (x, lo)
4095
- variance = saved
4096
- result
4097
- }
4080
+ if (lo eq hi) atVariance(variance * bounds.variance)(this (x, lo))
4098
4081
else {
4099
4082
variance = - variance
4100
4083
val y = this (x, lo)
0 commit comments