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