pub struct Body<'tcx> {
pub basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
pub local_decls: IndexVec<Local, LocalDecl>,
pub infcx: InferCtxt<'tcx>,
pub dominator_order_rank: IndexVec<BasicBlock, u32>,
fake_predecessors: IndexVec<BasicBlock, usize>,
body_with_facts: BodyWithBorrowckFacts<'tcx>,
pub local_names: UnordMap<Local, Symbol>,
}Fields§
§basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>§local_decls: IndexVec<Local, LocalDecl>§infcx: InferCtxt<'tcx>During borrow checking, rustc generates fresh region variable ids for each structurally
different position in a type. For example, given a function
fn foo<'a, 'b>(x: &'a S<'a>, y: &'b u32)
rustc will generate variables ?2 and ?3 for the universal regions 'a and 'b (the variable
?0 correspond to 'static and ?1 to the implicit lifetime of the function body). Additionally,
it will assign x type &‘?4 S<’?5>andytype&’?6 u32` (together with some constraints relating
region variables). Unfortunately, we cannot recover the exact region variables rustc used.
The exact ids picked for 'a and 'b are not too relevant to us, the important part is the regions
used in the types of x and y. To work around this, we generate fresh regions variables for
the function signature, different from the ones sued by rustc. To recover the correct regions, whenever
there’s an assignment of a refinement type T to a variable with (unrefined) Rust type S, we match
both types to infer a region substitution. For this to work, we need to give a different variable id to every
position in T. To avoid clashes, we need to use fresh ids, so we start enumerating from the last id
generated by borrow checking.
To do that, we replicate the InferCtxt use for mir typeck by generating region variables for every
region in the RegionInferenceContext. The InferCtxt is then used to generate new region variables.
The ids generated during refinement type checking are purely instrumental and temporary, they should never appear in a type bound in the environment.
Besides generating ids when checking a function’s body, we also need to generate fresh ids at function calls.
Additionally, the InferCtxt is used during type projection normalization.
dominator_order_rank: IndexVec<BasicBlock, u32>§fake_predecessors: IndexVec<BasicBlock, usize>§body_with_facts: BodyWithBorrowckFacts<'tcx>§local_names: UnordMap<Local, Symbol>Implementations§
Source§impl<'tcx> Body<'tcx>
impl<'tcx> Body<'tcx>
pub fn new( basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, local_decls: IndexVec<Local, LocalDecl>, body_with_facts: BodyWithBorrowckFacts<'tcx>, infcx: InferCtxt<'tcx>, ) -> Self
pub fn def_id(&self) -> DefId
pub fn span(&self) -> Span
pub fn inner(&self) -> &Body<'tcx>
pub fn args_iter(&self) -> impl ExactSizeIterator<Item = Local>
pub fn vars_and_temps_iter(&self) -> impl ExactSizeIterator<Item = Local>
pub fn is_join_point(&self, bb: BasicBlock) -> bool
pub fn dominators(&self) -> &Dominators<BasicBlock>
pub fn terminator_loc(&self, bb: BasicBlock) -> Location
pub fn calculate_borrows_out_of_scope_at_location( &self, ) -> FxIndexMap<Location, Vec<BorrowIndex>>
pub fn borrow_data(&self, idx: BorrowIndex) -> &BorrowData<'tcx>
pub fn rustc_body(&self) -> &Body<'tcx>
pub fn local_kind(&self, local: Local) -> LocalKind
Trait Implementations§
Auto Trait Implementations§
impl<'tcx> !Freeze for Body<'tcx>
impl<'tcx> !RefUnwindSafe for Body<'tcx>
impl<'tcx> !Send for Body<'tcx>
impl<'tcx> !Sync for Body<'tcx>
impl<'tcx> Unpin for Body<'tcx>
impl<'tcx> !UnwindSafe for Body<'tcx>
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
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> 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 more