我如何告诉 Dafny 一个方法总是 returns 一个“新”对象?

How can I tell Dafny that a method always returns a `new` object?

In this example,我有一个 return 新数组的方法:

method Zeroes(len: nat) returns (h: array<nat>)
  ensures h.Length == len && all_zeroes(h)
{
  h := new nat[len];
  ...
}

和另一种尝试使用它的方法:

method Histogram(a: array<nat>, limit: nat) returns (h: array<nat>)
  requires greater_than_all(limit, a)
  ensures h.Length == limit && histogram_of(h, a)
{
  h := Zeroes(limit);
  assert histogram_of_prefix(h, a, 0);

  var i := 0;
  while i < a.Length
    invariant 0 <= i <= a.Length
    invariant histogram_of_prefix(h, a, i)
  {
    var n := a[i];
    h[n] := h[n] + 1;
    i := i + 1;
  }
}

Dafny 抱怨是因为它无法证明 Zeroes(limit) 不会 return a。 (如果它真的发生了,我的代码将被完全破坏,Dafny 正确地指出。)

看来,通过将 Zeroes 分解为一个函数,我已经带走了一些信息。如果我将 Zeroes 的主体移回 Histogram,那么 Dafny 会看到 h := new nat[limit]; 它知道这与 a 不是同一个数组,并且验证成功。

如何更改 Zeroes 的签名以告诉 Dafny 它始终 return 是一个新数组?

您可以使用 fresh。如

ensures fresh(h)

另见