0

The example code will seem artificial as it is the smallest that I can find to illustrates my problem.

datatype Twee = Node(value : int, left : Twee, right : Twee) | Empty
method containsI(t : Twee, s : int) returns (r : bool) 
{
    var working :Twee := t;
    if (working.Node?) {
       r:= (working.value == s);
       assert r==true ==>  (working.value == s);
      while working.Node?
         decreases working
         invariant r==true ==>  (working.value == s)
      {  //assert r==true ==>  (working.value == s);
         r:=false; 
         working:= working.right;
         assert r==true ==>  (working.value == s);
      }
    }
    r:=false;
    assert r==true ==>  (working.value == s);
   }

Dafny complains about working.value in the invariant. Stating that it can only be applied when working is a Node event though Dafny reports no problems when the invariant is commented out. Hence Dafny seems to know that working is a Node.

Any corrections to my understanding much appreciated.

david streader
  • 589
  • 2
  • 7

1 Answers1

0

a loop invariant needs to hold before and after each iteration of the loop; in particular, it should hold on loop termination, when the loop condition is returning false.

So for example, anything in the body of the loop is guarded by working.Node? (like the line working:= working.right;) which is why Dafny reports no problems there. However, Dafny reports a problem with the line invariant r==true ==> (working.value == s) because this expression may need to be evaluated in a context where working.Node? does not hold.

Perhaps what you mean to do is write something like

invariant r==true ==> working.Node? ==> (working.value == s)

It's a little hard to tell what your intent is.

By the way, you may be wondering why the two lines at the end do not fail...

    r:=false;
    assert r==true ==>  (working.value == s);

This is because the assertion is a vacuous predicate here (r==true always evaluates to false)

tjhance
  • 961
  • 1
  • 7
  • 14
  • Let me refer to ```r==true ==> (working.value == s)``` as the assertion. Dafny seems to know that the assertion is true before and after the loop plus at the end of every execution of the body. So it seems to have enough to conclude the invariant assertion is true. Finally I see adding ```invariant r==true ==> working.Node?``` and now Dafny accepts the invariant. assertion. Many thanks – david streader Sep 02 '21 at 01:18