1#![cfg_attr(kani, feature(stmt_expr_attributes))]
4#![cfg_attr(kani, feature(proc_macro_hygiene))]
5
6#[cfg(not(creusot))]
7pub mod live;
8
9#[cfg(not(creusot))]
10pub mod verified;
11
12#[cfg(creusot)]
13pub mod creusot_rt;
14
15use std::{alloc::Layout, marker::PhantomData};
16
17#[cfg(creusot)]
18use creusot_std::model::DeepModel;
19
20#[cfg(creusot)]
21use creusot_std::macros::{ensures, logic, requires};
22
23#[cfg(creusot)]
24use creusot_std::prelude::trusted;
25
26#[cfg(creusot)]
27pub type VLayout = creusot_rt::CLayout;
28
29#[cfg(creusot)]
30pub type VLayoutError = creusot_rt::CLayoutError;
31
32#[cfg(not(creusot))]
33pub use verified::{VLayout, VLayoutError};
34
35pub trait IRuntime {
37 type Shape: IShape;
38 type Heap: IHeap<Self::Shape, Ptr: IPtr>;
39 type Arena<T>: IArena<T>;
40
41 fn heap() -> Self::Heap;
42 fn arena<T>() -> Self::Arena<T>;
43}
44
45#[cfg(not(creusot))]
47pub trait LiveRuntime:
48 IRuntime<Shape = &'static facet_core::Shape, Heap: IHeap<&'static facet_core::Shape, Ptr = *mut u8>>
49{
50}
51
52#[cfg(not(creusot))]
53impl<T> LiveRuntime for T where
54 T: IRuntime<
55 Shape = &'static facet_core::Shape,
56 Heap: IHeap<&'static facet_core::Shape, Ptr = *mut u8>,
57 >
58{
59}
60
61pub trait IShapeStore: Clone {
67 type Handle: Copy;
69
70 type View<'a>: IShape
72 where
73 Self: 'a;
74
75 fn get<'a>(&'a self, handle: Self::Handle) -> Self::View<'a>;
77}
78
79#[cfg(creusot)]
80pub trait IShapeExtra: DeepModel {
81 #[logic]
82 fn size_logic(self) -> usize;
83}
84
85#[cfg(creusot)]
86impl<T: DeepModel> IShapeExtra for T {
87 #[logic(opaque)]
88 fn size_logic(self) -> usize {
89 dead
90 }
91}
92
93#[cfg(not(creusot))]
94pub trait IShapeExtra {}
95
96#[cfg(not(creusot))]
97impl<T> IShapeExtra for T {}
98
99pub trait IShape: Copy + PartialEq + IShapeExtra {
106 type StructType: IStructType<Field = Self::Field>;
108
109 type Field: IField<Shape = Self>;
111
112 fn layout(&self) -> Option<Layout>;
116
117 fn is_struct(&self) -> bool;
119
120 fn as_struct(&self) -> Option<Self::StructType>;
122}
123
124pub trait IStructType: Copy {
126 type Field: IField;
128
129 fn field_count(&self) -> usize;
131
132 fn field(&self, idx: usize) -> Option<Self::Field>;
134}
135
136pub trait IField: Copy {
138 type Shape: IShape;
140
141 fn offset(&self) -> usize;
143
144 fn shape(&self) -> Self::Shape;
146}
147
148pub trait IHeap<S: IShape> {
154 type Ptr: IPtr;
156
157 unsafe fn alloc(&mut self, shape: S) -> Self::Ptr;
163
164 unsafe fn dealloc(&mut self, ptr: Self::Ptr, shape: S);
171
172 #[cfg_attr(creusot, requires(self.range_init(src, len)))]
179 #[cfg_attr(creusot, ensures(self.range_init(dst, len)))]
180 #[cfg_attr(creusot, ensures(forall<ptr2, shape2> ptr2 != dst ==> (^self).can_drop(ptr2, shape2) == (*self).can_drop(ptr2, shape2)))]
181 #[cfg_attr(creusot, ensures(forall<ptr2, range2> ptr2 != dst ==> (^self).range_init(ptr2, range2) == (*self).range_init(ptr2, range2)))]
182 unsafe fn memcpy(&mut self, dst: Self::Ptr, src: Self::Ptr, len: usize);
183
184 #[cfg_attr(creusot, requires(self.can_drop(ptr, shape)))]
190 #[cfg_attr(creusot, ensures(!(^self).can_drop(ptr, shape) && !(^self).range_init(ptr, shape.size_logic())))]
191 #[cfg_attr(creusot, ensures(forall<ptr2, shape2> ptr2 != ptr ==> (^self).can_drop(ptr2, shape2) == (*self).can_drop(ptr2, shape2)))]
192 #[cfg_attr(creusot, ensures(forall<ptr2, range2> ptr2 != ptr ==> (^self).range_init(ptr2, range2) == (*self).range_init(ptr2, range2)))]
193 unsafe fn drop_in_place(&mut self, ptr: Self::Ptr, shape: S);
194
195 #[cfg(creusot)]
197 #[logic]
198 fn can_drop(&self, ptr: Self::Ptr, shape: S) -> bool;
199
200 #[cfg(creusot)]
204 #[logic]
205 fn range_init(&self, ptr: Self::Ptr, len: usize) -> bool;
206
207 #[cfg_attr(creusot, ensures(result ==> self.can_drop(ptr, shape) && self.range_init(ptr, shape.size_logic())))]
215 #[cfg_attr(creusot, ensures(!result ==> (^self).can_drop(ptr, shape) == (*self).can_drop(ptr, shape)))]
216 #[cfg_attr(creusot, ensures(!result ==> (^self).range_init(ptr, shape.size_logic()) == (*self).range_init(ptr, shape.size_logic())))]
217 #[cfg_attr(creusot, ensures(forall<ptr2, shape2> ptr2 != ptr ==> (^self).can_drop(ptr2, shape2) == (*self).can_drop(ptr2, shape2)))]
218 #[cfg_attr(creusot, ensures(forall<ptr2, range2> ptr2 != ptr ==> (^self).range_init(ptr2, range2) == (*self).range_init(ptr2, range2)))]
219 unsafe fn default_in_place(&mut self, ptr: Self::Ptr, shape: S) -> bool;
220}
221
222pub trait IPtr: Copy {
224 unsafe fn byte_add(self, n: usize) -> Self;
229}
230
231#[cfg(not(creusot))]
232impl IPtr for *mut u8 {
233 #[inline]
234 unsafe fn byte_add(self, n: usize) -> Self {
235 unsafe { self.byte_add(n) }
237 }
238}
239
240pub trait IArena<T> {
246 fn alloc(&mut self, value: T) -> Idx<T>;
248
249 fn free(&mut self, id: Idx<T>) -> T;
254
255 #[cfg_attr(creusot, requires(self.contains(id)))]
260 #[cfg_attr(creusot, ensures(*result == self.get_logic(id)))]
261 fn get(&self, id: Idx<T>) -> &T;
262
263 #[cfg_attr(creusot, requires(self.contains(id)))]
268 #[cfg_attr(creusot, ensures(*result == (*self).get_logic(id)))]
269 #[cfg_attr(creusot, ensures(^result == (^self).get_logic(id)))]
270 #[cfg_attr(creusot, ensures((^self).contains(id)))]
271 #[cfg_attr(creusot, ensures(forall<j> j != id ==> (*self).contains(j) == (^self).contains(j)))]
272 #[cfg_attr(creusot, ensures(forall<j> j != id ==> (*self).get_logic(j) == (^self).get_logic(j)))]
273 fn get_mut(&mut self, id: Idx<T>) -> &mut T;
274
275 #[cfg(creusot)]
276 #[logic]
277 fn contains(self, id: Idx<T>) -> bool;
278
279 #[cfg(creusot)]
280 #[logic]
281 fn get_logic(self, id: Idx<T>) -> T;
282}
283
284#[derive(Debug)]
288pub struct Idx<T> {
289 pub raw: u32,
290 _ty: PhantomData<fn() -> T>,
291}
292
293#[cfg(creusot)]
294impl<T> creusot_std::model::DeepModel for Idx<T> {
295 type DeepModelTy = u32;
296
297 #[creusot_std::macros::logic(open, inline)]
298 fn deep_model(self) -> Self::DeepModelTy {
299 self.raw
300 }
301}
302
303impl<T> Clone for Idx<T> {
304 fn clone(&self) -> Self {
305 *self
306 }
307}
308
309impl<T> Copy for Idx<T> {}
310
311impl<T> PartialEq for Idx<T> {
312 #[cfg_attr(
313 creusot,
314 creusot_std::macros::ensures(result == (self.deep_model() == other.deep_model()))
315 )]
316 fn eq(&self, other: &Self) -> bool {
317 self.raw == other.raw
318 }
319}
320
321impl<T> Eq for Idx<T> {}
322
323impl<T> Idx<T> {
324 pub const fn not_started() -> Self {
326 Self {
327 raw: 0,
328 _ty: PhantomData,
329 }
330 }
331
332 pub const fn complete() -> Self {
334 Self {
335 raw: u32::MAX,
336 _ty: PhantomData,
337 }
338 }
339
340 #[cfg(not(creusot))]
342 pub const NOT_STARTED: Self = Self::not_started();
343
344 #[cfg(not(creusot))]
346 pub const COMPLETE: Self = Self::complete();
347
348 #[inline]
349 pub fn is_not_started(self) -> bool {
350 self.raw == 0
351 }
352
353 #[inline]
354 pub fn is_complete(self) -> bool {
355 self.raw == u32::MAX
356 }
357
358 #[inline]
359 pub fn is_valid(self) -> bool {
360 self.raw != 0 && self.raw != u32::MAX
361 }
362
363 #[inline]
364 pub fn same(self, other: Self) -> bool {
365 self.raw == other.raw
366 }
367
368 #[inline]
369 #[cfg_attr(creusot, trusted)]
370 fn index(self) -> usize {
371 debug_assert!(self.is_valid(), "cannot get index of sentinel");
372 self.raw as usize
373 }
374
375 fn from_raw(raw: u32) -> Self {
377 Self {
378 raw,
379 _ty: PhantomData,
380 }
381 }
382}
383
384