mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Make edition transitions easier.
This attempts to centralize all the edition stuff in one place (the `Edition` enum) so that adding a new edition or stabilizing one should be relatively little work (and more importantly, we don't miss things). Importantly, this changes `cargo new` to default to the latest stable. It also changes the `cargo fix --edition-idiom` behavior to only apply idioms for the *current* edition.
This commit is contained in:
parent
21cfac6c09
commit
aa61976c5f
@ -118,9 +118,35 @@ pub enum Edition {
|
||||
Edition2021,
|
||||
}
|
||||
|
||||
// Adding a new edition:
|
||||
// - Add the next edition to the enum.
|
||||
// - Update every match expression that now fails to compile.
|
||||
// - Update the `FromStr` impl.
|
||||
// - Update CLI_VALUES to include the new edition.
|
||||
// - Set LATEST_UNSTABLE to Some with the new edition.
|
||||
// - Add an unstable feature to the features! macro below for the new edition.
|
||||
// - Gate on that new feature in TomlManifest::to_real_manifest.
|
||||
// - Update the shell completion files.
|
||||
// - Update any failing tests (hopefully there are very few).
|
||||
//
|
||||
// Stabilization instructions:
|
||||
// - Set LATEST_UNSTABLE to None.
|
||||
// - Set LATEST_STABLE to the new version.
|
||||
// - Update `is_stable` to `true`.
|
||||
// - Set the editionNNNN feature to stable in the features macro below.
|
||||
// - Update the man page for the --edition flag.
|
||||
impl Edition {
|
||||
/// The latest edition (may or may not be stable).
|
||||
pub const LATEST: Edition = Edition::Edition2021;
|
||||
/// The latest edition that is unstable.
|
||||
///
|
||||
/// This is `None` if there is no next unstable edition.
|
||||
pub const LATEST_UNSTABLE: Option<Edition> = Some(Edition::Edition2021);
|
||||
/// The latest stable edition.
|
||||
pub const LATEST_STABLE: Edition = Edition::Edition2018;
|
||||
/// Possible values allowed for the `--edition` CLI flag.
|
||||
///
|
||||
/// This requires a static value due to the way clap works, otherwise I
|
||||
/// would have built this dynamically.
|
||||
pub const CLI_VALUES: &'static [&'static str] = &["2015", "2018", "2021"];
|
||||
|
||||
/// Returns the first version that a particular edition was released on
|
||||
/// stable.
|
||||
@ -180,6 +206,18 @@ impl Edition {
|
||||
Edition2021 => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not this edition supports the `rust_*_idioms` lint.
|
||||
///
|
||||
/// Ideally this would not be necessary...
|
||||
pub(crate) fn supports_idiom_lint(&self) -> bool {
|
||||
use Edition::*;
|
||||
match self {
|
||||
Edition2015 => false,
|
||||
Edition2018 => true,
|
||||
Edition2021 => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Edition {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::core::{Shell, Workspace};
|
||||
use crate::core::{Edition, Shell, Workspace};
|
||||
use crate::util::errors::{CargoResult, CargoResultExt};
|
||||
use crate::util::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo};
|
||||
use crate::util::{paths, restricted_names, Config};
|
||||
@ -743,7 +743,7 @@ edition = {}
|
||||
},
|
||||
match opts.edition {
|
||||
Some(edition) => toml::Value::String(edition.to_string()),
|
||||
None => toml::Value::String("2018".to_string()),
|
||||
None => toml::Value::String(Edition::LATEST_STABLE.to_string()),
|
||||
},
|
||||
match opts.registry {
|
||||
Some(registry) => format!(
|
||||
|
@ -675,8 +675,8 @@ impl FixArgs {
|
||||
cmd.args(&self.other).arg("--cap-lints=warn");
|
||||
if let Some(edition) = self.enabled_edition {
|
||||
cmd.arg("--edition").arg(edition.to_string());
|
||||
if self.idioms && edition >= Edition::Edition2018 {
|
||||
cmd.arg("-Wrust-2018-idioms");
|
||||
if self.idioms && edition.supports_idiom_lint() {
|
||||
cmd.arg(format!("-Wrust-{}-idioms", edition));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::core::compiler::{BuildConfig, MessageFormat};
|
||||
use crate::core::Workspace;
|
||||
use crate::core::{Edition, Workspace};
|
||||
use crate::ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};
|
||||
use crate::sources::CRATES_IO_REGISTRY;
|
||||
use crate::util::important_paths::find_root_manifest_for_wd;
|
||||
@ -188,7 +188,7 @@ pub trait AppExt: Sized {
|
||||
._arg(opt("lib", "Use a library template"))
|
||||
._arg(
|
||||
opt("edition", "Edition to set for the crate generated")
|
||||
.possible_values(&["2015", "2018", "2021"])
|
||||
.possible_values(Edition::CLI_VALUES)
|
||||
.value_name("YEAR"),
|
||||
)
|
||||
._arg(
|
||||
|
@ -39,11 +39,13 @@ fn edition_unstable_gated() {
|
||||
// During the period where a new edition is coming up, but not yet stable,
|
||||
// this test will verify that it cannot be used on stable. If there is no
|
||||
// next edition, it does nothing.
|
||||
let next = Edition::LATEST;
|
||||
if next.is_stable() {
|
||||
eprintln!("Next edition is currently not available, skipping test.");
|
||||
return;
|
||||
}
|
||||
let next = match Edition::LATEST_UNSTABLE {
|
||||
Some(next) => next,
|
||||
None => {
|
||||
eprintln!("Next edition is currently not available, skipping test.");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
@ -87,11 +89,13 @@ fn edition_unstable() {
|
||||
// This test is fundamentally always nightly.
|
||||
return;
|
||||
}
|
||||
let next = Edition::LATEST;
|
||||
if next.is_stable() {
|
||||
eprintln!("Next edition is currently not available, skipping test.");
|
||||
return;
|
||||
}
|
||||
let next = match Edition::LATEST_UNSTABLE {
|
||||
Some(next) => next,
|
||||
None => {
|
||||
eprintln!("Next edition is currently not available, skipping test.");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
|
@ -795,12 +795,14 @@ fn prepare_for_unstable() {
|
||||
// During the period where a new edition is coming up, but not yet stable,
|
||||
// this test will verify that it cannot be migrated to on stable. If there
|
||||
// is no next edition, it does nothing.
|
||||
let next = Edition::LATEST;
|
||||
if next.is_stable() {
|
||||
eprintln!("Next edition is currently not available, skipping test.");
|
||||
return;
|
||||
}
|
||||
let latest_stable = next.previous().unwrap();
|
||||
let next = match Edition::LATEST_UNSTABLE {
|
||||
Some(next) => next,
|
||||
None => {
|
||||
eprintln!("Next edition is currently not available, skipping test.");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let latest_stable = Edition::LATEST_STABLE;
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
@ -853,12 +855,7 @@ To learn more, run the command again with --verbose.
|
||||
#[cargo_test]
|
||||
fn prepare_for_latest_stable() {
|
||||
// This is the stable counterpart of prepare_for_unstable.
|
||||
let latest = Edition::LATEST;
|
||||
let latest_stable = if latest.is_stable() {
|
||||
latest
|
||||
} else {
|
||||
latest.previous().unwrap()
|
||||
};
|
||||
let latest_stable = Edition::LATEST_STABLE;
|
||||
let previous = latest_stable.previous().unwrap();
|
||||
let p = project()
|
||||
.file(
|
||||
@ -897,11 +894,13 @@ fn prepare_for_already_on_latest_unstable() {
|
||||
// This test is fundamentally always nightly.
|
||||
return;
|
||||
}
|
||||
let next_edition = Edition::LATEST;
|
||||
if next_edition.is_stable() {
|
||||
eprintln!("Next edition is currently not available, skipping test.");
|
||||
return;
|
||||
}
|
||||
let next_edition = match Edition::LATEST_UNSTABLE {
|
||||
Some(next) => next,
|
||||
None => {
|
||||
eprintln!("Next edition is currently not available, skipping test.");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
@ -936,11 +935,11 @@ fn prepare_for_already_on_latest_unstable() {
|
||||
#[cargo_test]
|
||||
fn prepare_for_already_on_latest_stable() {
|
||||
// Stable counterpart of prepare_for_already_on_latest_unstable.
|
||||
if !Edition::LATEST.is_stable() {
|
||||
if Edition::LATEST_UNSTABLE.is_some() {
|
||||
eprintln!("This test cannot run while the latest edition is unstable, skipping.");
|
||||
return;
|
||||
}
|
||||
let latest_stable = Edition::LATEST;
|
||||
let latest_stable = Edition::LATEST_STABLE;
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
|
Loading…
x
Reference in New Issue
Block a user