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