Skip to content

Commit 6502125

Browse files
committed
count rejected decision and steps in conflict resolution
1 parent 1044406 commit 6502125

File tree

3 files changed

+67
-51
lines changed

3 files changed

+67
-51
lines changed

src/internal/core.rs

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -208,34 +208,38 @@ impl<DP: DependencyProvider> State<DP> {
208208
.is_terminal(self.root_package, &self.root_version)
209209
{
210210
return Err(current_incompat_id);
211-
} else {
212-
let (package, satisfier_search_result) = self.partial_solution.satisfier_search(
213-
&self.incompatibility_store[current_incompat_id],
214-
&self.incompatibility_store,
215-
);
216-
match satisfier_search_result {
217-
SatisfierSearch::DifferentDecisionLevels {
211+
}
212+
let (package, satisfier_search_result) = self.partial_solution.satisfier_search(
213+
&self.incompatibility_store[current_incompat_id],
214+
&self.incompatibility_store,
215+
);
216+
match satisfier_search_result {
217+
SatisfierSearch::DifferentDecisionLevels {
218+
previous_satisfier_level,
219+
} => {
220+
self.backtrack(
221+
current_incompat_id,
222+
current_incompat_changed,
218223
previous_satisfier_level,
219-
} => {
220-
self.backtrack(
221-
current_incompat_id,
222-
current_incompat_changed,
223-
previous_satisfier_level,
224-
);
225-
log::info!("backtrack to {:?}", previous_satisfier_level);
226-
return Ok((package, current_incompat_id));
227-
}
228-
SatisfierSearch::SameDecisionLevels { satisfier_cause } => {
229-
let prior_cause = Incompatibility::prior_cause(
230-
current_incompat_id,
231-
satisfier_cause,
232-
package,
233-
&self.incompatibility_store,
234-
);
235-
log::info!("prior cause: {}", prior_cause.display(&self.package_store));
236-
current_incompat_id = self.incompatibility_store.alloc(prior_cause);
237-
current_incompat_changed = true;
224+
);
225+
log::info!("backtrack to {:?}", previous_satisfier_level);
226+
return Ok((package, current_incompat_id));
227+
}
228+
SatisfierSearch::SameDecisionLevels { satisfier_cause } => {
229+
let prior_cause = Incompatibility::prior_cause(
230+
current_incompat_id,
231+
satisfier_cause,
232+
package,
233+
&self.incompatibility_store,
234+
);
235+
236+
for (p, _) in prior_cause.iter() {
237+
*self.conflict_count.entry(p).or_default() += 1;
238238
}
239+
240+
log::info!("prior cause: {}", prior_cause.display(&self.package_store));
241+
current_incompat_id = self.incompatibility_store.alloc(prior_cause);
242+
current_incompat_changed = true;
239243
}
240244
}
241245
}

src/internal/partial_solution.rs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -408,34 +408,39 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
408408
version: DP::V,
409409
new_incompatibilities: std::ops::Range<IncompId<DP::P, DP::VS, DP::M>>,
410410
store: &Arena<Incompatibility<DP::P, DP::VS, DP::M>>,
411-
) {
411+
) -> Option<IncompId<DP::P, DP::VS, DP::M>> {
412412
if !self.has_ever_backtracked {
413-
// Nothing has yet gone wrong during this resolution. This call is unlikely to be the first problem.
413+
// Fast path: Nothing has yet gone wrong during this resolution. This call is unlikely to be the first problem.
414414
// So let's live with a little bit of risk and add the decision without checking the dependencies.
415415
// The worst that can happen is we will have to do a full backtrack which only removes this one decision.
416416
log::info!("add_decision: {package:?} @ {version} without checking dependencies");
417417
self.add_decision(package, version);
418+
return None;
419+
}
420+
421+
// Check if any of the dependencies preclude deciding on this crate version.
422+
let package_term = Term::exact(version.clone());
423+
let relation = |incompat: IncompId<DP::P, DP::VS, DP::M>| {
424+
store[incompat].relation(|p| {
425+
// The current package isn't part of the package assignments yet.
426+
if p == package {
427+
Some(&package_term)
428+
} else {
429+
self.term_intersection_for_package(p)
430+
}
431+
})
432+
};
433+
if let Some(satisfied) = Id::range_to_iter(new_incompatibilities)
434+
.find(|incompat| relation(*incompat) == Relation::Satisfied)
435+
{
436+
log::info!(
437+
"rejecting decision {package:?} @ {version} because its dependencies conflict"
438+
);
439+
Some(satisfied)
418440
} else {
419-
// Check if any of the new dependencies preclude deciding on this crate version.
420-
let exact = Term::exact(version.clone());
421-
let not_satisfied = |incompat: &Incompatibility<DP::P, DP::VS, DP::M>| {
422-
incompat.relation(|p| {
423-
if p == package {
424-
Some(&exact)
425-
} else {
426-
self.term_intersection_for_package(p)
427-
}
428-
}) != Relation::Satisfied
429-
};
430-
431-
// Check none of the dependencies (new_incompatibilities)
432-
// would create a conflict (be satisfied).
433-
if store[new_incompatibilities].iter().all(not_satisfied) {
434-
log::info!("add_decision: {package:?} @ {version}");
435-
self.add_decision(package, version);
436-
} else {
437-
log::info!("not adding {package:?} @ {version} because of its dependencies",);
438-
}
441+
log::info!("adding decision: {package:?} @ {version}");
442+
self.add_decision(package, version);
443+
None
439444
}
440445
}
441446

src/solver.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,16 @@ pub fn resolve<DP: DependencyProvider>(
175175
let dep_incompats =
176176
state.add_incompatibility_from_dependencies(p, v.clone(), dependencies);
177177

178-
state
179-
.partial_solution
180-
.add_version(p, v, dep_incompats, &state.incompatibility_store);
178+
if let Some(conflict) = state.partial_solution.add_version(
179+
p,
180+
v,
181+
dep_incompats,
182+
&state.incompatibility_store,
183+
) {
184+
for (incompat_package, _) in state.incompatibility_store[conflict].iter() {
185+
*state.conflict_count.entry(incompat_package).or_default() += 1;
186+
}
187+
}
181188
} else {
182189
// `dep_incompats` are already in `incompatibilities` so we know there are not satisfied
183190
// terms and can add the decision directly.

0 commit comments

Comments
 (0)