Question

I get a “call might violate context’s modifies clause” in the following context. I have a field in a class that is is an array whose elements are being modified by a call, but the field does not exist when the enclosing method is called. So how do I tell Dafny that it can be modified?

Here is an example situation:

class WrapArray {
  var intarray: array<int>; 
  constructor (i:int) 
    requires i > 0
  {
    this.intarray := new int[i];
  }
  method init(i: int)
    modifies intarray
  {
    var index: int := 0;
    while (index < intarray.Length){
      intarray[index] := i;
      index := index+1;
    }
  }
}

method Main()
{
  var sh:= new WrapArray(5);
  sh.init(4);
}

Answer

When dafny is asked to verify this, it complains about the call sh.init that it modifies objects that Main does not allow. Indeed sh.init does modify the elements of sh.intarray and says so in its modifies clause, but that array does not even exist, nor is sh in scope, in the pre-state of Main. So where should it be indicated that sh.intarray may be modified?

The key is in the fact that neither sh nor sh.intarray is allocated in Main’s pre-state. Main should be allowed to modify objects that are allocated after the pre-state. Indeed Main knows that sh is newly allocated, so its fields may be changed. That is, we are allowed to assign to sh.intarray. But here we want to change the state of sh.intarray, not sh. The array is newly allocated, but Main does not know this. After all, it is possible that the constructor initialized sh.intarray with some existing array and changing that array’s elements would change the state of some other object. We need to tell Main that the constructor of WrapArray allocates a new array of ints. The syntax to do that is to add a postcondition to the constructor that says fresh(intarray).

Writing the constructor like this

  constructor (i:int)
    requires i>0
    ensures fresh(intarray)
  {
      this.intarray := new int[i];
  }
  

solves the problem.