diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 2e6689efee5..e9fe94cdb4a 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -16,6 +16,8 @@ pub use self::CrateType::*; pub use self::Passes::*; pub use self::DebugInfoLevel::*; +use std::str::FromStr; + use session::{early_error, early_warn, Session}; use session::search_paths::SearchPaths; @@ -28,7 +30,7 @@ use middle::cstore; use syntax::ast::{self, IntTy, UintTy}; 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; use syntax::symbol::Symbol; @@ -410,6 +412,7 @@ top_level_options!( // Remap source path prefixes in all output (messages, object files, debug, etc) 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_thinlto_off: false, remap_path_prefix: Vec::new(), + edition: DEFAULT_EDITION, } } @@ -773,8 +777,6 @@ macro_rules! options { Some("`string` or `string=string`"); pub const parse_lto: Option<&'static str> = Some("one of `thin`, `fat`, or omitted"); - pub const parse_edition: Option<&'static str> = - Some("one of: `2015`, `2018`"); } #[allow(dead_code)] @@ -782,7 +784,6 @@ macro_rules! options { use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto}; use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel}; use std::path::PathBuf; - use syntax::edition::Edition; $( pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { @@ -985,20 +986,6 @@ macro_rules! options { 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 {}`), `hir` (the HIR), `hir,identified`, or `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 = (None, parse_opt_bool, [TRACKED], "run `dsymutil` and delete intermediate object files"), ui_testing: bool = (false, parse_bool, [UNTRACKED], @@ -1656,6 +1639,12 @@ pub fn rustc_optgroups() -> Vec { `expanded,identified` (fully parenthesized, AST nodes with IDs).", "TYPE", ), + opt::opt_s( + "", + "edition", + "Specify which edition of the compiler to use when compiling code.", + EDITION_NAME_LIST, + ), opt::multi_s( "", "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 // 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 @@ -2171,6 +2188,7 @@ pub fn build_session_options_and_crate_config( cli_forced_codegen_units: codegen_units, cli_forced_thinlto_off: disable_thinlto, remap_path_prefix, + edition, }, cfg, ) @@ -2300,11 +2318,12 @@ mod dep_tracking { use std::hash::Hash; use std::path::PathBuf; 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}; use syntax::feature_gate::UnstableFeatures; use rustc_back::{PanicStrategy, RelroLevel}; use rustc_back::target::TargetTriple; + use syntax::edition::Edition; pub trait DepTrackingHash { 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!(Sanitizer); impl_dep_tracking_hash_via_hash!(Option); - impl_dep_tracking_hash_via_hash!(Edition); 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!(PathBuf); @@ -2437,6 +2456,7 @@ mod tests { use super::{Externs, OutputType, OutputTypes}; use rustc_back::{PanicStrategy, RelroLevel}; use syntax::symbol::Symbol; + use syntax::edition::{Edition, DEFAULT_EDITION}; use syntax; fn optgroups() -> getopts::Options { @@ -3081,4 +3101,17 @@ mod tests { opts.debugging_opts.relro_level = Some(RelroLevel::Full); 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) + } } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 2993234f266..5e4dee7fb60 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -934,11 +934,11 @@ impl Session { /// Are we allowed to use features from the Rust 2018 edition? pub fn rust_2018(&self) -> bool { - self.opts.debugging_opts.edition >= Edition::Edition2018 + self.opts.edition >= Edition::Edition2018 } pub fn edition(&self) -> Edition { - self.opts.debugging_opts.edition + self.opts.edition } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f8c0289cc98..2c781fda4ed 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -691,7 +691,7 @@ where krate, &sess.parse_sess, sess.opts.test, - sess.opts.debugging_opts.edition, + sess.edition(), ); // these need to be set "early" so that expansion sees `quote` if enabled. sess.init_features(features); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 9fb024fd906..2bd1e72f0eb 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -155,10 +155,10 @@ pub fn run_core(search_paths: SearchPaths, actually_rustdoc: true, debugging_opts: config::DebuggingOptions { force_unstable_if_unmarked, - edition, ..config::basic_debugging_options() }, error_format, + edition, ..config::basic_options().clone() }; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 8cd5f373efe..c4eaa48e49d 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -80,9 +80,9 @@ pub fn run(input_path: &Path, lint_cap: Some(::rustc::lint::Level::Allow), actually_rustdoc: true, debugging_opts: config::DebuggingOptions { - edition, ..config::basic_debugging_options() }, + edition, ..config::basic_options().clone() }; @@ -223,9 +223,9 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, test: as_test_harness, unstable_features: UnstableFeatures::from_environment(), debugging_opts: config::DebuggingOptions { - edition, ..config::basic_debugging_options() }, + edition, ..config::basic_options().clone() }; diff --git a/src/libsyntax/edition.rs b/src/libsyntax/edition.rs index e579fc74b42..3fc1c279f5a 100644 --- a/src/libsyntax/edition.rs +++ b/src/libsyntax/edition.rs @@ -24,20 +24,19 @@ pub enum Edition { // 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 // - 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 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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = match *self { @@ -62,6 +61,13 @@ impl Edition { Edition::Edition2018 => "rust_2018_preview", } } + + pub fn is_stable(&self) -> bool { + match *self { + Edition::Edition2015 => true, + Edition::Edition2018 => false, + } + } } impl FromStr for Edition { diff --git a/src/test/compile-fail/edition-raw-pointer-method-2015.rs b/src/test/compile-fail/edition-raw-pointer-method-2015.rs index fdc9b4f704c..b304443f631 100644 --- a/src/test/compile-fail/edition-raw-pointer-method-2015.rs +++ b/src/test/compile-fail/edition-raw-pointer-method-2015.rs @@ -9,7 +9,7 @@ // except according to those terms. // 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 diff --git a/src/test/compile-fail/edition-raw-pointer-method-2018.rs b/src/test/compile-fail/edition-raw-pointer-method-2018.rs index 58b34591029..d01cac019e3 100644 --- a/src/test/compile-fail/edition-raw-pointer-method-2018.rs +++ b/src/test/compile-fail/edition-raw-pointer-method-2018.rs @@ -9,7 +9,7 @@ // except according to those terms. // 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