Consider the following example:
package exercises
// ##(--hyperMode extended --enableExperimentalHyperFeatures)
// @ requires rel(t,0) != rel(t,1)
func test_ghostIfandImplication(t uint64) {
//@ assume rel(t,0) < rel(t,1)
//Let's do logic table!
//@ assert rel(t,0) < rel(t,1) ==> true //T ==> T
//@ refute rel(t,0) < rel(t,1) ==> false //T ==> F
//@ assert rel(t,0) > rel(t,1) ==> true //F ==> T
//@ assert rel(t,0) > rel(t,1) ==> false //F ==> F
}
The program should verify, based on the logic truth table of implication. However, the truth is:
[info] Error at: </.../relissue12.go:15:2> Assert might fail.
[info] Assertion rel(t,0) > rel(t,1) ==> false might not hold.
[info] Gobra found 1 error.
If we dig into the SIF encoding, we have in the last assert:
assert (p1 ==> p1 && p2 ==> t_V0_CN0 > t_V0_CN0_0) && (p2 ==> true) ==>
(p1 ==> false) && (p2 ==> false)
If we set p1 to T and p2 to F, we end up with T ==> F (if we do with p2 == F, we get the same implication), which means we won't verify the stuff regardless of p2. According to Linard, the issue lies in the semantics of //@ assert rel(t,0) > rel(t,1) ==> false , which are completely unclear if we have only a single execution.
Changing it to:
//@ assert !(rel(t,0) > rel(t,1)) || false //F ==> F
will verify the statement, nevertheless.
Consider the following example:
The program should verify, based on the logic truth table of implication. However, the truth is:
If we dig into the SIF encoding, we have in the last
assert:If we set
p1toTandp2toF, we end up withT ==> F(if we do withp2 == F, we get the same implication), which means we won't verify the stuff regardless ofp2. According to Linard, the issue lies in the semantics of//@ assert rel(t,0) > rel(t,1) ==> false, which are completely unclear if we have only a single execution.Changing it to:
//@ assert !(rel(t,0) > rel(t,1)) || false //F ==> Fwill verify the statement, nevertheless.