From da9dc0507bc86104db8bf7a99e849bfd995fb1ef Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 22 Feb 2018 16:51:42 -0800 Subject: [PATCH] Allow future-incompat lints to mention an epoch --- src/librustc/lint/context.rs | 27 ++++++++++++++++++++++----- src/librustc/lint/levels.rs | 17 ++++++++++------- src/librustc/lint/mod.rs | 29 +++++++++++++++++++++++++---- src/librustc/session/config.rs | 11 ++++++++++- src/librustc/session/mod.rs | 4 ++++ src/librustc/ty/context.rs | 2 +- src/librustc_driver/driver.rs | 2 +- src/librustc_driver/lib.rs | 22 +++++++++++----------- src/librustc_lint/lib.rs | 18 ++++++++++++++++++ 9 files changed, 102 insertions(+), 30 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index ed937046e5ed..870b52c221f3 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -99,7 +99,11 @@ pub struct BufferedEarlyLint { /// guidelines. pub struct FutureIncompatibleInfo { pub id: LintId, - pub reference: &'static str // e.g., a URL for an issue/PR/RFC or error code + /// e.g., a URL for an issue/PR/RFC or error code + pub reference: &'static str, + /// If this is an epoch fixing lint, the epoch in which + /// this lint becomes obsolete + pub epoch: Option, } /// The target of the `by_name` map, which accounts for renaming/deprecation. @@ -194,11 +198,24 @@ impl LintStore { pub fn register_future_incompatible(&mut self, sess: Option<&Session>, lints: Vec) { - let ids = lints.iter().map(|f| f.id).collect(); - self.register_group(sess, false, "future_incompatible", ids); - for info in lints { - self.future_incompatible.insert(info.id, info); + + for epoch in config::ALL_EPOCHS { + let lints = lints.iter().filter(|f| f.epoch == Some(*epoch)).map(|f| f.id) + .collect::>(); + if !lints.is_empty() { + self.register_group(sess, false, epoch.lint_name(), lints) + } } + + let mut future_incompatible = vec![]; + for lint in lints { + future_incompatible.push(lint.id); + self.future_incompatible.insert(lint.id, lint); + } + + self.register_group(sess, false, "future_incompatible", future_incompatible); + + } pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> { diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 4bc37747f2a7..909904b4fc36 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -89,14 +89,15 @@ impl LintLevelSets { fn get_lint_level(&self, lint: &'static Lint, idx: u32, - aux: Option<&FxHashMap>) + aux: Option<&FxHashMap>, + sess: &Session) -> (Level, LintSource) { let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux); // If `level` is none then we actually assume the default level for this // lint. - let mut level = level.unwrap_or(lint.default_level); + let mut level = level.unwrap_or(lint.default_level(sess)); // If we're about to issue a warning, check at the last minute for any // directives against the warnings "lint". If, for example, there's an @@ -235,7 +236,8 @@ impl<'a> LintLevelsBuilder<'a> { let lint = builtin::RENAMED_AND_REMOVED_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, - Some(&specs)); + Some(&specs), + &sess); lint::struct_lint_level(self.sess, lint, level, @@ -248,7 +250,8 @@ impl<'a> LintLevelsBuilder<'a> { let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, - Some(&specs)); + Some(&specs), + self.sess); let msg = format!("unknown lint: `{}`", name); let mut db = lint::struct_lint_level(self.sess, lint, @@ -342,7 +345,7 @@ impl<'a> LintLevelsBuilder<'a> { msg: &str) -> DiagnosticBuilder<'a> { - let (level, src) = self.sets.get_lint_level(lint, self.cur, None); + let (level, src) = self.sets.get_lint_level(lint, self.cur, None, self.sess); lint::struct_lint_level(self.sess, lint, level, src, span, msg) } @@ -377,11 +380,11 @@ impl LintLevelMap { /// If the `id` was not previously registered, returns `None`. If `None` is /// returned then the parent of `id` should be acquired and this function /// should be called again. - pub fn level_and_source(&self, lint: &'static Lint, id: HirId) + pub fn level_and_source(&self, lint: &'static Lint, id: HirId, session: &Session) -> Option<(Level, LintSource)> { self.id_to_set.get(&id).map(|idx| { - self.sets.get_lint_level(lint, *idx, None) + self.sets.get_lint_level(lint, *idx, None, session) }) } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index b2a9859f68a3..e28cc9c201d0 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -37,7 +37,7 @@ use errors::{DiagnosticBuilder, DiagnosticId}; use hir::def_id::{CrateNum, LOCAL_CRATE}; use hir::intravisit::{self, FnKind}; use hir; -use session::{Session, DiagnosticMessageId}; +use session::{config, Session, DiagnosticMessageId}; use std::hash; use syntax::ast; use syntax::codemap::MultiSpan; @@ -74,6 +74,9 @@ pub struct Lint { /// /// e.g. "imports that are never used" pub desc: &'static str, + + /// Deny lint after this epoch + pub epoch_deny: Option, } impl Lint { @@ -81,18 +84,36 @@ impl Lint { pub fn name_lower(&self) -> String { self.name.to_ascii_lowercase() } + + pub fn default_level(&self, session: &Session) -> Level { + if let Some(epoch_deny) = self.epoch_deny { + if session.epoch() >= epoch_deny { + return Level::Deny + } + } + self.default_level + } } /// Declare a static item of type `&'static Lint`. #[macro_export] macro_rules! declare_lint { + ($vis: vis $NAME: ident, $Level: ident, $desc: expr, $epoch: expr) => ( + $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint { + name: stringify!($NAME), + default_level: $crate::lint::$Level, + desc: $desc, + epoch_deny: Some($epoch) + }; + ); ($vis: vis $NAME: ident, $Level: ident, $desc: expr) => ( $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint { name: stringify!($NAME), default_level: $crate::lint::$Level, - desc: $desc + desc: $desc, + epoch_deny: None, }; - ) + ); } /// Declare a static `LintArray` and return it as an expression. @@ -304,7 +325,7 @@ impl LintId { /// Setting for how to handle a lint. #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] pub enum Level { - Allow, Warn, Deny, Forbid + Allow, Warn, Deny, Forbid, } impl_stable_hash_for!(enum self::Level { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index ef85ef8e37e7..beb828ab91bf 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -113,7 +113,7 @@ pub enum OutputType { } /// The epoch of the compiler (RFC 2052) -#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq)] +#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)] #[non_exhaustive] pub enum Epoch { // epochs must be kept in order, newest to oldest @@ -148,6 +148,15 @@ impl ToString for Epoch { } } +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 { diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 9d7a9acc3d53..6901674a6cf8 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -869,6 +869,10 @@ impl Session { pub fn rust_2018(&self) -> bool { self.opts.debugging_opts.epoch >= Epoch::Epoch2018 } + + pub fn epoch(&self) -> Epoch { + self.opts.debugging_opts.epoch + } } pub fn build_session(sopts: config::Options, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index e4e07454c97a..414ddb9efb2c 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2234,7 +2234,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let sets = self.lint_levels(LOCAL_CRATE); loop { let hir_id = self.hir.definitions().node_to_hir_id(id); - if let Some(pair) = sets.level_and_source(lint, hir_id) { + if let Some(pair) = sets.level_and_source(lint, hir_id, self.sess) { return pair } let next = self.hir.get_parent_node(id); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b8a1fe991054..943d690d7671 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -735,7 +735,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, // Lint plugins are registered; now we can process command line flags. if sess.opts.describe_lints { - super::describe_lints(&sess.lint_store.borrow(), true); + super::describe_lints(&sess, &sess.lint_store.borrow(), true); return Err(CompileIncomplete::Stopped); } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 05dcaf731352..5f0d106877c0 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -774,15 +774,15 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { -> Option<(Input, Option)> { match matches.free.len() { 0 => { - if sopts.describe_lints { - let mut ls = lint::LintStore::new(); - rustc_lint::register_builtins(&mut ls, None); - describe_lints(&ls, false); - return None; - } let mut sess = build_session(sopts.clone(), None, descriptions.clone()); + if sopts.describe_lints { + let mut ls = lint::LintStore::new(); + rustc_lint::register_builtins(&mut ls, Some(&sess)); + describe_lints(&sess, &ls, false); + return None; + } rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let mut cfg = config::build_configuration(&sess, cfg.clone()); let trans = get_trans(&sess); @@ -1121,7 +1121,7 @@ fn usage(verbose: bool, include_unstable_options: bool) { verbose_help); } -fn describe_lints(lint_store: &lint::LintStore, loaded_plugins: bool) { +fn describe_lints(sess: &Session, lint_store: &lint::LintStore, loaded_plugins: bool) { println!(" Available lint options: -W Warn about @@ -1133,10 +1133,10 @@ Available lint options: "); - fn sort_lints(lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> { + fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> { let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect(); lints.sort_by(|x: &&Lint, y: &&Lint| { - match x.default_level.cmp(&y.default_level) { + match x.default_level(sess).cmp(&y.default_level(sess)) { // The sort doesn't case-fold but it's doubtful we care. Equal => x.name.cmp(y.name), r => r, @@ -1159,8 +1159,8 @@ Available lint options: .iter() .cloned() .partition(|&(_, p)| p); - let plugin = sort_lints(plugin); - let builtin = sort_lints(builtin); + let plugin = sort_lints(sess, plugin); + let builtin = sort_lints(sess, builtin); let (plugin_groups, builtin_groups): (Vec<_>, _) = lint_store.get_lint_groups() .iter() diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 699765dde03f..c35a3fbe419d 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -185,74 +185,92 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { FutureIncompatibleInfo { id: LintId::of(PRIVATE_IN_PUBLIC), reference: "issue #34537 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE), reference: "issue #34537 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY), reference: "issue #35203 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(SAFE_EXTERN_STATICS), reference: "issue #36247 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(INVALID_TYPE_PARAM_DEFAULT), reference: "issue #36887 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP), reference: "issue #37872 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(LEGACY_IMPORTS), reference: "issue #38260 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY), reference: "issue #39207 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT), reference: "issue #39216 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(MISSING_FRAGMENT_SPECIFIER), reference: "issue #40107 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN), reference: "issue #41620 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(ANONYMOUS_PARAMETERS), reference: "issue #41686 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES), reference: "issue #42238 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS), reference: "issue #42868 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(SAFE_PACKED_BORROWS), reference: "issue #46043 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(INCOHERENT_FUNDAMENTAL_IMPLS), reference: "issue #46205 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(COERCE_NEVER), reference: "issue #46325 ", + epoch: None, }, FutureIncompatibleInfo { id: LintId::of(TYVAR_BEHIND_RAW_POINTER), reference: "issue #46906 ", + epoch: None, }, ]);