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}