creusot_contracts/
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_contracts::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 std::{
20    marker::PhantomData,
21    ops::{Deref, DerefMut},
22};
23
24mod fn_ghost;
25pub mod local_invariant;
26mod ptr_own;
27pub mod resource;
28pub use fn_ghost::{FnGhost, FnGhostWrapper};
29pub use ptr_own::PtrOwn;
30
31/// A type that can be used in [`ghost!`] context.
32///
33/// This type may be used to make more complicated proofs possible. In particular, some
34/// proof may need a notion of non-duplicable token to carry around.
35///
36/// Conceptually, a `Ghost<T>` is an object of type `T` that resides in a special "ghost"
37/// heap. This heap is inaccessible from normal code, and `Ghost` values cannot be used
38/// to influence the behavior of normal code.
39///
40/// This box can be accessed in a [`ghost!`] block:
41/// ```compile_fail
42/// let b: Ghost<i32> = Ghost::new(1);
43/// ghost! {
44///     let value: i32 = b.into_inner();
45///     // use value here
46/// }
47/// let value: i32 = b.into_inner(); // compile error !
48/// ```
49#[opaque]
50#[intrinsic("ghost")]
51
52pub struct Ghost<T: ?Sized>(PhantomData<T>);
53
54impl<T: Copy> Copy for Ghost<T> {}
55
56// FIXME: we would like to have an instance that does not require T: Copy, but it would
57// require the underlying clone instance to be #[check(ghost)], which we cannot require in general
58impl<T: Clone + Copy> Clone for Ghost<T> {
59    #[check(ghost)]
60    #[ensures(result == *self)]
61    fn clone(&self) -> Self {
62        ghost!(**self)
63    }
64}
65
66impl<T: ?Sized> Deref for Ghost<T> {
67    type Target = T;
68
69    /// This function can only be called in `ghost!` context
70    #[trusted]
71    #[check(ghost)]
72    #[requires(false)] // If called from generic context, false precondition
73    #[ensures(result == &**self)]
74    #[intrinsic("ghost_deref")]
75    fn deref(&self) -> &Self::Target {
76        panic!()
77    }
78}
79impl<T: ?Sized> DerefMut for Ghost<T> {
80    /// This function can only be called in `ghost!` context
81    #[trusted]
82    #[check(ghost)]
83    #[requires(false)] // If called from generic context, false precondition
84    #[ensures(result == &mut **self)]
85    #[intrinsic("ghost_deref_mut")]
86    fn deref_mut(&mut self) -> &mut Self::Target {
87        panic!()
88    }
89}
90
91impl<T: ?Sized + Fin> Fin for Ghost<T> {
92    type Target = T::Target;
93
94    #[logic(open, prophetic, inline)]
95    fn fin<'a>(self) -> &'a Self::Target {
96        pearlite! { &^*self }
97    }
98}
99
100impl<T: ?Sized> Invariant for Ghost<T> {
101    #[logic(open, prophetic, inline)]
102    #[creusot::trusted_trivial_if_param_trivial]
103    fn invariant(self) -> bool {
104        inv(*self)
105    }
106}
107
108impl<T: ?Sized> Ghost<T> {
109    /// Transforms a `&Ghost<T>` into `Ghost<&T>`
110    #[trusted]
111    #[erasure(_)]
112    #[check(ghost)]
113    #[ensures(**result == **self)]
114    pub fn borrow(&self) -> Ghost<&T> {
115        Ghost::conjure()
116    }
117
118    /// Transforms a `&mut Ghost<T>` into a `Ghost<&mut T>`.
119    #[trusted]
120    #[erasure(_)]
121    #[check(ghost)]
122    #[ensures(*result == &mut **self)]
123    pub fn borrow_mut(&mut self) -> Ghost<&mut T> {
124        Ghost::conjure()
125    }
126
127    /// Conjures a `Ghost<T>` out of thin air.
128    ///
129    /// This would be unsound in verified code, hence the `false` precondition.
130    /// This function is nevertheless useful to create a `Ghost` in "trusted"
131    /// contexts, when axiomatizing an API that is believed to be sound for
132    /// external reasons.
133    #[trusted]
134    #[erasure(_)]
135    #[check(ghost)]
136    #[requires(false)]
137    pub fn conjure() -> Self {
138        Ghost(PhantomData)
139    }
140
141    // Internal function to easily create a `Ghost` in non-creusot mode.
142    #[cfg(not(creusot))]
143    #[doc(hidden)]
144    pub fn from_fn(_: impl FnOnce() -> T) -> Self {
145        Ghost::conjure()
146    }
147}
148
149impl<T: ?Sized> Ghost<T> {
150    /// Creates a new ghost variable.
151    ///
152    /// This function can only be called in `ghost!` code.
153    #[trusted]
154    #[check(ghost)]
155    #[ensures(*result == x)]
156    #[intrinsic("ghost_new")]
157    pub fn new(x: T) -> Self
158    where
159        T: Sized,
160    {
161        let _ = x;
162        panic!()
163    }
164
165    #[trusted]
166    #[logic(opaque)]
167    #[ensures(*result == x)]
168    pub fn new_logic(x: T) -> Self {
169        dead
170    }
171
172    /// Returns the inner value of the `Ghost`.
173    ///
174    /// This function can only be called in `ghost!` context.
175    #[trusted]
176    #[check(ghost)]
177    #[ensures(result == *self)]
178    #[intrinsic("ghost_into_inner")]
179    pub fn into_inner(self) -> T
180    where
181        T: Sized,
182    {
183        panic!()
184    }
185
186    /// Returns the inner value of the `Ghost`.
187    ///
188    /// You should prefer the dereference operator `*` instead.
189    #[logic]
190    #[builtin("identity")]
191    pub fn inner_logic(self) -> T
192    where
193        T: Sized,
194    {
195        dead
196    }
197}
198
199impl<T, U: ?Sized> Ghost<(T, U)> {
200    #[check(ghost)]
201    #[trusted]
202    #[erasure(_)]
203    #[ensures((*self).0 == *result.0)]
204    #[ensures((*self).1 == *result.1)]
205    pub fn split(self) -> (Ghost<T>, Ghost<U>) {
206        (Ghost::conjure(), Ghost::conjure())
207    }
208}
209
210/// A marker trait for types that can be extracted from snapshots in ghost code.
211/// These are type that only contain plain data and whose onership does not convey
212/// any additional information.
213///
214/// For example, Booleans and integers are plain, but references are not, be they
215/// mutable or not. Indeed, the ownership of a shared reference can be used to deduce
216/// facts, for example with `PtrOwn::disjoint_lemma`.
217#[trusted]
218pub trait Plain: Copy {}
219
220#[trusted]
221impl Plain for bool {}
222
223#[trusted]
224impl<T> Plain for *const T {}
225
226#[trusted]
227impl<T> Plain for *mut T {}