Skip to content

Heap-dependent function with QPs generates triggerless axiom #522

@jwkai

Description

@jwkai

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:

  1. 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.
  2. 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions