Skip to main content

vstd/
pervasive.rs

1#![allow(internal_features)]
2
3#[allow(unused_imports)]
4use super::prelude::*;
5#[cfg(all(verus_keep_ghost, feature = "alloc"))]
6use super::std_specs::fmt::DebugSpec;
7
8#[cfg(not(feature = "std"))]
9macro_rules! println {
10    ($($arg:tt)*) => {};
11}
12verus! {
13
14// TODO: remove this
15pub proof fn assert(b: bool)
16    requires
17        #![verifier::custom_err("assertion failure")]
18        b,
19    ensures
20        b,
21{
22}
23
24pub proof fn affirm(b: bool)
25    requires
26        b,
27{
28}
29
30// An artificial trigger that can be used in case no expression naturally serves as a trigger
31pub open spec fn trigger<A>(a: A) -> bool {
32    true
33}
34
35// TODO: when default trait methods are supported, most of these should be given defaults
36pub trait ForLoopGhostIterator {
37    type ExecIter;
38
39    type Item;
40
41    type Decrease;
42
43    // Connect the ExecIter to the GhostIter
44    // Always enabled
45    // Always true before and after each loop iteration
46    spec fn exec_invariant(&self, exec_iter: &Self::ExecIter) -> bool;
47
48    // Additional optional invariants about the GhostIter
49    // May be disabled with #[verifier::no_auto_loop_invariant]
50    // If enabled, always true before and after each loop iteration
51    // (When the analysis can infer a spec initial value, the analysis places the value in init)
52    spec fn ghost_invariant(&self, init: Option<&Self>) -> bool;
53
54    // True upon loop exit
55    spec fn ghost_ensures(&self) -> bool;
56
57    // Value used by default for decreases clause when no explicit decreases clause is provided
58    // (the user can override this with an explicit decreases clause).
59    // (If there's no appropriate decrease, this can return None,
60    // and the user will have to provide an explicit decreases clause.)
61    spec fn ghost_decrease(&self) -> Option<Self::Decrease>;
62
63    // If there will be Some next value, and we can make a useful guess as to what the next value
64    // will be, return Some of it.
65    // Otherwise, return None.
66    // TODO: in the long term, we could have VIR insert an assertion (or warning)
67    // that ghost_peek_next returns non-null if it is used in the invariants.
68    // (this will take a little bit of engineering since the syntax macro blindly inserts
69    // let bindings using ghost_peek_next, even if they aren't needed, and we only learn
70    // what is actually needed later in VIR.)
71    spec fn ghost_peek_next(&self) -> Option<Self::Item>;
72
73    // At the end of the for loop, advance to the next position.
74    // Future TODO: this may be better as a proof function
75    spec fn ghost_advance(&self, exec_iter: &Self::ExecIter) -> Self where Self: Sized;
76}
77
78pub trait ForLoopGhostIteratorNew {
79    type GhostIter;
80
81    // Create a new ghost iterator from an exec iterator
82    // Future TODO: this may be better as a proof function
83    spec fn ghost_iter(&self) -> Self::GhostIter;
84}
85
86#[cfg(verus_keep_ghost)]
87pub trait FnWithRequiresEnsures<Args, Output>: Sized {
88    spec fn requires(self, args: Args) -> bool;
89
90    spec fn ensures(self, args: Args, output: Output) -> bool;
91
92    spec fn opens_invariants(self, args: Args) -> ISet<int>;
93}
94
95#[cfg(verus_keep_ghost)]
96impl<Args: core::marker::Tuple, Output, F: FnOnce<Args, Output = Output>> FnWithRequiresEnsures<
97    Args,
98    Output,
99> for F {
100    #[verifier::inline]
101    open spec fn requires(self, args: Args) -> bool {
102        call_requires(self, args)
103    }
104
105    #[verifier::inline]
106    open spec fn ensures(self, args: Args, output: Output) -> bool {
107        call_ensures(self, args, output)
108    }
109
110    #[verifier::inline]
111    open spec fn opens_invariants(self, args: Args) -> ISet<int> {
112        call_opens_invariants(self, args)
113    }
114}
115
116// Non-statically-determined function calls are translated *internally* (at the VIR level)
117// to this function call. This should not actually be called directly by the user.
118// That is, Verus treats `f(x, y)` as `exec_nonstatic_call(f, (x, y))`.
119// (Note that this function wouldn't even satisfy the borrow-checker if you tried to
120// use it with a `&F` or `&mut F`, but this doesn't matter since it's only used at VIR.)
121#[cfg(verus_keep_ghost)]
122#[doc(hidden)]
123#[verifier::external_body]
124#[rustc_diagnostic_item = "verus::vstd::vstd::exec_nonstatic_call"]
125fn exec_nonstatic_call<Args: core::marker::Tuple, Output, F>(f: F, args: Args) -> (output:
126    Output) where F: FnOnce<Args, Output = Output>
127    requires
128        #![verifier::custom_err("Call to non-static function fails to satisfy `callee.requires(args)`")]
129        call_requires(f, args),
130    ensures
131        call_ensures(f, args, output),
132{
133    unimplemented!();
134}
135
136#[cfg(verus_keep_ghost)]
137#[doc(hidden)]
138#[verifier::external_body]
139#[rustc_diagnostic_item = "verus::vstd::vstd::proof_nonstatic_call"]
140proof fn proof_nonstatic_call<Args: core::marker::Tuple, Output, F>(
141    tracked f: F,
142    tracked args: Args,
143) -> (tracked output: Output) where F: FnOnce<Args, Output = Output>
144    requires
145        #![verifier::custom_err("Call to non-static function fails to satisfy `callee.requires(args)`")]
146        call_requires(f, args),
147    ensures
148        call_ensures(f, args, output),
149    opens_invariants call_opens_invariants(f, args)
150{
151    unimplemented!();
152}
153
154/// A tool to check one's reasoning while writing complex spec functions.
155/// Not intended to be used as a mechanism for instantiating quantifiers, `spec_affirm` should
156/// be removed from spec functions once they are complete.
157///
158/// ## Example
159///
160/// ```rust
161/// #[spec(checked)] fn some_predicate(a: nat) -> bool {
162///     recommends(a < 100);
163///     if (a >= 50) {
164///         let _ = spec_affirm(50 <= a && a < 100);
165///         a >= 75
166///     } else {
167///         let _ = spec_affirm(a < 50);
168///         // let _ = spec_affirm(a < 40); would raise a recommends note here
169///         a < 25
170///     }
171/// }
172/// ```
173pub closed spec fn spec_affirm(b: bool) -> bool
174    recommends
175        b,
176{
177    b
178}
179
180/// In spec, all types are inhabited
181#[verifier::external_body]  /* vattr */
182#[allow(dead_code)]
183pub uninterp spec fn arbitrary<A>() -> A;
184
185pub axiom fn proof_from_false<A>() -> (tracked a: A)
186    requires
187        false,
188;
189
190#[verifier::external_body]  /* vattr */
191#[allow(dead_code)]
192pub fn unreached<A>() -> A
193    requires
194        false,
195{
196    panic!("unreached_external")
197}
198
199#[allow(unused_variables)]  // when built with cfg(not(feature = "std"))
200#[verifier::external_body]  /* vattr */
201pub fn print_u64(i: u64) {
202    println!("{}", i);
203}
204
205#[verifier::external_body]
206pub fn runtime_assert(b: bool)
207    requires
208        b,
209{
210    runtime_assert_internal(b);
211}
212
213} // verus!
214#[inline(always)]
215#[cfg_attr(verus_keep_ghost, verifier::external)]
216fn runtime_assert_internal(b: bool) {
217    assert!(b);
218}
219
220/// Allows you to prove a boolean predicate by assuming its negation and proving
221/// a contradiction.
222///
223/// `assert_by_contradiction!(b, { /* proof */ });`
224/// Equivalent to writing `if !b { /* proof */; assert(false); }`
225/// but is more concise and documents intent.
226///
227/// ```rust
228/// assert_by_contradiction!(b, {
229///     // assume !b here
230///     // prove `false`
231/// });
232/// ```
233
234#[macro_export]
235macro_rules! assert_by_contradiction {
236    ($($a:tt)*) => {
237        $crate::vstd::prelude::verus_proof_macro_exprs!($crate::assert_by_contradiction_internal!($($a)*))
238    }
239}
240
241#[doc(hidden)]
242#[macro_export]
243macro_rules! assert_by_contradiction_internal {
244    ($predicate:expr, $bblock:block) => {
245        $crate::vstd::prelude::assert_by($predicate, {
246            if !$predicate {
247                $bblock
248                $crate::vstd::prelude::assert_(false);
249            }
250        });
251    };
252}
253
254/// Macro to help set up boilerplate for specifying invariants when using
255/// invariant-based datatypes.
256///
257/// This currently supports the `AtomicInvariant` and `LocalInvariant`
258/// types, as well as all the `atomic_ghost` types (e.g., `AtomicU64`, `AtomicBool`, and so on).
259/// It is important to first understand how these types work.
260/// In particular, `LocalInvariant` (for example) takes three type parameters,
261/// `K`, `V`, and `Pred: InvariantPredicate`.
262/// The `InvariantPredicate` trait lets the user specify an invariant at the static type
263/// level, while `K` allows the user to configure the invariant upon construction.
264/// `AtomicInvariant` uses the same system, and the `atomic_ghost` types are similar
265/// but use a different trait (`AtomicInvariantPredicate`).
266///
267/// However, setting all this up in a typical application tends to involve a bit
268/// of boilerplate. That's where this macro comes in.
269///
270/// # Usage
271///
272/// The `struct_with_invariants!` macro is used at the item level, and it should contains
273/// a single struct declaration followed by a single declaration of a `spec` function
274/// returning `bool`. However, this spec function should not contain a boolean predicate
275/// as usual, but instead a series of _invariant declarations_.
276/// Each invariant declaration applies to a single field of the struct.
277///
278/// ```rust
279/// struct_with_invariants!{
280///     (pub)? struct $struct_name (<...>)? (where ...)? {
281///         ( (pub)? $field_name: $type, )*
282///     }
283///
284///     (pub)? (open|closed)? spec fn(&self (, ...)?) $fn_name {
285///         ( InvariantDecl | BoolPredicateDecl )*
286///     }
287/// }
288/// ```
289///
290/// A field of the struct, if it uses a supported type, may leave the type _incomplete_ by
291/// omitting some of its type parameters.
292/// The following are valid incomplete types:
293///
294///  * `LocalInvariant<_, V, _>`
295///  * `AtomicInvariant<_, V, _>`
296///  * `AtomicBool<_, G, _>`
297///  * `AtomicU64<_, G, _>`
298///    * ... and so on for the other `atomic_ghost` types.
299///
300/// There must be exactly one invariant declaration for each incomplete type used in the
301/// struct declaration. The macro uses invariant declarations to fill in the type parameters.
302///
303/// The user can also provide boolean predicate declarations, which are copied verbatim
304/// into the `$fn_name` definition. This is a convenience, since it is common to want
305/// to add extra conditions, and it is fairly straightforward.
306/// The complex part of the macro expansion in the invariant declarations.
307///
308/// ```rust
309/// BoolPredicateDecl  :=  predicate { $bool_expr }
310///
311/// InvariantDecl  :=
312///     invariant on $field_name
313///         ( with ($dependencies) )?
314///         ( forall | ($ident: $type, )* | )?
315///         ( where ($where_expr) )?
316///         ( specifically ($specifically_expr) )?
317///         is ($params) {
318///             $bool_expr
319///         }
320/// ```
321///
322/// In the `InvariantDecl`, the user always needs to provide the following data:
323///
324///  * The `$field_name` is the field that this invariant applies to
325///     (which must have an incomplete type as described above)
326///  * The `$params` are the values constrained by the invariant.
327///      * For a `LocalInvariant<V>` or `AtomicInvariant<V>`, this should be a single
328///        parameter of type `V`.
329///      * For an `atomic_ghost` type, this should consist of two parameters,
330///        first the primitive type stored by the atomic, and secondly one of the ghost type, `G`.
331///        (For example, the type `AtomicBool<_, G, _>` should have two parameters
332///        here, `b: bool, g: G`.)
333///  * Finally, the `$bool_expr` is the invariant predicate, which may reference any of
334///     the fields declared in `$dependencies`, or any of the params.
335///
336/// The other input clauses handle additional complexities that often comes up.
337/// For example, it is often necessary for the invariant to refer to the values of other fields
338/// in the struct.
339///
340///  * The `with` input gives the list of field names (other fields
341///     from the struct definition) that may be referenced from
342///     the body of this invariant.
343///     The graph of dependencies across all fields must be acyclic.
344///
345/// Finally, when the field is a _container_ type, e.g., `vec: Vec<AtomicU64<_, G, _>>` or
346/// `opt: Option<AtomicU64<_, G, _>>`, there are some additional complexities.
347/// We might need the invariant to be conditional (e.g., for an optional, the invariant would only
348/// exist if `opt is Some`).
349/// We might need to quantify over a variable (e.g., in a vector, we want to specify an invariant
350/// for each element, element `i` where `0 <= i < vec.len()`).
351/// Finally, we need to indicate the value actually getting the invariant (e.g., `self.vec[i]`).
352///
353/// * The `forall` lets you specify additional bound variables. Everything after the `forall`---the
354///   `where`, the `specifically`, and finally the `$bool_expr$`---can all reference these bound variables.
355/// * The `where` lets you specify an additional hypothesis that the invariant is dependent on.
356/// * The `specifically` lets you indicate the value getting the invariant.
357///
358/// This all roughly means, "forall instantiations of the quantified variables, if the condition `$where_expr` holds,
359/// then the value given by `$specifically_expr` has the invariant given by `$bool_expr`.
360/// See the detailed information on the macro-expansion below for more details.
361///
362/// Given all the information from the `InvariantDecl`, the macro fills in the `_` placeholders as follows:
363///
364///  * The macro fills in the `K` type as the types of the fields marked as dependencies and
365///    the quantified variables in the forall (packing all these types into a tuple if necessary).
366///  * The macro fills in the `Pred` type by creating a new type and implementing the appropriate
367///    trait with the user-provided predicate.
368///
369/// # Example (TODO)
370///
371/// # Example using a container type (TODO)
372///
373/// # Macro Expansion (TODO)
374pub use verus_builtin_macros::struct_with_invariants;
375
376verus! {
377
378use super::view::View;
379
380#[cfg(feature = "alloc")]
381#[verifier::external]
382pub trait VecAdditionalExecFns<T> {
383    fn set(&mut self, i: usize, value: T);
384
385    fn set_and_swap(&mut self, i: usize, value: &mut T);
386}
387
388#[cfg(feature = "alloc")]
389impl<T> VecAdditionalExecFns<T> for alloc::vec::Vec<T> {
390    /// Replacement for `self[i] = value;` (which Verus does not support for technical reasons)
391    #[verifier::external_body]
392    fn set(&mut self, i: usize, value: T)
393        requires
394            i < old(self).len(),
395        ensures
396            final(self)@ == old(self)@.update(i as int, value),
397    {
398        self[i] = value;
399    }
400
401    /// Replacement for `swap(&mut self[i], &mut value)` (which Verus does not support for technical reasons)
402    #[verifier::external_body]
403    fn set_and_swap(&mut self, i: usize, value: &mut T)
404        requires
405            i < old(self).len(),
406        ensures
407            final(self)@ == old(self)@.update(i as int, *old(value)),
408            *final(value) == old(self)@.index(i as int),
409    {
410        core::mem::swap(&mut self[i], value);
411    }
412}
413
414/// Predicate indicating `b` could be the result of calling `a.clone()`
415///
416/// It is usually recommended to use [`cloned`] instead,
417/// which takes the reflexive closure.
418pub open spec fn strictly_cloned<T: Clone>(a: T, b: T) -> bool {
419    call_ensures(T::clone, (&a,), b)
420}
421
422/// Predicate indicating `b` is "a clone" of `a`; i.e., `b` could be the result of
423/// calling `a.clone()` or is equal to `a`.
424///
425/// By always considering a value to be a clone of itself, regardless of the definition
426/// of `T::clone`, this definition is useful in places where 'clone' calls might be
427/// optimized to copies. This is particularly common in the Rust stdlib.
428pub open spec fn cloned<T: Clone>(a: T, b: T) -> bool {
429    strictly_cloned(a, b) || a == b
430}
431
432} // verus!
433verus! {
434
435/// The default behavior of the vstd library enforces writing panic-free code.
436/// While developers may still use panic, verification should ensure that any
437/// panic is provably unreachable.
438/// cfg!(feature = "allow_panic") explicily allows code to panic.
439pub open spec fn allow_panic() -> bool {
440    cfg!(feature = "allow_panic")
441}
442
443#[doc(hidden)]
444#[verifier(external_body)]
445pub fn __call_panic(out: &[&str]) -> !
446    requires
447        allow_panic(),
448{
449    core::panic!("__call_panic {:?}", out);
450}
451
452// rt::Argument is a private type and we cannot add specification directly
453#[cfg(feature = "alloc")]
454#[doc(hidden)]
455#[verifier(external_body)]
456pub fn __new_argument<T: core::fmt::Debug>(v: &T) -> alloc::string::String
457    requires
458        forall|f: &core::fmt::Formatter<'_>| v.fmt_req(f),
459{
460    alloc::format!("{:?}", v)
461}
462
463} // verus!
464/// Replace panic macro with vpanic when needed.
465/// panic!{} may call panic_fmt with private rt::Argument, which could not
466/// be supported in verus.
467#[macro_export]
468macro_rules! vpanic {
469    // Case: Format string with arguments
470    ($fmt:expr $(,$val:expr)*) => {
471        vstd::pervasive::__call_panic(
472            &[vstd::pervasive::__new_argument(&$fmt).as_str(),
473            $(
474                vstd::pervasive::__new_argument(&$val).as_str(),
475            )*]
476        );
477    };
478    () => {
479        vstd::pervasive::__call_panic(&[]);
480    };
481}