diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs
index a6f144cb562..942b4535051 100644
--- a/src/cargo/util/toml/mod.rs
+++ b/src/cargo/util/toml/mod.rs
@@ -272,6 +272,8 @@ impl<'de, P: Deserialize<'de> + Clone> de::Deserialize<'de> for TomlDependency
{
}
#[derive(Deserialize, Serialize, Clone, Debug)]
+#[serde(rename_all = "kebab-case")]
pub struct TomlWorkspaceDependency {
workspace: bool,
features: Option>,
+ default_features: Option,
+ #[serde(rename = "default_features")]
+ default_features2: Option,
optional: Option,
}
@@ -2525,6 +2531,18 @@ impl TomlDependency {
cx: &mut Context<'_, '_>,
get_inheritable: impl FnOnce() -> CargoResult<&'a InheritableFields>,
) -> CargoResult {
+ fn default_features_msg(label: &str, ws_def_feat: Option, cx: &mut Context<'_, '_>) {
+ let ws_def_feat = match ws_def_feat {
+ Some(true) => "true",
+ Some(false) => "false",
+ None => "not specified",
+ };
+ cx.warnings.push(format!(
+ "`default-features` is ignored for {label}, since `default-features` was \
+ {ws_def_feat} for `workspace.dependencies.{label}`, \
+ this could become a hard error in the future"
+ ))
+ }
match self {
TomlDependency::Detailed(d) => Ok(TomlDependency::Detailed(d)),
TomlDependency::Simple(s) => Ok(TomlDependency::Simple(s)),
@@ -2532,7 +2550,12 @@ impl TomlDependency {
workspace: true,
features,
optional,
+ default_features,
+ default_features2,
}) => {
+ if default_features.is_some() && default_features2.is_some() {
+ warn_on_deprecated("default-features", label, "dependency", cx.warnings);
+ }
let inheritable = get_inheritable()?;
inheritable.get_dependency(label).context(format!(
"error reading `dependencies.{}` from workspace root manifest's `workspace.dependencies.{}`",
@@ -2540,6 +2563,9 @@ impl TomlDependency {
)).map(|dep| {
match dep {
TomlDependency::Simple(s) => {
+ if let Some(false) = default_features.or(default_features2) {
+ default_features_msg(label, None, cx);
+ }
if optional.is_some() || features.is_some() {
Ok(TomlDependency::Detailed(DetailedTomlDependency {
version: Some(s),
@@ -2553,6 +2579,29 @@ impl TomlDependency {
},
TomlDependency::Detailed(d) => {
let mut dep = d.clone();
+ match (
+ default_features.or(default_features2),
+ d.default_features.or(d.default_features2)
+ ) {
+ // member: default-features = true and
+ // workspace: default-features = false should turn on
+ // default-features
+ (Some(true), Some(false)) => {
+ dep.default_features = Some(true);
+ }
+ // member: default-features = false and
+ // workspace: default-features = true should ignore member
+ // default-features
+ (Some(false), Some(true)) => {
+ default_features_msg(label, Some(true), cx);
+ }
+ // member: default-features = false and
+ // workspace: dep = "1.0" should ignore member default-features
+ (Some(false), None) => {
+ default_features_msg(label, None, cx);
+ }
+ _ => {}
+ }
dep.add_features(features);
dep.update_optional(optional);
dep.resolve_path(label,inheritable.ws_root(), cx.root)?;
diff --git a/tests/testsuite/inheritable_workspace_fields.rs b/tests/testsuite/inheritable_workspace_fields.rs
index 2076c71287c..fe4667f6263 100644
--- a/tests/testsuite/inheritable_workspace_fields.rs
+++ b/tests/testsuite/inheritable_workspace_fields.rs
@@ -1356,3 +1356,145 @@ Caused by:
)
.run();
}
+
+#[cargo_test]
+fn warn_inherit_def_feat_true_member_def_feat_false() {
+ Package::new("dep", "0.1.0")
+ .feature("default", &["fancy_dep"])
+ .add_dep(Dependency::new("fancy_dep", "0.2").optional(true))
+ .file("src/lib.rs", "")
+ .publish();
+
+ Package::new("fancy_dep", "0.2.4").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "bar"
+ version = "0.2.0"
+ authors = []
+ [dependencies]
+ dep = { workspace = true, default-features = false }
+
+ [workspace]
+ members = []
+ [workspace.dependencies]
+ dep = { version = "0.1.0", default-features = true }
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ p.cargo("check")
+ .with_stderr(
+ "\
+[WARNING] [CWD]/Cargo.toml: `default-features` is ignored for dep, since `default-features` was \
+true for `workspace.dependencies.dep`, this could become a hard error in the future
+[UPDATING] `dummy-registry` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] fancy_dep v0.2.4 ([..])
+[DOWNLOADED] dep v0.1.0 ([..])
+[CHECKING] fancy_dep v0.2.4
+[CHECKING] dep v0.1.0
+[CHECKING] bar v0.2.0 ([CWD])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn warn_inherit_simple_member_def_feat_false() {
+ Package::new("dep", "0.1.0")
+ .feature("default", &["fancy_dep"])
+ .add_dep(Dependency::new("fancy_dep", "0.2").optional(true))
+ .file("src/lib.rs", "")
+ .publish();
+
+ Package::new("fancy_dep", "0.2.4").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "bar"
+ version = "0.2.0"
+ authors = []
+ [dependencies]
+ dep = { workspace = true, default-features = false }
+
+ [workspace]
+ members = []
+ [workspace.dependencies]
+ dep = "0.1.0"
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ p.cargo("check")
+ .with_stderr(
+ "\
+[WARNING] [CWD]/Cargo.toml: `default-features` is ignored for dep, since `default-features` was \
+not specified for `workspace.dependencies.dep`, this could become a hard error in the future
+[UPDATING] `dummy-registry` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] fancy_dep v0.2.4 ([..])
+[DOWNLOADED] dep v0.1.0 ([..])
+[CHECKING] fancy_dep v0.2.4
+[CHECKING] dep v0.1.0
+[CHECKING] bar v0.2.0 ([CWD])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn inherit_def_feat_false_member_def_feat_true() {
+ Package::new("dep", "0.1.0")
+ .feature("default", &["fancy_dep"])
+ .add_dep(Dependency::new("fancy_dep", "0.2").optional(true))
+ .file("src/lib.rs", "")
+ .publish();
+
+ Package::new("fancy_dep", "0.2.4").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "bar"
+ version = "0.2.0"
+ authors = []
+ [dependencies]
+ dep = { workspace = true, default-features = true }
+
+ [workspace]
+ members = []
+ [workspace.dependencies]
+ dep = { version = "0.1.0", default-features = false }
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ p.cargo("check")
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] fancy_dep v0.2.4 ([..])
+[DOWNLOADED] dep v0.1.0 ([..])
+[CHECKING] fancy_dep v0.2.4
+[CHECKING] dep v0.1.0
+[CHECKING] bar v0.2.0 ([CWD])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run();
+}