pub fn plan_scc_rules(
rules: &BTreeMap<String, Vec<Rule>>,
base_relations: &RefRelationStore,
) -> Result<BTreeMap<String, Vec<RulePlan>>, PlanError>Expand description
Plan a mutually-recursive rule group with PR 8 transitive type inference engaged.
Mirrors the input shape: returns a
BTreeMap<predicate, Vec<RulePlan>> where result[p][i]
corresponds to rules[p][i]. Each rule’s verdict is computed
after running infer_scc_predicate_schemas over the full
group, so a recursive-only join key whose type is established
only via inference is now flagged with
super::Boundary::UnsupportedKeyType consistent with
super::evaluate_scc_fixpoint_typed.
§Why this exists separately from plan_rules
plan_rule / plan_rules type variables from
base_relations only — they have no group context and can’t
run inference. Without plan_scc_rules, a planner driving
the per-rule API would mark even(X, Y) :- odd(X, Z), odd(Z, Y)
as RulePlan::MultiwayCandidate even when odd’s schema
(inferred via PR 8) propagates an unsupported type to Z —
i.e., the planner and the SCC evaluator would disagree on
the same fixture. PR 9 closes that gap.
§Errors
Returns PlanError::InferenceConflict for cross-rule
head-column conflicts detected during inference,
PlanError::ConflictingVariableType for within-rule body
conflicts (both layered the same way as
super::evaluate_scc_fixpoint_typed), and
PlanError::RuleHeadPredicateMismatch for misgrouped rules
(rule’s head predicate ≠ its BTreeMap group key).
§Structural-error precedence
Mirrors the super::evaluate_scc_fixpoint_typed pre-flight
(PR 9): if any rule is misgrouped, the function returns
PlanError::RuleHeadPredicateMismatch BEFORE running
inference, so a misgrouped rule whose body would also produce
inference conflicts surfaces the structural error first. This
keeps planner and evaluator verdicts symmetric for every
fixture class.