1use super::super::prelude::*;
19
20macro_rules! def_un_ops_spec {
21 ($trait:path, $extrait: ident, $spec_trait:ident, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident) => {
22 $crate::vstd::prelude::verus! {
23 #[verifier::external_trait_specification]
24 #[verifier::external_trait_extension($spec_trait via $impl_trait)]
25 pub trait $extrait {
26 type ExternalTraitSpecificationFor: $trait;
27
28 type Output;
29
30 spec fn $obeys() -> bool;
31
32 spec fn $req(self) -> bool
33 where Self: Sized;
34
35 spec fn $spec(self) -> Self::Output
36 where Self: Sized;
37
38 fn $fun(self) -> (ret: Self::Output)
39 requires
40 self.$req(),
41 ensures
42 Self::$obeys() ==> ret == self.$spec();
43 }
44 }
45};
46}
47
48macro_rules! def_bin_ops_spec {
49 ($trait:path, $extrait: ident, $spec_trait:ident, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident) => {
50 $crate::vstd::prelude::verus! {
51 #[verifier::external_trait_specification]
52 #[verifier::external_trait_extension($spec_trait via $impl_trait)]
53 pub trait $extrait<Rhs = Self> {
54 type ExternalTraitSpecificationFor: $trait<Rhs>;
55
56 type Output;
57
58 spec fn $obeys() -> bool;
59
60 spec fn $req(self, rhs: Rhs) -> bool
61 where Self: Sized;
62
63 spec fn $spec(self, rhs: Rhs) -> Self::Output
64 where Self: Sized;
65
66 fn $fun(self, rhs: Rhs) -> (ret: Self::Output)
67 requires
68 self.$req(rhs),
69 ensures
70 Self::$obeys() ==> ret == self.$spec(rhs);
71 }
72 }
73};
74}
75
76def_un_ops_spec!(
77 core::ops::Neg,
78 ExNeg,
79 NegSpec,
80 NegSpecImpl,
81 neg,
82 obeys_neg_spec,
83 neg_req,
84 neg_spec
85);
86
87def_un_ops_spec!(
88 core::ops::Not,
89 ExNot,
90 NotSpec,
91 NotSpecImpl,
92 not,
93 obeys_not_spec,
94 not_req,
95 not_spec
96);
97
98def_bin_ops_spec!(
99 core::ops::Add,
100 ExAdd,
101 AddSpec,
102 AddSpecImpl,
103 add,
104 obeys_add_spec,
105 add_req,
106 add_spec
107);
108
109def_bin_ops_spec!(
110 core::ops::Sub,
111 ExSub,
112 SubSpec,
113 SubSpecImpl,
114 sub,
115 obeys_sub_spec,
116 sub_req,
117 sub_spec
118);
119
120def_bin_ops_spec!(
121 core::ops::Mul,
122 ExMul,
123 MulSpec,
124 MulSpecImpl,
125 mul,
126 obeys_mul_spec,
127 mul_req,
128 mul_spec
129);
130
131def_bin_ops_spec!(
132 core::ops::Div,
133 ExDiv,
134 DivSpec,
135 DivSpecImpl,
136 div,
137 obeys_div_spec,
138 div_req,
139 div_spec
140);
141
142def_bin_ops_spec!(
143 core::ops::Rem,
144 ExRem,
145 RemSpec,
146 RemSpecImpl,
147 rem,
148 obeys_rem_spec,
149 rem_req,
150 rem_spec
151);
152
153def_bin_ops_spec!(
154 core::ops::BitAnd,
155 ExBitAnd,
156 BitAndSpec,
157 BitAndSpecImpl,
158 bitand,
159 obeys_bitand_spec,
160 bitand_req,
161 bitand_spec
162);
163
164def_bin_ops_spec!(
165 core::ops::BitOr,
166 ExBitOr,
167 BitOrSpec,
168 BitOrSpecImpl,
169 bitor,
170 obeys_bitor_spec,
171 bitor_req,
172 bitor_spec
173);
174
175def_bin_ops_spec!(
176 core::ops::BitXor,
177 ExBitXor,
178 BitXorSpec,
179 BitXorSpecImpl,
180 bitxor,
181 obeys_bitxor_spec,
182 bitxor_req,
183 bitxor_spec
184);
185
186def_bin_ops_spec!(
187 core::ops::Shl,
188 ExShl,
189 ShlSpec,
190 ShlSpecImpl,
191 shl,
192 obeys_shl_spec,
193 shl_req,
194 shl_spec
195);
196
197def_bin_ops_spec!(
198 core::ops::Shr,
199 ExShr,
200 ShrSpec,
201 ShrSpecImpl,
202 shr,
203 obeys_shr_spec,
204 shr_req,
205 shr_spec
206);
207
208macro_rules! def_uop_impls {
209 ($trait:path, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident, $self:ident, [$(($typ:ty, $req_expr:expr, $spec_expr:expr))*]) => {
210 $crate::vstd::prelude::verus! {
211 $(
212 impl $impl_trait for $typ {
213 open spec fn $obeys() -> bool {
214 true
215 }
216
217 open spec fn $req($self) -> bool {
218 $req_expr
219 }
220
221 open spec fn $spec($self) -> Self::Output {
222 $spec_expr
223 }
224 }
225
226 pub assume_specification[ <$typ as $trait>::$fun ](x: $typ) -> $typ;
227 )*
228 }
229};
230}
231
232macro_rules! def_bop_impls {
233 ($trait:path, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident, $self:ident, $rhs:ident, [$(($typ:ty, $req_expr:expr, $spec_expr:expr))*]) => {
234 $crate::vstd::prelude::verus! {
235 $(
236 impl $impl_trait for $typ {
237 open spec fn $obeys() -> bool {
238 true
239 }
240
241 open spec fn $req($self, $rhs: $typ) -> bool {
242 $req_expr
243 }
244
245 open spec fn $spec($self, $rhs: $typ) -> Self::Output {
246 $spec_expr
247 }
248 }
249
250 pub assume_specification[ <$typ as $trait>::$fun ](x: $typ, y: $typ) -> $typ;
251 )*
252 }
253};
254}
255
256macro_rules! def_uop_impls_no_check {
257 ($trait:path, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident, $self:ident, $op:tt, [$($typ:ty)*]) => {
258 $crate::vstd::prelude::verus! {
259 def_uop_impls!($trait, $impl_trait, $fun, $obeys, $req, $spec, $self, [
260 $(
261 (
262 $typ,
263 true,
264 $op $self
265 )
266 )*
267 ]);
268 }
269};
270}
271
272macro_rules! def_uop_impls_check_overflow {
273 ($trait:path, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident, $self:ident, $op:tt, [$($typ:ty)*]) => {
274 $crate::vstd::prelude::verus! {
275 def_uop_impls!($trait, $impl_trait, $fun, $obeys, $req, $spec, $self, [
276 $(
277 (
278 $typ,
279 ($op $self) as $typ == ($op $self),
280 ($op $self) as $typ
281 )
282 )*
283 ]);
284 }
285};
286}
287
288macro_rules! def_bop_impls_no_check {
289 ($trait:path, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident, $self:ident, $rhs:ident, $op:tt, [$($typ:ty)*]) => {
290 $crate::vstd::prelude::verus! {
291 def_bop_impls!($trait, $impl_trait, $fun, $obeys, $req, $spec, $self, $rhs, [
292 $(
293 (
294 $typ,
295 true,
296 $self $op $rhs
297 )
298 )*
299 ]);
300 }
301};
302}
303
304macro_rules! def_bop_impls_check_overflow {
305 ($trait:path, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident, $self:ident, $rhs:ident, $op:tt, [$($typ:ty)*]) => {
306 $crate::vstd::prelude::verus! {
307 def_bop_impls!($trait, $impl_trait, $fun, $obeys, $req, $spec, $self, $rhs, [
308 $(
309 (
310 $typ,
311 ($self $op $rhs) as $typ == ($self $op $rhs),
312 ($self $op $rhs) as $typ
313 )
314 )*
315 ]);
316 }
317};
318}
319
320macro_rules! def_bop_impls_unsigned_div_rem {
321 ($trait:path, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident, $self:ident, $rhs:ident, $op:tt, [$($typ:ty)*]) => {
322 $crate::vstd::prelude::verus! {
323 def_bop_impls!($trait, $impl_trait, $fun, $obeys, $req, $spec, $self, $rhs, [
324 $(
325 (
326 $typ,
327 $rhs != 0,
328 $self $op $rhs
329 )
330 )*
331 ]);
332 }
333};
334}
335
336macro_rules! def_bop_impls_signed_div_rem {
340 ($trait:path, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident, $self:ident, $rhs:ident, $op:tt, [$($typ:ty)*]) => {
341 $crate::vstd::prelude::verus! {
342 def_bop_impls!($trait, $impl_trait, $fun, $obeys, $req, $spec, $self, $rhs, [
343 $(
344 (
345 $typ,
346 $rhs != 0 && !($self == $typ::MIN && $rhs == -1),
347 if $self >= 0 {
348 ($self $op $rhs) as $typ
349 } else {
350 (-((-$self) $op ($rhs as int))) as $typ
351 }
352 )
353 )*
354 ]);
355 }
356};
357}
358
359macro_rules! def_bop_impls_shift {
362 ($trait:path, $impl_trait:ident, $fun:ident, $obeys:ident, $req:ident, $spec:ident, $self:ident, $rhs:ident, $op:tt, [$($typ:ty)*]) => {
363 $crate::vstd::prelude::verus! {
364 def_bop_impls!($trait, $impl_trait, $fun, $obeys, $req, $spec, $self, $rhs, [
365 $(
366 (
367 $typ,
368 $rhs < $typ::BITS,
369 $self $op $rhs
370 )
371 )*
372 ]);
373 }
374};
375}
376
377def_uop_impls_check_overflow!(core::ops::Neg, NegSpecImpl, neg, obeys_neg_spec, neg_req, neg_spec, self, -, [
378 isize i8 i16 i32 i64 i128
379]);
380
381def_uop_impls_no_check!(core::ops::Not, NotSpecImpl, not, obeys_not_spec, not_req, not_spec, self, !, [
382 bool
383 usize u8 u16 u32 u64 u128
384 isize i8 i16 i32 i64 i128
385]);
386
387def_bop_impls_check_overflow!(core::ops::Add, AddSpecImpl, add, obeys_add_spec, add_req, add_spec, self, rhs, +, [
388 usize u8 u16 u32 u64 u128
389 isize i8 i16 i32 i64 i128
390]);
391
392def_bop_impls_check_overflow!(core::ops::Sub, SubSpecImpl, sub, obeys_sub_spec, sub_req, sub_spec, self, rhs, -, [
393 usize u8 u16 u32 u64 u128
394 isize i8 i16 i32 i64 i128
395]);
396
397def_bop_impls_check_overflow!(core::ops::Mul, MulSpecImpl, mul, obeys_mul_spec, mul_req, mul_spec, self, rhs, *, [
398 usize u8 u16 u32 u64 u128
399 isize i8 i16 i32 i64 i128
400]);
401
402def_bop_impls_unsigned_div_rem!(core::ops::Div, DivSpecImpl, div, obeys_div_spec, div_req, div_spec, self, rhs, /, [
403 usize u8 u16 u32 u64 u128
404]);
405
406def_bop_impls_signed_div_rem!(core::ops::Div, DivSpecImpl, div, obeys_div_spec, div_req, div_spec, self, rhs, /, [
407 isize i8 i16 i32 i64 i128
408]);
409
410def_bop_impls_unsigned_div_rem!(core::ops::Rem, RemSpecImpl, rem, obeys_rem_spec, rem_req, rem_spec, self, rhs, %, [
411 usize u8 u16 u32 u64 u128
412]);
413
414def_bop_impls_signed_div_rem!(core::ops::Rem, RemSpecImpl, rem, obeys_rem_spec, rem_req, rem_spec, self, rhs, %, [
415 isize i8 i16 i32 i64 i128
416]);
417
418def_bop_impls_no_check!(core::ops::BitAnd, BitAndSpecImpl, bitand, obeys_bitand_spec, bitand_req, bitand_spec, self, rhs, &, [
419 usize u8 u16 u32 u64 u128
420 isize i8 i16 i32 i64 i128
421]);
422
423def_bop_impls_no_check!(core::ops::BitOr, BitOrSpecImpl, bitor, obeys_bitor_spec, bitor_req, bitor_spec, self, rhs, |, [
424 usize u8 u16 u32 u64 u128
425 isize i8 i16 i32 i64 i128
426]);
427
428def_bop_impls_no_check!(core::ops::BitXor, BitXorSpecImpl, bitxor, obeys_bitxor_spec, bitxor_req, bitxor_spec, self, rhs, ^, [
429 bool
430 usize u8 u16 u32 u64 u128
431 isize i8 i16 i32 i64 i128
432]);
433
434def_bop_impls_shift!(core::ops::Shl, ShlSpecImpl, shl, obeys_shl_spec, shl_req, shl_spec, self, rhs, <<, [
435 usize u8 u16 u32 u64 u128
436 isize i8 i16 i32 i64 i128
437]);
438
439def_bop_impls_shift!(core::ops::Shr, ShrSpecImpl, shr, obeys_shr_spec, shr_req, shr_spec, self, rhs, >>, [
440 usize u8 u16 u32 u64 u128
441 isize i8 i16 i32 i64 i128
442]);
443
444verus! {
445
446#[verusfmt::skip]
447#[verusfmt::skip]
453
454pub uninterp spec fn neg_ensures<A>(x: A, o: A) -> bool;
455
456pub uninterp spec fn add_ensures<A>(x: A, y: A, o: A) -> bool;
457
458pub uninterp spec fn sub_ensures<A>(x: A, y: A, o: A) -> bool;
459
460pub uninterp spec fn mul_ensures<A>(x: A, y: A, o: A) -> bool;
461
462pub uninterp spec fn div_ensures<A>(x: A, y: A, o: A) -> bool;
463
464pub assume_specification[ <f32 as core::ops::Neg>::neg ](x: f32) -> (o: f32)
465 ensures
466 neg_ensures::<f32>(x, o),
467;
468
469pub assume_specification[ <f32 as core::ops::Add>::add ](x: f32, y: f32) -> (o: f32)
470 ensures
471 add_ensures::<f32>(x, y, o),
472;
473
474pub assume_specification[ <f32 as core::ops::Sub>::sub ](x: f32, y: f32) -> (o: f32)
475 ensures
476 sub_ensures::<f32>(x, y, o),
477;
478
479pub assume_specification[ <f32 as core::ops::Mul>::mul ](x: f32, y: f32) -> (o: f32)
480 ensures
481 mul_ensures::<f32>(x, y, o),
482;
483
484pub assume_specification[ <f32 as core::ops::Div>::div ](x: f32, y: f32) -> (o: f32)
485 ensures
486 div_ensures::<f32>(x, y, o),
487;
488
489pub assume_specification[ <f64 as core::ops::Neg>::neg ](x: f64) -> (o: f64)
490 ensures
491 neg_ensures::<f64>(x, o),
492;
493
494pub assume_specification[ <f64 as core::ops::Add>::add ](x: f64, y: f64) -> (o: f64)
495 ensures
496 add_ensures::<f64>(x, y, o),
497;
498
499pub assume_specification[ <f64 as core::ops::Sub>::sub ](x: f64, y: f64) -> (o: f64)
500 ensures
501 sub_ensures::<f64>(x, y, o),
502;
503
504pub assume_specification[ <f64 as core::ops::Mul>::mul ](x: f64, y: f64) -> (o: f64)
505 ensures
506 mul_ensures::<f64>(x, y, o),
507;
508
509pub assume_specification[ <f64 as core::ops::Div>::div ](x: f64, y: f64) -> (o: f64)
510 ensures
511 div_ensures::<f64>(x, y, o),
512;
513
514}