#![cfg_attr(kani, feature(stmt_expr_attributes))]
#![cfg_attr(kani, feature(proc_macro_hygiene))]
#[cfg(not(creusot))]
pub mod live;
#[cfg(not(creusot))]
pub mod verified;
#[cfg(creusot)]
pub mod creusot_rt;
use std::{alloc::Layout, marker::PhantomData};
#[cfg(creusot)]
use creusot_std::model::DeepModel;
#[cfg(creusot)]
use creusot_std::macros::{ensures, logic, requires};
#[cfg(creusot)]
use creusot_std::prelude::trusted;
#[cfg(creusot)]
pub type VLayout = creusot_rt::CLayout;
#[cfg(creusot)]
pub type VLayoutError = creusot_rt::CLayoutError;
#[cfg(not(creusot))]
pub use verified::{VLayout, VLayoutError};
pub trait IRuntime {
type Shape: IShape;
type Heap: IHeap<Self::Shape, Ptr: IPtr>;
type Arena<T>: IArena<T>;
fn heap() -> Self::Heap;
fn arena<T>() -> Self::Arena<T>;
}
#[cfg(not(creusot))]
pub trait LiveRuntime:
IRuntime<Shape = &'static facet_core::Shape, Heap: IHeap<&'static facet_core::Shape, Ptr = *mut u8>>
{
}
#[cfg(not(creusot))]
impl<T> LiveRuntime for T where
T: IRuntime<
Shape = &'static facet_core::Shape,
Heap: IHeap<&'static facet_core::Shape, Ptr = *mut u8>,
>
{
}
pub trait IShapeStore: Clone {
type Handle: Copy;
type View<'a>: IShape
where
Self: 'a;
fn get<'a>(&'a self, handle: Self::Handle) -> Self::View<'a>;
}
#[cfg(creusot)]
pub trait IShapeExtra: DeepModel {
#[logic]
fn size_logic(self) -> usize;
}
#[cfg(creusot)]
impl<T: DeepModel> IShapeExtra for T {
#[logic(opaque)]
fn size_logic(self) -> usize {
dead
}
}
#[cfg(not(creusot))]
pub trait IShapeExtra {}
#[cfg(not(creusot))]
impl<T> IShapeExtra for T {}
pub trait IShape: Copy + PartialEq + IShapeExtra {
type StructType: IStructType<Field = Self::Field>;
type Field: IField<Shape = Self>;
fn layout(&self) -> Option<Layout>;
fn is_struct(&self) -> bool;
fn as_struct(&self) -> Option<Self::StructType>;
}
pub trait IStructType: Copy {
type Field: IField;
fn field_count(&self) -> usize;
fn field(&self, idx: usize) -> Option<Self::Field>;
}
pub trait IField: Copy {
type Shape: IShape;
fn offset(&self) -> usize;
fn shape(&self) -> Self::Shape;
}
pub trait IHeap<S: IShape> {
type Ptr: IPtr;
unsafe fn alloc(&mut self, shape: S) -> Self::Ptr;
unsafe fn dealloc(&mut self, ptr: Self::Ptr, shape: S);
#[cfg_attr(creusot, requires(self.range_init(src, len)))]
#[cfg_attr(creusot, ensures(self.range_init(dst, len)))]
#[cfg_attr(creusot, ensures(forall<ptr2, shape2> ptr2 != dst ==> (^self).can_drop(ptr2, shape2) == (*self).can_drop(ptr2, shape2)))]
#[cfg_attr(creusot, ensures(forall<ptr2, range2> ptr2 != dst ==> (^self).range_init(ptr2, range2) == (*self).range_init(ptr2, range2)))]
unsafe fn memcpy(&mut self, dst: Self::Ptr, src: Self::Ptr, len: usize);
#[cfg_attr(creusot, requires(self.can_drop(ptr, shape)))]
#[cfg_attr(creusot, ensures(!(^self).can_drop(ptr, shape) && !(^self).range_init(ptr, shape.size_logic())))]
#[cfg_attr(creusot, ensures(forall<ptr2, shape2> ptr2 != ptr ==> (^self).can_drop(ptr2, shape2) == (*self).can_drop(ptr2, shape2)))]
#[cfg_attr(creusot, ensures(forall<ptr2, range2> ptr2 != ptr ==> (^self).range_init(ptr2, range2) == (*self).range_init(ptr2, range2)))]
unsafe fn drop_in_place(&mut self, ptr: Self::Ptr, shape: S);
#[cfg(creusot)]
#[logic]
fn can_drop(&self, ptr: Self::Ptr, shape: S) -> bool;
#[cfg(creusot)]
#[logic]
fn range_init(&self, ptr: Self::Ptr, len: usize) -> bool;
#[cfg_attr(creusot, ensures(result ==> self.can_drop(ptr, shape) && self.range_init(ptr, shape.size_logic())))]
#[cfg_attr(creusot, ensures(!result ==> (^self).can_drop(ptr, shape) == (*self).can_drop(ptr, shape)))]
#[cfg_attr(creusot, ensures(!result ==> (^self).range_init(ptr, shape.size_logic()) == (*self).range_init(ptr, shape.size_logic())))]
#[cfg_attr(creusot, ensures(forall<ptr2, shape2> ptr2 != ptr ==> (^self).can_drop(ptr2, shape2) == (*self).can_drop(ptr2, shape2)))]
#[cfg_attr(creusot, ensures(forall<ptr2, range2> ptr2 != ptr ==> (^self).range_init(ptr2, range2) == (*self).range_init(ptr2, range2)))]
unsafe fn default_in_place(&mut self, ptr: Self::Ptr, shape: S) -> bool;
}
pub trait IPtr: Copy {
unsafe fn byte_add(self, n: usize) -> Self;
}
#[cfg(not(creusot))]
impl IPtr for *mut u8 {
#[inline]
unsafe fn byte_add(self, n: usize) -> Self {
unsafe { self.byte_add(n) }
}
}
pub trait IArena<T> {
fn alloc(&mut self, value: T) -> Idx<T>;
fn free(&mut self, id: Idx<T>) -> T;
#[cfg_attr(creusot, requires(self.contains(id)))]
#[cfg_attr(creusot, ensures(*result == self.get_logic(id)))]
fn get(&self, id: Idx<T>) -> &T;
#[cfg_attr(creusot, requires(self.contains(id)))]
#[cfg_attr(creusot, ensures(*result == (*self).get_logic(id)))]
#[cfg_attr(creusot, ensures(^result == (^self).get_logic(id)))]
#[cfg_attr(creusot, ensures((^self).contains(id)))]
#[cfg_attr(creusot, ensures(forall<j> j != id ==> (*self).contains(j) == (^self).contains(j)))]
#[cfg_attr(creusot, ensures(forall<j> j != id ==> (*self).get_logic(j) == (^self).get_logic(j)))]
fn get_mut(&mut self, id: Idx<T>) -> &mut T;
#[cfg(creusot)]
#[logic]
fn contains(self, id: Idx<T>) -> bool;
#[cfg(creusot)]
#[logic]
fn get_logic(self, id: Idx<T>) -> T;
}
#[derive(Debug)]
pub struct Idx<T> {
pub raw: u32,
_ty: PhantomData<fn() -> T>,
}
#[cfg(creusot)]
impl<T> creusot_std::model::DeepModel for Idx<T> {
type DeepModelTy = u32;
#[creusot_std::macros::logic(open, inline)]
fn deep_model(self) -> Self::DeepModelTy {
self.raw
}
}
impl<T> Clone for Idx<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Idx<T> {}
impl<T> PartialEq for Idx<T> {
#[cfg_attr(
creusot,
creusot_std::macros::ensures(result == (self.deep_model() == other.deep_model()))
)]
fn eq(&self, other: &Self) -> bool {
self.raw == other.raw
}
}
impl<T> Eq for Idx<T> {}
impl<T> Idx<T> {
pub const fn not_started() -> Self {
Self {
raw: 0,
_ty: PhantomData,
}
}
pub const fn complete() -> Self {
Self {
raw: u32::MAX,
_ty: PhantomData,
}
}
#[cfg(not(creusot))]
pub const NOT_STARTED: Self = Self::not_started();
#[cfg(not(creusot))]
pub const COMPLETE: Self = Self::complete();
#[inline]
pub fn is_not_started(self) -> bool {
self.raw == 0
}
#[inline]
pub fn is_complete(self) -> bool {
self.raw == u32::MAX
}
#[inline]
pub fn is_valid(self) -> bool {
self.raw != 0 && self.raw != u32::MAX
}
#[inline]
pub fn same(self, other: Self) -> bool {
self.raw == other.raw
}
#[inline]
#[cfg_attr(creusot, trusted)]
fn index(self) -> usize {
debug_assert!(self.is_valid(), "cannot get index of sentinel");
self.raw as usize
}
fn from_raw(raw: u32) -> Self {
Self {
raw,
_ty: PhantomData,
}
}
}