pub(crate) struct LocalAnalysis<'tcx, 'a> {
pub(crate) memo: &'a MemoPdgConstructor<'tcx>,
pub(crate) root: Instance<'tcx>,
body_with_facts: &'tcx CachedBody<'tcx>,
pub(crate) mono_body: Body<'tcx>,
pub(crate) def_id: DefId,
pub(crate) place_info: PlaceInfo<'tcx>,
control_dependencies: ControlDependencies<BasicBlock>,
pub(crate) body_assignments: BodyAssignments,
start_loc: FxHashSet<RichLocation>,
}
Fields§
§memo: &'a MemoPdgConstructor<'tcx>
§root: Instance<'tcx>
§body_with_facts: &'tcx CachedBody<'tcx>
§mono_body: Body<'tcx>
§def_id: DefId
§place_info: PlaceInfo<'tcx>
§control_dependencies: ControlDependencies<BasicBlock>
§body_assignments: BodyAssignments
§start_loc: FxHashSet<RichLocation>
Implementations§
Source§impl<'tcx, 'a> LocalAnalysis<'tcx, 'a>
impl<'tcx, 'a> LocalAnalysis<'tcx, 'a>
Sourcepub(crate) fn can_approximate_async_functions(
&self,
def_id: DefId,
) -> Option<fn(_: &LocalAnalysis<'tcx, 'a>, _: &mut dyn Visitor<'tcx>, _: ArgSlice<'a, 'tcx>, _: Place<'tcx>, _: Location)>
pub(crate) fn can_approximate_async_functions( &self, def_id: DefId, ) -> Option<fn(_: &LocalAnalysis<'tcx, 'a>, _: &mut dyn Visitor<'tcx>, _: ArgSlice<'a, 'tcx>, _: Place<'tcx>, _: Location)>
Special case behavior for calls to functions used in desugaring async functions.
Ensures that functions like Pin::new_unchecked
are not modularly-approximated.
fn approximate_into_future( &self, vis: &mut dyn Visitor<'tcx>, args: ArgSlice<'_, 'tcx>, destination: Place<'tcx>, location: Location, )
fn approximate_new_unchecked( &self, vis: &mut dyn Visitor<'tcx>, args: ArgSlice<'_, 'tcx>, destination: Place<'tcx>, location: Location, )
Source§impl<'tcx> LocalAnalysis<'tcx, '_>
impl<'tcx> LocalAnalysis<'tcx, '_>
Sourcepub(crate) fn try_poll_call_kind<'a>(
&'a self,
def_id: DefId,
resolved_fn: Instance<'tcx>,
original_args: ArgSlice<'a, 'tcx>,
) -> AsyncDeterminationResult<CallKind<'tcx>>
pub(crate) fn try_poll_call_kind<'a>( &'a self, def_id: DefId, resolved_fn: Instance<'tcx>, original_args: ArgSlice<'a, 'tcx>, ) -> AsyncDeterminationResult<CallKind<'tcx>>
Checks whether the function call, described by the unresolved def_id
and the resolved instance resolved_fn
is a call to <T as Future>::poll
where T
is the type of an
async fn
or async {}
created generator.
Resolves the original arguments that constituted the generator.
Sourcefn find_async_args<'a>(
&'a self,
args: ArgSlice<'a, 'tcx>,
) -> Result<AsyncFnPollEnv<'tcx>, String>
fn find_async_args<'a>( &'a self, args: ArgSlice<'a, 'tcx>, ) -> Result<AsyncFnPollEnv<'tcx>, String>
Given the arguments to a Future::poll
call, walk back through the
body to find the original future being polled, and get the arguments to the future.
Source§impl<'tcx, 'a> LocalAnalysis<'tcx, 'a>
impl<'tcx, 'a> LocalAnalysis<'tcx, 'a>
Sourcepub(crate) fn new(
memo: &'a MemoPdgConstructor<'tcx>,
root: Instance<'tcx>,
) -> LocalAnalysis<'tcx, 'a>
pub(crate) fn new( memo: &'a MemoPdgConstructor<'tcx>, root: Instance<'tcx>, ) -> LocalAnalysis<'tcx, 'a>
Creates [GraphConstructor
] for a function resolved as fn_resolution
in a given calling_context
.
Returns None
, if we were unable to load the body.
fn make_dep_node( &self, place: Place<'tcx>, location: impl Into<RichLocation>, ) -> DepNode<'tcx>
Sourcepub(crate) fn find_control_inputs(
&self,
location: Location,
) -> Vec<(DepNode<'tcx>, DepEdge)>
pub(crate) fn find_control_inputs( &self, location: Location, ) -> Vec<(DepNode<'tcx>, DepEdge)>
Returns all pairs of (src, edge)`` such that the given
locationis control-dependent on
edgewith input
src`.
fn call_change_callback(&self) -> Option<&dyn CallChangeCallback<'tcx>>
pub(crate) fn async_info(&self) -> &AsyncInfo
pub(crate) fn make_call_string( &self, location: impl Into<RichLocation>, ) -> CallString
Sourcepub(crate) fn aliases(
&'a self,
place: Place<'tcx>,
) -> impl Iterator<Item = Place<'tcx>> + 'a
pub(crate) fn aliases( &'a self, place: Place<'tcx>, ) -> impl Iterator<Item = Place<'tcx>> + 'a
Returns the aliases of place
. See PlaceInfo::aliases
for details.
pub(crate) fn tcx(&self) -> TyCtxt<'tcx>
pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx>
Sourcepub(crate) fn find_data_inputs(
&self,
state: &InstructionState<'tcx>,
input: Place<'tcx>,
) -> Vec<DepNode<'tcx>>
pub(crate) fn find_data_inputs( &self, state: &InstructionState<'tcx>, input: Place<'tcx>, ) -> Vec<DepNode<'tcx>>
Returns all nodes src
such that src
is:
- Part of the value of
input
- The most-recently modified location for
src
pub(crate) fn find_outputs( &self, mutated: Place<'tcx>, location: Location, ) -> Vec<(Place<'tcx>, DepNode<'tcx>)>
Sourcefn apply_mutation(
&self,
state: &mut InstructionState<'tcx>,
location: Location,
mutated: Place<'tcx>,
)
fn apply_mutation( &self, state: &mut InstructionState<'tcx>, location: Location, mutated: Place<'tcx>, )
Updates the last-mutated location for dst
to the given location
.
Sourcepub(crate) fn operand_to_def_id(
&self,
func: &Operand<'tcx>,
) -> Option<(DefId, GenericArgsRef<'tcx>)>
pub(crate) fn operand_to_def_id( &self, func: &Operand<'tcx>, ) -> Option<(DefId, GenericArgsRef<'tcx>)>
fn fmt_fn(&self, def_id: DefId) -> String
pub(crate) fn determine_call_handling<'b>( &'b self, location: Location, func: Cow<'_, Operand<'tcx>>, args: Cow<'b, [Spanned<Operand<'tcx>>]>, span: Span, ) -> Option<CallHandling<'tcx, 'b>>
Sourcefn handle_call(
&self,
state: &mut InstructionState<'tcx>,
location: Location,
func: &Operand<'tcx>,
args: &[Spanned<Operand<'tcx>>],
destination: Place<'tcx>,
span: Span,
) -> bool
fn handle_call( &self, state: &mut InstructionState<'tcx>, location: Location, func: &Operand<'tcx>, args: &[Spanned<Operand<'tcx>>], destination: Place<'tcx>, span: Span, ) -> bool
Attempt to inline a call to a function.
The return indicates whether we were successfully able to perform the inlining.
fn modular_mutation_visitor<'b: 'a>( &'b self, state: &'a mut InstructionState<'tcx>, ) -> ModularMutationVisitor<'b, 'tcx, impl FnMut(Location, Mutation<'tcx>) + 'b>
pub(crate) fn generic_args(&self) -> GenericArgsRef<'tcx>
pub(crate) fn construct_partial(&'a self) -> PartialGraph<'tcx>
Sourcefn classify_call_kind<'b>(
&'b self,
def_id: DefId,
resolved_fn: Instance<'tcx>,
original_args: &'b [Spanned<Operand<'tcx>>],
span: Span,
) -> CallKind<'tcx>
fn classify_call_kind<'b>( &'b self, def_id: DefId, resolved_fn: Instance<'tcx>, original_args: &'b [Spanned<Operand<'tcx>>], span: Span, ) -> CallKind<'tcx>
Determine the type of call-site.
The error case is if we tried to resolve this as async and failed. We know it is async but we couldn’t determine the information needed to analyze the function, therefore we will have to approximate it.
fn try_indirect_call_kind(&self, def_id: DefId) -> Option<CallKind<'tcx>>
fn terminator_visitor<'b: 'a>( &'b self, state: &'b mut InstructionState<'tcx>, time: Time, ) -> ModularMutationVisitor<'b, 'tcx, impl FnMut(Location, Mutation<'tcx>) + 'b>
Source§impl<'tcx> LocalAnalysis<'tcx, '_>
impl<'tcx> LocalAnalysis<'tcx, '_>
fn handle_terminator( &self, terminator: &Terminator<'tcx>, state: &mut InstructionState<'tcx>, location: Location, time: Time, )
Trait Implementations§
Source§impl<'a, 'tcx> Analysis<'tcx> for &'a LocalAnalysis<'tcx, 'a>
impl<'a, 'tcx> Analysis<'tcx> for &'a LocalAnalysis<'tcx, 'a>
Source§const NAME: &'static str = "LocalPdgConstruction"
const NAME: &'static str = "LocalPdgConstruction"
Source§type Domain = InstructionState<'tcx>
type Domain = InstructionState<'tcx>
Source§fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain
fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain
Source§fn initialize_start_block(&self, _body: &Body<'tcx>, _state: &mut Self::Domain)
fn initialize_start_block(&self, _body: &Body<'tcx>, _state: &mut Self::Domain)
START_BLOCK
. Read moreSource§fn apply_primary_statement_effect(
&mut self,
state: &mut Self::Domain,
statement: &Statement<'tcx>,
location: Location,
)
fn apply_primary_statement_effect( &mut self, state: &mut Self::Domain, statement: &Statement<'tcx>, location: Location, )
Source§fn apply_primary_terminator_effect<'mir>(
&mut self,
state: &mut Self::Domain,
terminator: &'mir Terminator<'tcx>,
location: Location,
) -> TerminatorEdges<'mir, 'tcx>
fn apply_primary_terminator_effect<'mir>( &mut self, state: &mut Self::Domain, terminator: &'mir Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx>
Source§fn apply_call_return_effect(
&mut self,
_state: &mut Self::Domain,
_block: BasicBlock,
_return_places: CallReturnPlaces<'_, 'tcx>,
)
fn apply_call_return_effect( &mut self, _state: &mut Self::Domain, _block: BasicBlock, _return_places: CallReturnPlaces<'_, 'tcx>, )
Call
terminator. Read more§fn apply_early_statement_effect(
&mut self,
_state: &mut Self::Domain,
_statement: &Statement<'tcx>,
_location: Location,
)
fn apply_early_statement_effect( &mut self, _state: &mut Self::Domain, _statement: &Statement<'tcx>, _location: Location, )
§fn apply_early_terminator_effect(
&mut self,
_state: &mut Self::Domain,
_terminator: &Terminator<'tcx>,
_location: Location,
)
fn apply_early_terminator_effect( &mut self, _state: &mut Self::Domain, _terminator: &Terminator<'tcx>, _location: Location, )
§fn apply_switch_int_edge_effects(
&mut self,
_block: BasicBlock,
_discr: &Operand<'tcx>,
_apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>,
)
fn apply_switch_int_edge_effects( &mut self, _block: BasicBlock, _discr: &Operand<'tcx>, _apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>, )
SwitchInt
terminator. Read moreSource§impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, &'mir LocalAnalysis<'tcx, 'mir>> for PartialGraph<'tcx>
impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, &'mir LocalAnalysis<'tcx, 'mir>> for PartialGraph<'tcx>
Source§fn visit_after_early_terminator_effect(
&mut self,
results: &mut Results<'tcx, &'mir LocalAnalysis<'tcx, 'mir>>,
state: &InstructionState<'tcx>,
terminator: &'mir Terminator<'tcx>,
location: Location,
)
fn visit_after_early_terminator_effect( &mut self, results: &mut Results<'tcx, &'mir LocalAnalysis<'tcx, 'mir>>, state: &InstructionState<'tcx>, terminator: &'mir Terminator<'tcx>, location: Location, )
We handle terminators during graph construction generally in the before state, because we’re interested in what the dependencies of our read places are before the modification pass overwrites the read places from any mutable arguments.
There is one exception which is that non-inlined function calls are handled in two steps. Before the primary effects we generate edges from the dependencies to the input arguments. After the primary effect we insert edges from each argument to each modified location. It is cleaner to do this afterwards, because the logic that resolves a place to a graph node assumes that you are reading all of your inputs from the “last_modification”. In the “before” state that map contains the “original” dependencies of each argument, e.g. we haven’t combined them with the reachable places yet. So this ordering means we can reuse the same logic but just have to run it twice for every non-inlined function call site.
Source§fn visit_after_early_statement_effect(
&mut self,
results: &mut Results<'tcx, &'mir LocalAnalysis<'tcx, 'mir>>,
state: &InstructionState<'tcx>,
statement: &'mir Statement<'tcx>,
location: Location,
)
fn visit_after_early_statement_effect( &mut self, results: &mut Results<'tcx, &'mir LocalAnalysis<'tcx, 'mir>>, state: &InstructionState<'tcx>, statement: &'mir Statement<'tcx>, location: Location, )
state
.Source§fn visit_after_primary_terminator_effect(
&mut self,
results: &mut Results<'tcx, &'mir LocalAnalysis<'tcx, 'mir>>,
state: &InstructionState<'tcx>,
terminator: &'mir Terminator<'tcx>,
location: Location,
)
fn visit_after_primary_terminator_effect( &mut self, results: &mut Results<'tcx, &'mir LocalAnalysis<'tcx, 'mir>>, state: &InstructionState<'tcx>, terminator: &'mir Terminator<'tcx>, location: Location, )
state
. Read morefn visit_block_start(&mut self, _state: &<A as Analysis<'tcx>>::Domain)
§fn visit_after_primary_statement_effect(
&mut self,
_results: &mut Results<'tcx, A>,
_state: &<A as Analysis<'tcx>>::Domain,
_statement: &'mir Statement<'tcx>,
_location: Location,
)
fn visit_after_primary_statement_effect( &mut self, _results: &mut Results<'tcx, A>, _state: &<A as Analysis<'tcx>>::Domain, _statement: &'mir Statement<'tcx>, _location: Location, )
state
.fn visit_block_end(&mut self, _state: &<A as Analysis<'tcx>>::Domain)
Auto Trait Implementations§
impl<'tcx, 'a> !Freeze for LocalAnalysis<'tcx, 'a>
impl<'tcx, 'a> !RefUnwindSafe for LocalAnalysis<'tcx, 'a>
impl<'tcx, 'a> !Send for LocalAnalysis<'tcx, 'a>
impl<'tcx, 'a> !Sync for LocalAnalysis<'tcx, 'a>
impl<'tcx, 'a> Unpin for LocalAnalysis<'tcx, 'a>
impl<'tcx, 'a> !UnwindSafe for LocalAnalysis<'tcx, 'a>
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> 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