carbon icon indicating copy to clipboard operation
carbon copied to clipboard

Incompleteness when unfolding a predicate under a quantifier.

Open viper-admin opened this issue 7 years ago • 1 comments

Created by @vakaras on 2018-07-23 16:31

In the example below, the second call to fails fails with an error that the precondition loc(fruits, j).val) >= 0 does not hold. However, if unfolding is pulled out to be the top level expression (method works), the example verifies successfully.

#!silver
field val: Int
domain Array {
    function loc(arr: Array, pos: Int): Ref
    function len(arr: Array): Int
    function arrayref(ref: Ref): Array
    function arraypos(ref: Ref): Int
    axiom len_nonneg {
        forall a: Array :: {len(a)} len(a) >= 0
    }
    axiom array_diff {
        forall a: Array, p: Int :: {loc(a, p)} arrayref(loc(a, p)) == a && arraypos(loc(a, p)) == p
    }
}

predicate arrayacc(a: Array) {
    forall i: Int :: { loc(a, i) } 0 <= i && i < len(a) ==> acc(loc(a, i).val)
}

method fails(fruits: Array, rdperm: Perm)
    requires none < rdperm && rdperm < write
    requires acc(arrayacc(fruits), rdperm)
    requires forall j: Int :: { loc(fruits, j) } 0 <= j && j < len(fruits) ==>
        (unfolding acc(arrayacc(fruits), rdperm) in loc(fruits, j).val) >= 0
{
    fails(fruits, rdperm / 2)
    //:: UnexpectedError: precondition does not hold.
    fails(fruits, rdperm / 2)
}

method works(fruits: Array, rdperm: Perm)
    requires none < rdperm && rdperm < write
    requires acc(arrayacc(fruits), rdperm)
    requires unfolding acc(arrayacc(fruits), rdperm) in
        forall j: Int :: { loc(fruits, j) } 0 <= j && j < len(fruits) ==>
        (loc(fruits, j).val) >= 0
{
    works(fruits, rdperm / 2)
    works(fruits, rdperm / 2)
}

viper-admin avatar Jul 23 '18 16:07 viper-admin

Here is another incompleteness with unfolding within a quantifier (havoc_qp5.vpr from the quasihavoc examples in the Silver tes suite after desugaring quasihavoc to exhale + inhale), where the assertion fails to verify:

method foo(x: Ref, y: Ref, s: Seq[Ref], t: Seq[Ref])
    requires |s| == |t| && |s| >= 2
    requires forall i: Int, j: Int :: 0 <= i && i < j && j < |s| ==> s[i] != s[j]
    requires forall i: Int :: 0 <= i && i < |s| ==>
                Pair(s[i], t[i])
    requires forall i: Int :: 0 <= i && i < |s| ==>
                unfolding Pair(s[i], t[i]) in s[i].f == i
    requires x == s[0] && y == t[0]
{
    exhale acc(Pair(x,y))
    inhale acc(Pair(x,y))
    unfold Pair(x, y)

    assert forall i: Int :: 1 <= i && i < |s| ==>
            unfolding Pair(s[i], t[i]) in s[i].f == i
}

gauravpartha avatar Nov 11 '22 19:11 gauravpartha