我有一个在堆上分配迭代器并在该迭代器上调用MoveNext()
的类。我想证明如果MoveNext()
返回true
,则Valid()
对于迭代器成立。
iterator Iter()
{}
class MyClass
{
var iter : Iter;
constructor ()
{
iter := new Iter();
}
method next() returns (more : bool)
requires iter.Valid();
modifies iter, iter._new, iter._modifies;
{
more := iter.MoveNext();
// This assertion fails:
assert more ==> iter.Valid();
}
}
我看了/rprint
的输出,方法MoveNext()
包含ensures more ==> this.Valid()
,这似乎暗示了我想要的断言。如果我将iter更改为在方法next()
中本地分配,则Dafny将验证断言。
答案 0 :(得分:1)
问题在于iter._modifies
和this
中的内容一无所知。如果this.iter
在这些集合之一中,则MoveNext()
在呼叫next()
的过程中可能已更改。
var i := iter;
more := iter.MoveNext();
assert i == iter; // this assertion fails
assert more ==> iter.Valid();
的正文确认了我刚才说的话:
more
因此,在Valid()
的假设下,iter
仍保留迭代器,但是more := iter.MoveNext();
assert more ==> old(iter).Valid(); // this holds
可能不再引用该迭代器:
next()
解决此问题的方法可能是向method next() returns (more : bool)
requires iter.Valid()
requires this !in iter._new + iter._modifies // add this precondition
modifies iter, iter._new, iter._modifies
{
more := iter.MoveNext();
assert more ==> iter.Valid(); // this now verifies
}
添加一个前提条件:
My Host Provider disconnects me every 15 minutes.
Rustan