Skip to content

Commit 85b9566

Browse files
committed
Auto merge of #7191 - debris:prerelease_error_message, r=Eh2406
improve error message for unmatched prerelease dependencies fixes #7007 error message before: ``` error: no matching package named `a` found location searched: [..] perhaps you meant: a required by package `b v0.1.0 ([..])` ``` error message now ``` error: no matching package named `a` found location searched: [..] prerelease package needs to be specified explicitly a = { version = "0.1.1-alpha.0" } required by package `b v0.1.0 ([..])` ```
2 parents 26092da + 577968e commit 85b9566

File tree

2 files changed

+150
-86
lines changed

2 files changed

+150
-86
lines changed

src/cargo/core/resolver/errors.rs

Lines changed: 101 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -203,100 +203,115 @@ pub(super) fn activation_error(
203203
};
204204
candidates.sort_unstable_by(|a, b| b.version().cmp(a.version()));
205205

206-
let mut msg = if !candidates.is_empty() {
207-
let versions = {
208-
let mut versions = candidates
209-
.iter()
210-
.take(3)
211-
.map(|cand| cand.version().to_string())
212-
.collect::<Vec<_>>();
206+
let mut msg =
207+
if !candidates.is_empty() {
208+
let versions = {
209+
let mut versions = candidates
210+
.iter()
211+
.take(3)
212+
.map(|cand| cand.version().to_string())
213+
.collect::<Vec<_>>();
214+
215+
if candidates.len() > 3 {
216+
versions.push("...".into());
217+
}
218+
219+
versions.join(", ")
220+
};
221+
222+
let mut msg = format!(
223+
"failed to select a version for the requirement `{} = \"{}\"`\n \
224+
candidate versions found which didn't match: {}\n \
225+
location searched: {}\n",
226+
dep.package_name(),
227+
dep.version_req(),
228+
versions,
229+
registry.describe_source(dep.source_id()),
230+
);
231+
msg.push_str("required by ");
232+
msg.push_str(&describe_path(
233+
&cx.parents.path_to_bottom(&parent.package_id()),
234+
));
213235

214-
if candidates.len() > 3 {
215-
versions.push("...".into());
236+
// If we have a path dependency with a locked version, then this may
237+
// indicate that we updated a sub-package and forgot to run `cargo
238+
// update`. In this case try to print a helpful error!
239+
if dep.source_id().is_path() && dep.version_req().to_string().starts_with('=') {
240+
msg.push_str(
241+
"\nconsider running `cargo update` to update \
242+
a path dependency's locked version",
243+
);
216244
}
217245

218-
versions.join(", ")
219-
};
220-
221-
let mut msg = format!(
222-
"failed to select a version for the requirement `{} = \"{}\"`\n \
223-
candidate versions found which didn't match: {}\n \
224-
location searched: {}\n",
225-
dep.package_name(),
226-
dep.version_req(),
227-
versions,
228-
registry.describe_source(dep.source_id()),
229-
);
230-
msg.push_str("required by ");
231-
msg.push_str(&describe_path(
232-
&cx.parents.path_to_bottom(&parent.package_id()),
233-
));
234-
235-
// If we have a path dependency with a locked version, then this may
236-
// indicate that we updated a sub-package and forgot to run `cargo
237-
// update`. In this case try to print a helpful error!
238-
if dep.source_id().is_path() && dep.version_req().to_string().starts_with('=') {
239-
msg.push_str(
240-
"\nconsider running `cargo update` to update \
241-
a path dependency's locked version",
242-
);
243-
}
244-
245-
if registry.is_replaced(dep.source_id()) {
246-
msg.push_str("\nperhaps a crate was updated and forgotten to be re-vendored?");
247-
}
246+
if registry.is_replaced(dep.source_id()) {
247+
msg.push_str("\nperhaps a crate was updated and forgotten to be re-vendored?");
248+
}
248249

249-
msg
250-
} else {
251-
// Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`
252-
// was meant. So we try asking the registry for a `fuzzy` search for suggestions.
253-
let mut candidates = Vec::new();
254-
if let Err(e) = registry.query(&new_dep, &mut |s| candidates.push(s.name()), true) {
255-
return to_resolve_err(e);
256-
};
257-
candidates.sort_unstable();
258-
candidates.dedup();
259-
let mut candidates: Vec<_> = candidates
260-
.iter()
261-
.map(|n| (lev_distance(&*new_dep.package_name(), &*n), n))
262-
.filter(|&(d, _)| d < 4)
263-
.collect();
264-
candidates.sort_by_key(|o| o.0);
265-
let mut msg = format!(
266-
"no matching package named `{}` found\n\
267-
location searched: {}\n",
268-
dep.package_name(),
269-
dep.source_id()
270-
);
271-
if !candidates.is_empty() {
272-
let mut names = candidates
250+
msg
251+
} else {
252+
// Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`
253+
// was meant. So we try asking the registry for a `fuzzy` search for suggestions.
254+
let mut candidates = Vec::new();
255+
if let Err(e) = registry.query(&new_dep, &mut |s| candidates.push(s.clone()), true) {
256+
return to_resolve_err(e);
257+
};
258+
candidates.sort_unstable_by(|a, b| a.name().cmp(&b.name()));
259+
candidates.dedup_by(|a, b| a.name() == b.name());
260+
let mut candidates: Vec<_> = candidates
273261
.iter()
274-
.take(3)
275-
.map(|c| c.1.as_str())
276-
.collect::<Vec<_>>();
277-
278-
if candidates.len() > 3 {
279-
names.push("...");
262+
.map(|n| (lev_distance(&*new_dep.package_name(), &*n.name()), n))
263+
.filter(|&(d, _)| d < 4)
264+
.collect();
265+
candidates.sort_by_key(|o| o.0);
266+
let mut msg = format!(
267+
"no matching package named `{}` found\n\
268+
location searched: {}\n",
269+
dep.package_name(),
270+
dep.source_id()
271+
);
272+
if !candidates.is_empty() {
273+
// If dependency package name is equal to the name of the candidate here
274+
// it may be a prerelease package which hasn't been speficied correctly
275+
if dep.package_name() == candidates[0].1.name()
276+
&& candidates[0].1.package_id().version().is_prerelease()
277+
{
278+
msg.push_str("prerelease package needs to be specified explicitly\n");
279+
msg.push_str(&format!(
280+
"{name} = {{ version = \"{version}\" }}",
281+
name = candidates[0].1.name(),
282+
version = candidates[0].1.package_id().version()
283+
));
284+
} else {
285+
let mut names = candidates
286+
.iter()
287+
.take(3)
288+
.map(|c| c.1.name().as_str())
289+
.collect::<Vec<_>>();
290+
291+
if candidates.len() > 3 {
292+
names.push("...");
293+
}
294+
295+
msg.push_str("perhaps you meant: ");
296+
msg.push_str(&names.iter().enumerate().fold(
297+
String::default(),
298+
|acc, (i, el)| match i {
299+
0 => acc + el,
300+
i if names.len() - 1 == i && candidates.len() <= 3 => acc + " or " + el,
301+
_ => acc + ", " + el,
302+
},
303+
));
304+
}
305+
306+
msg.push_str("\n");
280307
}
281-
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-
},
308+
msg.push_str("required by ");
309+
msg.push_str(&describe_path(
310+
&cx.parents.path_to_bottom(&parent.package_id()),
290311
));
291-
msg.push_str("\n");
292-
}
293-
msg.push_str("required by ");
294-
msg.push_str(&describe_path(
295-
&cx.parents.path_to_bottom(&parent.package_id()),
296-
));
297312

298-
msg
299-
};
313+
msg
314+
};
300315

301316
if let Some(config) = config {
302317
if config.offline() {

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)