Question:

This example

// dafny Example.dfy
class A {
  var x: string
}

type AA = a: A | a.x == "" witness * reads a


generates this error:

FAQReadsClause.dfy(6,37): Error: this symbol not expected in Dafny
1 parse errors detected in FAQReadsClause.dfy

but there is no obvious place to put a reads clause.

Answer:

There is no place for the reads clause because no such clause should be needed. A type definition is not allowed to depend on a mutable field; the predicate in the subset type must be pure.

The general idiom is to add a predicate, often named Valid(), to a class that reads its fields and returns true if the class members are appropriately consistent. Then call Valid() in the pre- and post-conditions of methods and in preconditions of functions and predicates. Here is an example:

class A {
  var x: string
  var y: string
  predicate Valid() reads this {
    |x| == |y|
  }
}

method Test(a: A)
  requires a.Valid()
  requires a.x == ""
  modifies a
  ensures a.Valid()
{
  assert a.Valid(); // That's correct thanks to the precondition.
  a.x := "abc"; // Because |a.y| == 0, we broke the Valid() predicate
  assert !a.Valid(); // But that's ok.
  a.y := "bca";
  assert a.Valid(); // Now Dafny can prove this
  // The postcondition holds
}

The {:autocontracts} attribute can be helpful here.

Note that the idiom using Valid() above is similar to the use of class invariants in other specification languages.