// RUN: %dafny /compile:0 "%s" > "%t" // RUN: %diff "%s.expect" "%t" class Cell { var data: int predicate P() reads this { data < 0 } predicate Q(e: Cell) reads this, e { e != null ==> e.data == data } method Test() { ghost var b; var c := new Cell; if { // In the current state, everything is allowed: case true => b := this.P(); case true => b := c.P(); case true => b := this.Q(this); case true => b := this.Q(c); case true => b := c.Q(this); case true => b := c.Q(c); // 'this' was allocated already in the 'old' state, so all of these are fine: case true => b := old(this.P()); case true => b := old(P()); // same as previous line, of course case true => b := old(this.Q(this)); // 'c' is freshly allocaed in this method, so it cannot be used inside 'old' case true => b := old(c.P()); // error: receiver argument must be allocated in the state in which the function is invoked case true => b := old(c.Q(this)); // error: receiver argument must be allocated in the state in which the function is invoked // The same rule should apply if 'c' is a non-receiver argument case true => b := old(this.Q(c)); // BOGUS: this should also generate an error // In the following, 'c' is used as both of the two arguments. It's not allowed as either argument. However, since the error // about the receiver masks the error about the other parameter, only one error (about the receiver) should be reported. case true => b := old(c.Q(c)); // BOGUS: this should generate an error about the receiver } } }