-
Notifications
You must be signed in to change notification settings - Fork 82
/
Copy pathwhen_used_as_spec.rs
155 lines (124 loc) · 4.03 KB
/
when_used_as_spec.rs
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#![feature(rustc_private)]
#[macro_use]
mod common;
use common::*;
test_verify_one_file! {
#[test] test1 verus_code! {
struct S {}
impl S {
spec fn f(&self) -> bool { true }
// Note: it's a good idea for g and f to return the same value,
// but, for testing purposes only, we have them return different values here.
#[verifier(when_used_as_spec(f))]
fn g(&self) -> bool { false }
fn h(&self) {
self.g(); // call g
assert(self.g()); // in a spec, so call f, not g
}
}
} => Ok(())
}
test_verify_one_file! {
#[test] fail_exec_false verus_code! {
struct S {}
impl S {
spec fn f(&self) -> bool { true }
#[verifier(when_used_as_spec(f))]
fn g(&self) -> bool { false }
fn h(&self) {
let b = self.g();
assert(b); // FAILS
}
}
} => Err(err) => assert_one_fails(err)
}
test_verify_one_file! {
#[test] fail_different_typarg verus_code! {
struct S {}
impl S {
spec fn f<A>(&self, k: &A) -> bool { true }
#[verifier(when_used_as_spec(f))]
fn g<B>(&self, k: &B) -> bool { true }
}
} => Err(err) => assert_vir_error_msg(err, "when_used_as_spec function should have the same type bounds")
}
test_verify_one_file! {
#[test] fail_different_arg verus_code! {
struct S {}
impl S {
spec fn f(&self, k: int) -> bool { true }
#[verifier(when_used_as_spec(f))]
fn g(&self, k: u64) -> bool { true }
}
} => Err(err) => assert_vir_error_msg(err, "when_used_as_spec function should have the same parameters")
}
test_verify_one_file! {
#[test] fail_different_returns verus_code! {
struct S {}
impl S {
spec fn f(&self) -> bool { true }
#[verifier(when_used_as_spec(f))]
fn g(&self) -> u8 { 0 }
}
} => Err(err) => assert_vir_error_msg(err, "when_used_as_spec function should have the same return types")
}
test_verify_one_file! {
#[test] fail_not_exec verus_code! {
struct S {}
impl S {
spec fn f(&self, k: u64) -> bool { true }
#[verifier(when_used_as_spec(f))]
proof fn g(&self, k: u64) -> bool { true }
}
} => Err(err) => assert_vir_error_msg(err, "when_used_as_spec must point from an exec function to a spec function")
}
test_verify_one_file! {
#[test] fail_not_spec verus_code! {
struct S {}
impl S {
proof fn f(&self, k: u64) -> bool { true }
#[verifier(when_used_as_spec(f))]
fn g(&self, k: u64) -> bool { true }
}
} => Err(err) => assert_vir_error_msg(err, "when_used_as_spec must point from an exec function to a spec function")
}
test_verify_one_file! {
#[test] fail_missing verus_code! {
struct S {}
impl S {
#[verifier(when_used_as_spec(f))]
fn g(&self, k: u64) -> bool { true }
}
} => Err(err) => assert_vir_error_msg(err, "cannot find function referred to in when_used_as_spec")
}
test_verify_one_file! {
#[test] vec_len_regression_issue212 verus_code! {
use vstd::prelude::*;
struct S {
pub vec: Vec<()>,
}
impl S {
spec fn f(&self) -> bool {
0 < self.vec.len()
}
}
fn test() {
let mut s = S { vec: Vec::new() };
assert(!s.f());
s.vec.push(());
assert(s.f());
}
} => Ok(())
}
test_verify_one_file! {
#[test] visibility verus_code! {
mod X {
spec fn spec_not(x: bool) -> bool { !x }
#[verifier::when_used_as_spec(spec_not)]
pub fn exec_not(x: bool) -> (res: bool)
{
!x
}
}
} => Err(err) => assert_vir_error_msg(err, "when_used_as_spec refers to function which is more private")
}