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