@@ -3,6 +3,7 @@ package core
3
3
4
4
import Types ._ , Contexts ._ , Flags ._ , Symbols ._ , Annotations ._
5
5
import TypeApplications .TypeParamInfo
6
+ import Decorators ._
6
7
7
8
object Variances {
8
9
@@ -108,24 +109,19 @@ object Variances {
108
109
Bivariant
109
110
}
110
111
111
- /** A map from the index of a lambda parameter to its variance in -1 .. 1 */
112
- type ParamVarianceMap = Map [Int , Int ]
113
-
114
- def lambdaVariances (lam : HKTypeLambda )(implicit ctx : Context ): ParamVarianceMap =
115
- object accu extends TypeAccumulator [ParamVarianceMap ] {
116
- def apply (vmap : ParamVarianceMap , t : Type ): ParamVarianceMap = t match {
112
+ def setStructuralVariances (lam : HKTypeLambda )(implicit ctx : Context ): Unit =
113
+ assert(! lam.isVariant)
114
+ for param <- lam.typeParams do param.storedVariance = Bivariant
115
+ object traverse extends TypeAccumulator [Unit ] {
116
+ def apply (x : Unit , t : Type ): Unit = t match
117
117
case t : TypeParamRef if t.binder eq lam =>
118
- val idx = t.paramNum
119
- vmap.get(idx) match
120
- case None =>
121
- vmap.updated(idx, variance)
122
- case Some (v) =>
123
- if v == variance || v == 0 then vmap else vmap.updated(idx, 0 )
118
+ lam.typeParams(t.paramNum).storedVariance &= varianceFromInt(variance)
119
+ case _ : LazyRef =>
120
+ x
124
121
case _ =>
125
- foldOver(vmap, t)
126
- }
122
+ foldOver(x, t)
127
123
}
128
- accu( Map (), lam.resType)
124
+ traverse( (), lam.resType)
129
125
130
126
/** Does variance `v1` conform to variance `v2`?
131
127
* This is the case if the variances are the same or `sym` is nonvariant.
@@ -136,21 +132,19 @@ object Variances {
136
132
/** Does the variance of type parameter `tparam1` conform to the variance of type parameter `tparam2`?
137
133
*/
138
134
def varianceConforms (tparam1 : TypeParamInfo , tparam2 : TypeParamInfo )(implicit ctx : Context ): Boolean =
139
- varianceConforms( tparam1.paramVarianceSign, tparam2.paramVarianceSign )
135
+ tparam1.paramVariance.isAllOf( tparam2.paramVariance )
140
136
141
137
/** Do the variances of type parameters `tparams1` conform to the variances
142
138
* of corresponding type parameters `tparams2`?
143
139
* This is only the case of `tparams1` and `tparams2` have the same length.
144
140
*/
145
141
def variancesConform (tparams1 : List [TypeParamInfo ], tparams2 : List [TypeParamInfo ])(implicit ctx : Context ): Boolean =
146
- tparams1.corresponds(tparams2)(varianceConforms)
147
-
148
- def variancesConform (vs1 : List [Variance ], vs2 : List [Variance ]): Boolean = vs2 match
149
- case v2 :: rest2 =>
150
- vs1 match
151
- case v1 :: rest1 => v1.isAllOf(v2) && variancesConform(rest1, rest2)
152
- case nil => v2.isEmpty && variancesConform(vs1, rest2)
153
- case nil => true
142
+ val needsDetailedCheck = tparams2 match
143
+ case (_ : Symbol ) :: _ => true
144
+ case LambdaParam (tl : HKTypeLambda , _) :: _ => tl.isVariant
145
+ case _ => false
146
+ if needsDetailedCheck then tparams1.corresponds(tparams2)(varianceConforms)
147
+ else tparams1.hasSameLengthAs(tparams2)
154
148
155
149
def varianceString (sym : Symbol )(implicit ctx : Context ): String =
156
150
varianceString(sym.variance)
0 commit comments