summaryrefslogtreecommitdiff
path: root/Test/dafny0/Reads.dfy
blob: 6dedbada3c7c91b89714b451cfd941e1f350c47d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// RUN: %dafny /compile:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"

// Checking that the reads clause also is checked over requires

class C { var u : int; }

function nope1(c : C):()
     requires c != null && c.u > 0;
{()}

function ok1(c : C):()
     requires c != null && c.u > 0;
     reads c;
{()}

function nope2(c : C):()
     requires c != null && c.u > 0;
     reads if c != null then {} else {c};
{()}

function ok2(c : C):()
     requires c != null && c.u > 0;
     reads if c != null then {c} else {};
{()}

function nope3(xs : seq<C>):()
     requires |xs| > 0 && xs[0] != null && xs[0].u > 0;
{()}

function ok3(xs : seq<C>):()
     requires |xs| > 0 && xs[0] != null && xs[0].u > 0;
     reads xs;
{()}

function nope4(c : C, xs : set<C>):()
     requires c != null && c !in xs ==> c.u > 0;
     reads xs;
{()}

function ok4(c : C, xs : set<C>):()
     requires c != null && c in xs ==> c.u > 0;
     reads xs;
{()}

// reads over itself

class R { var r : R; }

function nope5(r : R):()
  reads if r != null then {r.r} else {};
{()}

function ok5(r : R):()
  reads if r != null then {r, r.r} else {};
{()}

// Reads checking where there are circularities among the expressions

class CircularChecking {
  ghost var Repr: set<object>
    
  function F(): int
    reads this, Repr

  function F'(): int
    reads Repr, this  // this is also fine

  function G0(): int
    reads this
    requires Repr == {} && F() == 100

  function G1(): int
    reads this
    requires F() == 100  // fine, since the next line tells us that Repr is empty
    requires Repr == {}

  function H0(cell: Cell): int
    reads Repr  // by itself, this reads is not self-framing
    requires this in Repr  // lo and behold!  So, reads clause is fine after all

  function H1(cell: Cell): int
    reads this, Repr
    requires cell in Repr
    requires cell != null && cell.data == 10

  function H2(cell: Cell): int
    reads this, Repr
    requires cell != null && cell.data == 10  // this is okay, too, since reads checks are postponed
    requires cell in Repr
}

class Cell { var data: int }

// Test the benefits of the new reads checking for function checking

function ApplyToSet<X>(S: set<X>, f: X -> X): set<X>
  requires forall x :: x in S ==> f.reads(x) == {} && f.requires(x)
{
  if S == {} then {} else
    var x :| x in S;
    ApplyToSet(S - {x}, f) + {f(x)}
}

function ApplyToSet_AltSignature0<X>(S: set<X>, f: X -> X): set<X>
  requires forall x :: x in S ==> f.requires(x) && f.reads(x) == {}

function ApplyToSet_AltSignature1<X>(S: set<X>, f: X -> X): set<X>
  requires forall x :: x in S ==> f.reads(x) == {}
  requires forall x :: x in S ==> f.requires(x)

function ApplyToSet_AltSignature2<X>(S: set<X>, f: X -> X): set<X>
  requires (forall x :: x in S ==> f.reads(x) == {}) ==> forall x :: x in S ==> f.requires(x)
  // (this precondition would not be good enough to check the body above)

function FunctionInQuantifier0(): int
  requires exists f: int -> int :: f(10) == 100  // error (x2): precondition violation and insufficient reads

function FunctionInQuantifier1(): int
  requires exists f: int -> int :: f.requires(10) && f(10) == 100  // error: insufficient reads

function FunctionInQuantifier2(): int
  requires exists f: int -> int :: f.reads(10) == {} && f.requires(10) && f(10) == 100
  ensures FunctionInQuantifier2() == 100
{
  var f: int -> int :| f.reads(10) == {} && f.requires(10) && f(10) == 100;  // fine :) :)
  f(10)
}

class DynamicFramesIdiom {
  ghost var Repr: set<object>
  predicate IllFormed_Valid()
    reads Repr  // error: reads is not self framing (notice the absence of "this")
  {
    this in Repr  // this says that the predicate returns true if "this in Repr", but the
                  // predicate can also be invoked in a state where its body will evaluate to false
  }
}