-
Notifications
You must be signed in to change notification settings - Fork 37
Description
Consider the following dummy example when using rel():
package exercises
// ##(--hyperMode extended --enableExperimentalHyperFeatures)
/*@
ghost
pure
decreases
func Return_pure(x int, y int) (r int) {
return 0
}
ghost
requires acc(r1, _)
pure
decreases
func Return_wrapper(t2 int, target int, r1 []int) bool{
return exists idx int :: {r1[idx]} target < t2 ==> 0 <= idx && idx < len(r1) && Return_pure(target, t2) == r1[idx]
}
@*/
// @ requires target >= 0
// @ ensures acc(r1)
// @ ensures len(r1) > 0
// @ ensures forall t2 int :: {Return_wrapper(t2,target,r1)} Return_wrapper(t2,target,r1)
// @ ensures forall t2 int :: {Return_wrapper(target,t2,r1)} Return_wrapper(target,t2,r1)
// @ ensures forall j int :: 0 <= j && j < len(r1) ==> r1[j] >= 0
func ComputeSteps(target int) (r1 []int) {
r1 = make([]int, 1)
r1[0] = 0
return r1
}
// @ requires t >= 0
// @ requires rel(t,0) != rel(t,1)
func UseStepsSamePackage(t int) {
steps := ComputeSteps(t)
// assert forall t2 int :: exists idx int :: t < t2 ==> 0 <= idx && idx < len(steps) && Return_pure(t, t2) == steps[idx]
//@ assert forall t2 int :: {Return_wrapper(t2,t, steps)} Return_wrapper(t2,t,steps)
//@ assert forall t2 int :: {Return_wrapper(t,t2,steps)} Return_wrapper(t, t2, steps)
//@ assert Return_wrapper(rel(t,0), rel(t,1), rel(steps,0))
//@ assert Return_wrapper(rel(t,1), rel(t,0), rel(steps,1))
//@ assert rel(steps,1)[0] == 0
}
This issue would cause the following error:
No changes detected in the antlr4 files. Skipping parser generation.
[info] running (fork) viper.gobra.GobraRunner -i /.../exercises/relIssue.go
[info] Gobra 1.1-SNAPSHOT (351ad1fe@(detached))
[info] (c) Copyright ETH Zurich 2012 - 2024
[info] Verifying package .. - exercises [14:03:17]
[info] Error at: </.../exercises/relIssue.go:46:9> Precondition of call Return_wrapper(rel(t,1), rel(t,0), rel(steps,1)) might not hold.
[info] Permission to r1 might not suffice.
[info] Gobra found 1 error.
[info]
Based on Linard’s analysis, the issue stems from an incorrect encoding:
Return_wrapper(rel(t,1), rel(t,0), rel(steps,1)) is incorrectly resolved to a call to Return_wrapper_2a4eccf_F instead of Return_wrapper_2a4eccf_F_0.
According to Linard, this happens because rel(steps,1) selects the slice corresponding to the second execution, and therefore does not refer to the intended Return_wrapper_… function instance.
My proposed workaround was to use
//@ inhale acc(rel(steps,1), 1/18); however, this is a dangerous fix, as it may introduce unsoundness by artificially granting permissions.
Linard’s suggested fix is to replace
//@ assert Return_wrapper(rel(t,1), rel(t,0), rel(steps,1))
with
//@ assert rel(Return_wrapper(rel(t,1), rel(t,0), rel(steps,1)), 1)
This encoding issue is critical to address, since it leads to permission errors when accessing elements of slices from the first execution. For example, the assertion
//@ assert rel(steps,1)[0] == 0
will again result in a permission error during evaluation.
[info] Error at: </.../exercises/relIssue.go:46:9> Precondition of call Return_wrapper(rel(t,1), rel(t,0), rel(steps,1)) might not hold.
[info] Permission to r1 might not suffice.
[info] Gobra found 1 error.
If we use //@ assume acc(rel(steps,1),1) , we will have another Java.concurrency error:
[info] An unknown Exception was thrown.
[info] java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.RuntimeException: Unexpected expression rel(steps_V1, 1) cannot be symbolically evaluated