Skip to content

implement package feature unification #15684

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

mladedav
Copy link

@mladedav mladedav commented Jun 19, 2025

What does this PR try to resolve?

Implements another part of feature unification (#14774, rfc). The workspace option was implemented in #15157, this adds the package option.

How to test and review this PR?

The important change is changing WorkspaceResolve so it can contain multiple ResolvedFeatures. Along with that, it also needs to know which specs those features are resolved for. This was used in several other places:

  • cargo fix --edition (from 2018 to 2021) - I think it should be ok to disallow using cargo fix --edition when someone already uses this feature.
  • building std - it should be safe to assume std is not using this feature so I just unwrap there. I'm not sure if some attempt to later feature unification would be better.
  • cargo tree - I just use the first feature set. This is definitely not ideal, but I'm not entirely sure what's the correct solution here. Printing multiple trees? Disallowing this, forcing users to select only one package?

Based on comments in #15157 I've added tests first with selected feature unification and then changed that after implementation. I'm not sure if that's how you expect the tests to be added first, if not, I can change the history.

I've expanded the test checking that this is ignored for cargo install although it should work the same way even if it is not ignored (selected and package are the same thing when just one package is selected).

@rustbot
Copy link
Collaborator

rustbot commented Jun 19, 2025

r? @weihanglo

rustbot has assigned @weihanglo.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added A-configuration Area: cargo config files and env vars A-documenting-cargo-itself Area: Cargo's documentation Command-fix Command-tree S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 19, 2025
@mladedav mladedav force-pushed the dm/unification-package branch from ad48f18 to e94564d Compare June 19, 2025 21:41
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to have a cargo tree test as well

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and cargo fix

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a cargo tree test, I'll just have to fixup history so that it's added before the feature.

That said, I think it might need a bit of design work because using package and selected feature unification has almost identical outuput, but in the former each tree should be taken on its own while in the latter the user should be aware that the features are unified.

For example in one simplified case where a depends on common/a and b depends on common/b; package outputs:

common v0.1.0 ([ROOT]/foo/common)
a v0.1.0 ([ROOT]/foo/a)
└── common feature "a"
    └── common v0.1.0 ([ROOT]/foo/common)
b v0.1.0 ([ROOT]/foo/b)
└── common feature "b"
    └── common v0.1.0 ([ROOT]/foo/common)

while selected currently outputs:

a v0.1.0 ([ROOT]/foo/a)
└── common feature "a"
    └── common v0.1.0 ([ROOT]/foo/common)

b v0.1.0 ([ROOT]/foo/b)
└── common feature "b"
    └── common v0.1.0 ([ROOT]/foo/common)

common v0.1.0 ([ROOT]/foo/common)

and for completeness, workspace outputs:

a v0.1.0 ([ROOT]/foo/a)
└── common feature "a"
    └── common v0.1.0 ([ROOT]/foo/common)

b v0.1.0 ([ROOT]/foo/b)
└── common feature "b"
    └── common v0.1.0 ([ROOT]/foo/common)

common v0.1.0 ([ROOT]/foo/common)

I'm not sure what would be the ideal behavior here though, we probably don't want to have both features coming out of both packages in selected because people often use this to find out what package turned on a given feature. But I don't think we should keep it as is either. Maybe adding an edge that signifies a feature but somehow marks it as coming from unification elsewhere?

For example something like this?

a v0.1.0 ([ROOT]/foo/a)
└── common feature "a"
    └── common v0.1.0 ([ROOT]/foo/common)
└── common feature "b" (unified)
    └── common v0.1.0 ([ROOT]/foo/common)

b v0.1.0 ([ROOT]/foo/b)
└── common feature "b"
    └── common v0.1.0 ([ROOT]/foo/common)
└── common feature "a" (unified)
    └── common v0.1.0 ([ROOT]/foo/common)

common v0.1.0 ([ROOT]/foo/common)

Should there be some kind of proposal for these changes? And in that case should I just fixup history with the current behavior or wait for the outcome of that? Or is it fine to make the changes as part of this PR or a different one but without any larger proposal than just the PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be some kind of proposal for these changes? And in that case should I just fixup history with the current behavior or wait for the outcome of that? Or is it fine to make the changes as part of this PR or a different one but without any larger proposal than just the PR?

We can clean this up and get it merged and leave it as an Open Question on the tracking issue to have the discussion run independent of this PR

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, tree tests are added now as well as one fix test. I did not know what to test for though so I just took a random fix test from edition 2021 to 2024 since the relevant change should break just a specific upgrade from 2018. If you want to test for something different, let me know.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a note to the tracking issue

We should have a test specifically for the broken cargo fix --edition case

target_data,
force_all_targets,
)?;
for specs in individual_specs {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we're creating independent resolves for each package. I take it we can then leave merging of these graphs to a future possibility to further optimize this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just independent ResolvedFeatures, it seems everything works with just a single targeted_resolve, though I did not expect that since the field is documeted with "The narrowed resolve, with the specific features enabled." Then from those independent unit graphs are constructed and those are then merged into a single build context.

I probably don't understand the whole process well enough, but I don't see a way to merge anything earlier?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe phrased differently, if you have the following

a -> common w/ features=foo
b -> common w/ features=foo
c -> common

Will we have 2 or 3 entries in the unit graph?

@mladedav mladedav changed the title implement projects feature unification implement package feature unification Jun 19, 2025
@mladedav mladedav force-pushed the dm/unification-package branch from e94564d to c6090d5 Compare June 19, 2025 21:53
@epage
Copy link
Contributor

epage commented Jun 19, 2025

Thanks for moving this forward!

@mladedav mladedav force-pushed the dm/unification-package branch from c6090d5 to e5a3134 Compare June 20, 2025 20:13
@epage
Copy link
Contributor

epage commented Jun 20, 2025

Feel free to edit the commits as needed

@mladedav mladedav force-pushed the dm/unification-package branch from e5a3134 to 90a6e11 Compare June 21, 2025 20:45
@mladedav mladedav force-pushed the dm/unification-package branch 2 times, most recently from b10f5d9 to 2457810 Compare June 23, 2025 06:59
@mladedav
Copy link
Author

I've also just added a test with weak dependencies, which works. I tried to also add namespaced dep: features, but those seem to not be unified (#15694) so I'm ignoring that, but I guess that might also go towards the feature unification's unresolved questions.

@mladedav mladedav force-pushed the dm/unification-package branch from 2457810 to d28a30f Compare June 23, 2025 07:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-configuration Area: cargo config files and env vars A-documenting-cargo-itself Area: Cargo's documentation Command-fix Command-tree S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants