Skip to content

Commit cfbd5d5

Browse files
VLanvinfacebook-github-bot
authored andcommittedMar 11, 2025
Fix variance issue
Summary: Variance should never be `None`, if a variable does not appear in a type, it should be `Constant`. This fixes a bug where we try to get the variance of a type with no children, see T217516278. Reviewed By: ilya-klyuchnikov Differential Revision: D70898044 fbshipit-source-id: d2a9f95ffd95e66dd3e4cb20a3dfd9274e66d8be
1 parent 2955a81 commit cfbd5d5

File tree

1 file changed

+16
-19
lines changed
  • eqwalizer/src/main/scala/com/whatsapp/eqwalizer/tc/generics

1 file changed

+16
-19
lines changed
 

‎eqwalizer/src/main/scala/com/whatsapp/eqwalizer/tc/generics/Variance.scala

+16-19
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@ class Variance(pipelineContext: PipelineContext) {
2525
val id = Id(remoteId.name, remoteId.arity)
2626
DbApi.getType(remoteId.module, id) match {
2727
case Some(tDecl) =>
28-
tDecl.params.map(varType => varianceOf(tDecl.body, varType.n, isPositivePosition = true).get)
28+
tDecl.params.map(varType => varianceOf(tDecl.body, varType.n, isPositivePosition = true))
2929
case None =>
3030
// Opaques are covariant
3131
DbApi.getPrivateOpaque(remoteId.module, id).get.params.map(_ => Covariant)
3232
}
3333
}
3434

35-
private def varianceOf(ty: Type, tv: Var, isPositivePosition: Boolean): Option[Variance.Variance] =
35+
private def varianceOf(ty: Type, tv: Var, isPositivePosition: Boolean): Variance.Variance =
3636
getVarianceOf(ty, tv, isPositivePosition)(history = Set())
3737

3838
private def getVarianceOf(ty: Type, tv: Var, isPositivePosition: Boolean)(implicit
3939
history: Set[(RemoteType, Boolean)]
40-
): Option[Variance.Variance] = ty match {
40+
): Variance.Variance = ty match {
4141
case VarType(n) if tv == n =>
42-
if (isPositivePosition) Some(Covariant)
43-
else Some(Contravariant)
42+
if (isPositivePosition) Covariant
43+
else Contravariant
4444
case FunType(forall, argTys, resTy) =>
4545
// forall can only be non-empty only for top-level fun types
4646
// corresponding to generic specs
@@ -49,7 +49,7 @@ class Variance(pipelineContext: PipelineContext) {
4949
combineVariances(variances)
5050
case t @ RemoteType(rid, args) =>
5151
if (history((t, isPositivePosition))) {
52-
Some(Constant)
52+
Constant
5353
} else {
5454
val body = util.getTypeDeclBody(rid, args)
5555
getVarianceOf(body, tv, isPositivePosition)(history + ((t, isPositivePosition)))
@@ -61,27 +61,24 @@ class Variance(pipelineContext: PipelineContext) {
6161

6262
private def toTopLevelVariance(ft: FunType, tv: Var): Variance.Variance =
6363
varianceOf(ft.resTy, tv, isPositivePosition = true) match {
64-
case Some(variance) =>
65-
variance
66-
case None =>
67-
combineVariances(ft.argTys.map(varianceOf(_, tv, isPositivePosition = false))).getOrElse(Constant) match {
64+
case Constant =>
65+
combineVariances(ft.argTys.map(varianceOf(_, tv, isPositivePosition = false))) match {
6866
case Constant | Covariant | Invariant =>
6967
Covariant
7068
case Contravariant =>
7169
Contravariant
7270
}
71+
case variance =>
72+
variance
7373
}
7474

75-
private def combineVariances(variances: List[Option[Variance.Variance]]): Option[Variance.Variance] =
76-
variances.foldLeft(None: Option[Variance.Variance])((v1Opt, v2Opt) =>
75+
private def combineVariances(variances: List[Variance.Variance]): Variance.Variance =
76+
variances.foldLeft(Constant: Variance.Variance)((v1Opt, v2Opt) =>
7777
(v1Opt, v2Opt) match {
78-
case (None, Some(v)) => Some(v)
79-
case (Some(v), None) => Some(v)
80-
case (v, Some(Constant)) => v
81-
case (Some(Constant), v) => v
82-
case (None, None) => None
83-
case (Some(v1), Some(v2)) if v1 == v2 => Some(v1)
84-
case (Some(_), Some(_)) => Some(Invariant)
78+
case (v, Constant) => v
79+
case (Constant, v) => v
80+
case (v1, v2) if v1 == v2 => v1
81+
case (_, _) => Invariant
8582
}
8683
)
8784
}

0 commit comments

Comments
 (0)