Skip to content

Commit 1e9bd72

Browse files
committed
fix #7007, improve error message for unmatched prerelease dependencies
1 parent 1f74bdf commit 1e9bd72

File tree

2 files changed

+83
-21
lines changed

2 files changed

+83
-21
lines changed

src/cargo/core/resolver/errors.rs

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -251,14 +251,14 @@ pub(super) fn activation_error(
251251
// Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`
252252
// was meant. So we try asking the registry for a `fuzzy` search for suggestions.
253253
let mut candidates = Vec::new();
254-
if let Err(e) = registry.query(&new_dep, &mut |s| candidates.push(s.name()), true) {
254+
if let Err(e) = registry.query(&new_dep, &mut |s| candidates.push(s.clone()), true) {
255255
return to_resolve_err(e);
256256
};
257-
candidates.sort_unstable();
258-
candidates.dedup();
257+
candidates.sort_unstable_by(|a, b| a.name().cmp(&b.name()));
258+
candidates.dedup_by(|a, b| a.name() == b.name());
259259
let mut candidates: Vec<_> = candidates
260260
.iter()
261-
.map(|n| (lev_distance(&*new_dep.package_name(), &*n), n))
261+
.map(|n| (lev_distance(&*new_dep.package_name(), &*n.name()), n))
262262
.filter(|&(d, _)| d < 4)
263263
.collect();
264264
candidates.sort_by_key(|o| o.0);
@@ -269,25 +269,38 @@ pub(super) fn activation_error(
269269
dep.source_id()
270270
);
271271
if !candidates.is_empty() {
272-
let mut names = candidates
273-
.iter()
274-
.take(3)
275-
.map(|c| c.1.as_str())
276-
.collect::<Vec<_>>();
277-
278-
if candidates.len() > 3 {
279-
names.push("...");
272+
// If dependency package name is equal to the name of the candidate here
273+
// it may be a prerelease package which hasn't been speficied correctly
274+
if dep.package_name() == candidates[0].1.name() &&
275+
candidates[0].1.package_id().version().is_prerelease() {
276+
msg.push_str("prerelease package needs to be specified explicitly\n");
277+
msg.push_str(&format!(
278+
"{name} = {{ version = \"{version}\" }}",
279+
name = candidates[0].1.name(),
280+
version = candidates[0].1.package_id().version()
281+
));
282+
} else {
283+
let mut names = candidates
284+
.iter()
285+
.take(3)
286+
.map(|c| c.1.name().as_str())
287+
.collect::<Vec<_>>();
288+
289+
if candidates.len() > 3 {
290+
names.push("...");
291+
}
292+
293+
msg.push_str("perhaps you meant: ");
294+
msg.push_str(&names.iter().enumerate().fold(
295+
String::default(),
296+
|acc, (i, el)| match i {
297+
0 => acc + el,
298+
i if names.len() - 1 == i && candidates.len() <= 3 => acc + " or " + el,
299+
_ => acc + ", " + el,
300+
},
301+
));
280302
}
281303

282-
msg.push_str("perhaps you meant: ");
283-
msg.push_str(&names.iter().enumerate().fold(
284-
String::default(),
285-
|acc, (i, el)| match i {
286-
0 => acc + el,
287-
i if names.len() - 1 == i && candidates.len() <= 3 => acc + " or " + el,
288-
_ => acc + ", " + el,
289-
},
290-
));
291304
msg.push_str("\n");
292305
}
293306
msg.push_str("required by ");

tests/testsuite/registry.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,55 @@ fn use_semver() {
13951395
p.cargo("build").run();
13961396
}
13971397

1398+
#[cargo_test]
1399+
fn use_semver_package_incorrectly() {
1400+
let p = project()
1401+
.file(
1402+
"Cargo.toml",
1403+
r#"
1404+
[workspace]
1405+
members = ["a", "b"]
1406+
"#,
1407+
)
1408+
.file(
1409+
"a/Cargo.toml",
1410+
r#"
1411+
[project]
1412+
name = "a"
1413+
version = "0.1.1-alpha.0"
1414+
authors = []
1415+
"#,
1416+
)
1417+
.file(
1418+
"b/Cargo.toml",
1419+
r#"
1420+
[project]
1421+
name = "b"
1422+
version = "0.1.0"
1423+
authors = []
1424+
1425+
[dependencies]
1426+
a = { version = "^0.1", path = "../a" }
1427+
"#,
1428+
)
1429+
.file("a/src/main.rs", "fn main() {}")
1430+
.file("b/src/main.rs", "fn main() {}")
1431+
.build();
1432+
1433+
p.cargo("build")
1434+
.with_status(101)
1435+
.with_stderr(
1436+
"\
1437+
error: no matching package named `a` found
1438+
location searched: [..]
1439+
prerelease package needs to be specified explicitly
1440+
a = { version = \"0.1.1-alpha.0\" }
1441+
required by package `b v0.1.0 ([..])`
1442+
",
1443+
)
1444+
.run();
1445+
}
1446+
13981447
#[cargo_test]
13991448
fn only_download_relevant() {
14001449
let p = project()

0 commit comments

Comments
 (0)