1#![allow(unused_imports)]
2use super::super::prelude::*;
3
4use core::option::Option;
5
6verus! {
7
8pub trait OptionAdditionalFns<T>: Sized {
10 #[cfg_attr(not(verus_verify_core), deprecated = "is_Variant is deprecated - use `->` or `matches` instead: https://verus-lang.github.io/verus/guide/datatypes_enum.html")]
11 #[allow(non_snake_case)]
12 spec fn is_Some(&self) -> bool;
13
14 #[cfg_attr(not(verus_verify_core), deprecated = "get_Variant is deprecated - use `->` or `matches` instead: https://verus-lang.github.io/verus/guide/datatypes_enum.html")]
15 #[allow(non_snake_case)]
16 spec fn get_Some_0(&self) -> T;
17
18 #[cfg_attr(not(verus_verify_core), deprecated = "is_Variant is deprecated - use `->` or `matches` instead: https://verus-lang.github.io/verus/guide/datatypes_enum.html")]
19 #[allow(non_snake_case)]
20 spec fn is_None(&self) -> bool;
21
22 #[allow(non_snake_case)]
23 spec fn arrow_Some_0(&self) -> T;
24
25 #[allow(non_snake_case)]
26 spec fn arrow_0(&self) -> T;
27
28 #[allow(deprecated)]
29 proof fn tracked_unwrap(tracked self) -> (tracked t: T)
30 requires
31 self.is_Some(),
32 ensures
33 t == self->0,
34 ;
35
36 #[allow(deprecated)]
37 proof fn tracked_expect(tracked self, msg: &str) -> (tracked t: T)
38 requires
39 self.is_Some(),
40 ensures
41 t == self->0,
42 ;
43
44 #[allow(deprecated)]
45 proof fn tracked_borrow(tracked &self) -> (tracked t: &T)
46 requires
47 self.is_Some(),
48 ensures
49 t == self->0,
50 ;
51
52 #[allow(deprecated)]
53 #[verifier::tracked_take_option_primitive]
54 proof fn tracked_take(tracked &mut self) -> (tracked t: T)
55 requires
56 old(self).is_Some(),
57 ensures
58 t == old(self)->0,
59 final(self).is_None(),
60 ;
61}
62
63impl<T> OptionAdditionalFns<T> for Option<T> {
64 #[verifier::inline]
65 open spec fn is_Some(&self) -> bool {
66 is_variant(self, "Some")
67 }
68
69 #[verifier::inline]
70 open spec fn get_Some_0(&self) -> T {
71 get_variant_field(self, "Some", "0")
72 }
73
74 #[verifier::inline]
75 open spec fn is_None(&self) -> bool {
76 is_variant(self, "None")
77 }
78
79 #[verifier::inline]
80 open spec fn arrow_Some_0(&self) -> T {
81 get_variant_field(self, "Some", "0")
82 }
83
84 #[verifier::inline]
85 open spec fn arrow_0(&self) -> T {
86 get_variant_field(self, "Some", "0")
87 }
88
89 proof fn tracked_unwrap(tracked self) -> (tracked t: T) {
90 match self {
91 Option::Some(t) => t,
92 Option::None => proof_from_false(),
93 }
94 }
95
96 proof fn tracked_expect(tracked self, msg: &str) -> (tracked t: T) {
97 match self {
98 Option::Some(t) => t,
99 Option::None => proof_from_false(),
100 }
101 }
102
103 proof fn tracked_borrow(tracked &self) -> (tracked t: &T) {
104 match self {
105 Option::Some(t) => t,
106 Option::None => proof_from_false(),
107 }
108 }
109
110 #[verifier::tracked_take_option_primitive]
112 axiom fn tracked_take(tracked &mut self) -> (tracked t: T);
113}
114
115#[verifier::inline]
118pub open spec fn is_some<T>(option: &Option<T>) -> bool {
119 is_variant(option, "Some")
120}
121
122#[verifier::when_used_as_spec(is_some)]
123pub assume_specification<T>[ Option::<T>::is_some ](option: &Option<T>) -> (b: bool)
124 ensures
125 b == is_some(option),
126 no_unwind
127;
128
129#[verifier::inline]
131pub open spec fn is_none<T>(option: &Option<T>) -> bool {
132 is_variant(option, "None")
133}
134
135#[verifier::when_used_as_spec(is_none)]
136pub assume_specification<T>[ Option::<T>::is_none ](option: &Option<T>) -> (b: bool)
137 ensures
138 b == is_none(option),
139 no_unwind
140;
141
142pub assume_specification<T>[ Option::<T>::as_ref ](option: &Option<T>) -> (a: Option<&T>)
144 ensures
145 a is Some <==> option is Some,
146 a is Some ==> option->0 == a->0,
147 no_unwind
148;
149
150#[verifier::inline]
152pub open spec fn spec_unwrap<T>(option: Option<T>) -> T
153 recommends
154 option is Some,
155{
156 option->0
157}
158
159#[verifier::when_used_as_spec(spec_unwrap)]
160pub assume_specification<T>[ Option::<T>::unwrap ](option: Option<T>) -> (t: T)
161 requires
162 option is Some,
163 ensures
164 t == spec_unwrap(option),
165;
166
167#[verifier::inline]
169pub open spec fn spec_unwrap_or<T>(option: Option<T>, default: T) -> T {
170 match option {
171 Some(t) => t,
172 None => default,
173 }
174}
175
176#[verifier::when_used_as_spec(spec_unwrap_or)]
177pub assume_specification<T>[ Option::<T>::unwrap_or ](option: Option<T>, default: T) -> (t: T)
178 ensures
179 t == spec_unwrap_or(option, default),
180 no_unwind
181;
182
183#[verifier::inline]
185pub open spec fn spec_expect<T>(option: Option<T>, msg: &str) -> T
186 recommends
187 option is Some,
188{
189 option->0
190}
191
192#[verifier::when_used_as_spec(spec_expect)]
193pub assume_specification<T>[ Option::<T>::expect ](option: Option<T>, msg: &str) -> (t: T)
194 requires
195 option is Some,
196 ensures
197 t == spec_expect(option, msg),
198;
199
200pub assume_specification<T>[ Option::<T>::take ](option: &mut Option<T>) -> (t: Option<T>)
202 ensures
203 t == *old(option),
204 *final(option) is None,
205 no_unwind
206;
207
208pub assume_specification<T, U, F: FnOnce(T) -> U>[ Option::<T>::map ](a: Option<T>, f: F) -> (ret:
210 Option<U>)
211 requires
212 a.is_some() ==> f.requires((a.unwrap(),)),
213 ensures
214 ret.is_some() == a.is_some(),
215 ret.is_some() ==> f.ensures((a.unwrap(),), ret.unwrap()),
216;
217
218pub assume_specification<'a, T: Clone>[ Option::<&'a T>::cloned ](opt: Option<&'a T>) -> (res:
220 Option<T>)
221 ensures
222 opt.is_none() ==> res.is_none(),
223 opt.is_some() ==> res.is_some() && cloned::<T>(*opt.unwrap(), res.unwrap()),
224;
225
226pub assume_specification<'a, T: Copy>[ Option::<&'a T>::copied ](opt: Option<&'a T>) -> (res:
228 Option<T>)
229 ensures
230 res == match opt {
231 Some(x) => Some(*x),
232 None => None::<T>,
233 },
234;
235
236pub assume_specification<T, U, F: FnOnce(T) -> Option<U>>[ Option::<T>::and_then ](
238 option: Option<T>,
239 f: F,
240) -> (res: Option<U>)
241 requires
242 option.is_some() ==> f.requires((option.unwrap(),)),
243 ensures
244 option.is_none() ==> res.is_none(),
245 option.is_some() ==> f.ensures((option.unwrap(),), res),
246;
247
248pub assume_specification<T, E, F: FnOnce() -> E>[ Option::<T>::ok_or_else ](
250 option: Option<T>,
251 err: F,
252) -> (res: Result<T, E>)
253 requires
254 option.is_none() ==> err.requires(()),
255 ensures
256 option.is_some() ==> res == Ok::<T, E>(option.unwrap()),
257 option.is_none() ==> {
258 &&& res.is_err()
259 &&& err.ensures((), res->Err_0)
260 },
261;
262
263pub assume_specification<T: core::default::Default>[ Option::<T>::unwrap_or_default ](
265 option: Option<T>,
266) -> (res: T)
267 ensures
268 option.is_some() ==> res == option.unwrap(),
269 option.is_none() ==> T::default.ensures((), res),
270;
271
272pub assume_specification<T, F: FnOnce() -> T>[ Option::<T>::unwrap_or_else ](
274 option: Option<T>,
275 f: F,
276) -> (res: T)
277 requires
278 option.is_none() ==> f.requires(()),
279 ensures
280 option.is_some() ==> res == option.unwrap(),
281 option.is_none() ==> f.ensures((), res),
282;
283
284pub assume_specification<T: Clone>[ <Option<T> as Clone>::clone ](opt: &Option<T>) -> (res: Option<
286 T,
287>)
288 ensures
289 opt.is_none() ==> res.is_none(),
290 opt.is_some() ==> res.is_some() && cloned::<T>(opt.unwrap(), res.unwrap()),
291;
292
293impl<T: super::cmp::PartialEqSpec> super::cmp::PartialEqSpecImpl for Option<T> {
295 open spec fn obeys_eq_spec() -> bool {
296 T::obeys_eq_spec()
297 }
298
299 open spec fn eq_spec(&self, other: &Option<T>) -> bool {
300 match (self, other) {
301 (None, None) => true,
302 (Some(x), Some(y)) => x.eq_spec(y),
303 _ => false,
304 }
305 }
306}
307
308pub assume_specification<T: PartialEq>[ <Option<T> as PartialEq>::eq ](
309 x: &Option<T>,
310 y: &Option<T>,
311) -> bool
312;
313
314impl<T: super::cmp::PartialOrdSpec> super::cmp::PartialOrdSpecImpl for Option<T> {
316 open spec fn obeys_partial_cmp_spec() -> bool {
317 T::obeys_partial_cmp_spec()
318 }
319
320 open spec fn partial_cmp_spec(&self, other: &Option<T>) -> Option<core::cmp::Ordering> {
321 match (self, other) {
322 (None, None) => Some(core::cmp::Ordering::Equal),
323 (None, Some(_)) => Some(core::cmp::Ordering::Less),
324 (Some(_), None) => Some(core::cmp::Ordering::Greater),
325 (Some(x), Some(y)) => x.partial_cmp_spec(y),
326 }
327 }
328}
329
330pub assume_specification<T: PartialOrd>[ <Option<T> as PartialOrd>::partial_cmp ](
331 x: &Option<T>,
332 y: &Option<T>,
333) -> Option<core::cmp::Ordering>
334;
335
336impl<T: super::cmp::OrdSpec> super::cmp::OrdSpecImpl for Option<T> {
337 open spec fn obeys_cmp_spec() -> bool {
338 T::obeys_cmp_spec()
339 }
340
341 open spec fn cmp_spec(&self, other: &Option<T>) -> core::cmp::Ordering {
342 match (self, other) {
343 (None, None) => core::cmp::Ordering::Equal,
344 (None, Some(_)) => core::cmp::Ordering::Less,
345 (Some(_), None) => core::cmp::Ordering::Greater,
346 (Some(x), Some(y)) => x.cmp_spec(y),
347 }
348 }
349}
350
351pub assume_specification<T: Ord>[ <Option<T> as Ord>::cmp ](
352 x: &Option<T>,
353 y: &Option<T>,
354) -> core::cmp::Ordering
355;
356
357#[verifier::inline]
359pub open spec fn spec_ok_or<T, E>(option: Option<T>, err: E) -> Result<T, E> {
360 match option {
361 Some(t) => Ok(t),
362 None => Err(err),
363 }
364}
365
366#[verifier::when_used_as_spec(spec_ok_or)]
367pub assume_specification<T, E>[ Option::ok_or ](option: Option<T>, err: E) -> (res: Result<T, E>)
368 ensures
369 res == spec_ok_or(option, err),
370;
371
372#[doc(hidden)]
373pub assume_specification<T>[ Option::as_mut ](option: &mut Option<T>) -> (res: Option<&mut T>)
374 ensures
375 (match *old(option) {
376 None => final(option).is_none() && res.is_none(),
377 Some(r) => final(option).is_some() && res.is_some() && *res.unwrap() == r
378 && *final(res.unwrap()) == final(option).unwrap(),
379 }),
380;
381
382pub assume_specification<T>[ Option::as_slice ](option: &Option<T>) -> (res: &[T])
383 ensures
384 res@ == (match *option {
385 Some(x) => seq![x],
386 None => seq![],
387 }),
388;
389
390#[doc(hidden)]
391pub assume_specification<T>[ Option::as_mut_slice ](option: &mut Option<T>) -> (res: &mut [T])
392 ensures
393 res@ == (match *old(option) {
394 Some(x) => seq![x],
395 None => seq![],
396 }),
397 final(res)@.len() == res@.len(), final(option)@ == (match *old(option) {
399 Some(_) => Some(final(res)@[0]),
400 None => None,
401 }),
402;
403
404#[doc(hidden)]
405pub assume_specification<T>[ Option::insert ](option: &mut Option<T>, value: T) -> (res: &mut T)
406 ensures
407 *res == value,
408 *final(option) == Some(*final(res)),
409;
410
411#[doc(hidden)]
412pub assume_specification<T>[ Option::get_or_insert ](option: &mut Option<T>, value: T) -> (res:
413 &mut T)
414 ensures
415 *res == (match *old(option) {
416 Some(x) => x,
417 None => value,
418 }),
419 *final(option) == Some(*final(res)),
420;
421
422}