Skip to content

Commit 4efeda7

Browse files
authored
fix(toml): show required rust-version in unstable edition error (#16653)
## What does this PR try to resolve? Fixes the unhelpful error when a package declares an unstable edition on a stable Cargo toolchain. Previously the error told the user to "try a newer version of Cargo" but gave no indication of *which* version, forcing them to dig through docs. This PR adds a `help:` line that names the required toolchain version, derived from the package's `rust-version` field (or from `Edition::first_version()` once that is set at unstable time). Before: ``` Consider trying a newer version of Cargo (this may require the nightly release). See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#unstable-editions ``` After: ``` Consider trying a newer version of Cargo (this may require the nightly release). help: mypackage@0.1.0 requires rustc 1.90 See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#unstable-editions ``` Also fixes a latent bug in `edition_unstable_gated`: it expected `feature 'edition{next}'` but current code emits `feature 'unstable-editions'`. The test was silently skipping because `Edition::LATEST_UNSTABLE` is `None`. Fixes #15305
2 parents f298b8c + 2866bb6 commit 4efeda7

3 files changed

Lines changed: 62 additions & 1 deletion

File tree

src/cargo/core/features.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,19 @@ impl Features {
733733

734734
/// Checks if the given feature is enabled.
735735
pub fn require(&self, feature: &Feature) -> CargoResult<()> {
736+
self.require_with_hint(feature, None)
737+
}
738+
739+
/// Like [`require`][Self::require], but appends an optional help message
740+
/// to the error, placed just before the documentation link.
741+
///
742+
/// Use this when the call site has additional context (e.g. the package's
743+
/// `rust-version`) that can make the error more actionable.
744+
pub(crate) fn require_with_hint(
745+
&self,
746+
feature: &Feature,
747+
hint: Option<&str>,
748+
) -> CargoResult<()> {
736749
if feature.is_enabled(self) {
737750
return Ok(());
738751
}
@@ -773,6 +786,9 @@ impl Features {
773786
about the status of this feature.",
774787
feature.docs
775788
);
789+
if let Some(hint) = hint {
790+
let _ = writeln!(msg, "{hint}");
791+
}
776792

777793
bail!("{}", msg);
778794
}

src/cargo/util/toml/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1359,7 +1359,15 @@ pub fn to_real_manifest(
13591359
default_edition
13601360
};
13611361
if !edition.is_stable() {
1362-
features.require(Feature::unstable_editions())?;
1362+
let version = normalized_package
1363+
.normalized_version()
1364+
.expect("previously normalized")
1365+
.map(|v| format!("@{v}"))
1366+
.unwrap_or_default();
1367+
let hint = rust_version
1368+
.as_ref()
1369+
.map(|rv| format!("help: {package_name}{version} requires rust {rv}"));
1370+
features.require_with_hint(Feature::unstable_editions(), hint.as_deref())?;
13631371
}
13641372

13651373
if original_toml.project.is_some() {

tests/testsuite/edition.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,43 @@ Caused by:
242242
.run();
243243
}
244244

245+
#[cargo_test]
246+
fn future_edition_with_rust_version_hint() {
247+
// When an unstable edition is used and the package has `rust-version` set,
248+
// the error message should include a `help:` line pointing the user at the
249+
// required Rust toolchain version, matching the format used elsewhere in
250+
// Cargo (e.g. `{name}@{version} requires rust {msrv}`).
251+
let p = project()
252+
.file(
253+
"Cargo.toml",
254+
r#"
255+
[package]
256+
name = "foo"
257+
version = "0.1.0"
258+
edition = "future"
259+
rust-version = "1.90"
260+
"#,
261+
)
262+
.file("src/lib.rs", "")
263+
.build();
264+
265+
p.cargo("check")
266+
.with_status(101)
267+
.with_stderr_data(str![[r#"
268+
[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`
269+
270+
Caused by:
271+
feature `unstable-editions` is required
272+
273+
The package requires the Cargo feature called `unstable-editions`, but that feature is not stabilized in this version of Cargo ([..]).
274+
Consider trying a newer version of Cargo (this may require the nightly release).
275+
See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#unstable-editions for more information about the status of this feature.
276+
[HELP] foo@0.1.0 requires rust 1.90
277+
278+
"#]])
279+
.run();
280+
}
281+
245282
#[cargo_test(nightly, reason = "future edition is always unstable")]
246283
fn future_edition_works() {
247284
let p = project()

0 commit comments

Comments
 (0)