use chalk_solve::Solution;
use tracing::debug;
use chalk_ir::interner::Interner;
use chalk_ir::{ClausePriority, DomainGoal, GenericArg};
#[tracing::instrument(level = "Debug", skip(interner))]
pub(super) fn with_priorities<I: Interner>(
interner: I,
domain_goal: &DomainGoal<I>,
a: Solution<I>,
prio_a: ClausePriority,
b: Solution<I>,
prio_b: ClausePriority,
) -> (Solution<I>, ClausePriority) {
let result = match (prio_a, prio_b, a, b) {
(ClausePriority::High, ClausePriority::Low, higher, lower)
| (ClausePriority::Low, ClausePriority::High, lower, higher) => {
let inputs_higher = calculate_inputs(interner, domain_goal, &higher);
let inputs_lower = calculate_inputs(interner, domain_goal, &lower);
if inputs_higher == inputs_lower {
debug!(
"preferring solution: {:?} over {:?} because of higher prio",
higher, lower
);
(higher, ClausePriority::High)
} else {
(higher.combine(lower, interner), ClausePriority::High)
}
}
(_, _, a, b) => (a.combine(b, interner), prio_a),
};
debug!(?result, "combined result");
result
}
fn calculate_inputs<I: Interner>(
interner: I,
domain_goal: &DomainGoal<I>,
solution: &Solution<I>,
) -> Vec<GenericArg<I>> {
if let Some(subst) = solution.constrained_subst(interner) {
let subst_goal = subst.value.subst.apply(domain_goal.clone(), interner);
subst_goal.inputs(interner)
} else {
domain_goal.inputs(interner)
}
}