Skip to content

Commit 07340c9

Browse files
committed
Auto merge of #9437 - In-line:unknown-feature-resolver-1, r=ehuss
Fix bug when with resolver = "1" non-virtual package was allowing unknown features
2 parents 6ca6dd0 + 61b762b commit 07340c9

File tree

2 files changed

+97
-40
lines changed

2 files changed

+97
-40
lines changed

src/cargo/core/workspace.rs

+49-38
Original file line numberDiff line numberDiff line change
@@ -1224,7 +1224,10 @@ impl<'cfg> Workspace<'cfg> {
12241224
// really mean anything (either the member is built or it isn't).
12251225
// * With `--features nonmember?/feat`, cwd_features will
12261226
// handle processing it correctly.
1227-
let is_member = self.members().any(|member| member.name() == *dep_name);
1227+
let is_member = self.members().any(|member| {
1228+
// Check if `dep_name` is member of the workspace, but isn't associated with current package.
1229+
self.current_opt() != Some(member) && member.name() == *dep_name
1230+
});
12281231
if is_member && specs.iter().any(|spec| spec.name() == *dep_name) {
12291232
member_specific_features
12301233
.entry(*dep_name)
@@ -1237,49 +1240,57 @@ impl<'cfg> Workspace<'cfg> {
12371240
}
12381241
}
12391242

1240-
let ms = self.members().filter_map(|member| {
1241-
let member_id = member.package_id();
1242-
match self.current_opt() {
1243-
// The features passed on the command-line only apply to
1244-
// the "current" package (determined by the cwd).
1245-
Some(current) if member_id == current.package_id() => {
1246-
let feats = CliFeatures {
1247-
features: Rc::new(cwd_features.clone()),
1248-
all_features: cli_features.all_features,
1249-
uses_default_features: cli_features.uses_default_features,
1250-
};
1251-
Some((member, feats))
1252-
}
1253-
_ => {
1254-
// Ignore members that are not enabled on the command-line.
1255-
if specs.iter().any(|spec| spec.matches(member_id)) {
1256-
// -p for a workspace member that is not the "current"
1257-
// one.
1258-
//
1259-
// The odd behavior here is due to backwards
1260-
// compatibility. `--features` and
1261-
// `--no-default-features` used to only apply to the
1262-
// "current" package. As an extension, this allows
1263-
// member-name/feature-name to set member-specific
1264-
// features, which should be backwards-compatible.
1243+
let ms: Vec<_> = self
1244+
.members()
1245+
.filter_map(|member| {
1246+
let member_id = member.package_id();
1247+
match self.current_opt() {
1248+
// The features passed on the command-line only apply to
1249+
// the "current" package (determined by the cwd).
1250+
Some(current) if member_id == current.package_id() => {
12651251
let feats = CliFeatures {
1266-
features: Rc::new(
1267-
member_specific_features
1268-
.remove(member.name().as_str())
1269-
.unwrap_or_default(),
1270-
),
1271-
uses_default_features: true,
1252+
features: Rc::new(cwd_features.clone()),
12721253
all_features: cli_features.all_features,
1254+
uses_default_features: cli_features.uses_default_features,
12731255
};
12741256
Some((member, feats))
1275-
} else {
1276-
// This member was not requested on the command-line, skip.
1277-
None
1257+
}
1258+
_ => {
1259+
// Ignore members that are not enabled on the command-line.
1260+
if specs.iter().any(|spec| spec.matches(member_id)) {
1261+
// -p for a workspace member that is not the "current"
1262+
// one.
1263+
//
1264+
// The odd behavior here is due to backwards
1265+
// compatibility. `--features` and
1266+
// `--no-default-features` used to only apply to the
1267+
// "current" package. As an extension, this allows
1268+
// member-name/feature-name to set member-specific
1269+
// features, which should be backwards-compatible.
1270+
let feats = CliFeatures {
1271+
features: Rc::new(
1272+
member_specific_features
1273+
.remove(member.name().as_str())
1274+
.unwrap_or_default(),
1275+
),
1276+
uses_default_features: true,
1277+
all_features: cli_features.all_features,
1278+
};
1279+
Some((member, feats))
1280+
} else {
1281+
// This member was not requested on the command-line, skip.
1282+
None
1283+
}
12781284
}
12791285
}
1280-
}
1281-
});
1282-
ms.collect()
1286+
})
1287+
.collect();
1288+
1289+
// If any member specific features were not removed while iterating over members
1290+
// some features will be ignored.
1291+
assert!(member_specific_features.is_empty());
1292+
1293+
ms
12831294
}
12841295
}
12851296

tests/testsuite/package_features.rs

+48-2
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,11 @@ fn virtual_no_default_features() {
6565
.run();
6666

6767
p.cargo("check --features foo")
68-
.masquerade_as_nightly_cargo()
6968
.with_status(101)
7069
.with_stderr("[ERROR] none of the selected packages contains these features: foo")
7170
.run();
7271

7372
p.cargo("check --features a/dep1,b/f1,b/f2,f2")
74-
.masquerade_as_nightly_cargo()
7573
.with_status(101)
7674
.with_stderr("[ERROR] none of the selected packages contains these features: b/f2, f2")
7775
.run();
@@ -272,6 +270,48 @@ fn other_member_from_current() {
272270
.run();
273271
}
274272

273+
#[cargo_test]
274+
fn feature_default_resolver() {
275+
let p = project()
276+
.file(
277+
"Cargo.toml",
278+
r#"
279+
[package]
280+
name = "a"
281+
version = "0.1.0"
282+
283+
[features]
284+
test = []
285+
"#,
286+
)
287+
.file(
288+
"src/main.rs",
289+
r#"
290+
fn main() {
291+
if cfg!(feature = "test") {
292+
println!("feature set");
293+
}
294+
}
295+
"#,
296+
)
297+
.build();
298+
299+
p.cargo("check --features testt")
300+
.with_status(101)
301+
.with_stderr("[ERROR] Package `a[..]` does not have the feature `testt`")
302+
.run();
303+
304+
p.cargo("run --features test")
305+
.with_status(0)
306+
.with_stdout("feature set")
307+
.run();
308+
309+
p.cargo("run --features a/test")
310+
.with_status(101)
311+
.with_stderr("[ERROR] package `a[..]` does not have a dependency named `a`")
312+
.run();
313+
}
314+
275315
#[cargo_test]
276316
fn virtual_member_slash() {
277317
// member slash feature syntax
@@ -458,6 +498,12 @@ fn resolver1_member_features() {
458498
.cwd("member2")
459499
.with_stdout("m1-feature set")
460500
.run();
501+
502+
p.cargo("check -p member1 --features member1/m2-feature")
503+
.cwd("member2")
504+
.with_status(101)
505+
.with_stderr("[ERROR] Package `member1[..]` does not have the feature `m2-feature`")
506+
.run();
461507
}
462508

463509
#[cargo_test]

0 commit comments

Comments
 (0)