creusot_std/
lib.rs

1//! The "standard library" of Creusot.
2//!
3//! To start using Creusot, you should always import that crate. The recommended way is
4//! to have a glob import:
5//!
6//! ```
7//! use creusot_std::prelude::*;
8//! ```
9//!
10//! # Writing specifications
11//!
12//! To start writing specification, use the [`requires`][crate::macros::requires] and [`ensures`][crate::macros::ensures] macros:
13//!
14//! ```
15//! use creusot_std::prelude::*;
16//!
17//! #[requires(x < i32::MAX)]
18//! #[ensures(result@ == x@ + 1)]
19//! fn add_one(x: i32) -> i32 {
20//!     x + 1
21//! }
22//! ```
23//!
24//! For a more detailed explanation, see the [guide](https://creusot-rs.github.io/creusot/guide).
25//!
26//! # Module organization
27//!
28//! 1. Core features of Creusot
29//!
30//!     - [`invariant`][mod@invariant]: Type invariants
31//!     - [`macros`]: `#[requires]`, `#[ensures]`, etc.
32//!     - [`resolve`][mod@resolve]: Resolve mutable borrows
33//!     - [`snapshot`][mod@snapshot]: Snapshots
34//!
35//! 2. [`logic`][mod@logic]: Logical structures used in specifications
36//!
37//! 3. [`ghost`][mod@ghost]: Ghost code
38//!
39//! 4. [`std`][mod@std]: Specifications for the `std` crate
40//!
41//! 5. [`cell`][mod@cell]: Interior mutability
42//!
43//! 6. [`prelude`][mod@prelude]: What you should import before doing anything with Creusot
44#![cfg_attr(feature = "nightly", allow(incomplete_features, internal_features))]
45#![cfg_attr(
46    feature = "nightly",
47    feature(
48        core_intrinsics,
49        const_destruct,
50        fn_traits,
51        fmt_internals,
52        fmt_helpers_for_derive,
53        step_trait,
54        try_trait_v2,
55        allocator_api,
56        unboxed_closures,
57        tuple_trait,
58        panic_internals,
59        never_type,
60        ptr_metadata,
61        hint_must_use,
62        pointer_is_aligned_to,
63        edition_panic,
64        new_range_api,
65        range_bounds_is_empty,
66        decl_macro
67    )
68)]
69#![cfg_attr(all(doc, feature = "nightly"), feature(intra_doc_pointers))]
70#![cfg_attr(
71    all(feature = "nightly", feature = "std"),
72    feature(print_internals, libstd_sys_internals, rt,)
73)]
74#![cfg_attr(not(feature = "std"), no_std)]
75
76extern crate alloc;
77
78extern crate creusot_std_proc as base_macros;
79extern crate self as creusot_std;
80
81/// Specification are written using these macros
82///
83/// All of those are re-exported at the top of the crate.
84pub mod macros {
85    /// A pre-condition of a function or trait item
86    ///
87    /// The inside of a `requires` may look like Rust code, but it is in fact
88    /// [pearlite](https://creusot-rs.github.io/creusot/guide/pearlite).
89    ///
90    /// # Example
91    ///
92    /// ```
93    /// # use creusot_std::prelude::*;
94    /// #[requires(x@ == 1)]
95    /// fn foo(x: i32) {}
96    /// ```
97    pub use base_macros::requires;
98
99    /// A post-condition of a function or trait item
100    ///
101    /// The inside of a `ensures` may look like Rust code, but it is in fact
102    /// [pearlite](https://creusot-rs.github.io/creusot/guide/pearlite).
103    ///
104    /// # Example
105    ///
106    /// ```
107    /// # use creusot_std::prelude::*;
108    /// #[ensures(result@ == 1)]
109    /// fn foo() -> i32 { 1 }
110    /// ```
111    pub use base_macros::ensures;
112
113    /// Create a new [`Snapshot`](crate::snapshot::Snapshot) object.
114    ///
115    /// The inside of `snapshot` may look like Rust code, but it is in fact
116    /// [pearlite](https://creusot-rs.github.io/creusot/guide/pearlite).
117    ///
118    /// # Example
119    ///
120    /// ```
121    /// # use creusot_std::prelude::*;
122    /// let mut x = 1;
123    /// let s = snapshot!(x);
124    /// x = 2;
125    /// proof_assert!(*s == 1i32);
126    /// ```
127    ///
128    /// # `snapshot!` and ownership
129    ///
130    /// Snapshots are used to talk about the logical value of an object, and as such
131    /// they carry no ownership. This means that code like this is perfectly fine:
132    ///
133    /// ```
134    /// # use creusot_std::prelude::{vec, *};
135    /// let v: Vec<i32> = vec![1, 2];
136    /// let s = snapshot!(v);
137    /// assert!(v[0] == 1); // ok, `s` does not have ownership of `v`
138    /// drop(v);
139    /// proof_assert!(s[0] == 1i32); // also ok!
140    /// ```
141    pub use base_macros::snapshot;
142
143    /// Opens a 'ghost block'.
144    ///
145    /// Ghost blocks are used to execute ghost code: code that will be erased in the
146    /// normal execution of the program, but could influence the proof.
147    ///
148    /// Note that ghost blocks are subject to some constraints, that ensure the behavior
149    /// of the code stays the same with and without ghost blocks:
150    /// - They may not contain code that crashes or runs indefinitely. In other words,
151    ///   they can only call [`check(ghost)`][check#checkghost] functions.
152    /// - All variables that are read in the ghost block must either be [`Copy`], or a
153    ///   [`Ghost`].
154    /// - All variables that are modified in the ghost block must be [`Ghost`]s.
155    /// - The variable returned by the ghost block will automatically be wrapped in a
156    ///   [`Ghost`].
157    ///
158    /// # Example
159    ///
160    /// ```
161    /// # use creusot_std::prelude::*;
162    /// let x = 1;
163    /// let mut g = ghost!(Seq::new()); // g is a zero-sized variable at runtime
164    /// ghost! {
165    ///     g.push_back_ghost(x);
166    /// };
167    /// ```
168    ///
169    /// [`Ghost`]: crate::ghost::Ghost
170    pub use base_macros::ghost;
171
172    pub use base_macros::ghost_let;
173
174    /// Specify that the function can be called in additionnal contexts.
175    ///
176    /// # Syntax
177    ///
178    /// Checking modes are specified as arguments:
179    ///
180    /// ```
181    /// # use creusot_std::prelude::*;
182    /// #[check(terminates)]
183    /// fn foo() { /* */ }
184    ///
185    /// #[check(ghost)]
186    /// fn bar() { /* */ }
187    ///
188    /// // cannot be called in neither ghost nor terminates contexts
189    /// fn baz() { /* */ }
190    /// ```
191    ///
192    /// # `#[check(terminates)]`
193    ///
194    /// The function is guaranteed to terminate.
195    ///
196    /// At this moment, this means that:
197    /// - the function cannot be recursive
198    /// - the function cannot contain loops
199    /// - the function can only call other `terminates` or `ghost` functions.
200    ///
201    /// The first two limitations may be lifted at some point.
202    ///
203    /// # `#[check(ghost)]`
204    ///
205    /// The function can be called from ghost code. In particular, this means
206    /// that the fuction will not panic.
207    ///
208    /// # No panics ?
209    ///
210    /// "But I though Creusot was supposed to check the absence of panics ?"
211    ///
212    /// That's true, but with a caveat: some functions of the standard library
213    /// are allowed to panic in specific cases. The main example is `Vec::push`:
214    /// we want its specification to be
215    /// ```ignore
216    /// #[ensures((^self)@ == self@.push(v))]
217    /// fn push(&mut self, v: T) { /* ... */ }
218    /// ```
219    ///
220    /// But the length of a vector [cannot overflow `isize::MAX`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.push).
221    /// This is a very annoying condition to check, so we don't. In exchange,
222    /// this means `Vec::push` might panic in some cases, even though your
223    /// code passed Creusot's verification.
224    ///
225    /// # Non-ghost std function
226    ///
227    /// Here are some examples of functions in `std` that are not marked as
228    /// `terminates` but not `ghost` (this list is not exhaustive):
229    /// - `Vec::push`, `Vec::insert`, `Vec::reserve`, `Vec::with_capacity`
230    /// - `str::to_string`
231    /// - `<&[T]>::into_vec`
232    /// - `Deque::push_front`, `Deque::push_back`, `Deque::with_capacity`
233    pub use base_macros::check;
234
235    /// A loop invariant
236    ///
237    /// The inside of a `invariant` may look like Rust code, but it is in fact
238    /// [pearlite](https://creusot-rs.github.io/creusot/guide/pearlite).
239    ///
240    /// # Produced
241    ///
242    /// If the loop is a `for` loop, you have access to a special variable `produced`, that
243    /// holds a [sequence](crate::logic::Seq) of all the (logical representations of) items the
244    /// iterator yielded so far.
245    ///
246    /// # Example
247    ///
248    /// ```ignore
249    /// # use creusot_std::prelude::*;
250    /// let mut v = Vec::new();
251    /// #[invariant(v@.len() == produced.len())]
252    /// #[invariant(forall<j> 0 <= j && j < produced.len() ==> v@[j]@ == j)]
253    /// for i in 0..10 {
254    ///     v.push(i);
255    /// }
256    /// ```
257    pub use base_macros::invariant;
258
259    /// Declare a function as being a logical function
260    ///
261    /// This declaration must be pure and total. It cannot be called from Rust programs,
262    /// but in exchange it can use logical operations and syntax with the help of the
263    /// [`pearlite!`] macro.
264    ///
265    /// # `open`
266    ///
267    /// Allows the body of a logical definition to be made visible to provers
268    ///
269    /// By default, bodies are *opaque*: they are only visible to definitions in the same
270    /// module (like `pub(self)` for visibility).
271    /// An optional visibility modifier can be provided to restrict the context in which
272    /// the body is opened.
273    ///
274    /// A body can only be visible in contexts where all the symbols used in the body are also visible.
275    /// This means you cannot open a body which refers to a `pub(crate)` symbol.
276    ///
277    /// # Example
278    ///
279    /// ```
280    /// mod inner {
281    ///     use creusot_std::prelude::*;
282    ///     #[logic]
283    ///     #[ensures(result == x + 1)]
284    ///     pub(super) fn foo(x: Int) -> Int {
285    ///         // ...
286    /// # x + 1
287    ///     }
288    ///
289    ///     #[logic(open)]
290    ///     pub(super) fn bar(x: Int) -> Int {
291    ///         x + 1
292    ///     }
293    /// }
294    ///
295    /// // The body of `foo` is not visible here, only the `ensures`.
296    /// // But the whole body of `bar` is visible
297    /// ```
298    ///
299    /// # `prophetic`
300    ///
301    /// If you wish to use the `^` operator on mutable borrows to get the final value, you need to
302    /// specify that the function is _prophetic_, like so:
303    /// ```
304    /// # use creusot_std::prelude::*;
305    /// #[logic(prophetic)]
306    /// fn uses_prophecies(x: &mut Int) -> Int {
307    ///     pearlite! { if ^x == 0 { 0 } else { 1 } }
308    /// }
309    /// ```
310    /// Such a logic function cannot be used in [`snapshot!`] anymore, and cannot be
311    /// called from a regular [`logic`] function.
312    ///
313    /// # law
314    ///
315    /// Declares a trait item as being a law which is autoloaded as soon another
316    /// trait item is used in a function.
317    ///
318    /// ```ignore
319    /// trait CommutativeOp {
320    ///     fn op(self, other: Self) -> Int;
321    ///
322    ///     #[logic(law)]
323    ///     #[ensures(forall<x: Self, y: Self> x.op(y) == y.op(x))]
324    ///     fn commutative();
325    /// }
326    /// ```
327    pub use base_macros::logic;
328
329    /// Inserts a *logical* assertion into the code
330    ///
331    /// This assertion will not be checked at runtime but only during proofs. However,
332    /// it can use [pearlite](https://creusot-rs.github.io/creusot/guide/pearlite) syntax.
333    ///
334    /// # Example
335    ///
336    /// ```
337    /// # use creusot_std::prelude::{vec, *};
338    /// let x = 1;
339    /// let v = vec![x, 2];
340    /// let s = snapshot!(v);
341    /// proof_assert!(s[0] == 1i32);
342    /// ```
343    pub use base_macros::proof_assert;
344
345    /// Makes a logical definition or a type declaration opaque, meaning that users of this declaration will not see
346    /// its definition.
347    ///
348    /// # Example
349    ///
350    /// ```
351    /// # use creusot_std::prelude::*;
352    /// #[opaque]
353    /// struct Opaque(()); // This will is an abstract type
354    ///
355    /// #[logic]
356    /// #[opaque] // Synonym: #[logic(opaque)]
357    /// fn foo() -> i32 { // This is an uninterpreted logic function
358    ///     dead
359    /// }
360    /// ```
361    pub use base_macros::opaque;
362
363    /// Instructs Creusot to not emit any VC for a declaration, assuming any contract the declaration has is
364    /// valid.
365    ///
366    /// # Example
367    ///
368    /// ```
369    /// # use creusot_std::prelude::*;
370    /// #[trusted] // this is too hard to prove :(
371    /// #[ensures(result@ == 1)]
372    /// fn foo() -> i32 {
373    ///     // complicated code...
374    /// # 1
375    /// }
376    /// ```
377    ///
378    /// These declarations are part of the trusted computing base (TCB). You should strive to use
379    /// this as little as possible.
380    pub use base_macros::trusted;
381
382    /// Declares a variant for a function or a loop.
383    ///
384    /// This is primarily used in combination with recursive logical functions.
385    ///
386    /// The variant must be an expression whose type implements
387    /// [`WellFounded`](crate::logic::WellFounded).
388    ///
389    /// # Example
390    ///
391    /// - Recursive logical function:
392    /// ```
393    /// # use creusot_std::prelude::*;
394    /// #[logic]
395    /// #[variant(x)]
396    /// #[requires(x >= 0)]
397    /// fn recursive_add(x: Int, y: Int) -> Int {
398    ///     if x == 0 {
399    ///         y
400    ///     } else {
401    ///         recursive_add(x - 1, y + 1)
402    ///     }
403    /// }
404    /// ```
405    /// - Loop variant:
406    /// ```
407    /// # use creusot_std::prelude::*;
408    /// #[check(terminates)]
409    /// #[ensures(result == x)]
410    /// fn inneficient_identity(mut x: i32) -> i32 {
411    ///     let mut res = 0;
412    ///     let total = snapshot!(x);
413    ///     // Attribute on loop are experimental in Rust, just pretend the next 2 lines are uncommented :)
414    ///     // #[variant(x)]
415    ///     // #[invariant(x@ + res@ == total@)]
416    ///     while x > 0 {
417    ///         x -= 1;
418    ///         res += 1;
419    ///     }
420    ///     res
421    /// }
422    /// ```
423    pub use base_macros::variant;
424
425    /// Enables [pearlite](https://creusot-rs.github.io/creusot/guide/pearlite) syntax, granting access to Pearlite specific operators and syntax
426    ///
427    /// This is meant to be used in [`logic`] functions.
428    ///
429    /// # Example
430    ///
431    /// ```
432    /// # use creusot_std::prelude::*;
433    /// #[logic]
434    /// fn all_ones(s: Seq<Int>) -> bool {
435    ///     // Allow access to `forall` and `==>` among other things
436    ///     pearlite! {
437    ///         forall<i> 0 <= i && i < s.len() ==> s[i] == 1
438    ///     }
439    /// }
440    /// ```
441    pub use base_macros::pearlite;
442
443    /// Allows specifications to be attached to functions coming from external crates
444    ///
445    /// TODO: Document syntax
446    pub use base_macros::extern_spec;
447
448    /// Allows specifying both a pre- and post-condition in a single statement.
449    ///
450    /// Expects an expression in either the form of a method or function call
451    /// Arguments to the call can be prefixed with `mut` to indicate that they are mutable borrows.
452    ///
453    /// Generates a `requires` and `ensures` clause in the shape of the input expression, with
454    /// `mut` replaced by `*` in the `requires` and `^` in the ensures.
455    pub use base_macros::maintains;
456
457    /// This attribute can be used on a function or closure to instruct Creusot not to ensure as a postcondition that the
458    /// return value of the function satisfies its [type invariant](crate::invariant::Invariant).
459    pub use base_macros::open_inv_result;
460
461    /// This attribute indicates that the function need to be proved in "bitwise" mode, which means that Creusot will use
462    /// the bitvector theory of SMT solvers.
463    pub use base_macros::bitwise_proof;
464
465    /// This attribute indicates that a logic function or a type should be translated to a specific type in Why3.
466    pub use base_macros::builtin;
467
468    /// Check that the annotated function erases to another function.
469    ///
470    /// See the [guide: Erasure check](https://creusot-rs.github.io/creusot/guide/erasure.html).
471    ///
472    /// # Usage
473    ///
474    /// ```
475    /// # use creusot_std::prelude::*;
476    /// #[erasure(f)]
477    /// fn g(x: usize, i: Ghost<Int>) { /* ... */ }
478    ///
479    /// #[erasure(private crate_name::full::path::to::f2)]
480    /// fn g2(y: bool) { /* ... */ }
481    ///
482    /// #[trusted]
483    /// #[erasure(_)]
484    /// fn split<T, U>(g: Ghost<(T, U)>) -> (Ghost<T>, Ghost<U>) {
485    ///     /* ... */
486    /// # unimplemented!()
487    /// }
488    /// ```
489    ///
490    /// # Inside `extern_spec!`
491    ///
492    /// The shorter `#[erasure]` (without argument) can be used in `extern_spec!` to check
493    /// that the annotated function body matches the original one.
494    ///
495    /// ```
496    /// # use creusot_std::prelude::*;
497    /// extern_spec! {
498    ///   #[erasure]
499    ///   fn some_external_function() { /* ... */ }
500    /// }
501    /// ```
502    pub use base_macros::erasure;
503
504    pub(crate) use base_macros::intrinsic;
505}
506
507#[doc(hidden)]
508#[cfg(creusot)]
509#[path = "stubs.rs"]
510pub mod __stubs;
511
512pub mod cell;
513pub mod ghost;
514pub mod invariant;
515pub mod logic;
516pub mod model;
517pub mod peano;
518pub mod resolve;
519pub mod snapshot;
520#[cfg_attr(not(creusot), allow(unused))]
521pub mod std;
522
523// We add some common things at the root of the creusot-std library
524mod base_prelude {
525    pub use crate::{
526        ghost::Ghost,
527        invariant::Invariant,
528        logic::{Int, OrdLogic, Seq, ops::IndexLogic as _},
529        model::{DeepModel, View},
530        resolve::Resolve,
531        snapshot::Snapshot,
532        std::iter::{DoubleEndedIteratorSpec, FromIteratorSpec, IteratorSpec},
533    };
534
535    pub use crate::std::{
536        // Shadow std::prelude by our version of derive macros and of vec!.
537        // If the user write the glob pattern "use creusot_std::prelude::*",
538        // then rustc will either shadow the old identifier or complain about
539        // the ambiguity (ex: for the derive macros Clone and PartialEq, a glob
540        // pattern is not enough to force rustc to use our version, but at least
541        // we get an error message).
542        clone::Clone,
543        cmp::PartialEq,
544        default::Default,
545    };
546
547    #[cfg(feature = "std")]
548    pub use crate::std::vec::vec;
549
550    // Export extension traits anonymously
551    pub use crate::std::{
552        char::CharExt as _,
553        iter::{SkipExt as _, TakeExt as _},
554        ops::{FnExt as _, FnMutExt as _, FnOnceExt as _, RangeInclusiveExt as _},
555        option::OptionExt as _,
556        ptr::{PointerExt as _, SizedPointerExt as _, SlicePointerExt as _},
557        slice::SliceExt as _,
558    };
559
560    #[cfg(creusot)]
561    pub use crate::{invariant::inv, resolve::resolve};
562}
563/// Re-exports available under the `creusot_std` namespace
564pub mod prelude {
565    pub use crate::{base_prelude::*, macros::*};
566}