Skip to content

Commit 726e2a7

Browse files
authored
Get all members as available targets even though default-members was specified. (#15199)
### What does this PR try to resolve? The old behavior gets members from `default-members` if specified in a virtual workspace, this PR gets all workspace members for `Available` target hints. Fixes #14544 ### How should we test and review this PR? The first commit added the test, the second commit addressed the issue. ### Additional information
2 parents 8686e24 + fa7712d commit 726e2a7

File tree

6 files changed

+250
-30
lines changed

6 files changed

+250
-30
lines changed

src/cargo/ops/cargo_compile/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ pub fn create_bcx<'a, 'gctx>(
374374
let generator = UnitGenerator {
375375
ws,
376376
packages: &to_builds,
377+
spec,
377378
target_data: &target_data,
378379
filter,
379380
requested_kinds: &build_config.requested_kinds,

src/cargo/ops/cargo_compile/unit_generator.rs

Lines changed: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::util::{closest_msg, CargoResult};
1717

1818
use super::compile_filter::{CompileFilter, FilterRule, LibRule};
1919
use super::packages::build_glob;
20+
use super::Packages;
2021

2122
/// A proposed target.
2223
///
@@ -47,6 +48,7 @@ struct Proposal<'a> {
4748
pub(super) struct UnitGenerator<'a, 'gctx> {
4849
pub ws: &'a Workspace<'gctx>,
4950
pub packages: &'a [&'a Package],
51+
pub spec: &'a Packages,
5052
pub target_data: &'a RustcTargetData<'gctx>,
5153
pub filter: &'a CompileFilter,
5254
pub requested_kinds: &'a [CompileKind],
@@ -247,15 +249,15 @@ impl<'a> UnitGenerator<'a, '_> {
247249
mode: CompileMode,
248250
) -> CargoResult<Vec<Proposal<'a>>> {
249251
let is_glob = is_glob_pattern(target_name);
250-
let proposals = if is_glob {
251-
let pattern = build_glob(target_name)?;
252-
let filter = |t: &Target| is_expected_kind(t) && pattern.matches(t.name());
253-
self.filter_targets(filter, true, mode)
254-
} else {
255-
let filter = |t: &Target| t.name() == target_name && is_expected_kind(t);
256-
self.filter_targets(filter, true, mode)
252+
let pattern = build_glob(target_name)?;
253+
let filter = |t: &Target| {
254+
if is_glob {
255+
is_expected_kind(t) && pattern.matches(t.name())
256+
} else {
257+
is_expected_kind(t) && t.name() == target_name
258+
}
257259
};
258-
260+
let proposals = self.filter_targets(filter, true, mode);
259261
if proposals.is_empty() {
260262
let targets = self
261263
.packages
@@ -267,35 +269,103 @@ impl<'a> UnitGenerator<'a, '_> {
267269
})
268270
.collect::<Vec<_>>();
269271
let suggestion = closest_msg(target_name, targets.iter(), |t| t.name(), "target");
272+
let targets_elsewhere = self.get_targets_from_other_packages(filter)?;
273+
let need_append_targets_elsewhere = !targets_elsewhere.is_empty();
274+
let append_targets_elsewhere = |msg: &mut String, prefix: &str| {
275+
let mut available_msg = Vec::new();
276+
for (package, targets) in targets_elsewhere {
277+
if !targets.is_empty() {
278+
available_msg.push(format!(
279+
"help: Available {target_desc} in `{package}` package:"
280+
));
281+
for target in targets {
282+
available_msg.push(format!(" {target}"));
283+
}
284+
}
285+
}
286+
if !available_msg.is_empty() {
287+
write!(msg, "{prefix}{}", available_msg.join("\n"))?;
288+
}
289+
CargoResult::Ok(())
290+
};
291+
292+
let unmatched_packages = || match self.spec {
293+
Packages::Default | Packages::OptOut(_) | Packages::All(_) => {
294+
"default-run packages".to_owned()
295+
}
296+
Packages::Packages(packages) => {
297+
let first = packages
298+
.first()
299+
.expect("The number of packages must be at least 1");
300+
if packages.len() == 1 {
301+
format!("`{}` package", first)
302+
} else {
303+
format!("`{}`, ... packages", first)
304+
}
305+
}
306+
};
307+
308+
let mut msg = String::new();
270309
if !suggestion.is_empty() {
271-
anyhow::bail!(
272-
"no {} target {} `{}`{}",
310+
write!(
311+
msg,
312+
"no {} target {} `{}` in {}{}",
273313
target_desc,
274314
if is_glob { "matches pattern" } else { "named" },
275315
target_name,
276-
suggestion
277-
);
316+
unmatched_packages(),
317+
suggestion,
318+
)?;
319+
append_targets_elsewhere(&mut msg, "\n")?;
278320
} else {
279-
let mut msg = String::new();
280321
writeln!(
281322
msg,
282-
"no {} target {} `{}`.",
323+
"no {} target {} `{}` in {}.",
283324
target_desc,
284325
if is_glob { "matches pattern" } else { "named" },
285326
target_name,
327+
unmatched_packages()
286328
)?;
287-
if !targets.is_empty() {
329+
330+
append_targets_elsewhere(&mut msg, "")?;
331+
if !targets.is_empty() && !need_append_targets_elsewhere {
288332
writeln!(msg, "Available {} targets:", target_desc)?;
289333
for target in targets {
290334
writeln!(msg, " {}", target.name())?;
291335
}
292336
}
293-
anyhow::bail!(msg);
294337
}
338+
anyhow::bail!(msg);
295339
}
296340
Ok(proposals)
297341
}
298342

343+
fn get_targets_from_other_packages(
344+
&self,
345+
filter_fn: impl Fn(&Target) -> bool,
346+
) -> CargoResult<Vec<(&str, Vec<&str>)>> {
347+
let packages = Packages::All(Vec::new()).get_packages(self.ws)?;
348+
let targets = packages
349+
.into_iter()
350+
.filter_map(|pkg| {
351+
let mut targets: Vec<_> = pkg
352+
.manifest()
353+
.targets()
354+
.iter()
355+
.filter_map(|target| filter_fn(target).then(|| target.name()))
356+
.collect();
357+
if targets.is_empty() {
358+
None
359+
} else {
360+
targets.sort();
361+
Some((pkg.name().as_str(), targets))
362+
}
363+
})
364+
.collect();
365+
366+
Ok(targets)
367+
}
368+
299369
/// Returns a list of proposed targets based on command-line target selection flags.
300370
fn list_rule_targets(
301371
&self,

tests/testsuite/build.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,7 @@ fn cargo_compile_with_filename() {
13371337
p.cargo("build --bin bin.rs")
13381338
.with_status(101)
13391339
.with_stderr_data(str![[r#"
1340-
[ERROR] no bin target named `bin.rs`.
1340+
[ERROR] no bin target named `bin.rs` in default-run packages.
13411341
Available bin targets:
13421342
a
13431343
@@ -1348,7 +1348,7 @@ Available bin targets:
13481348
p.cargo("build --bin a.rs")
13491349
.with_status(101)
13501350
.with_stderr_data(str![[r#"
1351-
[ERROR] no bin target named `a.rs`
1351+
[ERROR] no bin target named `a.rs` in default-run packages
13521352
13531353
[HELP] a target with a similar name exists: `a`
13541354
@@ -1358,7 +1358,7 @@ Available bin targets:
13581358
p.cargo("build --example example.rs")
13591359
.with_status(101)
13601360
.with_stderr_data(str![[r#"
1361-
[ERROR] no example target named `example.rs`.
1361+
[ERROR] no example target named `example.rs` in default-run packages.
13621362
Available example targets:
13631363
a
13641364
@@ -1369,7 +1369,7 @@ Available example targets:
13691369
p.cargo("build --example a.rs")
13701370
.with_status(101)
13711371
.with_stderr_data(str![[r#"
1372-
[ERROR] no example target named `a.rs`
1372+
[ERROR] no example target named `a.rs` in default-run packages
13731373
13741374
[HELP] a target with a similar name exists: `a`
13751375
@@ -5906,7 +5906,7 @@ fn target_filters_workspace() {
59065906
ws.cargo("build -v --example ex")
59075907
.with_status(101)
59085908
.with_stderr_data(str![[r#"
5909-
[ERROR] no example target named `ex`
5909+
[ERROR] no example target named `ex` in default-run packages
59105910
59115911
[HELP] a target with a similar name exists: `ex1`
59125912
@@ -5916,7 +5916,7 @@ fn target_filters_workspace() {
59165916
ws.cargo("build -v --example 'ex??'")
59175917
.with_status(101)
59185918
.with_stderr_data(str![[r#"
5919-
[ERROR] no example target matches pattern `ex??`
5919+
[ERROR] no example target matches pattern `ex??` in default-run packages
59205920
59215921
[HELP] a target with a similar name exists: `ex1`
59225922

tests/testsuite/run.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ automatically infer them to be a target, such as in subfolders.
623623
624624
For more information on this warning you can consult
625625
https://github.com/rust-lang/cargo/issues/5330
626-
[ERROR] no example target named `a`.
626+
[ERROR] no example target named `a` in default-run packages.
627627
Available example targets:
628628
do_magic
629629
@@ -655,7 +655,7 @@ fn run_example_autodiscover_2015_with_autoexamples_disabled() {
655655
p.cargo("run --example a")
656656
.with_status(101)
657657
.with_stderr_data(str![[r#"
658-
[ERROR] no example target named `a`.
658+
[ERROR] no example target named `a` in default-run packages.
659659
Available example targets:
660660
do_magic
661661
@@ -743,7 +743,7 @@ fn run_with_filename() {
743743
p.cargo("run --bin bin.rs")
744744
.with_status(101)
745745
.with_stderr_data(str![[r#"
746-
[ERROR] no bin target named `bin.rs`.
746+
[ERROR] no bin target named `bin.rs` in default-run packages.
747747
Available bin targets:
748748
a
749749
@@ -754,7 +754,7 @@ Available bin targets:
754754
p.cargo("run --bin a.rs")
755755
.with_status(101)
756756
.with_stderr_data(str![[r#"
757-
[ERROR] no bin target named `a.rs`
757+
[ERROR] no bin target named `a.rs` in default-run packages
758758
759759
[HELP] a target with a similar name exists: `a`
760760
@@ -764,7 +764,7 @@ Available bin targets:
764764
p.cargo("run --example example.rs")
765765
.with_status(101)
766766
.with_stderr_data(str![[r#"
767-
[ERROR] no example target named `example.rs`.
767+
[ERROR] no example target named `example.rs` in default-run packages.
768768
Available example targets:
769769
a
770770
@@ -775,7 +775,7 @@ Available example targets:
775775
p.cargo("run --example a.rs")
776776
.with_status(101)
777777
.with_stderr_data(str![[r#"
778-
[ERROR] no example target named `a.rs`
778+
[ERROR] no example target named `a.rs` in default-run packages
779779
780780
[HELP] a target with a similar name exists: `a`
781781

tests/testsuite/test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,15 +2447,15 @@ fn bad_example() {
24472447
p.cargo("run --example foo")
24482448
.with_status(101)
24492449
.with_stderr_data(str![[r#"
2450-
[ERROR] no example target named `foo`.
2450+
[ERROR] no example target named `foo` in default-run packages.
24512451
24522452
24532453
"#]])
24542454
.run();
24552455
p.cargo("run --bin foo")
24562456
.with_status(101)
24572457
.with_stderr_data(str![[r#"
2458-
[ERROR] no bin target named `foo`.
2458+
[ERROR] no bin target named `foo` in default-run packages.
24592459
24602460
24612461
"#]])

0 commit comments

Comments
 (0)