Skip to main content

PathGraph

Struct PathGraph 

Source
pub struct PathGraph<'tcx> {
    pub cfg: ControlFlowGraph<'tcx>,
    pub block_info: Vec<BlockConstantInfo>,
    pub disc_info: DiscriminantInfo,
    pub aggregate_field_sources: FxHashMap<usize, usize>,
    pub cast_chains: FxHashMap<usize, usize>,
    pub field_projection_source: FxHashMap<usize, usize>,
    pub inline_bindings: FxHashMap<usize, InlineBinding>,
    pub inline_parents: FxHashMap<usize, DefId>,
    pub inlined_call_blocks: FxHashSet<usize>,
    local_bases: FxHashMap<DefId, usize>,
    next_local_base: usize,
}
Expand description

CFG augmented with per-block constant info and discriminant metadata for path reachability analysis.

PathGraph wraps a ControlFlowGraph and adds block-indexed data that track assignments, constants, and copy chains. These are used by check_transition to update a set of discriminant constraints while traversing the CFG, enabling early pruning of infeasible SwitchInt branches during path enumeration.

Fields§

§cfg: ControlFlowGraph<'tcx>§block_info: Vec<BlockConstantInfo>§disc_info: DiscriminantInfo§aggregate_field_sources: FxHashMap<usize, usize>

Global store: maps encoded (local, field_idx) to source local from Aggregates.

§cast_chains: FxHashMap<usize, usize>

Global store: maps dest to src for pointer-cast chains.

§field_projection_source: FxHashMap<usize, usize>

Global store: maps _dest to encoded (base, field_idx) from field-projection copies.

§inline_bindings: FxHashMap<usize, InlineBinding>

Per-inlined-callee argument binding: maps the callee’s entry block (global index) to the caller’s argument locals and destination local.

§inline_parents: FxHashMap<usize, DefId>

Per-inlined-callee parent: entry block (global index) → the DefId of the caller whose Call was inlined at that entry.

§inlined_call_blocks: FxHashSet<usize>

Caller blocks whose Call terminator was inlined (their successor edge now leads into a callee). The slicer skips these calls.

§local_bases: FxHashMap<DefId, usize>

Per-function local-index namespace: def_id → base offset. The root caller uses base 0; every inlined callee gets a fresh base so its MIR locals do not clash with the caller’s in the flat constraint maps (block_info, disc_info, cast_chains, …). A constraint key k in the namespace of def_id denotes MIR local k - base.

§next_local_base: usize

Next unused local-namespace base (monotonic counter).

Implementations§

Source§

impl<'tcx> PathGraph<'tcx>

Source

pub fn new(tcx: TyCtxt<'tcx>, def_id: DefId) -> PathGraph<'tcx>

Source

pub fn inline_callees(&mut self)

Inline the CFG of inlinable callees into this graph so that path enumeration covers the callee’s branches.

Inlining is recursive within the local crate: a local callee’s own calls are inlined too. Cross-crate callees are inlined only at the level where a local function calls them — their bodies are not recursed into, so the standard library’s internal branchy precondition machinery (is_aligned_to, ub_checks, …) is not pulled in, which would blow up path enumeration with branches that have no constraint tracking.

Each callee is otherwise subject to the same shape constraints as before: cross-crate callees with MIR are always inlined, and a local callee is inlined only when it is small (at most LOCAL_INLINE_BLOCK_LIMIT basic blocks), so branch-free accessors (get, count_ones, …) also land in the CFG and their field provenance is reconstructed element-by-element. Intrinsics have no MIR; callees with a builtin model are kept opaque because their summary is more precise than their body.

Recursion is bounded by an expanded set so that (mutually) recursive local functions do not grow the CFG without bound — a back-edge to an already-inlined callee is left as an ordinary call edge for the VM’s fallback handling.

Opt-in — callers that assume a single-function block space (e.g. alias analysis) must not call this.

Source

fn inline_one(&mut self, caller_idx: usize, callee: DefId)

Inline a single callee into caller_idx, reconnecting the caller’s normal successor edge through the callee body.

Source

pub fn find_scc(&mut self)

Source

pub fn def_id(&self) -> DefId

Source

pub fn tcx(&self) -> TyCtxt<'tcx>

Source

pub fn cfg_block(&self, index: usize) -> &CfgBlock

Source

pub fn cfg_block_mut(&mut self, index: usize) -> &mut CfgBlock

Source

pub fn terminator(&self, index: usize) -> Option<&Terminator<'tcx>>

Retrieve the MIR terminator for the block at index on demand.

Source

pub fn is_cleanup_block(&self, index: usize) -> bool

Source

fn local_base_of(&self, def_id: DefId) -> usize

The local-index base of def_id’s MIR locals in the flat constraint maps. The root caller is base 0; inlined callees get a fresh base.

Source

fn remap_local(&self, def_id: DefId, local: usize) -> usize

Remap def_id’s MIR local local into the global constraint namespace.

Source

fn assign_local_base(&mut self, def_id: DefId) -> usize

Assign a fresh local-namespace base for def_id (or return its existing base if the function has already been inlined).

Source

fn get_variant_count(&self, local: usize, def_id: DefId) -> Option<usize>

Get the number of variants for a constraint local (in def_id’s local namespace). First checks the pre-populated variant_count_of hashmap, then falls back to the local’s declared type (for ADT locals that gained their type through field projections in nested destructuring patterns rather than explicit construction).

Source

pub fn check_transition( &self, cur: usize, next: usize, constraints: &mut FxHashMap<usize, usize>, ) -> bool

Check a single transition cur -> next for reachability and update discriminant constraints. Returns false if the transition is provably unreachable.

Source

fn check_assert_transition( &self, cur: usize, next: usize, constraints: &FxHashMap<usize, usize>, ) -> bool

Source

fn resolve_simple_bool( &self, local: usize, constraints: &FxHashMap<usize, usize>, ) -> Option<usize>

Source

fn resolve_bool_local( &self, local: usize, constraints: &FxHashMap<usize, usize>, ) -> Option<usize>

Source

fn check_switch_transition( &self, cur: usize, next: usize, constraints: &mut FxHashMap<usize, usize>, ) -> bool

Check whether cur → next is a valid SwitchInt transition given current discriminant constraints. Returns false when the transition contradicts a known discriminant value. Also records newly learned constraints from the taken branch into constraints.

Source

fn learn_constraint_with_backprop( &self, cur: usize, constraint_local: Option<usize>, targets: &SwitchTargets, next: usize, constraints: &mut FxHashMap<usize, usize>, )

After learning a constraint for a discriminant local, propagate the constraint backward through the copy chain so that source locals also receive the value. This prevents losing track of the constraint when the destination temporary is reassigned on loop back-edges.

Source

fn backprop_constraint( &self, cur: usize, local: usize, val: usize, constraints: &mut FxHashMap<usize, usize>, )

Source

fn resolve_local_value_direct( &self, local: usize, constraints: &FxHashMap<usize, usize>, ) -> Option<usize>

Recursively resolve a local’s value through constraint copies, cast chains, field projections, and aggregate sources (global maps). Like resolve_local_value but does NOT follow increment chains. Used in conservative path filtering where we need high confidence.

Source

fn resolve_local_value( &self, local: usize, constraints: &FxHashMap<usize, usize>, ) -> Option<usize>

Source

fn infer_otherwise_value( &self, cur: usize, targets: &SwitchTargets, discr_local: usize, ) -> Option<usize>

For the “otherwise” branch of a SwitchInt, try to infer the single concrete value that the discriminant must have (because all other possible values are covered by explicit targets).

Source

fn is_unwind_target(&self, cur: usize, next: usize) -> bool

Check whether next is an unwind target reachable from cur via a call or drop terminator (may not be recorded as a normal CFG successor).

Source

fn local_is_known_nonnull( &self, constraints: &FxHashMap<usize, usize>, local: usize, ) -> bool

Return true if local is known to be a non-null pointer.

Source

fn local_is_known_null( &self, constraints: &FxHashMap<usize, usize>, local: usize, ) -> bool

Return true if local is known to be a null pointer.

Source

fn populate_child_sccs(&mut self, enter: usize)

Populate the child_sccs field for a given SCC entry block, then recurse into those child SCCs. Called eagerly from find_scc() so that enumeration can be purely read-only on the graph.

Source

fn populate_all_child_sccs(&mut self)

Trait Implementations§

Source§

impl<'tcx> Clone for PathGraph<'tcx>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<'tcx> !RefUnwindSafe for PathGraph<'tcx>

§

impl<'tcx> !Send for PathGraph<'tcx>

§

impl<'tcx> !Sync for PathGraph<'tcx>

§

impl<'tcx> !UnwindSafe for PathGraph<'tcx>

§

impl<'tcx> DynSend for PathGraph<'tcx>

§

impl<'tcx> DynSync for PathGraph<'tcx>

§

impl<'tcx> Freeze for PathGraph<'tcx>

§

impl<'tcx> Unpin for PathGraph<'tcx>

§

impl<'tcx> UnsafeUnpin for PathGraph<'tcx>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V