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