Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates to edition handling. #9184

Merged
merged 11 commits into from
Feb 23, 2021
Prev Previous commit
Next Next commit
Add edition2021 cargo feature.
This is intended to help make it easier to test the 2021 edition.
  • Loading branch information
ehuss committed Feb 18, 2021
commit 2ae72ff747285b02a68a4ed4f983ff9425d624f0
6 changes: 2 additions & 4 deletions src/cargo/core/compiler/compilation.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ use semver::Version;

use super::BuildContext;
use crate::core::compiler::{CompileKind, Metadata, Unit};
use crate::core::{Edition, Package};
use crate::core::Package;
use crate::util::{self, config, join_paths, process, CargoResult, Config, ProcessBuilder};

/// Structure with enough information to run `rustdoc --test`.
@@ -187,9 +187,7 @@ impl<'cfg> Compilation<'cfg> {
let rustdoc = process(&*self.config.rustdoc()?);
let cmd = fill_rustc_tool_env(rustdoc, unit);
let mut p = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, true)?;
if unit.target.edition() != Edition::Edition2015 {
p.arg(format!("--edition={}", unit.target.edition()));
}
unit.target.edition().cmd_edition_arg(&mut p);

for crate_type in unit.target.rustc_crate_types() {
p.arg("--crate-type").arg(crate_type.as_str());
6 changes: 2 additions & 4 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ pub use crate::core::compiler::unit::{Unit, UnitInterner};
use crate::core::features::nightly_features_allowed;
use crate::core::manifest::TargetSourcePath;
use crate::core::profiles::{PanicStrategy, Profile, Strip};
use crate::core::{Edition, Feature, PackageId, Target};
use crate::core::{Feature, PackageId, Target};
use crate::util::errors::{self, CargoResult, CargoResultExt, ProcessError, VerboseError};
use crate::util::interning::InternedString;
use crate::util::machine_message::Message;
@@ -782,9 +782,7 @@ fn build_base_args(
cmd.arg("--crate-name").arg(&unit.target.crate_name());

let edition = unit.target.edition();
if edition != Edition::Edition2015 {
cmd.arg(format!("--edition={}", edition));
}
edition.cmd_edition_arg(cmd);

add_path_args(bcx, unit, cmd);
add_error_format_and_color(cx, cmd, cx.rmeta_required(unit));
32 changes: 31 additions & 1 deletion src/cargo/core/features.rs
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ use anyhow::{bail, Error};
use serde::{Deserialize, Serialize};

use crate::util::errors::CargoResult;
use crate::util::indented_lines;
use crate::util::{indented_lines, ProcessBuilder};

pub const SEE_CHANNELS: &str =
"See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information \
@@ -119,14 +119,41 @@ pub enum Edition {
}

impl Edition {
/// The latest edition (may or may not be stable).
pub const LATEST: Edition = Edition::Edition2021;

/// Returns the first version that a particular edition was released on
/// stable.
pub(crate) fn first_version(&self) -> Option<semver::Version> {
use Edition::*;
match self {
Edition2015 => None,
Edition2018 => Some(semver::Version::new(1, 31, 0)),
// FIXME: This will likely be 1.56, update when that seems more likely.
Edition2021 => Some(semver::Version::new(1, 62, 0)),
}
}

/// Returns `true` if this edition is stable in this release.
pub fn is_stable(&self) -> bool {
use Edition::*;
match self {
Edition2015 => true,
Edition2018 => true,
Edition2021 => false,
}
}

/// Updates the given [`ProcessBuilder`] to include the appropriate flags
/// for setting the edition.
pub(crate) fn cmd_edition_arg(&self, cmd: &mut ProcessBuilder) {
if *self != Edition::Edition2015 {
cmd.arg(format!("--edition={}", self));
}
if !self.is_stable() {
cmd.arg("-Z").arg("unstable-options");
}
}
}

impl fmt::Display for Edition {
@@ -282,6 +309,9 @@ features! {

// Specifying a minimal 'rust-version' attribute for crates
(unstable, rust_version, "", "reference/unstable.html#rust-version"),

// Support for 2021 edition.
(unstable, edition2021, "", "reference/unstable.html#edition-2021"),
}

const PUBLISH_LOCKFILE_REMOVED: &str = "The publish-lockfile key in Cargo.toml \
9 changes: 9 additions & 0 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
@@ -1061,6 +1061,15 @@ impl TomlManifest {
} else {
Edition::Edition2015
};
if edition == Edition::Edition2021 {
features.require(Feature::edition2021())?;
} else if !edition.is_stable() {
// Guard in case someone forgets to add .require()
return Err(util::errors::internal(format!(
"edition {} should be gated",
edition
)));
}

let rust_version = if let Some(rust_version) = &project.rust_version {
if features.require(Feature::rust_version()).is_err() {
20 changes: 20 additions & 0 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
@@ -1064,6 +1064,26 @@ version = "0.0.1"
rust-version = "1.42"
```

### edition 2021

Support for the 2021 [edition] can be enabled by adding the `edition2021`
unstable feature to the top of `Cargo.toml`:

```toml
cargo-features = ["edition2021"]

[package]
name = "my-package"
version = "0.1.0"
edition = "2021"
```

This feature is very unstable, and is only intended for early testing and
experimentation. Future nightly releases may introduce changes for the 2021
edition that may break your build.

[edition]: ../../edition-guide/index.html

<script>
(function() {
var fragments = {
90 changes: 89 additions & 1 deletion tests/testsuite/edition.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Tests for edition setting.

use cargo_test_support::{basic_lib_manifest, project};
use cargo::core::Edition;
use cargo_test_support::{basic_lib_manifest, is_nightly, project};

#[cargo_test]
fn edition_works_for_build_script() {
@@ -32,3 +33,90 @@ fn edition_works_for_build_script() {

p.cargo("build -v").run();
}

#[cargo_test]
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 p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "{}"
"#,
next
),
)
.file("src/lib.rs", "")
.build();

p.cargo("check")
.with_status(101)
.with_stderr(&format!(
"\
[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml`

Caused by:
feature `edition{next}` is required

this Cargo does not support nightly features, but if you
switch to nightly channel you can add
`cargo-features = [\"edition{next}\"]` to enable this feature
",
next = next
))
.run();
}

#[cargo_test]
fn edition_unstable() {
// During the period where a new edition is coming up, but not yet stable,
// this test will verify that it can be used with `cargo-features`. If
// there is no next edition, it does nothing.
if !is_nightly() {
// 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 p = project()
.file(
"Cargo.toml",
&format!(
r#"
cargo-features = ["edition{next}"]

[package]
name = "foo"
version = "0.1.0"
edition = "{next}"
"#,
next = next
),
)
.file("src/lib.rs", "")
.build();

p.cargo("check")
.masquerade_as_nightly_cargo()
.with_stderr(
"\
[CHECKING] foo [..]
[FINISHED] [..]
",
)
.run();
}