-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix overriding mixing with default features #3843
Fix overriding mixing with default features #3843
Conversation
Previously Cargo had a bug where if a crate *without* a default feature was overridden with one that did indeed have a default feature then the default may not end up getting activated by accident. The fix was to avoid returning too quickly hen activating dependencies until after we've inspected and learned about replacements. Closes rust-lang#3812
r? @brson (rust_highfive has picked a reviewer for you, use r? to override) |
r? @matklad |
Whew this must have been a pain to figure out! Thanks a lot. If you run the test in this PR on the old code, will it sometimes pass non-deterministically? I think this works... sort-of. Since the failure mode of this bug was that most of the time, the default feature would not be selected, this might be considered a breaking change since the default feature will now always be selected. Looks like I'm running into #1796 with this fix. |
Yeah the test would fail nondeterministically, that's how I figured this fixed it :). A thousand or so runs with no failures makes me think this is confirmed as the right fix. Yeah features across build deps and across actual deps are kinda hairy unfortunately :( |
|
||
let candidate = match candidate.replace { | ||
Some(replace) => { | ||
cx.resolve_replacements.insert(candidate.summary.package_id().clone(), | ||
replace.package_id().clone()); | ||
if cx.flag_activated(&replace, method) { | ||
if cx.flag_activated(&replace, method) && activated { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure about this && activated
. Can it cause the same replacement to be activated twice? Is it bad?
If I remove && activated
, the tests pass just as well. So we either don't need it, or don't have some test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is, we can move perhaps all ifs after replacement:
let candidate = match candidate.replace {
Some(replace) => {
cx.resolve_replacements.insert(candidate.summary.package_id().clone(),
replace.package_id().clone());
trace!("replacing {} with {}", candidate.summary.package_id(),
replace.package_id());
replace
}
None => candidate.summary,
};
if cx.flag_activated(&candidate, method) {
return Ok(None)
}
trace!("activating {}", candidate.package_id());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, looks like moving if forward won't work because during replacement we need to activate both the original and the replacement.
@bors: r+ Okey, I am still not sure if |
📌 Commit 2d4cb3e has been approved by |
…atklad Fix overriding mixing with default features Previously Cargo had a bug where if a crate *without* a default feature was overridden with one that did indeed have a default feature then the default may not end up getting activated by accident. The fix was to avoid returning too quickly hen activating dependencies until after we've inspected and learned about replacements. Closes #3812
☀️ Test successful - status-appveyor, status-travis |
Ah yeah so we definitely need to activate both the original and the replacement, but to answer your original question: In general Cargo's resolution algorithm is just a brute force search with some heuristics thrown in. We then pick the first successful resolution reached, or we try every possible resolution and determine they're all errors and return an error. (I don't actually know which error...) In that sense what this Note that the crux of this bug was that we were returning too soon! When activating a crate you have to follow through with dependency traversal if any new features were activated, but if you've already activated all relevant features then you don't have to go further. The bug here was that we thought that we had already activated a crate when in fact we had forgotten to activate the replacement's default feature. |
Previously Cargo had a bug where if a crate without a default feature was
overridden with one that did indeed have a default feature then the default may
not end up getting activated by accident. The fix was to avoid returning too
quickly hen activating dependencies until after we've inspected and learned
about replacements.
Closes #3812