Skip to main content

SideConditionChecker

Struct SideConditionChecker 

Source
pub struct SideConditionChecker<'a> { /* private fields */ }
Expand description

Answers side-condition queries for plan rewrites.

Used by the certificate verifier and rewrite engine to check whether a rewrite is safe to apply.

Implementations§

Source§

impl<'a> SideConditionChecker<'a>

Source

pub fn new(dag: &'a PlanDag) -> Self

Creates a new checker, running the analysis eagerly.

Source

pub fn analysis(&self) -> &PlanAnalysis

Returns the underlying analysis.

Source

pub fn obligations_safe(&self, id: PlanId) -> bool

Check if a node’s children are obligation-safe (no cancel leaks).

Source

pub fn cancel_safe(&self, id: PlanId) -> bool

Check if a node’s cancel behavior is safe (losers drained).

Source

pub fn are_independent(&self, a: PlanId, b: PlanId) -> bool

Check if two subtrees are independent (no shared mutable state).

Conservative: returns true only if neither subtree contains nodes that appear in the other’s reachable set. This is a structural check — it cannot detect aliased external state.

Source

pub fn rewrite_preserves_obligations( &self, before: PlanId, after: PlanId, ) -> bool

Check if a rewrite from before to after preserves obligation safety.

Conservative: requires both the before and after nodes to be obligation-safe.

Source

pub fn rewrite_preserves_cancel(&self, before: PlanId, after: PlanId) -> bool

Check if a rewrite preserves cancel safety.

Source

pub fn rewrite_preserves_budget(&self, before: PlanId, after: PlanId) -> bool

Check if a rewrite preserves budget monotonicity.

Source

pub fn rewrite_preserves_deadline(&self, before: PlanId, after: PlanId) -> bool

Check if a rewrite preserves deadline guarantees specifically.

This is a more focused check than rewrite_preserves_budget:

  • If the original has no deadline, any deadline is acceptable
  • If the original has a deadline, the rewritten must have one that is at least as tight
Source

pub fn effective_deadline(&self, id: PlanId) -> Option<DeadlineMicros>

Returns the effective deadline for a node, if any.

Source

pub fn deadline_within_tolerance( &self, before: PlanId, after: PlanId, tolerance_micros: u64, ) -> bool

Check if a rewrite does not worsen the deadline by more than a given amount.

Useful for allowing small deadline relaxations in exchange for other benefits.

Source

pub fn rewrite_preserves_loser_drain( &self, before: PlanId, after: PlanId, ) -> bool

Returns true when a rewrite preserves the loser-drain property.

A rewrite is safe if it does not degrade cancel-safety (Safe → non-Safe) and does not introduce new obligation leak candidates on the cancel path.

Source

pub fn rewrite_preserves_finalize_order( &self, before: PlanId, after: PlanId, ) -> bool

Returns true when a rewrite preserves the relative order of obligation-bearing children inside a Join node.

For Race/Timeout/Leaf rewrites this always returns true (no ordering contract). Race → Join (e.g., DedupRaceJoin) is allowed because a Race imposes no finalize ordering on its children; any ordering in the resulting Join is valid.

Source

pub fn rewrite_no_new_obligation_leaks( &self, before: PlanId, after: PlanId, ) -> bool

Returns true when a rewrite does not introduce new obligation leaks.

This checks three properties:

  1. Obligation safety does not degrade (safe → unsafe).
  2. The all_paths_resolve flag does not become false.
  3. The set of leak_on_cancel obligations does not grow.
  4. Previously must_resolve obligations are not demoted to leak-or-reserve.
Source

pub fn children_pairwise_independent(&self, children: &[PlanId]) -> bool

Check whether all children are pairwise independent.

Source§

impl SideConditionChecker<'_>

Source

pub fn check_independence(&self, a: PlanId, b: PlanId) -> IndependenceResult

Check if two nodes are independent (can be safely reordered).

Two nodes are independent if:

  • They don’t share any common descendants (structural independence)
  • They don’t have data dependencies through obligations
  • Reordering them doesn’t change observable behavior

This is a conservative analysis: if uncertain, returns Uncertain.

Source

pub fn commutes(&self, a: PlanId, b: PlanId) -> bool

Check if two nodes commute (can be reordered without changing semantics).

This is an alias for check_independence with a clearer name for users thinking in terms of commutativity.

Source

pub fn compute_independence_relation(&self) -> IndependenceRelation

Compute the independence relation for all leaf nodes in the DAG.

This builds a relation that can be used for Mazurkiewicz trace equivalence checking: two sequences are equivalent if one can be transformed into the other by commuting independent operations.

Source

pub fn rewrite_valid_up_to_trace(&self, before: PlanId, after: PlanId) -> bool

Check if a rewrite is valid up to Mazurkiewicz trace equivalence.

A rewrite is valid if:

  1. The structural transformation is correct
  2. The rewrite preserves the independence relation
  3. The observable behavior is preserved (up to reordering of independent operations)

This is useful for rewrites like Join[a, b] -> Join[b, a] where the order doesn’t matter if a and b are independent.

Source

pub fn reorderable_join_children(&self, children: &[PlanId]) -> Vec<Vec<usize>>

Check if the children of a Join can be reordered.

Returns the indices of children that can be freely reordered (all pairs in the returned set are mutually independent).

Source

pub fn trace_equivalence_hint(&self, id: PlanId) -> TraceEquivalenceHint

Get a trace equivalence hint for a node.

Returns a summary of which operations can commute, useful for the rewrite engine to know when certain rewrites are safe.

Auto Trait Implementations§

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

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, _span: NoopSpan) -> Self

Instruments this future with a span (no-op when disabled).
Source§

fn in_current_span(self) -> Self

Instruments this future with the current span (no-op when disabled).
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> Same for T

Source§

type Output = T

Should always be Self
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.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more