Skip to content

Commit f6bebb6

Browse files
committed
better wording for the comment
1 parent 49f3f9d commit f6bebb6

File tree

1 file changed

+28
-29
lines changed

1 file changed

+28
-29
lines changed

src/internal/core.rs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -192,37 +192,36 @@ impl<DP: DependencyProvider> State<DP> {
192192
Ok(satisfier_causes)
193193
}
194194

195-
/// Return the root cause or the terminal incompatibility.
196-
/// CF <https://github.com/dart-lang/pub/blob/master/doc/solver.md#unit-propagation>
195+
/// Return the root cause or the terminal incompatibility. CF
196+
/// <https://github.com/dart-lang/pub/blob/master/doc/solver.md#unit-propagation>
197197
///
198-
/// Usually by the time we have a conflict `unit_propagation` has done a lot of work.
199-
/// So the actual conflict we find is important, but not particularly actionable.
200-
/// It says something like "the dependency on package X and the dependency on package Y are incompatible".
201-
/// To make it actionable we want to track it back to decisions that made the dependency required.
202-
/// "The decision on B is incompatible with the decision on C,
203-
/// because unit propagation from just those decisions will lead to the conflict about X and Y"
204-
/// is much more actionable, backtrack until one of those decisions can be revisited.
205-
/// To make a practical, we really only need one of the terms to be a decision.
206-
/// We may as well leave the other terms general. Something like
207-
/// "the dependency on the package X is incompatible with the decision on C" tends to work out pretty well.
208-
/// Then if A turns out to also have a dependency on X the resulting root cause is still useful.
209-
/// Of course, this is more heuristics than science. If the output is too general, then `unit_propagation` will
210-
/// handle the confusion by calling us again with the next most specific conflict it comes across.
211-
/// If the output is to specific, then the outer `solver` loop will eventually end up calling us again
212-
/// until all possibilities are enumerated.
198+
/// When we found a conflict, we want to learn as much as possible from it, to avoid making (or
199+
/// keeping) decisions that will be rejected. Say we found that the dependency requirements on X and the
200+
/// dependency requirements on Y are incompatible. We may find that the decisions on earlier packages B and C
201+
/// require us to make incompatible requirements on X and Y, so we backtrack until either B or C
202+
/// can be revisited. To make it practical, we really only need one of the terms to be a
203+
/// decision. We may as well leave the other terms general. Something like "the dependency on
204+
/// the package X is incompatible with the decision on C" tends to work out pretty well. Then if
205+
/// A turns out to also have a dependency on X the resulting root cause is still useful.
206+
/// (`unit_propagation` will ensure we don't try that version of C.)
207+
/// Of course, this is more heuristics than science. If the output is too general, then
208+
/// `unit_propagation` will handle the confusion by calling us again with the next most specific
209+
/// conflict it comes across. If the output is too specific, then the outer `solver` loop will
210+
/// eventually end up calling us again until all possibilities are enumerated.
213211
///
214-
/// This function combines incompatibilities with things that make the problem inevitable to end up with a
215-
/// more useful incompatibility. For the correctness of the PubGrub algorithm only the final output is required.
216-
/// By banning the final output, unit propagation will prevent the intermediate steps from occurring again,
217-
/// at least prevent the exact same way. However, the statistics collected for `prioritize`may want
218-
/// to analyze those intermediate steps. For example we might start with "there is no version 1 of Z",
219-
/// and `conflict_resolution` may be able to determine that "that was inevitable when we picked version 1 of X"
220-
/// which was inevitable when picked W and ... and version 1 of B, which was depended on by version 1 of A.
221-
/// Therefore the root cause may simplify all the way down to "we cannot pick version 1 of A".
222-
/// This will prevent us going down this path again. However when we start looking at version 2 of A,
223-
/// and discover that it depends on version 2 of B, we will want to prioritize the chain of intermediate steps
224-
/// to confirm if it has a problem with the same shape.
225-
/// The `satisfier_causes` argument keeps track of these intermediate steps so that the caller can use.
212+
/// To end up with a more useful incompatibility, this function combines incompatibilities into
213+
/// derivations. Fulfilling this derivation implies the later conflict. By banning it, we
214+
/// prevent the intermediate steps from occurring again, at least in the exact same way.
215+
/// However, the statistics collected for `prioritize` may want to analyze those intermediate
216+
/// steps. For example we might start with "there is no version 1 of Z", and
217+
/// `conflict_resolution` may be able to determine that "that was inevitable when we picked
218+
/// version 1 of X" which was inevitable when we picked W and so on, until version 1 of B, which
219+
/// was depended on by version 1 of A. Therefore the root cause may simplify all the way down to
220+
/// "we cannot pick version 1 of A". This will prevent us going down this path again. However
221+
/// when we start looking at version 2 of A, and discover that it depends on version 2 of B, we
222+
/// will want to prioritize the chain of intermediate steps to check if it has a problem with
223+
/// the same shape. The `satisfier_causes` argument keeps track of these intermediate steps so
224+
/// that the caller can use them for prioritization.
226225
#[allow(clippy::type_complexity)]
227226
#[cold]
228227
fn conflict_resolution(

0 commit comments

Comments
 (0)