Skip to content

Commit 2f72f07

Browse files
authored
Merge pull request #670 from viperproject/meilers_func_pre_trafo_fix
Fixed two incompletenesses in the way we assume function preconditions
2 parents 8b250ac + 3c13e08 commit 2f72f07

2 files changed

Lines changed: 20 additions & 6 deletions

File tree

src/main/scala/rules/Evaluator.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,16 @@ object evaluator extends EvaluationRules {
652652
v1.decider.prover.comment("Nested auxiliary terms: non-globals (aux)")
653653
v1.decider.assume(tAuxHeapIndep/*tAux*/)
654654

655+
if (qantOp == Exists) {
656+
// For universal quantification, the non-global auxiliary assumptions will contain the information that
657+
// forall vars :: all function preconditions are fulfilled.
658+
// However, if this quantifier is existential, they will only assume that there exist values s.t.
659+
// all function preconditions hold. This is not enough: We need to know (and have checked that)
660+
// function preconditions hold for *all* possible values of the quantified variables.
661+
// So we explicitly add this assumption here.
662+
v1.decider.assume(Quantification(Forall, tVars, FunctionPreconditionTransformer.transform(tBody, s1.program), tTriggers, name))
663+
}
664+
655665
val tQuant = Quantification(qantOp, tVars, tBody, tTriggers, name)
656666
Q(s1, tQuant, v1)
657667
}

src/main/scala/state/FunctionPreconditionTransformer.scala

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package viper.silicon.state
22

33
import viper.silicon.rules.functionSupporter
4-
import viper.silicon.state.terms.{And, App, HeapDepFun, Implies, Ite, Let, Literal, Not, Or, Quantification, Term, True}
4+
import viper.silicon.state.terms.{And, App, Forall, HeapDepFun, Implies, Ite, Let, Literal, Not, Or, Quantification, Term, True}
55
import viper.silver.ast
66

77

@@ -28,13 +28,17 @@ object FunctionPreconditionTransformer {
2828
case Or(ts) => And(transform(ts.head, p), Implies(Not(ts.head), transform(Or(ts.tail), p)))
2929
case Implies(t0, t1) => And(transform(t0, p), Implies(t0, transform(t1, p)))
3030
case Ite(t, t1, t2) => And(transform(t, p), Ite(t, transform(t1, p), transform(t2, p)))
31-
case Let(bindings, body) => Let(bindings, transform(body, p))
32-
case Quantification(q, vars, body, triggers, name, isGlobal) =>
31+
case Let(bindings, body) =>
32+
And(And(bindings.map(b => transform(b._2, p))), Let(bindings, transform(body, p)))
33+
case Quantification(_, vars, body, triggers, name, isGlobal) =>
3334
val tBody = transform(body, p)
34-
if (tBody == True())
35+
if (tBody == True()) {
3536
tBody
36-
else
37-
Quantification(q, vars, tBody, triggers, name, isGlobal)
37+
} else {
38+
// We assume well-definedness for *all* possible values even for existential quantifiers
39+
// (since that is also what we check).
40+
Quantification(Forall, vars, tBody, triggers, name, isGlobal)
41+
}
3842
case App(hdf@HeapDepFun(_, _, _), args) =>
3943
And(args.map(transform(_, p)) :+ App(functionSupporter.preconditionVersion(hdf), args))
4044
case other => And(other.subterms.map(transform(_, p)))

0 commit comments

Comments
 (0)