diff --git a/src/Cargo.lock b/src/Cargo.lock index 34c077a6f7a..646ddf1a744 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -78,7 +78,7 @@ dependencies = [ [[package]] name = "atty" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -179,7 +179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "cargo" version = "0.26.0" dependencies = [ - "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "cargotest 0.1.0", "core-foundation 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -289,7 +289,7 @@ version = "2.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -645,7 +645,7 @@ name = "env_logger" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1923,9 +1923,11 @@ dependencies = [ name = "rustc_errors" version = "0.0.0" dependencies = [ + "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "serialize 0.0.0", "syntax_pos 0.0.0", + "termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2843,7 +2845,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" -"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859" +"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" "checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index a951265d458..8e1f76c5018 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -17,7 +17,6 @@ use errors::DiagnosticBuilder; use lint::{LintPass, LateLintPass, LintArray}; use session::Session; -use session::config::Epoch; use syntax::codemap::Span; declare_lint! { @@ -264,9 +263,8 @@ declare_lint! { pub BARE_TRAIT_OBJECT, - Warn, - "suggest using `dyn Trait` for trait objects", - Epoch::Epoch2018 + Allow, + "suggest using `dyn Trait` for trait objects" } declare_lint! { diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index bfd2034dd6c..b1e28f729ed 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -42,6 +42,7 @@ use std::default::Default as StdDefault; use std::cell::{Ref, RefCell}; use syntax::ast; +use syntax::epoch; use syntax_pos::{MultiSpan, Span}; use errors::DiagnosticBuilder; use hir; @@ -105,7 +106,7 @@ pub struct FutureIncompatibleInfo { pub reference: &'static str, /// If this is an epoch fixing lint, the epoch in which /// this lint becomes obsolete - pub epoch: Option, + pub epoch: Option, } /// The target of the `by_name` map, which accounts for renaming/deprecation. @@ -201,7 +202,7 @@ pub fn register_future_incompatible(&mut self, sess: Option<&Session>, lints: Vec) { - for epoch in config::ALL_EPOCHS { + for epoch in epoch::ALL_EPOCHS { let lints = lints.iter().filter(|f| f.epoch == Some(*epoch)).map(|f| f.id) .collect::>(); if !lints.is_empty() { diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index affd02aa518..668e099ebab 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -38,10 +38,11 @@ use hir::intravisit::{self, FnKind}; use hir; use lint::builtin::BuiltinLintDiagnostics; -use session::{config, Session, DiagnosticMessageId}; +use session::{Session, DiagnosticMessageId}; use std::hash; use syntax::ast; use syntax::codemap::MultiSpan; +use syntax::epoch::Epoch; use syntax::symbol::Symbol; use syntax::visit as ast_visit; use syntax_pos::Span; @@ -77,7 +78,7 @@ pub struct Lint { pub desc: &'static str, /// Deny lint after this epoch - pub epoch_deny: Option, + pub epoch_deny: Option, } impl Lint { @@ -492,9 +493,14 @@ pub fn struct_lint_level<'a>(sess: &'a Session, // Check for future incompatibility lints and issue a stronger warning. let lints = sess.lint_store.borrow(); if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) { + let future = if let Some(epoch) = future_incompatible.epoch { + format!("the {} epoch", epoch) + } else { + "a future release".to_owned() + }; let explanation = format!("this was previously accepted by the compiler \ but is being phased out; \ - it will become a hard error in a future release!"); + it will become a hard error in {}!", future); let citation = format!("for more information, see {}", future_incompatible.reference); err.warn(&explanation); diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 75b4409695e..1c5cfa87ef4 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -28,6 +28,7 @@ use syntax::ast::{self, IntTy, UintTy}; use syntax::codemap::{FileName, FilePathMapping}; +use syntax::epoch::Epoch; use syntax::parse::token; use syntax::parse; use syntax::symbol::Symbol; @@ -111,59 +112,6 @@ pub enum OutputType { DepInfo, } -/// The epoch of the compiler (RFC 2052) -#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)] -#[non_exhaustive] -pub enum Epoch { - // epochs must be kept in order, newest to oldest - /// The 2015 epoch - Epoch2015, - /// The 2018 epoch - Epoch2018, - // when adding new epochs, be sure to update: - // - // - the list in the `parse_epoch` static - // - the match in the `parse_epoch` function - // - add a `rust_####()` function to the session - // - update the enum in Cargo's sources as well - // - // When -Zepoch becomes --epoch, there will - // also be a check for the epoch being nightly-only - // somewhere. That will need to be updated - // whenever we're stabilizing/introducing a new epoch - // as well as changing the default Cargo template. -} - -pub const ALL_EPOCHS: &[Epoch] = &[Epoch::Epoch2015, Epoch::Epoch2018]; - -impl ToString for Epoch { - fn to_string(&self) -> String { - match *self { - Epoch::Epoch2015 => "2015".into(), - Epoch::Epoch2018 => "2018".into(), - } - } -} - -impl Epoch { - pub fn lint_name(&self) -> &'static str { - match *self { - Epoch::Epoch2015 => "epoch_2015", - Epoch::Epoch2018 => "epoch_2018", - } - } -} - -impl str::FromStr for Epoch { - type Err = (); - fn from_str(s: &str) -> Result { - match s { - "2015" => Ok(Epoch::Epoch2015), - "2018" => Ok(Epoch::Epoch2018), - _ => Err(()), - } - } -} impl_stable_hash_for!(enum self::OutputType { Bitcode, @@ -829,9 +777,10 @@ mod $mod_desc { #[allow(dead_code)] mod $mod_set { - use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto, Epoch}; + use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto}; use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel}; use std::path::PathBuf; + use syntax::epoch::Epoch; $( pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index a355a1ca501..cdbbcf6a8dd 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -20,7 +20,7 @@ use middle::allocator::AllocatorKind; use middle::dependency_format; use session::search_paths::PathKind; -use session::config::{DebugInfoLevel, Epoch, OutputType}; +use session::config::{DebugInfoLevel, OutputType}; use ty::tls; use util::nodemap::{FxHashMap, FxHashSet}; use util::common::{duration_to_secs_str, ErrorReported}; @@ -30,6 +30,7 @@ use syntax::ast::NodeId; use errors::{self, DiagnosticBuilder, DiagnosticId}; use errors::emitter::{Emitter, EmitterWriter}; +use syntax::epoch::Epoch; use syntax::json::JsonEmitter; use syntax::feature_gate; use syntax::symbol::Symbol; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c9cf3f3b81f..f020f86b686 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -647,7 +647,9 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, { let time_passes = sess.time_passes(); - let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess, sess.opts.test); + let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess, + sess.opts.test, + sess.opts.debugging_opts.epoch); // these need to be set "early" so that expansion sees `quote` if enabled. sess.init_features(features); diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index 3e15af7558d..e412d1749d1 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -13,3 +13,5 @@ serialize = { path = "../libserialize" } syntax_pos = { path = "../libsyntax_pos" } rustc_data_structures = { path = "../librustc_data_structures" } unicode-width = "0.1.4" +atty = "0.2" +termcolor = "0.3" diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 33fce7b1968..f481b36daa3 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -17,12 +17,14 @@ use styled_buffer::StyledBuffer; use rustc_data_structures::sync::Lrc; +use atty; use std::borrow::Cow; use std::io::prelude::*; use std::io; -use term; use std::collections::{HashMap, HashSet}; use std::cmp::min; +use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter}; +use termcolor::{WriteColor, Color, Buffer}; use unicode_width; const ANONYMIZED_LINE_NUM: &str = "LL"; @@ -95,11 +97,14 @@ pub enum ColorConfig { } impl ColorConfig { - fn use_color(&self) -> bool { + fn to_color_choice(&self) -> ColorChoice { match *self { - ColorConfig::Always => true, - ColorConfig::Never => false, - ColorConfig::Auto => stderr_isatty(), + ColorConfig::Always => ColorChoice::Always, + ColorConfig::Never => ColorChoice::Never, + ColorConfig::Auto if atty::is(atty::Stream::Stderr) => { + ColorChoice::Auto + } + ColorConfig::Auto => ColorChoice::Never, } } } @@ -123,25 +128,26 @@ impl Drop for EmitterWriter { fn drop(&mut self) { if !self.short_message && !self.error_codes.is_empty() { let mut error_codes = self.error_codes.clone().into_iter().collect::>(); + let mut dst = self.dst.writable(); error_codes.sort(); if error_codes.len() > 1 { let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() }; - writeln!(self.dst, + writeln!(dst, "You've got a few errors: {}{}", error_codes[..limit].join(", "), if error_codes.len() > 9 { "..." } else { "" } ).expect("failed to give tips..."); - writeln!(self.dst, + writeln!(dst, "If you want more information on an error, try using \ \"rustc --explain {}\"", &error_codes[0]).expect("failed to give tips..."); } else { - writeln!(self.dst, + writeln!(dst, "If you want more information on this error, try using \ \"rustc --explain {}\"", &error_codes[0]).expect("failed to give tips..."); } - self.dst.flush().expect("failed to emit errors"); + dst.flush().expect("failed to emit errors"); } } } @@ -152,25 +158,14 @@ pub fn stderr(color_config: ColorConfig, short_message: bool, teach: bool) -> EmitterWriter { - if color_config.use_color() { - let dst = Destination::from_stderr(); - EmitterWriter { - dst, - cm: code_map, - short_message, - teach, - error_codes: HashSet::new(), - ui_testing: false, - } - } else { - EmitterWriter { - dst: Raw(Box::new(io::stderr())), - cm: code_map, - short_message, - teach, - error_codes: HashSet::new(), - ui_testing: false, - } + let dst = Destination::from_stderr(color_config); + EmitterWriter { + dst, + cm: code_map, + short_message, + teach, + error_codes: HashSet::new(), + ui_testing: false, } } @@ -1356,10 +1351,12 @@ fn emit_messages_default(&mut self, } Err(e) => panic!("failed to emit error: {}", e), } - match write!(&mut self.dst, "\n") { + + let mut dst = self.dst.writable(); + match write!(dst, "\n") { Err(e) => panic!("failed to emit error: {}", e), _ => { - match self.dst.flush() { + match dst.flush() { Err(e) => panic!("failed to emit error: {}", e), _ => (), } @@ -1424,6 +1421,8 @@ fn emit_to_destination(rendered_buffer: &Vec>, -> io::Result<()> { use lock; + let mut dst = dst.writable(); + // In order to prevent error message interleaving, where multiple error lines get intermixed // when multiple compiler processes error simultaneously, we emit errors with additional // steps. @@ -1444,7 +1443,7 @@ fn emit_to_destination(rendered_buffer: &Vec>, if !short_message && part.text.len() == 12 && part.text.starts_with("error[E") { error_codes.insert(part.text[6..11].to_owned()); } - dst.reset_attrs()?; + dst.reset()?; } if !short_message { write!(dst, "\n")?; @@ -1454,180 +1453,136 @@ fn emit_to_destination(rendered_buffer: &Vec>, Ok(()) } -#[cfg(unix)] -fn stderr_isatty() -> bool { - use libc; - unsafe { libc::isatty(libc::STDERR_FILENO) != 0 } -} -#[cfg(windows)] -fn stderr_isatty() -> bool { - type DWORD = u32; - type BOOL = i32; - type HANDLE = *mut u8; - const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; - extern "system" { - fn GetStdHandle(which: DWORD) -> HANDLE; - fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: *mut DWORD) -> BOOL; - } - unsafe { - let handle = GetStdHandle(STD_ERROR_HANDLE); - let mut out = 0; - GetConsoleMode(handle, &mut out) != 0 - } -} - -pub type BufferedStderr = term::Terminal + Send; - pub enum Destination { - Terminal(Box), - BufferedTerminal(Box), + Terminal(StandardStream), + Buffered(BufferWriter), Raw(Box), } -/// Buffered writer gives us a way on Unix to buffer up an entire error message before we output -/// it. This helps to prevent interleaving of multiple error messages when multiple compiler -/// processes error simultaneously -pub struct BufferedWriter { - buffer: Vec, -} - -impl BufferedWriter { - // note: we use _new because the conditional compilation at its use site may make this - // this function unused on some platforms - fn _new() -> BufferedWriter { - BufferedWriter { buffer: vec![] } - } -} - -impl Write for BufferedWriter { - fn write(&mut self, buf: &[u8]) -> io::Result { - for b in buf { - self.buffer.push(*b); - } - Ok(buf.len()) - } - fn flush(&mut self) -> io::Result<()> { - let mut stderr = io::stderr(); - let result = stderr.write_all(&self.buffer) - .and_then(|_| stderr.flush()); - self.buffer.clear(); - result - } +pub enum WritableDst<'a> { + Terminal(&'a mut StandardStream), + Buffered(&'a mut BufferWriter, Buffer), + Raw(&'a mut Box), } impl Destination { - #[cfg(not(windows))] - /// When not on Windows, prefer the buffered terminal so that we can buffer an entire error - /// to be emitted at one time. - fn from_stderr() -> Destination { - let stderr: Option> = - term::TerminfoTerminal::new(BufferedWriter::_new()) - .map(|t| Box::new(t) as Box); - - match stderr { - Some(t) => BufferedTerminal(t), - None => Raw(Box::new(io::stderr())), + fn from_stderr(color: ColorConfig) -> Destination { + let choice = color.to_color_choice(); + // On Windows we'll be performing global synchronization on the entire + // system for emitting rustc errors, so there's no need to buffer + // anything. + // + // On non-Windows we rely on the atomicity of `write` to ensure errors + // don't get all jumbled up. + if cfg!(windows) { + Terminal(StandardStream::stderr(choice)) + } else { + Buffered(BufferWriter::stderr(choice)) } } - #[cfg(windows)] - /// Return a normal, unbuffered terminal when on Windows. - fn from_stderr() -> Destination { - let stderr: Option> = term::TerminfoTerminal::new(io::stderr()) - .map(|t| Box::new(t) as Box) - .or_else(|| { - term::WinConsole::new(io::stderr()) - .ok() - .map(|t| Box::new(t) as Box) - }); - - match stderr { - Some(t) => Terminal(t), - None => Raw(Box::new(io::stderr())), + fn writable<'a>(&'a mut self) -> WritableDst<'a> { + match *self { + Destination::Terminal(ref mut t) => WritableDst::Terminal(t), + Destination::Buffered(ref mut t) => { + let buf = t.buffer(); + WritableDst::Buffered(t, buf) + } + Destination::Raw(ref mut t) => WritableDst::Raw(t), } } +} +impl<'a> WritableDst<'a> { fn apply_style(&mut self, lvl: Level, style: Style) -> io::Result<()> { + let mut spec = ColorSpec::new(); match style { Style::LineAndColumn => {} Style::LineNumber => { - self.start_attr(term::Attr::Bold)?; + spec.set_bold(true); + spec.set_intense(true); if cfg!(windows) { - self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_CYAN))?; + spec.set_fg(Some(Color::Cyan)); } else { - self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_BLUE))?; + spec.set_fg(Some(Color::Blue)); } } Style::Quotation => {} Style::OldSchoolNoteText | Style::HeaderMsg => { - self.start_attr(term::Attr::Bold)?; + spec.set_bold(true); if cfg!(windows) { - self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_WHITE))?; + spec.set_intense(true) + .set_fg(Some(Color::White)); } } Style::UnderlinePrimary | Style::LabelPrimary => { - self.start_attr(term::Attr::Bold)?; - self.start_attr(term::Attr::ForegroundColor(lvl.color()))?; + spec = lvl.color(); + spec.set_bold(true); } Style::UnderlineSecondary | Style::LabelSecondary => { - self.start_attr(term::Attr::Bold)?; + spec.set_bold(true) + .set_intense(true); if cfg!(windows) { - self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_CYAN))?; + spec.set_fg(Some(Color::Cyan)); } else { - self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_BLUE))?; + spec.set_fg(Some(Color::Blue)); } } Style::NoStyle => {} - Style::Level(l) => { - self.start_attr(term::Attr::Bold)?; - self.start_attr(term::Attr::ForegroundColor(l.color()))?; + Style::Level(lvl) => { + spec = lvl.color(); + spec.set_bold(true); + } + Style::Highlight => { + spec.set_bold(true); } - Style::Highlight => self.start_attr(term::Attr::Bold)?, } - Ok(()) + self.set_color(&spec) } - fn start_attr(&mut self, attr: term::Attr) -> io::Result<()> { + fn set_color(&mut self, color: &ColorSpec) -> io::Result<()> { match *self { - Terminal(ref mut t) => { - t.attr(attr)?; - } - BufferedTerminal(ref mut t) => { - t.attr(attr)?; - } - Raw(_) => {} + WritableDst::Terminal(ref mut t) => t.set_color(color), + WritableDst::Buffered(_, ref mut t) => t.set_color(color), + WritableDst::Raw(_) => Ok(()) } - Ok(()) } - fn reset_attrs(&mut self) -> io::Result<()> { + fn reset(&mut self) -> io::Result<()> { match *self { - Terminal(ref mut t) => { - t.reset()?; - } - BufferedTerminal(ref mut t) => { - t.reset()?; - } - Raw(_) => {} + WritableDst::Terminal(ref mut t) => t.reset(), + WritableDst::Buffered(_, ref mut t) => t.reset(), + WritableDst::Raw(_) => Ok(()), } - Ok(()) } } -impl Write for Destination { +impl<'a> Write for WritableDst<'a> { fn write(&mut self, bytes: &[u8]) -> io::Result { match *self { - Terminal(ref mut t) => t.write(bytes), - BufferedTerminal(ref mut t) => t.write(bytes), - Raw(ref mut w) => w.write(bytes), + WritableDst::Terminal(ref mut t) => t.write(bytes), + WritableDst::Buffered(_, ref mut buf) => buf.write(bytes), + WritableDst::Raw(ref mut w) => w.write(bytes), } } + fn flush(&mut self) -> io::Result<()> { match *self { - Terminal(ref mut t) => t.flush(), - BufferedTerminal(ref mut t) => t.flush(), - Raw(ref mut w) => w.flush(), + WritableDst::Terminal(ref mut t) => t.flush(), + WritableDst::Buffered(_, ref mut buf) => buf.flush(), + WritableDst::Raw(ref mut w) => w.flush(), + } + } +} + +impl<'a> Drop for WritableDst<'a> { + fn drop(&mut self) { + match *self { + WritableDst::Buffered(ref mut dst, ref mut buf) => { + drop(dst.print(buf)); + } + _ => {} } } } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 3eea311a5af..924ed71ef0d 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -21,7 +21,8 @@ #![feature(i128_type)] #![feature(optin_builtin_traits)] -extern crate term; +extern crate atty; +extern crate termcolor; #[cfg(unix)] extern crate libc; extern crate rustc_data_structures; @@ -47,6 +48,8 @@ use std::sync::atomic::Ordering::SeqCst; use std::panic; +use termcolor::{ColorSpec, Color}; + mod diagnostic; mod diagnostic_builder; pub mod emitter; @@ -660,20 +663,28 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } impl Level { - fn color(self) -> term::color::Color { + fn color(self) -> ColorSpec { + let mut spec = ColorSpec::new(); match self { - Bug | Fatal | PhaseFatal | Error => term::color::BRIGHT_RED, - Warning => { - if cfg!(windows) { - term::color::BRIGHT_YELLOW - } else { - term::color::YELLOW - } + Bug | Fatal | PhaseFatal | Error => { + spec.set_fg(Some(Color::Red)) + .set_intense(true); + } + Warning => { + spec.set_fg(Some(Color::Yellow)) + .set_intense(cfg!(windows)); + } + Note => { + spec.set_fg(Some(Color::Green)) + .set_intense(true); + } + Help => { + spec.set_fg(Some(Color::Cyan)) + .set_intense(true); } - Note => term::color::BRIGHT_GREEN, - Help => term::color::BRIGHT_CYAN, Cancelled => unreachable!(), } + return spec } pub fn to_str(self) -> &'static str { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 831d4fc755f..d39e00ab18f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1263,7 +1263,7 @@ fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) { pub struct UnreachablePub; declare_lint! { - UNREACHABLE_PUB, + pub UNREACHABLE_PUB, Allow, "`pub` items not reachable from crate root" } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index e941f2e4e1c..81609db6292 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -43,10 +43,12 @@ extern crate syntax_pos; use rustc::lint; +use rustc::lint::builtin::BARE_TRAIT_OBJECT; use rustc::session; use rustc::util; use session::Session; +use syntax::epoch::Epoch; use lint::LintId; use lint::FutureIncompatibleInfo; @@ -176,6 +178,11 @@ macro_rules! add_lint_group { UNUSED_FEATURES, UNUSED_PARENS); + add_lint_group!(sess, + "rust_2018_idioms", + BARE_TRAIT_OBJECT, + UNREACHABLE_PUB); + // Guidelines for creating a future incompatibility lint: // // - Create a lint defaulting to warn as normal, with ideally the same error @@ -274,13 +281,8 @@ macro_rules! add_lint_group { FutureIncompatibleInfo { id: LintId::of(TYVAR_BEHIND_RAW_POINTER), reference: "issue #46906 ", - epoch: None, - }, - FutureIncompatibleInfo { - id: LintId::of(lint::builtin::BARE_TRAIT_OBJECT), - reference: "issue #48457 ", - epoch: Some(session::config::Epoch::Epoch2018), - } + epoch: Some(Epoch::Epoch2018), + } ]); // Register renamed and removed lints diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index a18c811d196..b804cf7cd90 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -472,7 +472,7 @@ macro_rules! concat { /// The expanded expression has type `u32` and is 1-based, so the first line /// in each file evaluates to 1, the second to 2, etc. This is consistent /// with error messages by common compilers or popular editors. - /// The returned line is not the invocation of the `line!` macro itself, + /// The returned line is *not necessarily* the line of the `line!` invocation itself, /// but rather the first macro invocation leading up to the invocation /// of the `line!` macro. /// @@ -497,7 +497,7 @@ macro_rules! line { () => ({ /* compiler built-in */ }) } /// The expanded expression has type `u32` and is 1-based, so the first column /// in each line evaluates to 1, the second to 2, etc. This is consistent /// with error messages by common compilers or popular editors. - /// The returned column is not the invocation of the `column!` macro itself, + /// The returned column is *not necessarily* the line of the `column!` invocation itself, /// but rather the first macro invocation leading up to the invocation /// of the `column!` macro. /// diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index aa360ed1bf5..6013c20daf2 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -13,6 +13,7 @@ use {fold, attr}; use ast; use codemap::Spanned; +use epoch::Epoch; use parse::{token, ParseSess}; use ptr::P; @@ -26,7 +27,7 @@ pub struct StripUnconfigured<'a> { } // `cfg_attr`-process the crate's attributes and compute the crate's features. -pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool) +pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool, epoch: Epoch) -> (ast::Crate, Features) { let features; { @@ -46,7 +47,7 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool) return (krate, Features::new()); } - features = get_features(&sess.span_diagnostic, &krate.attrs); + features = get_features(&sess.span_diagnostic, &krate.attrs, epoch); // Avoid reconfiguring malformed `cfg_attr`s if err_count == sess.span_diagnostic.err_count() { diff --git a/src/libsyntax/epoch.rs b/src/libsyntax/epoch.rs new file mode 100644 index 00000000000..32cbc79c550 --- /dev/null +++ b/src/libsyntax/epoch.rs @@ -0,0 +1,69 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fmt; +use std::str::FromStr; + +/// The epoch of the compiler (RFC 2052) +#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)] +#[non_exhaustive] +pub enum Epoch { + // epochs must be kept in order, newest to oldest + + /// The 2015 epoch + Epoch2015, + /// The 2018 epoch + Epoch2018, + + // when adding new epochs, be sure to update: + // + // - the list in the `parse_epoch` static in librustc::session::config + // - add a `rust_####()` function to the session + // - update the enum in Cargo's sources as well + // + // When -Zepoch becomes --epoch, there will + // also be a check for the epoch being nightly-only + // somewhere. That will need to be updated + // whenever we're stabilizing/introducing a new epoch + // as well as changing the default Cargo template. +} + +// must be in order from oldest to newest +pub const ALL_EPOCHS: &[Epoch] = &[Epoch::Epoch2015, Epoch::Epoch2018]; + +impl fmt::Display for Epoch { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s = match *self { + Epoch::Epoch2015 => "2015", + Epoch::Epoch2018 => "2018", + }; + write!(f, "{}", s) + } +} + +impl Epoch { + pub fn lint_name(&self) -> &'static str { + match *self { + Epoch::Epoch2015 => "epoch_2015", + Epoch::Epoch2018 => "epoch_2018", + } + } +} + +impl FromStr for Epoch { + type Err = (); + fn from_str(s: &str) -> Result { + match s { + "2015" => Ok(Epoch::Epoch2015), + "2018" => Ok(Epoch::Epoch2018), + _ => Err(()) + } + } +} diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1a790bf78bd..ec9a15d9f2b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -28,8 +28,9 @@ use abi::Abi; use ast::{self, NodeId, PatKind, RangeEnd, RangeSyntax}; use attr; +use epoch::Epoch; use codemap::Spanned; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; use errors::{DiagnosticBuilder, Handler, FatalError}; use visit::{self, FnKind, Visitor}; use parse::ParseSess; @@ -54,12 +55,13 @@ fn f(features: &mut Features, _: Span) { } macro_rules! declare_features { - ($((active, $feature: ident, $ver: expr, $issue: expr),)+) => { + ($((active, $feature: ident, $ver: expr, $issue: expr, $epoch: expr),)+) => { /// Represents active features that are currently being implemented or /// currently being considered for addition/removal. const ACTIVE_FEATURES: - &'static [(&'static str, &'static str, Option, fn(&mut Features, Span))] = - &[$((stringify!($feature), $ver, $issue, set!($feature))),+]; + &'static [(&'static str, &'static str, Option, + Option, fn(&mut Features, Span))] = + &[$((stringify!($feature), $ver, $issue, $epoch, set!($feature))),+]; /// A set of features to be used by later passes. #[derive(Clone)] @@ -88,21 +90,21 @@ pub fn walk_feature_fields(&self, mut f: F) } }; - ($((removed, $feature: ident, $ver: expr, $issue: expr),)+) => { + ($((removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => { /// Represents unstable features which have since been removed (it was once Active) const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option)] = &[ $((stringify!($feature), $ver, $issue)),+ ]; }; - ($((stable_removed, $feature: ident, $ver: expr, $issue: expr),)+) => { + ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => { /// Represents stable features which have since been removed (it was once Accepted) const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option)] = &[ $((stringify!($feature), $ver, $issue)),+ ]; }; - ($((accepted, $feature: ident, $ver: expr, $issue: expr),)+) => { + ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => { /// Those language feature has since been Accepted (it was once Active) const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option)] = &[ $((stringify!($feature), $ver, $issue)),+ @@ -122,78 +124,78 @@ pub fn walk_feature_fields(&self, mut f: F) // source, so take care when modifying it. declare_features! ( - (active, asm, "1.0.0", Some(29722)), - (active, concat_idents, "1.0.0", Some(29599)), - (active, link_args, "1.0.0", Some(29596)), - (active, log_syntax, "1.0.0", Some(29598)), - (active, non_ascii_idents, "1.0.0", Some(28979)), - (active, plugin_registrar, "1.0.0", Some(29597)), - (active, thread_local, "1.0.0", Some(29594)), - (active, trace_macros, "1.0.0", Some(29598)), + (active, asm, "1.0.0", Some(29722), None), + (active, concat_idents, "1.0.0", Some(29599), None), + (active, link_args, "1.0.0", Some(29596), None), + (active, log_syntax, "1.0.0", Some(29598), None), + (active, non_ascii_idents, "1.0.0", Some(28979), None), + (active, plugin_registrar, "1.0.0", Some(29597), None), + (active, thread_local, "1.0.0", Some(29594), None), + (active, trace_macros, "1.0.0", Some(29598), None), // rustc internal, for now: - (active, intrinsics, "1.0.0", None), - (active, lang_items, "1.0.0", None), + (active, intrinsics, "1.0.0", None, None), + (active, lang_items, "1.0.0", None, None), - (active, link_llvm_intrinsics, "1.0.0", Some(29602)), - (active, linkage, "1.0.0", Some(29603)), - (active, quote, "1.0.0", Some(29601)), + (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), + (active, linkage, "1.0.0", Some(29603), None), + (active, quote, "1.0.0", Some(29601), None), // rustc internal - (active, rustc_diagnostic_macros, "1.0.0", None), - (active, rustc_const_unstable, "1.0.0", None), - (active, advanced_slice_patterns, "1.0.0", Some(23121)), - (active, box_syntax, "1.0.0", Some(27779)), - (active, placement_in_syntax, "1.0.0", Some(27779)), - (active, unboxed_closures, "1.0.0", Some(29625)), + (active, rustc_diagnostic_macros, "1.0.0", None, None), + (active, rustc_const_unstable, "1.0.0", None, None), + (active, advanced_slice_patterns, "1.0.0", Some(23121), None), + (active, box_syntax, "1.0.0", Some(27779), None), + (active, placement_in_syntax, "1.0.0", Some(27779), None), + (active, unboxed_closures, "1.0.0", Some(29625), None), - (active, fundamental, "1.0.0", Some(29635)), - (active, main, "1.0.0", Some(29634)), - (active, needs_allocator, "1.4.0", Some(27389)), - (active, on_unimplemented, "1.0.0", Some(29628)), - (active, plugin, "1.0.0", Some(29597)), - (active, simd_ffi, "1.0.0", Some(27731)), - (active, start, "1.0.0", Some(29633)), - (active, structural_match, "1.8.0", Some(31434)), - (active, panic_runtime, "1.10.0", Some(32837)), - (active, needs_panic_runtime, "1.10.0", Some(32837)), + (active, fundamental, "1.0.0", Some(29635), None), + (active, main, "1.0.0", Some(29634), None), + (active, needs_allocator, "1.4.0", Some(27389), None), + (active, on_unimplemented, "1.0.0", Some(29628), None), + (active, plugin, "1.0.0", Some(29597), None), + (active, simd_ffi, "1.0.0", Some(27731), None), + (active, start, "1.0.0", Some(29633), None), + (active, structural_match, "1.8.0", Some(31434), None), + (active, panic_runtime, "1.10.0", Some(32837), None), + (active, needs_panic_runtime, "1.10.0", Some(32837), None), // OIBIT specific features - (active, optin_builtin_traits, "1.0.0", Some(13231)), + (active, optin_builtin_traits, "1.0.0", Some(13231), None), // macro re-export needs more discussion and stabilization - (active, macro_reexport, "1.0.0", Some(29638)), + (active, macro_reexport, "1.0.0", Some(29638), None), // Allows use of #[staged_api] // rustc internal - (active, staged_api, "1.0.0", None), + (active, staged_api, "1.0.0", None, None), // Allows using #![no_core] - (active, no_core, "1.3.0", Some(29639)), + (active, no_core, "1.3.0", Some(29639), None), // Allows using `box` in patterns; RFC 469 - (active, box_patterns, "1.0.0", Some(29641)), + (active, box_patterns, "1.0.0", Some(29641), None), // Allows using the unsafe_destructor_blind_to_params attribute; // RFC 1238 - (active, dropck_parametricity, "1.3.0", Some(28498)), + (active, dropck_parametricity, "1.3.0", Some(28498), None), // Allows using the may_dangle attribute; RFC 1327 - (active, dropck_eyepatch, "1.10.0", Some(34761)), + (active, dropck_eyepatch, "1.10.0", Some(34761), None), // Allows the use of custom attributes; RFC 572 - (active, custom_attribute, "1.0.0", Some(29642)), + (active, custom_attribute, "1.0.0", Some(29642), None), // Allows the use of #[derive(Anything)] as sugar for // #[derive_Anything]. - (active, custom_derive, "1.0.0", Some(29644)), + (active, custom_derive, "1.0.0", Some(29644), None), // Allows the use of rustc_* attributes; RFC 572 - (active, rustc_attrs, "1.0.0", Some(29642)), + (active, rustc_attrs, "1.0.0", Some(29642), None), // Allows the use of non lexical lifetimes; RFC 2094 - (active, nll, "1.0.0", Some(43234)), + (active, nll, "1.0.0", Some(43234), None), // Allows the use of #[allow_internal_unstable]. This is an // attribute on macro_rules! and can't use the attribute handling @@ -201,7 +203,7 @@ pub fn walk_feature_fields(&self, mut f: F) // macros disappear). // // rustc internal - (active, allow_internal_unstable, "1.0.0", None), + (active, allow_internal_unstable, "1.0.0", None, None), // Allows the use of #[allow_internal_unsafe]. This is an // attribute on macro_rules! and can't use the attribute handling @@ -209,349 +211,349 @@ pub fn walk_feature_fields(&self, mut f: F) // macros disappear). // // rustc internal - (active, allow_internal_unsafe, "1.0.0", None), + (active, allow_internal_unsafe, "1.0.0", None, None), // #23121. Array patterns have some hazards yet. - (active, slice_patterns, "1.0.0", Some(23121)), + (active, slice_patterns, "1.0.0", Some(23121), None), // Allows the definition of `const fn` functions. - (active, const_fn, "1.2.0", Some(24111)), + (active, const_fn, "1.2.0", Some(24111), None), // Allows using #[prelude_import] on glob `use` items. // // rustc internal - (active, prelude_import, "1.2.0", None), + (active, prelude_import, "1.2.0", None, None), // Allows default type parameters to influence type inference. - (active, default_type_parameter_fallback, "1.3.0", Some(27336)), + (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), // Allows associated type defaults - (active, associated_type_defaults, "1.2.0", Some(29661)), + (active, associated_type_defaults, "1.2.0", Some(29661), None), // allow `repr(simd)`, and importing the various simd intrinsics - (active, repr_simd, "1.4.0", Some(27731)), + (active, repr_simd, "1.4.0", Some(27731), None), // Allows cfg(target_feature = "..."). - (active, cfg_target_feature, "1.4.0", Some(29717)), + (active, cfg_target_feature, "1.4.0", Some(29717), None), // allow `extern "platform-intrinsic" { ... }` - (active, platform_intrinsics, "1.4.0", Some(27731)), + (active, platform_intrinsics, "1.4.0", Some(27731), None), // allow `#[unwind(..)]` // rust runtime internal - (active, unwind_attributes, "1.4.0", None), + (active, unwind_attributes, "1.4.0", None, None), // allow the use of `#[naked]` on functions. - (active, naked_functions, "1.9.0", Some(32408)), + (active, naked_functions, "1.9.0", Some(32408), None), // allow `#[no_debug]` - (active, no_debug, "1.5.0", Some(29721)), + (active, no_debug, "1.5.0", Some(29721), None), // allow `#[omit_gdb_pretty_printer_section]` // rustc internal. - (active, omit_gdb_pretty_printer_section, "1.5.0", None), + (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), // Allows cfg(target_vendor = "..."). - (active, cfg_target_vendor, "1.5.0", Some(29718)), + (active, cfg_target_vendor, "1.5.0", Some(29718), None), // Allow attributes on expressions and non-item statements - (active, stmt_expr_attributes, "1.6.0", Some(15701)), + (active, stmt_expr_attributes, "1.6.0", Some(15701), None), // allow using type ascription in expressions - (active, type_ascription, "1.6.0", Some(23416)), + (active, type_ascription, "1.6.0", Some(23416), None), // Allows cfg(target_thread_local) - (active, cfg_target_thread_local, "1.7.0", Some(29594)), + (active, cfg_target_thread_local, "1.7.0", Some(29594), None), // rustc internal - (active, abi_vectorcall, "1.7.0", None), + (active, abi_vectorcall, "1.7.0", None, None), // a..=b and ..=b - (active, inclusive_range_syntax, "1.7.0", Some(28237)), + (active, inclusive_range_syntax, "1.7.0", Some(28237), None), // X..Y patterns - (active, exclusive_range_pattern, "1.11.0", Some(37854)), + (active, exclusive_range_pattern, "1.11.0", Some(37854), None), // impl specialization (RFC 1210) - (active, specialization, "1.7.0", Some(31844)), + (active, specialization, "1.7.0", Some(31844), None), // Allows cfg(target_has_atomic = "..."). - (active, cfg_target_has_atomic, "1.9.0", Some(32976)), + (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), // Allows `impl Trait` in function return types. - (active, conservative_impl_trait, "1.12.0", Some(34511)), + (active, conservative_impl_trait, "1.12.0", Some(34511), None), // Allows `impl Trait` in function arguments. - (active, universal_impl_trait, "1.23.0", Some(34511)), + (active, universal_impl_trait, "1.23.0", Some(34511), None), // The `!` type - (active, never_type, "1.13.0", Some(35121)), + (active, never_type, "1.13.0", Some(35121), None), // Allows all literals in attribute lists and values of key-value pairs. - (active, attr_literals, "1.13.0", Some(34981)), + (active, attr_literals, "1.13.0", Some(34981), None), // Allows untagged unions `union U { ... }` - (active, untagged_unions, "1.13.0", Some(32836)), + (active, untagged_unions, "1.13.0", Some(32836), None), // Used to identify the `compiler_builtins` crate // rustc internal - (active, compiler_builtins, "1.13.0", None), + (active, compiler_builtins, "1.13.0", None, None), // Allows attributes on lifetime/type formal parameters in generics (RFC 1327) - (active, generic_param_attrs, "1.11.0", Some(34761)), + (active, generic_param_attrs, "1.11.0", Some(34761), None), // Allows #[link(..., cfg(..))] - (active, link_cfg, "1.14.0", Some(37406)), + (active, link_cfg, "1.14.0", Some(37406), None), - (active, use_extern_macros, "1.15.0", Some(35896)), + (active, use_extern_macros, "1.15.0", Some(35896), None), // Allows #[target_feature(...)] - (active, target_feature, "1.15.0", None), + (active, target_feature, "1.15.0", None, None), // `extern "ptx-*" fn()` - (active, abi_ptx, "1.15.0", None), + (active, abi_ptx, "1.15.0", None, None), // The `i128` type - (active, i128_type, "1.16.0", Some(35118)), + (active, i128_type, "1.16.0", Some(35118), None), // The `repr(i128)` annotation for enums - (active, repr128, "1.16.0", Some(35118)), + (active, repr128, "1.16.0", Some(35118), None), // The `unadjusted` ABI. Perma unstable. - (active, abi_unadjusted, "1.16.0", None), + (active, abi_unadjusted, "1.16.0", None, None), // Procedural macros 2.0. - (active, proc_macro, "1.16.0", Some(38356)), + (active, proc_macro, "1.16.0", Some(38356), None), // Declarative macros 2.0 (`macro`). - (active, decl_macro, "1.17.0", Some(39412)), + (active, decl_macro, "1.17.0", Some(39412), None), // Allows #[link(kind="static-nobundle"...] - (active, static_nobundle, "1.16.0", Some(37403)), + (active, static_nobundle, "1.16.0", Some(37403), None), // `extern "msp430-interrupt" fn()` - (active, abi_msp430_interrupt, "1.16.0", Some(38487)), + (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), // Used to identify crates that contain sanitizer runtimes // rustc internal - (active, sanitizer_runtime, "1.17.0", None), + (active, sanitizer_runtime, "1.17.0", None, None), // Used to identify crates that contain the profiler runtime // rustc internal - (active, profiler_runtime, "1.18.0", None), + (active, profiler_runtime, "1.18.0", None, None), // `extern "x86-interrupt" fn()` - (active, abi_x86_interrupt, "1.17.0", Some(40180)), + (active, abi_x86_interrupt, "1.17.0", Some(40180), None), // Allows the `catch {...}` expression - (active, catch_expr, "1.17.0", Some(31436)), + (active, catch_expr, "1.17.0", Some(31436), None), // Used to preserve symbols (see llvm.used) - (active, used, "1.18.0", Some(40289)), + (active, used, "1.18.0", Some(40289), None), // Allows module-level inline assembly by way of global_asm!() - (active, global_asm, "1.18.0", Some(35119)), + (active, global_asm, "1.18.0", Some(35119), None), // Allows overlapping impls of marker traits - (active, overlapping_marker_traits, "1.18.0", Some(29864)), + (active, overlapping_marker_traits, "1.18.0", Some(29864), None), // Allows use of the :vis macro fragment specifier - (active, macro_vis_matcher, "1.18.0", Some(41022)), + (active, macro_vis_matcher, "1.18.0", Some(41022), None), // rustc internal - (active, abi_thiscall, "1.19.0", None), + (active, abi_thiscall, "1.19.0", None, None), // Allows a test to fail without failing the whole suite - (active, allow_fail, "1.19.0", Some(42219)), + (active, allow_fail, "1.19.0", Some(42219), None), // Allows unsized tuple coercion. - (active, unsized_tuple_coercion, "1.20.0", Some(42877)), + (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), // Generators - (active, generators, "1.21.0", None), + (active, generators, "1.21.0", None, None), // Trait aliases - (active, trait_alias, "1.24.0", Some(41517)), + (active, trait_alias, "1.24.0", Some(41517), None), // global allocators and their internals - (active, global_allocator, "1.20.0", None), - (active, allocator_internals, "1.20.0", None), + (active, global_allocator, "1.20.0", None, None), + (active, allocator_internals, "1.20.0", None, None), // #[doc(cfg(...))] - (active, doc_cfg, "1.21.0", Some(43781)), + (active, doc_cfg, "1.21.0", Some(43781), None), // #[doc(masked)] - (active, doc_masked, "1.21.0", Some(44027)), + (active, doc_masked, "1.21.0", Some(44027), None), // #[doc(spotlight)] - (active, doc_spotlight, "1.22.0", Some(45040)), + (active, doc_spotlight, "1.22.0", Some(45040), None), // #[doc(include="some-file")] - (active, external_doc, "1.22.0", Some(44732)), + (active, external_doc, "1.22.0", Some(44732), None), // allow `#[must_use]` on functions and comparison operators (RFC 1940) - (active, fn_must_use, "1.21.0", Some(43302)), + (active, fn_must_use, "1.21.0", Some(43302), None), // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008) - (active, non_exhaustive, "1.22.0", Some(44109)), + (active, non_exhaustive, "1.22.0", Some(44109), None), // Copy/Clone closures (RFC 2132) - (active, clone_closures, "1.22.0", Some(44490)), - (active, copy_closures, "1.22.0", Some(44490)), + (active, clone_closures, "1.22.0", Some(44490), None), + (active, copy_closures, "1.22.0", Some(44490), None), // allow `'_` placeholder lifetimes - (active, underscore_lifetimes, "1.22.0", Some(44524)), + (active, underscore_lifetimes, "1.22.0", Some(44524), None), // allow `..=` in patterns (RFC 1192) - (active, dotdoteq_in_patterns, "1.22.0", Some(28237)), + (active, dotdoteq_in_patterns, "1.22.0", Some(28237), None), // Default match binding modes (RFC 2005) - (active, match_default_bindings, "1.22.0", Some(42640)), + (active, match_default_bindings, "1.22.0", Some(42640), None), // Trait object syntax with `dyn` prefix - (active, dyn_trait, "1.22.0", Some(44662)), + (active, dyn_trait, "1.22.0", Some(44662), Some(Epoch::Epoch2018)), // `crate` as visibility modifier, synonymous to `pub(crate)` - (active, crate_visibility_modifier, "1.23.0", Some(45388)), + (active, crate_visibility_modifier, "1.23.0", Some(45388), None), // extern types - (active, extern_types, "1.23.0", Some(43467)), + (active, extern_types, "1.23.0", Some(43467), None), // Allow trait methods with arbitrary self types - (active, arbitrary_self_types, "1.23.0", Some(44874)), + (active, arbitrary_self_types, "1.23.0", Some(44874), None), // `crate` in paths - (active, crate_in_paths, "1.23.0", Some(45477)), + (active, crate_in_paths, "1.23.0", Some(45477), None), // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`) - (active, in_band_lifetimes, "1.23.0", Some(44524)), + (active, in_band_lifetimes, "1.23.0", Some(44524), None), // generic associated types (RFC 1598) - (active, generic_associated_types, "1.23.0", Some(44265)), + (active, generic_associated_types, "1.23.0", Some(44265), None), // Resolve absolute paths as paths from other crates - (active, extern_absolute_paths, "1.24.0", Some(44660)), + (active, extern_absolute_paths, "1.24.0", Some(44660), None), // `foo.rs` as an alternative to `foo/mod.rs` - (active, non_modrs_mods, "1.24.0", Some(44660)), + (active, non_modrs_mods, "1.24.0", Some(44660), None), // Termination trait in main (RFC 1937) - (active, termination_trait, "1.24.0", Some(43301)), + (active, termination_trait, "1.24.0", Some(43301), None), // Allows use of the :lifetime macro fragment specifier - (active, macro_lifetime_matcher, "1.24.0", Some(46895)), + (active, macro_lifetime_matcher, "1.24.0", Some(46895), None), // `extern` in paths - (active, extern_in_paths, "1.23.0", Some(44660)), + (active, extern_in_paths, "1.23.0", Some(44660), None), // Allows `#[repr(transparent)]` attribute on newtype structs - (active, repr_transparent, "1.25.0", Some(43036)), + (active, repr_transparent, "1.25.0", Some(43036), None), // Use `?` as the Kleene "at most one" operator - (active, macro_at_most_once_rep, "1.25.0", Some(48075)), + (active, macro_at_most_once_rep, "1.25.0", Some(48075), None), // Multiple patterns with `|` in `if let` and `while let` - (active, if_while_or_patterns, "1.26.0", Some(48215)), + (active, if_while_or_patterns, "1.26.0", Some(48215), None), // Parentheses in patterns - (active, pattern_parentheses, "1.26.0", None), + (active, pattern_parentheses, "1.26.0", None, None), ); declare_features! ( - (removed, import_shadowing, "1.0.0", None), - (removed, managed_boxes, "1.0.0", None), + (removed, import_shadowing, "1.0.0", None, None), + (removed, managed_boxes, "1.0.0", None, None), // Allows use of unary negate on unsigned integers, e.g. -e for e: u8 - (removed, negate_unsigned, "1.0.0", Some(29645)), - (removed, reflect, "1.0.0", Some(27749)), + (removed, negate_unsigned, "1.0.0", Some(29645), None), + (removed, reflect, "1.0.0", Some(27749), None), // A way to temporarily opt out of opt in copy. This will *never* be accepted. - (removed, opt_out_copy, "1.0.0", None), - (removed, quad_precision_float, "1.0.0", None), - (removed, struct_inherit, "1.0.0", None), - (removed, test_removed_feature, "1.0.0", None), - (removed, visible_private_types, "1.0.0", None), - (removed, unsafe_no_drop_flag, "1.0.0", None), + (removed, opt_out_copy, "1.0.0", None, None), + (removed, quad_precision_float, "1.0.0", None, None), + (removed, struct_inherit, "1.0.0", None, None), + (removed, test_removed_feature, "1.0.0", None, None), + (removed, visible_private_types, "1.0.0", None, None), + (removed, unsafe_no_drop_flag, "1.0.0", None, None), // Allows using items which are missing stability attributes // rustc internal - (removed, unmarked_api, "1.0.0", None), - (removed, pushpop_unsafe, "1.2.0", None), - (removed, allocator, "1.0.0", None), + (removed, unmarked_api, "1.0.0", None, None), + (removed, pushpop_unsafe, "1.2.0", None, None), + (removed, allocator, "1.0.0", None, None), // Allows the `#[simd]` attribute -- removed in favor of `#[repr(simd)]` - (removed, simd, "1.0.0", Some(27731)), + (removed, simd, "1.0.0", Some(27731), None), ); declare_features! ( - (stable_removed, no_stack_check, "1.0.0", None), + (stable_removed, no_stack_check, "1.0.0", None, None), ); declare_features! ( - (accepted, associated_types, "1.0.0", None), + (accepted, associated_types, "1.0.0", None, None), // allow overloading augmented assignment operations like `a += b` - (accepted, augmented_assignments, "1.8.0", Some(28235)), + (accepted, augmented_assignments, "1.8.0", Some(28235), None), // allow empty structs and enum variants with braces - (accepted, braced_empty_structs, "1.8.0", Some(29720)), + (accepted, braced_empty_structs, "1.8.0", Some(29720), None), // Allows indexing into constant arrays. - (accepted, const_indexing, "1.24.0", Some(29947)), - (accepted, default_type_params, "1.0.0", None), - (accepted, globs, "1.0.0", None), - (accepted, if_let, "1.0.0", None), + (accepted, const_indexing, "1.24.0", Some(29947), None), + (accepted, default_type_params, "1.0.0", None, None), + (accepted, globs, "1.0.0", None, None), + (accepted, if_let, "1.0.0", None, None), // A temporary feature gate used to enable parser extensions needed // to bootstrap fix for #5723. - (accepted, issue_5723_bootstrap, "1.0.0", None), - (accepted, macro_rules, "1.0.0", None), + (accepted, issue_5723_bootstrap, "1.0.0", None, None), + (accepted, macro_rules, "1.0.0", None, None), // Allows using #![no_std] - (accepted, no_std, "1.6.0", None), - (accepted, slicing_syntax, "1.0.0", None), - (accepted, struct_variant, "1.0.0", None), + (accepted, no_std, "1.6.0", None, None), + (accepted, slicing_syntax, "1.0.0", None, None), + (accepted, struct_variant, "1.0.0", None, None), // These are used to test this portion of the compiler, they don't actually // mean anything - (accepted, test_accepted_feature, "1.0.0", None), - (accepted, tuple_indexing, "1.0.0", None), + (accepted, test_accepted_feature, "1.0.0", None, None), + (accepted, tuple_indexing, "1.0.0", None, None), // Allows macros to appear in the type position. - (accepted, type_macros, "1.13.0", Some(27245)), - (accepted, while_let, "1.0.0", None), + (accepted, type_macros, "1.13.0", Some(27245), None), + (accepted, while_let, "1.0.0", None, None), // Allows `#[deprecated]` attribute - (accepted, deprecated, "1.9.0", Some(29935)), + (accepted, deprecated, "1.9.0", Some(29935), None), // `expr?` - (accepted, question_mark, "1.13.0", Some(31436)), + (accepted, question_mark, "1.13.0", Some(31436), None), // Allows `..` in tuple (struct) patterns - (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)), - (accepted, item_like_imports, "1.15.0", Some(35120)), + (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), + (accepted, item_like_imports, "1.15.0", Some(35120), None), // Allows using `Self` and associated types in struct expressions and patterns. - (accepted, more_struct_aliases, "1.16.0", Some(37544)), + (accepted, more_struct_aliases, "1.16.0", Some(37544), None), // elide `'static` lifetimes in `static`s and `const`s - (accepted, static_in_const, "1.17.0", Some(35897)), + (accepted, static_in_const, "1.17.0", Some(35897), None), // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. - (accepted, field_init_shorthand, "1.17.0", Some(37340)), + (accepted, field_init_shorthand, "1.17.0", Some(37340), None), // Allows the definition recursive static items. - (accepted, static_recursion, "1.17.0", Some(29719)), + (accepted, static_recursion, "1.17.0", Some(29719), None), // pub(restricted) visibilities (RFC 1422) - (accepted, pub_restricted, "1.18.0", Some(32409)), + (accepted, pub_restricted, "1.18.0", Some(32409), None), // The #![windows_subsystem] attribute - (accepted, windows_subsystem, "1.18.0", Some(37499)), + (accepted, windows_subsystem, "1.18.0", Some(37499), None), // Allows `break {expr}` with a value inside `loop`s. - (accepted, loop_break_value, "1.19.0", Some(37339)), + (accepted, loop_break_value, "1.19.0", Some(37339), None), // Permits numeric fields in struct expressions and patterns. - (accepted, relaxed_adts, "1.19.0", Some(35626)), + (accepted, relaxed_adts, "1.19.0", Some(35626), None), // Coerces non capturing closures to function pointers - (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)), + (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), // Allows attributes on struct literal fields. - (accepted, struct_field_attributes, "1.20.0", Some(38814)), + (accepted, struct_field_attributes, "1.20.0", Some(38814), None), // Allows the definition of associated constants in `trait` or `impl` // blocks. - (accepted, associated_consts, "1.20.0", Some(29646)), + (accepted, associated_consts, "1.20.0", Some(29646), None), // Usage of the `compile_error!` macro - (accepted, compile_error, "1.20.0", Some(40872)), + (accepted, compile_error, "1.20.0", Some(40872), None), // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work. - (accepted, rvalue_static_promotion, "1.21.0", Some(38865)), + (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), // Allow Drop types in constants (RFC 1440) - (accepted, drop_types_in_const, "1.22.0", Some(33156)), + (accepted, drop_types_in_const, "1.22.0", Some(33156), None), // Allows the sysV64 ABI to be specified on all platforms // instead of just the platforms on which it is the C ABI - (accepted, abi_sysv64, "1.24.0", Some(36167)), + (accepted, abi_sysv64, "1.24.0", Some(36167), None), // Allows `repr(align(16))` struct attribute (RFC 1358) - (accepted, repr_align, "1.25.0", Some(33626)), + (accepted, repr_align, "1.25.0", Some(33626), None), // allow '|' at beginning of match arms (RFC 1925) - (accepted, match_beginning_vert, "1.25.0", Some(44101)), + (accepted, match_beginning_vert, "1.25.0", Some(44101), None), // Nested groups in `use` (RFC 2128) - (accepted, use_nested_groups, "1.25.0", Some(44494)), + (accepted, use_nested_groups, "1.25.0", Some(44494), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1793,11 +1795,22 @@ fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) { } } -pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features { +pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], + epoch: Epoch) -> Features { let mut features = Features::new(); let mut feature_checker = FeatureChecker::default(); + for &(.., f_epoch, set) in ACTIVE_FEATURES.iter() { + if let Some(f_epoch) = f_epoch { + if epoch >= f_epoch { + // FIXME(Manishearth) there is currently no way to set + // lang features by epoch + set(&mut features, DUMMY_SP); + } + } + } + for attr in krate_attrs { if !attr.check_name("feature") { continue @@ -1818,8 +1831,8 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F continue }; - if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter() - .find(|& &(n, _, _, _)| name == n) { + if let Some(&(_, _, _, _, set)) = ACTIVE_FEATURES.iter() + .find(|& &(n, ..)| name == n) { set(&mut features, mi.span); feature_checker.collect(&features, mi.span); } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 14e39b5af42..50e94e5cba7 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -23,6 +23,7 @@ #![feature(unicode)] #![feature(rustc_diagnostic_macros)] #![feature(match_default_bindings)] +#![feature(non_exhaustive)] #![feature(i128_type)] #![feature(const_atomic_usize_new)] #![feature(rustc_attrs)] @@ -114,6 +115,7 @@ pub mod syntax { #[macro_use] pub mod config; pub mod entry; +pub mod epoch; pub mod feature_gate; pub mod fold; pub mod parse; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index da2a22df997..847733e1e37 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3318,7 +3318,7 @@ pub fn parse_for_expr(&mut self, opt_label: Option