creusot_std/
ghost.rs

1//! Definitions for ghost code
2//!
3//! Ghost code is code that will be erased during the normal compilation of the program.
4//! To use ghost code in creusot, you must use the [`ghost!`] macro:
5//!
6//! ```
7//! # use creusot_std::prelude::*;
8//! let x: Ghost<i32> = ghost!(1);
9//! ghost! {
10//!     let y: i32 = *x;
11//!     assert!(y == 1);
12//! };
13//! ```
14//!
15//! There are restrictions on the values that can enter/exit a `ghost!` block: see
16//! [`Ghost`] and [`ghost!`] for more details.
17
18use crate::{logic::ops::Fin, prelude::*};
19use core::{
20    marker::PhantomData,
21    ops::{Deref, DerefMut},
22};
23
24mod fn_ghost;
25pub mod invariant;
26pub mod resource;
27pub use fn_ghost::{FnGhost, FnGhostWrapper};
28pub mod perm;
29
30/// A type that can be used in [`ghost!`] context.
31///
32/// This type may be used to make more complicated proofs possible. In particular, some
33/// proof may need a notion of non-duplicable token to carry around.
34///
35/// Conceptually, a `Ghost<T>` is an object of type `T` that resides in a special "ghost"
36/// heap. This heap is inaccessible from normal code, and `Ghost` values cannot be used
37/// to influence the behavior of normal code.
38///
39/// This box can be accessed in a [`ghost!`] block:
40/// ```compile_fail
41/// let b: Ghost<i32> = Ghost::new(1);
42/// ghost! {
43///     let value: i32 = b.into_inner();
44///     // use value here
45/// }
46/// let value: i32 = b.into_inner(); // compile error !
47/// ```
48#[opaque]
49#[intrinsic("ghost")]
50
51pub struct Ghost<T: ?Sized>(PhantomData<T>);
52
53impl<T: Copy> Copy for Ghost<T> {}
54
55// FIXME: we would like to have an instance that does not require T: Copy, but it would
56// require the underlying clone instance to be #[check(ghost)], which we cannot require in general
57impl<T: Clone + Copy> Clone for Ghost<T> {
58    #[check(ghost)]
59    #[ensures(result == *self)]
60    fn clone(&self) -> Self {
61        ghost!(**self)
62    }
63}
64
65impl<T: ?Sized> Deref for Ghost<T> {
66    type Target = T;
67
68    /// This function can only be called in `ghost!` context
69    #[trusted]
70    #[check(ghost)]
71    #[requires(false)] // If called from generic context, false precondition
72    #[ensures(result == &**self)]
73    #[intrinsic("ghost_deref")]
74    fn deref(&self) -> &Self::Target {
75        panic!()
76    }
77}
78impl<T: ?Sized> DerefMut for Ghost<T> {
79    /// This function can only be called in `ghost!` context
80    #[trusted]
81    #[check(ghost)]
82    #[requires(false)] // If called from generic context, false precondition
83    #[ensures(result == &mut **self)]
84    #[intrinsic("ghost_deref_mut")]
85    fn deref_mut(&mut self) -> &mut Self::Target {
86        panic!()
87    }
88}
89
90impl<T: ?Sized + Fin> Fin for Ghost<T> {
91    type Target = T::Target;
92
93    #[logic(open, prophetic, inline)]
94    fn fin<'a>(self) -> &'a Self::Target {
95        pearlite! { &^*self }
96    }
97}
98
99impl<T: ?Sized> Invariant for Ghost<T> {
100    #[logic(open, prophetic, inline)]
101    #[creusot::trusted_trivial_if_param_trivial]
102    fn invariant(self) -> bool {
103        inv(*self)
104    }
105}
106
107impl<T: ?Sized> Ghost<T> {
108    /// Transforms a `&Ghost<T>` into `Ghost<&T>`
109    #[trusted]
110    #[erasure(_)]
111    #[check(ghost)]
112    #[ensures(**result == **self)]
113    pub fn borrow(&self) -> Ghost<&T> {
114        Ghost::conjure()
115    }
116
117    /// Transforms a `&mut Ghost<T>` into a `Ghost<&mut T>`.
118    #[trusted]
119    #[erasure(_)]
120    #[check(ghost)]
121    #[ensures(*result == &mut **self)]
122    pub fn borrow_mut(&mut self) -> Ghost<&mut T> {
123        Ghost::conjure()
124    }
125
126    /// Conjures a `Ghost<T>` out of thin air.
127    ///
128    /// This would be unsound in verified code, hence the `false` precondition.
129    /// This function is nevertheless useful to create a `Ghost` in "trusted"
130    /// contexts, when axiomatizing an API that is believed to be sound for
131    /// external reasons.
132    #[trusted]
133    #[erasure(_)]
134    #[check(ghost)]
135    #[requires(false)]
136    pub fn conjure() -> Self {
137        Ghost(PhantomData)
138    }
139
140    // Internal function to easily create a `Ghost` in non-creusot mode.
141    #[cfg(not(creusot))]
142    #[doc(hidden)]
143    pub fn from_fn(_: impl FnOnce() -> T) -> Self {
144        Ghost::conjure()
145    }
146}
147
148impl<T: ?Sized> Ghost<T> {
149    /// Creates a new ghost variable.
150    ///
151    /// This function can only be called in `ghost!` code.
152    #[trusted]
153    #[check(ghost)]
154    #[ensures(*result == x)]
155    #[intrinsic("ghost_new")]
156    pub fn new(x: T) -> Self
157    where
158        T: Sized,
159    {
160        let _ = x;
161        panic!()
162    }
163
164    #[trusted]
165    #[logic(opaque)]
166    #[ensures(*result == x)]
167    pub fn new_logic(x: T) -> Self {
168        dead
169    }
170
171    /// Returns the inner value of the `Ghost`.
172    ///
173    /// This function can only be called in `ghost!` context.
174    #[trusted]
175    #[check(ghost)]
176    #[ensures(result == *self)]
177    #[intrinsic("ghost_into_inner")]
178    pub fn into_inner(self) -> T
179    where
180        T: Sized,
181    {
182        panic!()
183    }
184
185    /// Returns the inner value of the `Ghost`.
186    ///
187    /// You should prefer the dereference operator `*` instead.
188    #[logic]
189    #[builtin("identity")]
190    pub fn inner_logic(self) -> T
191    where
192        T: Sized,
193    {
194        dead
195    }
196}
197
198impl<T, U: ?Sized> Ghost<(T, U)> {
199    #[check(ghost)]
200    #[trusted]
201    #[erasure(_)]
202    #[ensures((*self).0 == *result.0)]
203    #[ensures((*self).1 == *result.1)]
204    pub fn split(self) -> (Ghost<T>, Ghost<U>) {
205        (Ghost::conjure(), Ghost::conjure())
206    }
207}
208
209/// A marker trait for types that can be extracted from snapshots in ghost code.
210/// These are type that only contain plain data and whose onership does not convey
211/// any additional information.
212///
213/// For example, Booleans and integers are plain, but references are not, be they
214/// mutable or not. Indeed, the ownership of a shared reference can be used to deduce
215/// facts, for example with `Perm::disjoint_lemma`.
216#[trusted]
217pub trait Plain: Copy {}
218
219#[trusted]
220impl Plain for bool {}
221
222#[trusted]
223impl<T> Plain for *const T {}
224
225#[trusted]
226impl<T> Plain for *mut T {}
227
228/// Wrapper around a single atomic operation, where multiple ghost steps can be
229/// performed.
230#[opaque]
231pub struct Committer;
232
233impl Committer {
234    /// Status of the committer
235    #[logic(opaque)]
236    pub fn shot(self) -> bool {
237        dead
238    }
239
240    /// Identity of the committer
241    ///
242    /// This is used so that we can only use the committer with the right [`AtomicOwn`].
243    #[logic(opaque)]
244    #[cfg(feature = "std")]
245    pub fn ward(self) -> crate::std::sync::AtomicI32 {
246        dead
247    }
248
249    /// Value held by the [`AtomicOwn`], before the [`shoot`].
250    #[logic(opaque)]
251    pub fn old_value(self) -> i32 {
252        dead
253    }
254
255    /// Value held by the [`AtomicOwn`], after the [`shoot`].
256    #[logic(opaque)]
257    pub fn new_value(self) -> i32 {
258        dead
259    }
260
261    /// 'Shoot' the committer
262    ///
263    /// This does the write on the atomic in ghost code, and can only be called once.
264    #[requires(!self.shot())]
265    #[requires(self.ward() == *own.ward())]
266    #[ensures((^self).shot())]
267    #[ensures((^own).ward() == (*own).ward())]
268    #[ensures(*(*own).val() == (*self).old_value())]
269    #[ensures(*(^own).val() == (*self).new_value())]
270    #[check(ghost)]
271    #[trusted]
272    #[allow(unused_variables)]
273    #[cfg(feature = "std")]
274    pub fn shoot(&mut self, own: &mut perm::Perm<crate::std::sync::AtomicI32>) {
275        panic!("Should not be called outside ghost code")
276    }
277}