@@ -3,6 +3,7 @@ package core
33
44import Types ._ , Contexts ._ , Flags ._ , Symbols ._ , Annotations ._
55import TypeApplications .TypeParamInfo
6+ import Decorators ._
67
78object Variances {
89
@@ -108,24 +109,19 @@ object Variances {
108109 Bivariant
109110 }
110111
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
117117 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
124121 case _ =>
125- foldOver(vmap, t)
126- }
122+ foldOver(x, t)
127123 }
128- accu( Map (), lam.resType)
124+ traverse( (), lam.resType)
129125
130126 /** Does variance `v1` conform to variance `v2`?
131127 * This is the case if the variances are the same or `sym` is nonvariant.
@@ -136,21 +132,19 @@ object Variances {
136132 /** Does the variance of type parameter `tparam1` conform to the variance of type parameter `tparam2`?
137133 */
138134 def varianceConforms (tparam1 : TypeParamInfo , tparam2 : TypeParamInfo )(implicit ctx : Context ): Boolean =
139- varianceConforms( tparam1.paramVarianceSign, tparam2.paramVarianceSign )
135+ tparam1.paramVariance.isAllOf( tparam2.paramVariance )
140136
141137 /** Do the variances of type parameters `tparams1` conform to the variances
142138 * of corresponding type parameters `tparams2`?
143139 * This is only the case of `tparams1` and `tparams2` have the same length.
144140 */
145141 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)
154148
155149 def varianceString (sym : Symbol )(implicit ctx : Context ): String =
156150 varianceString(sym.variance)
0 commit comments