2017-10-18 92 views
1

在试图验证数组支持的通用FIFO队列时,我遇到了一个令人困惑的错误。该队列被发现在this论文中,由Dafny的创建者撰写。Dafny泛型类型数组错误

在考虑中的错误是:

除非一个初始化设置为阵列的元素,“数据”的一个新的数组必须具有涉及两行分配一个空的大小

数组通过new Data[whatever]在构造函数和enqueue方法中。

Dafny版本:Dafny 2.0.0.00922技术预览参考0

的完整代码。

class {:autocontracts} SimpleQueue<Data> 
{ 
    ghost var Contents: seq<Data>; 
    var a: array<Data>; 
    var m: int, n: int; 
    predicate Valid() { 
     a != null && a.Length != 0 && 0 <= m <= n <= a.Length && Contents == a[m..n] 
    } 
    constructor() 
    ensures Contents == []; 
    { 
     a := new Data[10]; 
     m := 0; 
     n := 0; 
     Contents := []; 
    } 
    method Enqueue(d: Data) 
    ensures Contents == old(Contents) + [d]; 
    { 
     if n == a.Length { 
      var b := a; 
      if m == 0 { 
       b := new Data[2 * a.Length]; 
      } 
      forall (i | 0 <= i < n - m) { 
       b[i] := a[m + i]; 
      } 
      a, m, n := b, 0, n - m; 
     } 
     a[n], n, Contents := d, n + 1, Contents + [d]; 
    } 

    method Dequeue() returns (d: Data) 
    requires Contents != []; 
    ensures d == old(Contents)[0] && Contents == old(Contents)[1..]; 
    { 
     assert a[m] == a[m..n][0]; 
     d, m, Contents := a[m], m + 1, Contents[1..]; 
    } 
} 
method Main() 
{ 
    var q := new SimpleQueue(); 
    q.Enqueue(5); q.Enqueue(12); 
    var x := q.Dequeue(); 
    assert x == 5; 
} 

回答

0

自写这篇论文以来,Dafny的类型系统已经被推广到支持那些不是“默认初始化”的类型。这导致了一些倒退的不兼容性。

,最简单的解决方法是改变

class SimpleQueue<Data> 

class SimpleQueue<Data(0)> 

这意味着该类型的可变Data只能与缺省initializable类型实例化。

另一个解决方法是将构造函数更改为接受类型为Data的默认值作为参数。然后你可以使用初始化函数分配一个数组,如

new Data[10] (_ => d)