-
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
WIP: Features vs packages #5351
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
Just a drive-by review: your goals mostly sound good; I definitely agree that the CWD should not affect what gets build if the command-line arguments are explicit. However, I would suggest that The addition of |
I am afraid we can't do that :(
Yeah, I just find it impossible to refactor things by replacing them: I usually try to build a new better thing alongside the old one, keeping the code compiling and the tests green, and then remove the old thing separately (well, actually I am not that wise yet, so I typically start replacing the thing, go half-way through to an incomprehensible mess with thousands of compiler errors, and then start afresh with "first add, then remove" strategy :-) ). This PR is an intermediate state, when both new and old thing coexist. I intend to remove |
89c0b17
to
51661da
Compare
Another interesting finding: |
Oh, that looks quite a bit nicer already! |
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.
Nice! I'm definitely on board with this idea.
I think we won't be able to turn -p foo -p bar --features baz
into a hard error immediately though. I suspect that it's used as a workaround in a few locations where it otherwise wouldn't be possible to invoke. Could we start out with a warning and a tracking issue perhaps? That way if people hit it all the tiem we can figure out a way to not have a warning and otherwise we can delete it eventually.
let summaries = ws.members().filter(|m| take_all || requested.contains(m.package_id())) | ||
.map(|member| { | ||
let summary = registry.lock(member.summary().clone()); | ||
(summary, method) |
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'm having a tough time proving to myself that this loop is equivalent to what was there before. I think the idea is that if cli flags affect method
they're forbidden earlier, right?
That is, if method
has features: &["some_feature"]
, then we're guaranteed there's only one member here at this point, right? If so, can that be asserted here?
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.
this loop is equivalent to what was there before
It is not exactly equivalent, --all-features
and --no-default-features
would now apply to all members of the workspace, and not just the current one. This also technically is a breaking change, and it also seems much more intuitive than the previous behavior. The reasoning about features: &["some_feature"]
is correct, I think.
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.
Hm ok so something liek cargo build --all --all-features
is now changing meaning? (just to make sure I understand)
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.
Hm ok so something liek cargo build --all --all-features is now changing meaning?
Yep!
And I think even cargo build -p foo
can change meaning, because we no longer activate cwd package unconditionally.
) -> CargoResult<CompileOptions<'a>> { | ||
let compile_opts = self.compile_options(ws, mode)?; | ||
if compile_opts.requested.specs.len() != 1 { | ||
ws.current()?; |
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'm personally not a huge fan of doing this sort of verification in argument parsing, could these move into the main library?
Cargo-as-a-library I think would be easier to use if we didn't shift too much of the validation to cli argument parsing (which may cause panics/weird bugs if this data gets into cargo-as-a-library). Additionally I feel like argument parsing is primarily concerned with sort of syntactically what's passed in rather than interpreting it which happens in later layers. (also helps us keep everything centralized as much as we can)
So, what exactly do we want to preserve here? If we want to preserve the semantics exactly, that would mean that We can probably switch behavior when there's only one The third option is to just ignore All in all, I think we are in a tough situation: current behavior seems to be highly surprising and wrong, but there's no clear path for opt-in for a new behavior, short for a completely new command line flags :( |
Ah yes I see, good points! It was more cut-and-dry in my head where we only had to worry about two Perhaps we could try this out and see what happens in that case? It's true that the behavior is surprising and probably wrong, but that wouldn't stop people from relying on it. It may be best to:
|
@matklad hm so how about this. What if we implement all these new semantics behind a new |
@alexcrichton sounds reasonable! I think I can implement this without disruptive refactoring. I still would want to clean up the code here a lot, but figuring out the actual semantics we want is for sure much more important! |
Closing for now in favor of #5353 |
This is intended to fix just one weird thing about feature resolution in Cargo. However, fixing it could break someone's spacebar heater, so I've decided to submit a PR early to make sure we indeed want this fix :-)
So, the problematic piece of logic is here:
cargo/src/cargo/ops/resolve.rs
Lines 247 to 255 in 4b1c1b7
The cwd of Cargo affects the resolution logic, and that seems just plain wrong. It is a known issue that
cargo build -p foo
andcargo build -p foo -p bar
could give different results forfoo
because of feature selection. However, justcargo bulid -p foo
can give different results depending on Cargo's cwd, because the current package always gets activated implicitly! Another related piece of weirdness is thatcargo build -p foo --features bar
does not activate thebar
feature offoo
. It activates the feature of the package at the cwd.This PR removes special casing of cwd, and, as a result:
cargo build -p foo --feature bar
does what it looks like it does.cargo test -p foo -p bar --feature baz
no longer works. It is an error to specify--feature
for more than one package.cargo build -p not-a-member
is just weird. Because it is not a member, we need to resolve some member to get to it, and this is truly ambiguous. Previously, we would have looked at cwd package. Now we resolve the whole workspace instead.@alexcrichton do you feel comfortable with these changes in behavior of features/workspaces combination?