-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Open
Labels
A-featuresArea: features — conditional compilationArea: features — conditional compilationC-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`PerformanceGotta go fast!Gotta go fast!S-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.
Description
Problem
Cargo's resolver has 3 phases, narrowing down the packages used at each step
- Resolve for lockfile
- Resolve for target and some other settings
- Resolve features
Resolving of features requires downloading and parsing all packages from step (2)
cargo/src/cargo/ops/resolve.rs
Lines 259 to 309 in 02bcdd2
pkg_set.download_accessible( | |
&resolved_with_overrides, | |
&member_ids, | |
has_dev_units, | |
requested_targets, | |
target_data, | |
force_all_targets, | |
)?; | |
let mut specs_and_features = Vec::new(); | |
for specs in individual_specs { | |
let feature_opts = FeatureOpts::new(ws, has_dev_units, force_all_targets)?; | |
// We want to narrow the features to the current specs so that stuff like `cargo check -p a | |
// -p b -F a/a,b/b` works and the resolver does not contain that `a` does not have feature | |
// `b` and vice-versa. However, resolver v1 needs to see even features of unselected | |
// packages turned on if it was because of working directory being inside the unselected | |
// package, because they might turn on a feature of a selected package. | |
let narrowed_features = match feature_unification { | |
FeatureUnification::Package => { | |
let mut narrowed_features = cli_features.clone(); | |
let enabled_features = members_with_features | |
.iter() | |
.filter_map(|(package, cli_features)| { | |
specs | |
.iter() | |
.any(|spec| spec.matches(package.package_id())) | |
.then_some(cli_features.features.iter()) | |
}) | |
.flatten() | |
.cloned() | |
.collect(); | |
narrowed_features.features = Rc::new(enabled_features); | |
Cow::Owned(narrowed_features) | |
} | |
FeatureUnification::Selected | FeatureUnification::Workspace => { | |
Cow::Borrowed(cli_features) | |
} | |
}; | |
let resolved_features = FeatureResolver::resolve( | |
ws, | |
target_data, | |
&resolved_with_overrides, | |
&pkg_set, | |
&*narrowed_features, | |
&specs, | |
requested_targets, | |
feature_opts, | |
)?; |
so we can then know what proc macros there are
cargo/src/cargo/core/resolver/features.rs
Lines 951 to 970 in 02bcdd2
/// Whether the given package has any proc macro target, including proc-macro examples. | |
fn has_any_proc_macro(&self, package_id: PackageId) -> bool { | |
self.package_set | |
.get_one(package_id) | |
.expect("packages downloaded") | |
.proc_macro() | |
} | |
/// Whether the given package is a proc macro lib target. | |
/// | |
/// This is useful for checking if a dependency is a proc macro, | |
/// as it is not possible to depend on a non-lib target as a proc-macro. | |
fn has_proc_macro_lib(&self, package_id: PackageId) -> bool { | |
self.package_set | |
.get_one(package_id) | |
.expect("packages downloaded") | |
.library() | |
.map(|lib| lib.proc_macro()) | |
.unwrap_or_default() | |
} |
so we can know whether a package and its features are being resolved for the host-platform or target-platform
Without this, resolving of features could operate on the Index and we could download packages after step 3, reducing how many we download.
Problems with this:
- Network, file IO, and CPU performance in downloading and parsing more manifests than needed
- This makes a plumbing command for a feature resolver take in a lot more input than it would otherwise need, slowing down the plumbing command operations
- The plumbing commands are also providing light on how ways we might be able to better isolate cargo's architecture for easier maintainability and contributor approachability
Proposed Solution
- Add proc macro information to the Index Summary
- Have crates.io backfill this Summary entry
Open question
- How do we deal with non-backfilled data, like third-party registries
Notes
No response
Metadata
Metadata
Assignees
Labels
A-featuresArea: features — conditional compilationArea: features — conditional compilationC-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`PerformanceGotta go fast!Gotta go fast!S-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.