Skip to content

Commit aadbac1

Browse files
VLanvinfacebook-github-bot
authored andcommitted
Always use positive part of occurrence typing in clauses
Summary: Only disable the negative part under size conditions (>7 clauses, etc...). `unlimited_refinement` can override this, as before. Reviewed By: ilya-klyuchnikov Differential Revision: D60237928 fbshipit-source-id: 7e065084048799d7d460daa944ff63c4ecd49d4e
1 parent c473783 commit aadbac1

File tree

5 files changed

+54
-100
lines changed

5 files changed

+54
-100
lines changed

eqwalizer/src/main/scala/com/whatsapp/eqwalizer/tc/Check.scala

+24-50
Original file line numberDiff line numberDiff line change
@@ -33,36 +33,23 @@ final class Check(pipelineContext: PipelineContext) {
3333
def checkFun(f: FunDecl, spec: FunSpec): Unit = {
3434
val ft = freshen(spec.ty)
3535
val FunType(_, argTys, resTy) = ft
36-
if (occurrence.eqwater(f.clauses)) {
37-
val clauseEnvs = occurrence.clausesEnvs(f.clauses, ft.argTys, Map.empty)
38-
f.clauses
39-
.lazyZip(1 to f.clauses.length)
40-
.lazyZip(clauseEnvs)
41-
.foreach((clause, index, occEnv) =>
42-
checkClause(clause, argTys, resTy, occEnv, Set.empty, checkCoverage = (index != f.clauses.length))
43-
)
44-
} else {
45-
f.clauses
46-
.lazyZip(1 to f.clauses.length)
47-
.foreach((clause, index) =>
48-
checkClause(clause, argTys, resTy, Env.empty, Set.empty, checkCoverage = (index != f.clauses.length))
49-
)
50-
}
36+
val clauseEnvs = occurrence.clausesEnvs(f.clauses, ft.argTys, Map.empty)
37+
f.clauses
38+
.lazyZip(1 to f.clauses.length)
39+
.lazyZip(clauseEnvs)
40+
.foreach((clause, index, occEnv) =>
41+
checkClause(clause, argTys, resTy, occEnv, Set.empty, checkCoverage = (index != f.clauses.length))
42+
)
5143
}
5244

5345
def checkOverloadedFun(f: FunDecl, overloadedSpec: OverloadedFunSpec): Unit = {
54-
val occTyping = occurrence.eqwater(f.clauses)
5546
overloadedSpec.tys.foreach { funTy =>
5647
val ft = freshen(funTy)
5748
val FunType(_, argTys, resTy) = ft
58-
if (occTyping) {
59-
val clauseEnvs = occurrence.clausesEnvs(f.clauses, ft.argTys, Env.empty)
60-
f.clauses
61-
.lazyZip(clauseEnvs)
62-
.map((clause, occEnv) => checkClauseOverloadedClause(clause, argTys, resTy, occEnv))
63-
} else {
64-
f.clauses.map(checkClauseOverloadedClause(_, argTys, resTy, Env.empty))
65-
}
49+
val clauseEnvs = occurrence.clausesEnvs(f.clauses, ft.argTys, Env.empty)
50+
f.clauses
51+
.lazyZip(clauseEnvs)
52+
.map((clause, occEnv) => checkClauseOverloadedClause(clause, argTys, resTy, occEnv))
6653
}
6754
}
6855

@@ -250,14 +237,10 @@ final class Check(pipelineContext: PipelineContext) {
250237
val env2 = env.updated(name, funType)
251238
checkExpr(l, funType, env2)
252239
case _ =>
253-
if (occurrence.eqwater(l.clauses)) {
254-
val envs = occurrence.clausesEnvs(l.clauses, argTys, env1)
255-
l.clauses
256-
.lazyZip(envs)
257-
.map((clause, occEnv) => checkClause(clause, argTys, resTy, occEnv, Set.empty))
258-
} else {
259-
l.clauses.foreach(checkClause(_, argTys, resTy, env1, Set.empty))
260-
}
240+
val envs = occurrence.clausesEnvs(l.clauses, argTys, env1)
241+
l.clauses
242+
.lazyZip(envs)
243+
.map((clause, occEnv) => checkClause(clause, argTys, resTy, occEnv, Set.empty))
261244
}
262245
env1
263246
case DynCall(dynRemoteFun: DynRemoteFun, args) =>
@@ -378,16 +361,11 @@ final class Check(pipelineContext: PipelineContext) {
378361
case TryOfCatchExpr(tryBody, tryClauses, catchClauses, afterBody) =>
379362
val (tryBodyT, tryEnv) = elab.elabBody(tryBody, env)
380363
val stackType = clsExnStackTypeDynamic
381-
if (occurrence.eqwater(tryClauses)) {
382-
val tryEnvs = occurrence.clausesEnvs(tryClauses, List(tryBodyT), tryEnv)
383-
tryClauses
384-
.lazyZip(tryEnvs)
385-
.map((clause, occEnv) => checkClause(clause, List(tryBodyT), resTy, occEnv, Set.empty))
386-
catchClauses.map(checkClause(_, List(stackType), resTy, env, Set.empty))
387-
} else {
388-
tryClauses.map(checkClause(_, List(tryBodyT), resTy, tryEnv, Set.empty))
389-
catchClauses.map(checkClause(_, List(stackType), resTy, env, Set.empty))
390-
}
364+
val tryEnvs = occurrence.clausesEnvs(tryClauses, List(tryBodyT), tryEnv)
365+
tryClauses
366+
.lazyZip(tryEnvs)
367+
.map((clause, occEnv) => checkClause(clause, List(tryBodyT), resTy, occEnv, Set.empty))
368+
catchClauses.map(checkClause(_, List(stackType), resTy, env, Set.empty))
391369
afterBody match {
392370
case Some(block) => elab.elabBody(block, env)._2
393371
case None => env
@@ -516,14 +494,10 @@ final class Check(pipelineContext: PipelineContext) {
516494
case _ =>
517495
env
518496
}
519-
if (occurrence.eqwater(lambda.clauses)) {
520-
val envs = occurrence.clausesEnvs(lambda.clauses, fParamTys, env1)
521-
lambda.clauses
522-
.lazyZip(envs)
523-
.map((clause, occEnv) => checkClause(clause, fParamTys, fResTy, occEnv, Set.empty))
524-
} else {
525-
lambda.clauses.foreach(checkClause(_, fParamTys, fResTy, env1, exportedVars = Set.empty))
526-
}
497+
val envs = occurrence.clausesEnvs(lambda.clauses, fParamTys, env1)
498+
lambda.clauses
499+
.lazyZip(envs)
500+
.map((clause, occEnv) => checkClause(clause, fParamTys, fResTy, occEnv, Set.empty))
527501
env
528502
}
529503

eqwalizer/src/main/scala/com/whatsapp/eqwalizer/tc/Elab.scala

+13-25
Original file line numberDiff line numberDiff line change
@@ -165,14 +165,12 @@ final class Elab(pipelineContext: PipelineContext) {
165165
check.checkExpr(l, funType, env2)
166166
(DynamicType, env1)
167167
case _ =>
168-
val (resTys, _) = if (occurrence.eqwater(l.clauses)) {
169-
val envs = occurrence.clausesEnvs(l.clauses, argTys, env1)
168+
val envs = occurrence.clausesEnvs(l.clauses, argTys, env1)
169+
val (resTys, _) =
170170
l.clauses
171171
.lazyZip(envs)
172172
.map((clause, occEnv) => elabClause(clause, argTys, occEnv, Set.empty))
173173
.unzip
174-
} else
175-
l.clauses.map(elabClause(_, argTys, env1, Set.empty)).unzip
176174
(subtype.join(resTys), env1)
177175
}
178176
case DynCall(dynRemoteFun: DynRemoteFun, args) =>
@@ -446,28 +444,18 @@ final class Elab(pipelineContext: PipelineContext) {
446444
case TryOfCatchExpr(tryBody, tryClauses, catchClauses, afterBody) =>
447445
val (tryT, tryEnv) = elabBody(tryBody, env)
448446
val stackType = clsExnStackTypeDynamic
449-
if (occurrence.eqwater(tryClauses)) {
450-
val tryEnvs = occurrence.clausesEnvs(tryClauses, List(tryT), tryEnv)
451-
val (tryTs, _) =
452-
tryClauses
453-
.lazyZip(tryEnvs)
454-
.map((clause, occEnv) => elabClause(clause, List(tryT), occEnv, Set.empty))
455-
.unzip
456-
val (catchTs, _) = catchClauses.map(elabClause(_, List(stackType), env, Set.empty)).unzip
457-
val env1 = afterBody match {
458-
case Some(block) => elabBody(block, env)._2
459-
case None => env
460-
}
461-
(subtype.join(tryTs ::: catchTs), env1)
462-
} else {
463-
val (tryTs, _) = tryClauses.map(elabClause(_, List(tryT), tryEnv, Set.empty)).unzip
464-
val (catchTs, _) = catchClauses.map(elabClause(_, List(stackType), env, Set.empty)).unzip
465-
val env1 = afterBody match {
466-
case Some(block) => elabBody(block, env)._2
467-
case None => env
468-
}
469-
(subtype.join(tryTs ::: catchTs), env1)
447+
val tryEnvs = occurrence.clausesEnvs(tryClauses, List(tryT), tryEnv)
448+
val (tryTs, _) =
449+
tryClauses
450+
.lazyZip(tryEnvs)
451+
.map((clause, occEnv) => elabClause(clause, List(tryT), occEnv, Set.empty))
452+
.unzip
453+
val (catchTs, _) = catchClauses.map(elabClause(_, List(stackType), env, Set.empty)).unzip
454+
val env1 = afterBody match {
455+
case Some(block) => elabBody(block, env)._2
456+
case None => env
470457
}
458+
(subtype.join(tryTs ::: catchTs), env1)
471459
case Receive(clauses) =>
472460
val effVars = Vars.clausesVars(clauses)
473461
val argType = DynamicType

eqwalizer/src/main/scala/com/whatsapp/eqwalizer/tc/ElabApply.scala

+5-8
Original file line numberDiff line numberDiff line change
@@ -178,15 +178,12 @@ class ElabApply(pipelineContext: PipelineContext) {
178178
env
179179
}
180180

181+
val envs = occurrence.clausesEnvs(lambda.clauses, argTys, env1)
181182
val clauseTys =
182-
if (occurrence.eqwater(lambda.clauses)) {
183-
val envs = occurrence.clausesEnvs(lambda.clauses, argTys, env1)
184-
lambda.clauses
185-
.lazyZip(envs)
186-
.map((clause, occEnv) => elab.elabClause(clause, argTys, occEnv, Set.empty))
187-
.map(_._1)
188-
} else
189-
lambda.clauses.map(elab.elabClause(_, argTys, env1, Set.empty)).map(_._1)
183+
lambda.clauses
184+
.lazyZip(envs)
185+
.map((clause, occEnv) => elab.elabClause(clause, argTys, occEnv, Set.empty))
186+
.map(_._1)
190187

191188
val resTy = subtype.join(clauseTys)
192189
ft.copy(argTys = argTys, resTy = resTy)

eqwalizer/src/main/scala/com/whatsapp/eqwalizer/tc/ElabApplyCustom.scala

+8-16
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,10 @@ class ElabApplyCustom(pipelineContext: PipelineContext) {
139139
case lambda: Lambda =>
140140
check.checkLambda(lambda, expFunTy, env)
141141
val lamEnv = lambda.name.map(name => env.updated(name, expFunTy)).getOrElse(env)
142-
if (occurrence.eqwater(lambda.clauses)) {
143-
val clauseEnvs = occurrence.clausesEnvs(lambda.clauses, List(elemTy), lamEnv)
144-
lambda.clauses
145-
.lazyZip(clauseEnvs)
146-
.map((clause, occEnv) => elab.elabClause(clause, List(elemTy), occEnv, Set.empty)._1)
147-
} else {
148-
lambda.clauses.map(elab.elabClause(_, List(elemTy), lamEnv, Set.empty)).map(_._1)
149-
}
142+
val clauseEnvs = occurrence.clausesEnvs(lambda.clauses, List(elemTy), lamEnv)
143+
lambda.clauses
144+
.lazyZip(clauseEnvs)
145+
.map((clause, occEnv) => elab.elabClause(clause, List(elemTy), occEnv, Set.empty)._1)
150146
case _ =>
151147
if (!subtype.subType(funArgTy, expFunTy)) {
152148
diagnosticsInfo.add(ExpectedSubtype(funArg.pos, funArg, expected = expFunTy, got = funArgTy))
@@ -391,14 +387,10 @@ class ElabApplyCustom(pipelineContext: PipelineContext) {
391387
case lambda: Lambda =>
392388
check.checkLambda(lambda, expFunTy, env)
393389
val lamEnv = lambda.name.map(name => env.updated(name, expFunTy)).getOrElse(env)
394-
if (occurrence.eqwater(lambda.clauses)) {
395-
val clauseEnvs = occurrence.clausesEnvs(lambda.clauses, List(keyTy, valTy), lamEnv)
396-
lambda.clauses
397-
.lazyZip(clauseEnvs)
398-
.map((clause, occEnv) => elab.elabClause(clause, List(keyTy, valTy), occEnv, Set.empty)._1)
399-
} else {
400-
lambda.clauses.map(elab.elabClause(_, List(keyTy, valTy), lamEnv, Set.empty)).map(_._1)
401-
}
390+
val clauseEnvs = occurrence.clausesEnvs(lambda.clauses, List(keyTy, valTy), lamEnv)
391+
lambda.clauses
392+
.lazyZip(clauseEnvs)
393+
.map((clause, occEnv) => elab.elabClause(clause, List(keyTy, valTy), occEnv, Set.empty)._1)
402394
case _ =>
403395
val funArgCoercedTy = coerce(funArg, funArgTy, expFunTy)
404396
narrow.asFunType(funArgCoercedTy, 2).get.map(_.resTy)

eqwalizer/src/main/scala/com/whatsapp/eqwalizer/tc/Occurrence.scala

+4-1
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ final class Occurrence(pipelineContext: PipelineContext) {
282282
}
283283

284284
def clausesEnvs(clauses: List[Clause], argTys: List[Type], env: Env): List[Env] = {
285+
val accumulateNegProps = eqwater(clauses)
285286
var propsAcc = List.empty[Prop]
286287
val clauseEnvs = ListBuffer.empty[Env]
287288

@@ -308,7 +309,9 @@ final class Occurrence(pipelineContext: PipelineContext) {
308309
patNeg.foreach(allNeg.addOne)
309310
}
310311
val (testPos, testNeg) = guardsProps(clause.guards, aMap)
311-
val clauseProps = combine((allPos ++ testPos).toList, propsAcc)
312+
val clauseProps =
313+
if (accumulateNegProps) combine((allPos ++ testPos).toList, propsAcc)
314+
else (allPos ++ testPos).toList
312315
val clauseEnv = batchSelect(env1, clauseProps, aMap)
313316
clauseEnvs.addOne(clauseEnv)
314317
propsAcc = {

0 commit comments

Comments
 (0)