Auto merge of #50080 - klnusbaum:edition_49591, r=Manishearth
add --edition option This adds an official `edition` flag to the rust compiler
This commit is contained in:
commit
9af69fe232
8 changed files with 78 additions and 39 deletions
|
@ -16,6 +16,8 @@ pub use self::CrateType::*;
|
||||||
pub use self::Passes::*;
|
pub use self::Passes::*;
|
||||||
pub use self::DebugInfoLevel::*;
|
pub use self::DebugInfoLevel::*;
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use session::{early_error, early_warn, Session};
|
use session::{early_error, early_warn, Session};
|
||||||
use session::search_paths::SearchPaths;
|
use session::search_paths::SearchPaths;
|
||||||
|
|
||||||
|
@ -28,7 +30,7 @@ use middle::cstore;
|
||||||
|
|
||||||
use syntax::ast::{self, IntTy, UintTy};
|
use syntax::ast::{self, IntTy, UintTy};
|
||||||
use syntax::codemap::{FileName, FilePathMapping};
|
use syntax::codemap::{FileName, FilePathMapping};
|
||||||
use syntax::edition::Edition;
|
use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use syntax::parse;
|
use syntax::parse;
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
|
@ -410,6 +412,7 @@ top_level_options!(
|
||||||
|
|
||||||
// Remap source path prefixes in all output (messages, object files, debug, etc)
|
// Remap source path prefixes in all output (messages, object files, debug, etc)
|
||||||
remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
|
remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
|
||||||
|
edition: Edition [TRACKED],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -589,6 +592,7 @@ pub fn basic_options() -> Options {
|
||||||
cli_forced_codegen_units: None,
|
cli_forced_codegen_units: None,
|
||||||
cli_forced_thinlto_off: false,
|
cli_forced_thinlto_off: false,
|
||||||
remap_path_prefix: Vec::new(),
|
remap_path_prefix: Vec::new(),
|
||||||
|
edition: DEFAULT_EDITION,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,8 +777,6 @@ macro_rules! options {
|
||||||
Some("`string` or `string=string`");
|
Some("`string` or `string=string`");
|
||||||
pub const parse_lto: Option<&'static str> =
|
pub const parse_lto: Option<&'static str> =
|
||||||
Some("one of `thin`, `fat`, or omitted");
|
Some("one of `thin`, `fat`, or omitted");
|
||||||
pub const parse_edition: Option<&'static str> =
|
|
||||||
Some("one of: `2015`, `2018`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -782,7 +784,6 @@ macro_rules! options {
|
||||||
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
|
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
|
||||||
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
|
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use syntax::edition::Edition;
|
|
||||||
|
|
||||||
$(
|
$(
|
||||||
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
|
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
|
||||||
|
@ -985,20 +986,6 @@ macro_rules! options {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool {
|
|
||||||
match v {
|
|
||||||
Some(s) => {
|
|
||||||
let edition = s.parse();
|
|
||||||
if let Ok(parsed) = edition {
|
|
||||||
*slot = parsed;
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
) }
|
) }
|
||||||
|
|
||||||
|
@ -1292,10 +1279,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
`everybody_loops` (all function bodies replaced with `loop {}`),
|
`everybody_loops` (all function bodies replaced with `loop {}`),
|
||||||
`hir` (the HIR), `hir,identified`, or
|
`hir` (the HIR), `hir,identified`, or
|
||||||
`hir,typed` (HIR with types for each node)."),
|
`hir,typed` (HIR with types for each node)."),
|
||||||
edition: Edition = (Edition::Edition2015, parse_edition, [TRACKED],
|
|
||||||
"The edition to build Rust with. Newer editions may include features
|
|
||||||
that require breaking changes. The default edition is 2015 (the first
|
|
||||||
edition). Crates compiled with different editions can be linked together."),
|
|
||||||
run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||||
"run `dsymutil` and delete intermediate object files"),
|
"run `dsymutil` and delete intermediate object files"),
|
||||||
ui_testing: bool = (false, parse_bool, [UNTRACKED],
|
ui_testing: bool = (false, parse_bool, [UNTRACKED],
|
||||||
|
@ -1656,6 +1639,12 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
|
||||||
`expanded,identified` (fully parenthesized, AST nodes with IDs).",
|
`expanded,identified` (fully parenthesized, AST nodes with IDs).",
|
||||||
"TYPE",
|
"TYPE",
|
||||||
),
|
),
|
||||||
|
opt::opt_s(
|
||||||
|
"",
|
||||||
|
"edition",
|
||||||
|
"Specify which edition of the compiler to use when compiling code.",
|
||||||
|
EDITION_NAME_LIST,
|
||||||
|
),
|
||||||
opt::multi_s(
|
opt::multi_s(
|
||||||
"",
|
"",
|
||||||
"remap-path-prefix",
|
"remap-path-prefix",
|
||||||
|
@ -1715,6 +1704,34 @@ pub fn build_session_options_and_crate_config(
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let edition = match matches.opt_str("edition") {
|
||||||
|
Some(arg) => match Edition::from_str(&arg){
|
||||||
|
Ok(edition) => edition,
|
||||||
|
Err(_) => early_error(
|
||||||
|
ErrorOutputType::default(),
|
||||||
|
&format!(
|
||||||
|
"argument for --edition must be one of: \
|
||||||
|
{}. (instead was `{}`)",
|
||||||
|
EDITION_NAME_LIST,
|
||||||
|
arg
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
None => DEFAULT_EDITION,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !edition.is_stable() && !nightly_options::is_nightly_build() {
|
||||||
|
early_error(
|
||||||
|
ErrorOutputType::default(),
|
||||||
|
&format!(
|
||||||
|
"Edition {} is unstable an only\
|
||||||
|
available for nightly builds of rustc.",
|
||||||
|
edition,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// We need the opts_present check because the driver will send us Matches
|
// We need the opts_present check because the driver will send us Matches
|
||||||
// with only stable options if no unstable options are used. Since error-format
|
// with only stable options if no unstable options are used. Since error-format
|
||||||
// is unstable, it will not be present. We have to use opts_present not
|
// is unstable, it will not be present. We have to use opts_present not
|
||||||
|
@ -2171,6 +2188,7 @@ pub fn build_session_options_and_crate_config(
|
||||||
cli_forced_codegen_units: codegen_units,
|
cli_forced_codegen_units: codegen_units,
|
||||||
cli_forced_thinlto_off: disable_thinlto,
|
cli_forced_thinlto_off: disable_thinlto,
|
||||||
remap_path_prefix,
|
remap_path_prefix,
|
||||||
|
edition,
|
||||||
},
|
},
|
||||||
cfg,
|
cfg,
|
||||||
)
|
)
|
||||||
|
@ -2300,11 +2318,12 @@ mod dep_tracking {
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use super::{CrateType, DebugInfoLevel, Edition, ErrorOutputType, Lto, OptLevel, OutputTypes,
|
use super::{CrateType, DebugInfoLevel, ErrorOutputType, Lto, OptLevel, OutputTypes,
|
||||||
Passes, Sanitizer};
|
Passes, Sanitizer};
|
||||||
use syntax::feature_gate::UnstableFeatures;
|
use syntax::feature_gate::UnstableFeatures;
|
||||||
use rustc_back::{PanicStrategy, RelroLevel};
|
use rustc_back::{PanicStrategy, RelroLevel};
|
||||||
use rustc_back::target::TargetTriple;
|
use rustc_back::target::TargetTriple;
|
||||||
|
use syntax::edition::Edition;
|
||||||
|
|
||||||
pub trait DepTrackingHash {
|
pub trait DepTrackingHash {
|
||||||
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
|
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
|
||||||
|
@ -2363,8 +2382,8 @@ mod dep_tracking {
|
||||||
impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
|
impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
|
||||||
impl_dep_tracking_hash_via_hash!(Sanitizer);
|
impl_dep_tracking_hash_via_hash!(Sanitizer);
|
||||||
impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
|
impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
|
||||||
impl_dep_tracking_hash_via_hash!(Edition);
|
|
||||||
impl_dep_tracking_hash_via_hash!(TargetTriple);
|
impl_dep_tracking_hash_via_hash!(TargetTriple);
|
||||||
|
impl_dep_tracking_hash_via_hash!(Edition);
|
||||||
|
|
||||||
impl_dep_tracking_hash_for_sortable_vec_of!(String);
|
impl_dep_tracking_hash_for_sortable_vec_of!(String);
|
||||||
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
|
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
|
||||||
|
@ -2437,6 +2456,7 @@ mod tests {
|
||||||
use super::{Externs, OutputType, OutputTypes};
|
use super::{Externs, OutputType, OutputTypes};
|
||||||
use rustc_back::{PanicStrategy, RelroLevel};
|
use rustc_back::{PanicStrategy, RelroLevel};
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
|
use syntax::edition::{Edition, DEFAULT_EDITION};
|
||||||
use syntax;
|
use syntax;
|
||||||
|
|
||||||
fn optgroups() -> getopts::Options {
|
fn optgroups() -> getopts::Options {
|
||||||
|
@ -3081,4 +3101,17 @@ mod tests {
|
||||||
opts.debugging_opts.relro_level = Some(RelroLevel::Full);
|
opts.debugging_opts.relro_level = Some(RelroLevel::Full);
|
||||||
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
|
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_edition_parsing() {
|
||||||
|
// test default edition
|
||||||
|
let options = super::basic_options();
|
||||||
|
assert!(options.edition == DEFAULT_EDITION);
|
||||||
|
|
||||||
|
let matches = optgroups()
|
||||||
|
.parse(&["--edition=2018".to_string()])
|
||||||
|
.unwrap();
|
||||||
|
let (sessopts, _) = build_session_options_and_crate_config(&matches);
|
||||||
|
assert!(sessopts.edition == Edition::Edition2018)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -934,11 +934,11 @@ impl Session {
|
||||||
|
|
||||||
/// Are we allowed to use features from the Rust 2018 edition?
|
/// Are we allowed to use features from the Rust 2018 edition?
|
||||||
pub fn rust_2018(&self) -> bool {
|
pub fn rust_2018(&self) -> bool {
|
||||||
self.opts.debugging_opts.edition >= Edition::Edition2018
|
self.opts.edition >= Edition::Edition2018
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edition(&self) -> Edition {
|
pub fn edition(&self) -> Edition {
|
||||||
self.opts.debugging_opts.edition
|
self.opts.edition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -691,7 +691,7 @@ where
|
||||||
krate,
|
krate,
|
||||||
&sess.parse_sess,
|
&sess.parse_sess,
|
||||||
sess.opts.test,
|
sess.opts.test,
|
||||||
sess.opts.debugging_opts.edition,
|
sess.edition(),
|
||||||
);
|
);
|
||||||
// these need to be set "early" so that expansion sees `quote` if enabled.
|
// these need to be set "early" so that expansion sees `quote` if enabled.
|
||||||
sess.init_features(features);
|
sess.init_features(features);
|
||||||
|
|
|
@ -155,10 +155,10 @@ pub fn run_core(search_paths: SearchPaths,
|
||||||
actually_rustdoc: true,
|
actually_rustdoc: true,
|
||||||
debugging_opts: config::DebuggingOptions {
|
debugging_opts: config::DebuggingOptions {
|
||||||
force_unstable_if_unmarked,
|
force_unstable_if_unmarked,
|
||||||
edition,
|
|
||||||
..config::basic_debugging_options()
|
..config::basic_debugging_options()
|
||||||
},
|
},
|
||||||
error_format,
|
error_format,
|
||||||
|
edition,
|
||||||
..config::basic_options().clone()
|
..config::basic_options().clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -80,9 +80,9 @@ pub fn run(input_path: &Path,
|
||||||
lint_cap: Some(::rustc::lint::Level::Allow),
|
lint_cap: Some(::rustc::lint::Level::Allow),
|
||||||
actually_rustdoc: true,
|
actually_rustdoc: true,
|
||||||
debugging_opts: config::DebuggingOptions {
|
debugging_opts: config::DebuggingOptions {
|
||||||
edition,
|
|
||||||
..config::basic_debugging_options()
|
..config::basic_debugging_options()
|
||||||
},
|
},
|
||||||
|
edition,
|
||||||
..config::basic_options().clone()
|
..config::basic_options().clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -223,9 +223,9 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
|
||||||
test: as_test_harness,
|
test: as_test_harness,
|
||||||
unstable_features: UnstableFeatures::from_environment(),
|
unstable_features: UnstableFeatures::from_environment(),
|
||||||
debugging_opts: config::DebuggingOptions {
|
debugging_opts: config::DebuggingOptions {
|
||||||
edition,
|
|
||||||
..config::basic_debugging_options()
|
..config::basic_debugging_options()
|
||||||
},
|
},
|
||||||
|
edition,
|
||||||
..config::basic_options().clone()
|
..config::basic_options().clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,20 +24,19 @@ pub enum Edition {
|
||||||
|
|
||||||
// when adding new editions, be sure to update:
|
// when adding new editions, be sure to update:
|
||||||
//
|
//
|
||||||
// - the list in the `parse_edition` static in librustc::session::config
|
// - Update the `ALL_EDITIONS` const
|
||||||
|
// - Update the EDITION_NAME_LIST const
|
||||||
// - add a `rust_####()` function to the session
|
// - add a `rust_####()` function to the session
|
||||||
// - update the enum in Cargo's sources as well
|
// - update the enum in Cargo's sources as well
|
||||||
//
|
|
||||||
// When -Zedition becomes --edition, there will
|
|
||||||
// also be a check for the edition being nightly-only
|
|
||||||
// somewhere. That will need to be updated
|
|
||||||
// whenever we're stabilizing/introducing a new edition
|
|
||||||
// as well as changing the default Cargo template.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// must be in order from oldest to newest
|
// must be in order from oldest to newest
|
||||||
pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];
|
pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];
|
||||||
|
|
||||||
|
pub const EDITION_NAME_LIST: &'static str = "2015|2018";
|
||||||
|
|
||||||
|
pub const DEFAULT_EDITION: Edition = Edition::Edition2015;
|
||||||
|
|
||||||
impl fmt::Display for Edition {
|
impl fmt::Display for Edition {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let s = match *self {
|
let s = match *self {
|
||||||
|
@ -62,6 +61,13 @@ impl Edition {
|
||||||
Edition::Edition2018 => "rust_2018_preview",
|
Edition::Edition2018 => "rust_2018_preview",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_stable(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Edition::Edition2015 => true,
|
||||||
|
Edition::Edition2018 => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Edition {
|
impl FromStr for Edition {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
// compile-flags: -Zedition=2015 -Zunstable-options
|
// compile-flags: --edition=2015 -Zunstable-options
|
||||||
|
|
||||||
// tests that editions work with the tyvar warning-turned-error
|
// tests that editions work with the tyvar warning-turned-error
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
// compile-flags: -Zedition=2018 -Zunstable-options
|
// compile-flags: --edition=2018 -Zunstable-options
|
||||||
|
|
||||||
// tests that editions work with the tyvar warning-turned-error
|
// tests that editions work with the tyvar warning-turned-error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue