-
-
Notifications
You must be signed in to change notification settings - Fork 3k
feat(manifest)!: implement feature-metadata RFC3416 #15056
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -115,6 +115,7 @@ Each new feature described below should explain how to use it. | |
| * [artifact dependencies](#artifact-dependencies) --- Allow build artifacts to be included into other build artifacts and build them for different targets. | ||
| * [Profile `trim-paths` option](#profile-trim-paths-option) --- Control the sanitization of file paths in build outputs. | ||
| * [path bases](#path-bases) --- Named base directories for path dependencies. | ||
| * [feature-metadata](#feature-metadata) --- Table syntax for feature definitions. | ||
| * [`unstable-editions`](#unstable-editions) --- Allows use of editions that are not yet stable. | ||
| * Information and metadata | ||
| * [unit-graph](#unit-graph) --- Emits JSON for Cargo's internal graph structure. | ||
|
|
@@ -2444,6 +2445,21 @@ See the [`include` config documentation](config.md#include) for more. | |
|
|
||
| The `pubtime` index field has been stabilized in Rust 1.94.0. | ||
|
|
||
| ## feature-metadata | ||
|
|
||
| * Tracking Issue: [#14157](https://github.com/rust-lang/cargo/issues/14157) | ||
|
|
||
| This allows to use a table when defining features, with a required `enables` key: | ||
|
|
||
| ```toml | ||
| [features] | ||
| # same as `foo = []` | ||
| foo = { enables = [] } | ||
| ``` | ||
|
|
||
| This is equivalent to the array-of-strings syntax. | ||
| Support for other keys should be added later. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Look at other unstable for example Above just FYI, docs updates don't block this PR merge.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for pointing that out; I didn't include this in this round to not further delay the merge if you want it now.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've opened #17446 to update the documentation when this eventually stabilizes; I don't think this can be really be added as a doc snippet to the unstable feature docs as this is not purely additive.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can't really merge #17446 now but when stabilizing. |
||
|
|
||
| ## lockfile-path | ||
|
|
||
| Support for `resolver.lockfile-path` config field has been stabilized in Rust 1.97.0. | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -15,8 +15,8 @@ use anyhow::{Context as _, anyhow, bail}; | |||||
| use cargo_platform::Platform; | ||||||
| use cargo_util::paths; | ||||||
| use cargo_util_schemas::manifest::{ | ||||||
| self, PackageName, PathBaseName, TomlDependency, TomlDetailedDependency, TomlManifest, | ||||||
| TomlPackageBuild, TomlWorkspace, | ||||||
| self, FeatureDefinition, FeatureMetadata, FeatureName, PackageName, PathBaseName, | ||||||
| TomlDependency, TomlDetailedDependency, TomlManifest, TomlPackageBuild, TomlWorkspace, | ||||||
| }; | ||||||
| use cargo_util_schemas::manifest::{RustVersion, StringOrBool}; | ||||||
| use itertools::Itertools; | ||||||
|
|
@@ -877,8 +877,8 @@ pub(crate) fn default_readme_from_package_root(package_root: &Path) -> Option<St | |||||
|
|
||||||
| #[tracing::instrument(skip_all)] | ||||||
| fn normalize_features( | ||||||
| original_features: Option<&BTreeMap<manifest::FeatureName, Vec<String>>>, | ||||||
| ) -> CargoResult<Option<BTreeMap<manifest::FeatureName, Vec<String>>>> { | ||||||
| original_features: Option<&BTreeMap<manifest::FeatureName, FeatureDefinition>>, | ||||||
| ) -> CargoResult<Option<BTreeMap<manifest::FeatureName, FeatureDefinition>>> { | ||||||
| let Some(normalized_features) = original_features.cloned() else { | ||||||
| return Ok(None); | ||||||
| }; | ||||||
|
|
@@ -1563,6 +1563,8 @@ pub fn to_real_manifest( | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| validate_feature_definitions(&features, original_toml.features.as_ref(), warnings)?; | ||||||
|
|
||||||
| validate_dependencies(original_toml.dependencies.as_ref(), None, None, warnings)?; | ||||||
| validate_dependencies( | ||||||
| original_toml.dev_dependencies(), | ||||||
|
|
@@ -1765,7 +1767,7 @@ pub fn to_real_manifest( | |||||
| .map(|(k, v)| { | ||||||
| ( | ||||||
| k.to_string().into(), | ||||||
| v.iter().map(InternedString::from).collect(), | ||||||
| v.enables().iter().map(InternedString::from).collect(), | ||||||
| ) | ||||||
| }) | ||||||
| .collect(), | ||||||
|
|
@@ -2049,6 +2051,30 @@ fn to_virtual_manifest( | |||||
| Ok(manifest) | ||||||
| } | ||||||
|
|
||||||
| fn validate_feature_definitions( | ||||||
| cargo_features: &Features, | ||||||
| features: Option<&BTreeMap<FeatureName, FeatureDefinition>>, | ||||||
| warnings: &mut Vec<String>, | ||||||
| ) -> CargoResult<()> { | ||||||
| let Some(features) = features else { | ||||||
| return Ok(()); | ||||||
| }; | ||||||
| for (feature, feature_definition) in features { | ||||||
| match feature_definition { | ||||||
| FeatureDefinition::Array(..) => {} | ||||||
| FeatureDefinition::Metadata(FeatureMetadata { _unused_keys, .. }) => { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. haven't got time into full review, though I think the meta field should be behind a nightly feature flag.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes. Probably behind a cargo-feature "feature-metadata".
Could add a doc comment on relevant field/variant indicating it is unstable/nightly only. cargo/crates/cargo-util-schemas/src/manifest/mod.rs Lines 936 to 937 in f15df8f
There is a CI job checking if a member crate needs a version bump. It didn't warn you so I assume it has already been bumped in this release cycle. You do not need to do anything.
Summary is more like a thing for dependency resolution. I think we revisit it in the future. Regardless, see epage's comment #14157 (comment) that the feature itself is not particularly useful until other RFC gets merged. Anyway, thanks for the contribution! |
||||||
| cargo_features.require(Feature::feature_metadata())?; | ||||||
| warnings.extend( | ||||||
| _unused_keys | ||||||
| .keys() | ||||||
| .map(|k| format!("unused manifest key: `features.{feature}.{k}`")), | ||||||
|
AudaciousAxiom marked this conversation as resolved.
|
||||||
| ); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| Ok(()) | ||||||
| } | ||||||
|
|
||||||
| #[tracing::instrument(skip_all)] | ||||||
| fn validate_dependencies( | ||||||
| original_deps: Option<&BTreeMap<manifest::PackageName, manifest::InheritableDependency>>, | ||||||
|
|
@@ -3185,16 +3211,23 @@ fn prepare_toml_for_publish( | |||||
| }; | ||||||
|
|
||||||
| features.values_mut().for_each(|feature_deps| { | ||||||
| feature_deps.retain(|feature_dep| { | ||||||
| let feature_value = FeatureValue::new(feature_dep.into()); | ||||||
| match feature_value { | ||||||
| FeatureValue::Dep { dep_name } | FeatureValue::DepFeature { dep_name, .. } => { | ||||||
| let k = &manifest::PackageName::new(dep_name.to_string()).unwrap(); | ||||||
| dep_name_set.contains(k) | ||||||
| let feature_array = feature_deps | ||||||
| .enables() | ||||||
| .iter() | ||||||
| .filter(|feature_dep| { | ||||||
| let feature_value = FeatureValue::new((*feature_dep).into()); | ||||||
| match feature_value { | ||||||
| FeatureValue::Dep { dep_name } | ||||||
| | FeatureValue::DepFeature { dep_name, .. } => { | ||||||
| let k = &manifest::PackageName::new(dep_name.to_string()).unwrap(); | ||||||
| dep_name_set.contains(k) | ||||||
| } | ||||||
| _ => true, | ||||||
| } | ||||||
| _ => true, | ||||||
| } | ||||||
| }); | ||||||
| }) | ||||||
| .cloned() | ||||||
| .collect(); | ||||||
| *feature_deps = FeatureDefinition::Array(feature_array); | ||||||
|
Comment on lines
+3214
to
+3230
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For compatibility, this uses the array syntax for generating the normalized manifest, even when the table syntax is used by authors (see the corresponding integration 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.
This method could also return an
impl Iterator<Item = String>if preferred.