Skip to main content

LoopSensitivityAnalyzer

Struct LoopSensitivityAnalyzer 

Source
pub(crate) struct LoopSensitivityAnalyzer<'tcx> {
    tcx: TyCtxt<'tcx>,
}
Expand description

Computes the repeat plan for one verification target.

The analyzer is intentionally target-local. It does not cache across functions because MIR bodies, SCCs, and property roots are small enough for the current auto pass, and keeping the state local prevents stale repeat choices when the same function is checked under a virtual target.

Fields§

§tcx: TyCtxt<'tcx>

Implementations§

Source§

impl<'tcx> LoopSensitivityAnalyzer<'tcx>

Source

pub(crate) fn new(tcx: TyCtxt<'tcx>) -> Self

Create an analyzer over the current compiler type context.

Source

pub(crate) fn analyze(&self, target: &FunctionTarget<'tcx>) -> RepeatPlan

Build a loop-sensitivity repeat plan for target.

The algorithm is:

  1. Collect all safety sinks and bind their roots to caller locals.
  2. Build an SCC-aware PathGraph for the target function.
  3. Build a whole-function local dependency index.
  4. Produce dataflow-distance hints from loop-carried local transfers.
  5. Produce numeric-range hints from simple induction-sensitive sinks.
  6. Calibrate both hint streams into one repeat budget.

This is a conservative planner: it may choose a deeper repeat for loops that turn out to be safe, but it avoids adding tag-specific verifier reruns or new user-visible output.

Source

fn dataflow_distance_hints<'target>( &self, sinks: &[SafetySink<'target, 'tcx>], graph: &PathGraph<'_>, dependencies: &LocalDependencyIndex, component_summaries: &[(LoopComponent, LoopLocalSummary, LoopNumericSummary)], ) -> Vec<DataflowDistanceHint>

Compute loop-carried dataflow hints for every safety sink.

This detector is tag-agnostic: it only asks whether the sink’s caller locals depend on state locals that are redefined across an SCC. The concrete safety checker remains responsible for deciding whether the propagated value is actually invalid once the deeper path is enumerated.

Source

fn numeric_range_hints<'target>( &self, sinks: &[SafetySink<'target, 'tcx>], graph: &PathGraph<'_>, dependencies: &LocalDependencyIndex, component_summaries: &[(LoopComponent, LoopLocalSummary, LoopNumericSummary)], ) -> Vec<NumericRangeHint>

Compute numeric/index range hints for induction-sensitive sinks.

This is intentionally small but already separates numeric planning from generic dataflow. ValidNum tries to recover a concrete violating iteration for positive affine increments; InBound currently marks the first iteration missed by shallow unrolling when the pointer/index root depends on an induction variable.

Source

fn collect_sinks<'target>( &self, target: &'target FunctionTarget<'tcx>, ) -> Vec<SafetySink<'target, 'tcx>>

Collect caller-side sinks from all checkpoint kinds in a target.

This mirrors VerifyDriver::properties_for_callsite so the planner and verifier operate on the same obligations. Keeping it here avoids constructing a VerifyDriver only to learn whether a deeper repeat is needed before path extraction.

Auto Trait Implementations§

§

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

§

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

§

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

§

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

§

impl<'tcx> DynSend for LoopSensitivityAnalyzer<'tcx>

§

impl<'tcx> DynSync for LoopSensitivityAnalyzer<'tcx>

§

impl<'tcx> Freeze for LoopSensitivityAnalyzer<'tcx>

§

impl<'tcx> Unpin for LoopSensitivityAnalyzer<'tcx>

§

impl<'tcx> UnsafeUnpin for LoopSensitivityAnalyzer<'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> 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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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