Skip to main content

resolve

Function resolve 

Source
pub fn resolve(profile: &Profile) -> Result<ResolvedLoadOrder>
Expand description

Resolve a profile into a topologically sorted load order.

Stability contract: the output preserves profile.mods input order wherever possible, deviating only when a LoadAfter / LoadBefore rule would otherwise be violated. This means:

  1. No rules → exact input order. resolve(profile).order equals the enabled subset of profile.mods in the same sequence.
  2. Round-trip via swap. Swapping two adjacent mods in profile.mods produces a resolved order with those two mods swapped, as long as no rule spans the swap. This is what makes Message::ReorderMod visible in the load_order view — without stability, reordering could silently vanish.
  3. Minimal change under rules. When a rule does force movement, only the rule-involved pair shifts; unrelated neighbors stay put.
  4. Deterministic. Identical inputs always produce identical outputs; we don’t rely on HashMap iteration order anywhere.

§Algorithm

Stable Kahn’s with input-position tiebreaking:

  1. Collect enabled mods, recording each mod_id → input_pos.
  2. Build adjacency + in-degree from LoadAfter / LoadBefore rules, silently dropping edges whose endpoints aren’t enabled (matches the old behaviour).
  3. Seed a min-heap (BinaryHeap<Reverse<(input_pos, mod_id)>>) with every node whose in-degree is 0.
  4. Pop the smallest-input-position ready node, emit it, decrement the in-degree of its successors, pushing any that hit 0.
  5. If fewer nodes come out than went in, there’s a cycle — pick any remaining node to name in CoreError::DependencyCycle.

Incompatible rules are checked up-front and short-circuit the resolution with a FileConflict error (unchanged from the old impl).