Skip to main content

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