Allow future-incompat lints to mention an epoch
This commit is contained in:
parent
d9438c30d5
commit
da9dc0507b
9 changed files with 102 additions and 30 deletions
|
|
@ -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<config::Epoch>,
|
||||
}
|
||||
|
||||
/// 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<FutureIncompatibleInfo>) {
|
||||
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::<Vec<_>>();
|
||||
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> {
|
||||
|
|
|
|||
|
|
@ -89,14 +89,15 @@ impl LintLevelSets {
|
|||
fn get_lint_level(&self,
|
||||
lint: &'static Lint,
|
||||
idx: u32,
|
||||
aux: Option<&FxHashMap<LintId, (Level, LintSource)>>)
|
||||
aux: Option<&FxHashMap<LintId, (Level, LintSource)>>,
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<config::Epoch>,
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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<Self, ()> {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue