While considering performance issues for heap-dependent functions, we found that the following function definition in Viper:
field f: Bool
function heapFun(refs: Set[Ref]): Map[Ref, Bool]
requires (forall ref: Ref ::
{ ref in refs }
( ref in refs ) ==> acc(ref.f))
will generate this axiom in the Boogie translation using Carbon:
// ==================================================
// Function used for framing of quantified permission (forall ref: Ref :: { (ref in refs) } (ref in refs) ==> acc(ref.f, write)) in function heapFun
// ==================================================
function heapFun#condqp1(Heap: HeapType, refs_1_1: (Set Ref)): int;
axiom (forall Heap2Heap: HeapType, Heap1Heap: HeapType, refs: (Set Ref) ::
{ heapFun#condqp1(Heap2Heap, refs), heapFun#condqp1(Heap1Heap, refs), succHeapTrans(Heap2Heap, Heap1Heap) }
(forall ref: Ref ::
(refs[ref] && NoPerm < FullPerm <==> refs[ref] && NoPerm < FullPerm) && (refs[ref] && NoPerm < FullPerm ==> Heap2Heap[ref, f_7] == Heap1Heap[ref, f_7])
) ==> heapFun#condqp1(Heap2Heap, refs) == heapFun#condqp1(Heap1Heap, refs)
);
The inner quantifier (forall ref: Ref :: ...) is missing a trigger, presumably because in the context of the outer implication, it will become an existential that the solver uses to generate a Skolemized term with the bound variable ref replaced.
@alexanderjsummers and I discussed two changes:
- Add a trigger with a dummy function application to the inner quantifier
(forall ref: Ref :: ...) to at indicate (at least to anyone reading this Boogie code) that this quantifier shouldn't be triggered.
- Consider replacing this inner quantifier with a Boolean-valued "Skolem function" taking
heapFun#condqp1(Heap2Heap, refs) and heapFun#condqp1(Heap1Heap, refs) as arguments. This could potentially reduce the number of Map#Equal obligations arising from the quantifier body of the Skolemized (forall ref: Ref :: ...) terms in the situation where heapFun must be framed across many heaps (so that this axiom (forall Heap2Heap: HeapType, Heap1Heap: HeapType, refs: (Set Ref) :: ...) gets triggered on many pairs of HeapType objects, and we lose progress on input values for which heapFun has previously been shown to be equal).
While considering performance issues for heap-dependent functions, we found that the following function definition in Viper:
will generate this axiom in the Boogie translation using Carbon:
The inner quantifier
(forall ref: Ref :: ...)is missing a trigger, presumably because in the context of the outer implication, it will become an existential that the solver uses to generate a Skolemized term with the bound variablerefreplaced.@alexanderjsummers and I discussed two changes:
(forall ref: Ref :: ...)to at indicate (at least to anyone reading this Boogie code) that this quantifier shouldn't be triggered.heapFun#condqp1(Heap2Heap, refs)andheapFun#condqp1(Heap1Heap, refs)as arguments. This could potentially reduce the number ofMap#Equalobligations arising from the quantifier body of the Skolemized(forall ref: Ref :: ...)terms in the situation whereheapFunmust be framed across many heaps (so that thisaxiom (forall Heap2Heap: HeapType, Heap1Heap: HeapType, refs: (Set Ref) :: ...)gets triggered on many pairs ofHeapTypeobjects, and we lose progress on input values for whichheapFunhas previously been shown to be equal).