-
Notifications
You must be signed in to change notification settings - Fork 269
/
Copy pathgit-issue-1016.dfy
131 lines (112 loc) · 3.36 KB
/
git-issue-1016.dfy
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
// RUN: %exits-with 2 %verify --allow-axioms "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
datatype Option<T> = Some(value: T) | None {
predicate IsFailure() {
None?
}
function PropagateFailure<U>(): Option<U>
requires None?
{
None
}
function Extract(): T
requires Some?
{
value
}
}
type Process(==)
type State(==)
datatype Event = Event(process: Process, state: State)
function Find(process: Process, log: seq<Event>): (r: Option<nat>)
ensures r.Some? ==> r.value < |log|
function Gimmie(): Option<int>
method Test0(process: Process, m: map<Process, State>, log: seq<Event>)
requires process in m.Keys
{
// x has type Option<State>
var x :=
Some(m[process]);
// y has type Option<Process>
var y :=
var L := Find(process, log);
if L == None then None else Some(log[L.value].process);
// z's RHS is a different way of writing y's RHS
// so, z also has type Option<Process>
var z :=
var last :- Find(process, log);
Some(log[last].process);
// Without the type errors in the other methods, the following assertion
// type checks and verifies.
assert y == z;
}
method Test1(process: Process, m: map<Process, State>, log: seq<Event>)
requires process in m.Keys
{
// The definitions of x, y, and z are exactly like in Test0
var x :=
Some(m[process]);
var y :=
var L := Find(process, log);
if L == None then None else Some(log[L.value].process);
var z :=
var last :- Find(process, log);
Some(log[last].process);
// The following line gives the expected type error
var b := x == y; // error: incompatible types Option<State> and Option<Process>
}
method Test2(process: Process, m: map<Process, State>, log: seq<Event>)
requires process in m.Keys
{
// The definitions of x, y, and z are exactly like in Test0
var x :=
Some(m[process]);
var y :=
var L := Find(process, log);
if L == None then None else Some(log[L.value].process);
var z :=
var last :- Find(process, log);
Some(log[last].process);
var c := x == z; // ERROR: this should give a type error
}
method Test3(process: Process, m: map<Process, State>, log: seq<Event>)
requires process in m.Keys
{
// The definitions of x, y, and z are like in Test0, except the types are given
// explicitly here.
var x: Option<State> :=
Some(m[process]);
var y: Option<Process> :=
var L := Find(process, log);
if L == None then None else Some(log[L.value].process);
var z: Option<Process> :=
var last :- Find(process, log);
Some(log[last].process);
// With the explicit types above, the assignments above type check, and
// the following line gives the expected type error.
var c := x == z; // error: incompatible types Option<State> and Option<Process>
}
method Test4(process: Process, m: map<Process, State>, log: seq<Event>)
requires process in m.Keys
{
// The definitions of x, y, and z are exactly like in Test0
var x :=
Some(m[process]);
var y :=
var L := Find(process, log);
if L == None then None else Some(log[L.value].process);
var z :=
var last :- Find(process, log);
Some(100);
var c := x == z; // ERROR: this should give a type error
}
method Test5(s: State)
{
// The definitions of x, y, and z are exactly like in Test0
var x :=
Some(s);
var z :=
var n :- Gimmie();
Some(100.0);
var c := x == z; // ERROR: this should give a type error
}