pub enum Body {
Unstructured(ExprBody),
Structured(ExprBody),
TargetDispatch(SeqHashMap<TargetTriple, FunDeclRef>),
Extern(String),
Intrinsic {
name: String,
arg_names: Vec<Option<String>>,
},
Opaque,
Missing,
Error(Error),
}Expand description
The body of a function.
A normal function has a body that’s either structured or unstructured. These are two equivalent
representations of the same function body, which only differ in how control-flow is
represented. By default bodies are structured; passing --ullbc to Charon makes bodies
unstructured.
Besides these, some functions have virtual bodies or no body, see the doc for each variant.
Variants§
Unstructured(ExprBody)
Body represented as a control-flow graph (CFG), i.e. with numbered blocks and jumps/GOTOs
between them. This is available when passing --ullbc to Charon.
This is also the same structure as rustc’s MIR, and is in fact a direct translation of it.
Structured(ExprBody)
Body represented with structured control flow, i.e. with nested if/match/loop blocks.
This is available when --ullbc is not passed to Charon.
This structure is recovered from the unstructured body in the ullbc_to_llbc pass.
TargetDispatch(SeqHashMap<TargetTriple, FunDeclRef>)
A façade body that dispatches to one of several per-target function bodies. This is created
during multi-target merging (using --target) to represent functions that have a different
implementation across targets.
Extern(String)
Function declared in an extern { ... } block. The string is the foreign symbol name.
Intrinsic
Rust intrinsic function. This has no body and describes a “built-in” operation that must be handled by the codegen backend.
Fields
Opaque
A body that the user chose not to translate, based on opacity settings like
--include/--opaque.
Missing
A body that was not available.
These can occur when using a sysroot that doesn’t have MIR for all the standard library
functions. This is the case of the sysroot that ships with every Rust toolchain, but Charon
uses a custom-built sysroot that does. So this shouldn’t happen unless you’re passing
--sysroot to charon.
Error(Error)
We encountered an error while translating this body.
Implementations§
Source§impl Body
impl Body
pub fn is_unstructured(&self) -> bool
pub fn is_structured(&self) -> bool
pub fn is_target_dispatch(&self) -> bool
pub fn is_extern(&self) -> bool
pub fn is_intrinsic(&self) -> bool
pub fn is_opaque(&self) -> bool
pub fn is_missing(&self) -> bool
pub fn is_error(&self) -> bool
Source§impl Body
impl Body
pub fn as_unstructured(&self) -> Option<&ExprBody>
pub fn as_structured(&self) -> Option<&ExprBody>
pub fn as_target_dispatch( &self, ) -> Option<&SeqHashMap<TargetTriple, FunDeclRef>>
pub fn as_extern(&self) -> Option<&String>
pub fn as_intrinsic(&self) -> Option<(&String, &Vec<Option<String>>)>
pub fn as_opaque(&self) -> Option<()>
pub fn as_missing(&self) -> Option<()>
pub fn as_error(&self) -> Option<&Error>
Source§impl Body
impl Body
pub fn as_unstructured_mut(&mut self) -> Option<&mut ExprBody>
pub fn as_structured_mut(&mut self) -> Option<&mut ExprBody>
pub fn as_target_dispatch_mut( &mut self, ) -> Option<&mut SeqHashMap<TargetTriple, FunDeclRef>>
pub fn as_extern_mut(&mut self) -> Option<&mut String>
pub fn as_intrinsic_mut( &mut self, ) -> Option<(&mut String, &mut Vec<Option<String>>)>
pub fn as_opaque_mut(&mut self) -> Option<()>
pub fn as_missing_mut(&mut self) -> Option<()>
pub fn as_error_mut(&mut self) -> Option<&mut Error>
Source§impl Body
impl Body
pub fn to_unstructured(self) -> Option<ExprBody>
pub fn to_structured(self) -> Option<ExprBody>
pub fn to_target_dispatch(self) -> Option<SeqHashMap<TargetTriple, FunDeclRef>>
pub fn to_extern(self) -> Option<String>
pub fn to_intrinsic(self) -> Option<(String, Vec<Option<String>>)>
pub fn to_opaque(self) -> Option<()>
pub fn to_missing(self) -> Option<()>
pub fn to_error(self) -> Option<Error>
Trait Implementations§
Source§impl AstVisitable for Body
impl AstVisitable for Body
Source§fn drive<V: VisitAst>(&self, v: &mut V) -> ControlFlow<V::Break>
fn drive<V: VisitAst>(&self, v: &mut V) -> ControlFlow<V::Break>
visit_$any
method if it exists, otherwise visit_inner.Source§fn drive_mut<V: VisitAstMut>(&mut self, v: &mut V) -> ControlFlow<V::Break>
fn drive_mut<V: VisitAstMut>(&mut self, v: &mut V) -> ControlFlow<V::Break>
visit_$any
method if it exists, otherwise visit_inner.Source§fn drive_two<V: ZipAst>(&self, other: &Self, v: &mut V) -> ControlFlow<V::Break>
fn drive_two<V: ZipAst>(&self, other: &Self, v: &mut V) -> ControlFlow<V::Break>
visit_$any
method if it exists, otherwise visit_inner.Source§fn dyn_visit<T: AstVisitable>(&self, f: impl FnMut(&T))where
Self: Sized,
fn dyn_visit<T: AstVisitable>(&self, f: impl FnMut(&T))where
Self: Sized,
self, in pre-order traversal.Source§fn dyn_visit_mut<T: AstVisitable>(&mut self, f: impl FnMut(&mut T))where
Self: Sized,
fn dyn_visit_mut<T: AstVisitable>(&mut self, f: impl FnMut(&mut T))where
Self: Sized,
self, in pre-order traversal.Source§impl BodyVisitable for Body
impl BodyVisitable for Body
Source§fn drive_body<V: VisitBody>(&self, v: &mut V) -> ControlFlow<V::Break>
fn drive_body<V: VisitBody>(&self, v: &mut V) -> ControlFlow<V::Break>
visit_$any
method if it exists, otherwise visit_inner.Source§fn drive_body_mut<V: VisitBodyMut>(
&mut self,
v: &mut V,
) -> ControlFlow<V::Break>
fn drive_body_mut<V: VisitBodyMut>( &mut self, v: &mut V, ) -> ControlFlow<V::Break>
visit_$any
method if it exists, otherwise visit_inner.Source§fn dyn_visit_in_body<T: BodyVisitable>(&self, f: impl FnMut(&T))where
Self: Sized,
fn dyn_visit_in_body<T: BodyVisitable>(&self, f: impl FnMut(&T))where
Self: Sized,
self, in pre-order traversal.Source§fn dyn_visit_in_body_mut<T: BodyVisitable>(&mut self, f: impl FnMut(&mut T))where
Self: Sized,
fn dyn_visit_in_body_mut<T: BodyVisitable>(&mut self, f: impl FnMut(&mut T))where
Self: Sized,
self, in pre-order traversal.Source§impl<'de, __State: ?Sized + DedupSerializerState> DeserializeState<'de, __State> for Body
impl<'de, __State: ?Sized + DedupSerializerState> DeserializeState<'de, __State> for Body
fn deserialize_state<__D>(
__state: &__State,
__deserializer: __D,
) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl<'s, V> Drive<'s, V> for Bodywhere
V: Visitor + Visit<'s, ExprBody> + Visit<'s, ExprBody> + Visit<'s, SeqHashMap<TargetTriple, FunDeclRef>> + Visit<'s, String> + Visit<'s, Vec<Option<String>>> + Visit<'s, Error>,
impl<'s, V> Drive<'s, V> for Bodywhere
V: Visitor + Visit<'s, ExprBody> + Visit<'s, ExprBody> + Visit<'s, SeqHashMap<TargetTriple, FunDeclRef>> + Visit<'s, String> + Visit<'s, Vec<Option<String>>> + Visit<'s, Error>,
Source§fn drive_inner(&'s self, visitor: &mut V) -> ControlFlow<V::Break>
fn drive_inner(&'s self, visitor: &mut V) -> ControlFlow<V::Break>
v.visit() on the immediate contents of self.Source§impl<'s, V> DriveMut<'s, V> for Bodywhere
V: Visitor + VisitMut<'s, ExprBody> + VisitMut<'s, ExprBody> + VisitMut<'s, SeqHashMap<TargetTriple, FunDeclRef>> + VisitMut<'s, String> + VisitMut<'s, Vec<Option<String>>> + VisitMut<'s, Error>,
impl<'s, V> DriveMut<'s, V> for Bodywhere
V: Visitor + VisitMut<'s, ExprBody> + VisitMut<'s, ExprBody> + VisitMut<'s, SeqHashMap<TargetTriple, FunDeclRef>> + VisitMut<'s, String> + VisitMut<'s, Vec<Option<String>>> + VisitMut<'s, Error>,
Source§fn drive_inner_mut(&'s mut self, visitor: &mut V) -> ControlFlow<V::Break>
fn drive_inner_mut(&'s mut self, visitor: &mut V) -> ControlFlow<V::Break>
v.visit() on the immediate contents of self.Source§impl<'s, V> DriveTwo<'s, V> for Bodywhere
V: Visitor<Break: Default> + VisitTwo<'s, ExprBody> + VisitTwo<'s, ExprBody> + VisitTwo<'s, SeqHashMap<TargetTriple, FunDeclRef>> + VisitTwo<'s, String> + VisitTwo<'s, Vec<Option<String>>> + VisitTwo<'s, Error>,
impl<'s, V> DriveTwo<'s, V> for Bodywhere
V: Visitor<Break: Default> + VisitTwo<'s, ExprBody> + VisitTwo<'s, ExprBody> + VisitTwo<'s, SeqHashMap<TargetTriple, FunDeclRef>> + VisitTwo<'s, String> + VisitTwo<'s, Vec<Option<String>>> + VisitTwo<'s, Error>,
Source§fn drive_two_inner(
&'s self,
other: &'s Self,
visitor: &mut V,
) -> ControlFlow<V::Break>
fn drive_two_inner( &'s self, other: &'s Self, visitor: &mut V, ) -> ControlFlow<V::Break>
v.visit() on the immediate contents of self and other, if they correspond. If
the values don’t match up, this returns Break(Default::default()).Source§impl<C: AstFormatter> FmtWithCtx<C> for Body
impl<C: AstFormatter> FmtWithCtx<C> for Body
Source§impl<__State: ?Sized + DedupSerializerState> SerializeState<__State> for Body
impl<__State: ?Sized + DedupSerializerState> SerializeState<__State> for Body
fn serialize_state<__S>(
&self,
__state: &__State,
__serializer: __S,
) -> Result<__S::Ok, __S::Error>where
__S: Serializer,
Auto Trait Implementations§
impl Freeze for Body
impl RefUnwindSafe for Body
impl Send for Body
impl Sync for Body
impl Unpin for Body
impl UnsafeUnpin for Body
impl UnwindSafe for Body
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreimpl<T> Mappable for T
Source§impl<T> TyVisitable for Twhere
T: AstVisitable,
impl<T> TyVisitable for Twhere
T: AstVisitable,
Source§fn visit_vars(&mut self, v: &mut impl VarsVisitor)
fn visit_vars(&mut self, v: &mut impl VarsVisitor)
self, as seen from the outside of self. This means
that any variable bound inside self will be skipped, and all the seen De Bruijn indices
will count from the outside of self.Source§fn substitute(self, generics: &GenericArgs) -> Self
fn substitute(self, generics: &GenericArgs) -> Self
self by replacing them with the provided values.
Note: if self is an item that comes from a TraitDecl, you must use
substitute_with_self or substitute_inner_binder, otherwise you’ll get panics.Source§fn substitute_inner_binder(self, generics: &GenericArgs) -> Self
fn substitute_inner_binder(self, generics: &GenericArgs) -> Self
self by replacing them with the provided values.
This is appropriate when substituting an inner binder.Source§fn substitute_explicits(self, generics: &GenericArgs) -> Self
fn substitute_explicits(self, generics: &GenericArgs) -> Self
Source§fn substitute_with_self(
self,
generics: &GenericArgs,
self_ref: &TraitRefKind,
) -> Self
fn substitute_with_self( self, generics: &GenericArgs, self_ref: &TraitRefKind, ) -> Self
TraitRefKind::SelfId trait ref.Source§fn substitute_with_tref(self, tref: &TraitRef) -> Self
fn substitute_with_tref(self, tref: &TraitRef) -> Self
TraitRefKind::SelfId trait ref.Source§fn try_substitute_with_tref(
self,
tref: &TraitRef,
) -> Result<Self, GenericsMismatch>
fn try_substitute_with_tref( self, tref: &TraitRef, ) -> Result<Self, GenericsMismatch>
TraitRefKind::SelfId trait ref.fn try_substitute( self, generics: &GenericArgs, ) -> Result<Self, GenericsMismatch>
fn try_substitute_with_self( self, generics: &GenericArgs, self_ref: &TraitRefKind, ) -> Result<Self, GenericsMismatch>
Source§fn move_under_binder(self) -> Self
fn move_under_binder(self) -> Self
Source§fn move_under_binders(self, depth: DeBruijnId) -> Self
fn move_under_binders(self, depth: DeBruijnId) -> Self
depth binders.Source§fn move_from_under_binder(self) -> Option<Self>
fn move_from_under_binder(self) -> Option<Self>
Source§fn move_from_under_binders(self, depth: DeBruijnId) -> Option<Self>
fn move_from_under_binders(self, depth: DeBruijnId) -> Option<Self>
depth binders. Returns None if it contains a variable bound in
one of these depth binders.Source§fn visit_db_id<B>(
&mut self,
f: impl FnMut(&mut DeBruijnId) -> ControlFlow<B>,
) -> ControlFlow<B>
fn visit_db_id<B>( &mut self, f: impl FnMut(&mut DeBruijnId) -> ControlFlow<B>, ) -> ControlFlow<B>
self, as seen from the outside of self. This means
that any variable bound inside self will be skipped, and all the seen indices will count
from the outside of self.