Skip to content

Commit 0ee0bf0

Browse files
committed
Attempting to fix multiple issues with limited functions in triggers
1 parent b0dcf54 commit 0ee0bf0

File tree

3 files changed

+38
-21
lines changed

3 files changed

+38
-21
lines changed

src/main/scala/rules/Evaluator.scala

+25-15
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import viper.silicon.state.terms._
2121
import viper.silicon.state.terms.implicits._
2222
import viper.silicon.state.terms.perms.IsPositive
2323
import viper.silicon.state.terms.predef.`?r`
24+
import viper.silicon.state.terms.utils.makeAllLimited
2425
import viper.silicon.utils.ast._
2526
import viper.silicon.utils.toSf
2627
import viper.silicon.verifier.Verifier
@@ -1348,12 +1349,33 @@ object evaluator extends EvaluationRules {
13481349
case (s2, ts1, es1New1, Some((ts2, es2New1, tTriggers, (tAuxGlobal, tAux), eAuxExps, additionalPossibleTriggers))) =>
13491350
val s3 = s.copy(possibleTriggers = s.possibleTriggers ++ additionalPossibleTriggers)
13501351
.preserveAfterLocalEvaluation(s2)
1351-
Q(s3, tVars, Option.when(withExp)(varPairs map (e => ast.LocalVarDecl(e._2.get.name, e._2.get.typ)(e._2.get.pos, e._2.get.info, e._2.get.errT))), ts1, es1New1, Some((ts2, es2New1, tTriggers, (tAuxGlobal, tAux), Option.when(withExp)((eAuxExps.get._1, eAuxExps.get._2)))), v)
1352+
val triggerTerms = tTriggers.flatMap(_.p)
1353+
val triggerTermFuncs = triggerTerms.flatMap{
1354+
case App(f: HeapDepFun, _) => Some(f)
1355+
case _ => None
1356+
}.toSet
1357+
val ts2TriggersReplaced = replaceTriggersIn(triggerTerms, ts2)
1358+
val tAuxTriggersReplaced = replaceTriggersIn(triggerTerms, tAux)
1359+
val tAuxGlobalTriggersReplaced = replaceTriggersIn(triggerTerms, tAuxGlobal)
1360+
Q(s3, tVars, Option.when(withExp)(varPairs map (e => ast.LocalVarDecl(e._2.get.name, e._2.get.typ)(e._2.get.pos, e._2.get.info, e._2.get.errT))), ts1, es1New1, Some((ts2TriggersReplaced, es2New1, tTriggers, (tAuxGlobalTriggersReplaced, tAuxTriggersReplaced), Option.when(withExp)((eAuxExps.get._1, eAuxExps.get._2)))), v)
13521361
case (s2, ts1, es1New1, None) =>
13531362
Q(s2, tVars, Option.when(withExp)(varPairs map (e => ast.LocalVarDecl(e._2.get.name, e._2.get.typ)(e._2.get.pos, e._2.get.info, e._2.get.errT))), ts1, es1New1, None, v)
13541363
}
13551364
}
13561365

1366+
private def replaceTriggersIn[T <: Term](triggerTerms: Seq[Term], replaceIn: Seq[T]) : Seq[T] = {
1367+
val triggerTermFuncs = triggerTerms.flatMap {
1368+
case App(f: HeapDepFun, _) => Some(f)
1369+
case _ => None
1370+
}.toSet
1371+
1372+
replaceIn.map(t => {
1373+
t.transform {
1374+
case app@App(f: HeapDepFun, _) if triggerTermFuncs.contains(f) && triggerTerms.contains(makeAllLimited(app)) => makeAllLimited(app)
1375+
}()
1376+
})
1377+
}
1378+
13571379
private def evalImplies(s: State,
13581380
tLhs: Term,
13591381
eLhs: (ast.Exp, Option[ast.Exp]),
@@ -1563,22 +1585,10 @@ object evaluator extends EvaluationRules {
15631585
(Q: (State, Seq[Term], Verifier) => VerificationResult)
15641586
: VerificationResult = {
15651587

1566-
def transformPotentialFuncApp(t: Term) = t match {
1567-
case app@App(fun: HeapDepFun, _) =>
1568-
/** Heap-dependent functions that are used as tTriggerSets should be used
1569-
* in the limited version, because it allows for more instantiations.
1570-
* Keep this code in sync with [[viper.silicon.supporters.ExpressionTranslator.translate]]
1571-
*
1572-
*/
1573-
app.copy(applicable = functionSupporter.limitedVersion(fun))
1574-
case other =>
1575-
other
1576-
}
1577-
15781588
val (cachedTriggerTerms, remainingTriggerExpressions) =
15791589
exps.map {
15801590
case pt @ (_: ast.PossibleTrigger | _: ast.FieldAccess | _: ast.LabelledOld | _: ast.Old) =>
1581-
val cachedTrigger = s.possibleTriggers.get(pt).map(t => transformPotentialFuncApp(t))
1591+
val cachedTrigger = s.possibleTriggers.get(pt).map(t => makeAllLimited(t))
15821592
(cachedTrigger, if (cachedTrigger.isDefined) None else Some(pt))
15831593
case e => (None, Some(e))
15841594
}.unzip match {
@@ -1647,7 +1657,7 @@ object evaluator extends EvaluationRules {
16471657
(r, optRemainingTriggerTerms) match {
16481658
case (Success(), Some(remainingTriggerTerms)) =>
16491659
v.decider.assume(pcDelta, Option.when(withExp)(DebugExp.createInstance("pcDeltaExp", children = pcDeltaExp)), enforceAssumption = false)
1650-
Q(s, cachedTriggerTerms ++ remainingTriggerTerms, v)
1660+
Q(s, cachedTriggerTerms ++ remainingTriggerTerms.map(t => makeAllLimited(t)), v)
16511661
case _ =>
16521662
for (e <- remainingTriggerExpressions)
16531663
v.reporter.report(WarningsDuringVerification(Seq(

src/main/scala/state/Terms.scala

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import scala.annotation.tailrec
1111
import scala.reflect.ClassTag
1212
import viper.silver.ast
1313
import viper.silicon.common.collections.immutable.InsertionOrderedSet
14+
import viper.silicon.rules.functionSupporter
1415
import viper.silicon.{Map, Stack, state, toMap}
1516
import viper.silicon.state.{Identifier, MagicWandChunk, MagicWandIdentifier, SortBasedIdentifier}
1617
import viper.silicon.verifier.Verifier
@@ -2612,6 +2613,11 @@ object utils {
26122613
*/
26132614
def cartesianProduct[A](xs: Iterable[Iterable[A]]): Seq[Seq[A]] =
26142615
xs.foldLeft(Seq(Seq.empty[A])){(x, y) => for (a <- x; b <- y) yield a :+ b}
2616+
2617+
def makeAllLimited(t: Term) = t.transform {
2618+
case app@App(fun: HeapDepFun, _) =>
2619+
app.copy(applicable = functionSupporter.limitedVersion(fun))
2620+
}()
26152621
}
26162622

26172623
object implicits {

src/main/scala/supporters/ExpressionTranslator.scala

+7-6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import viper.silver.ast
1010
import viper.silicon.rules.functionSupporter
1111
import viper.silicon.state.Identifier
1212
import viper.silicon.state.terms._
13+
import viper.silicon.state.terms.utils.makeAllLimited
1314
import viper.silver.ast.{AnnotationInfo, WeightedQuantifier}
1415

1516
trait ExpressionTranslator {
@@ -91,11 +92,7 @@ trait ExpressionTranslator {
9192

9293
/** IMPORTANT: Keep in sync with [[viper.silicon.rules.evaluator.evalTrigger]] */
9394
val translatedTriggers = eTriggers map (triggerSet => Trigger(triggerSet.exps map (trigger =>
94-
f(trigger) match {
95-
case app @ App(fun: HeapDepFun, _) =>
96-
app.copy(applicable = functionSupporter.limitedVersion(fun))
97-
case other => other
98-
}
95+
makeAllLimited(f(trigger))
9996
)))
10097
val weight = sourceQuant.info.getUniqueInfo[WeightedQuantifier] match {
10198
case Some(w) =>
@@ -117,10 +114,14 @@ trait ExpressionTranslator {
117114
case _ => None
118115
}
119116
}
117+
val triggerTerms = translatedTriggers.flatMap(_.p)
118+
val translatedBody = f(body).transform{
119+
case app@App(_: HeapDepFun, _) if triggerTerms.contains(makeAllLimited(app)) => makeAllLimited(app)
120+
}()
120121

121122
Quantification(qantOp,
122123
vars map (v => Var(Identifier(v.name), toSort(v.typ), false)),
123-
f(body),
124+
translatedBody,
124125
translatedTriggers,
125126
"",
126127
false,

0 commit comments

Comments
 (0)