2014-06-06 15:49:48 -07:00
|
|
|
//! Implementation of lint checking.
|
|
|
|
//!
|
2018-05-08 16:10:16 +03:00
|
|
|
//! The lint checking is mostly consolidated into one pass which runs
|
|
|
|
//! after all other analyses. Throughout compilation, lint warnings
|
2014-06-06 15:49:48 -07:00
|
|
|
//! can be added via the `add_lint` method on the Session structure. This
|
2019-02-08 14:53:55 +01:00
|
|
|
//! requires a span and an ID of the node that the lint is being added to. The
|
2014-06-06 15:49:48 -07:00
|
|
|
//! lint isn't actually emitted at that time because it is unknown what the
|
|
|
|
//! actual lint level at that location is.
|
|
|
|
//!
|
2018-05-08 16:10:16 +03:00
|
|
|
//! To actually emit lint warnings/errors, a separate pass is used.
|
|
|
|
//! A context keeps track of the current state of all lint levels.
|
2014-06-06 15:49:48 -07:00
|
|
|
//! Upon entering a node of the ast which can modify the lint settings, the
|
|
|
|
//! previous lint state is pushed onto a stack and the ast is then recursed
|
2019-02-08 14:53:55 +01:00
|
|
|
//! upon. As the ast is traversed, this keeps track of the current lint level
|
2014-06-06 15:49:48 -07:00
|
|
|
//! for all lint attributes.
|
2017-07-26 21:51:09 -07:00
|
|
|
|
2014-11-06 00:05:53 -08:00
|
|
|
use self::TargetLint::*;
|
2014-06-06 15:49:48 -07:00
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
use crate::hir;
|
|
|
|
use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
|
|
|
use crate::hir::intravisit as hir_visit;
|
|
|
|
use crate::hir::intravisit::Visitor;
|
|
|
|
use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
|
2019-01-31 01:36:11 +01:00
|
|
|
use crate::lint::{EarlyLintPass, LateLintPass, EarlyLintPassObject, LateLintPassObject};
|
2019-10-08 21:49:21 -04:00
|
|
|
use crate::lint::{Level, Lint, LintId, LintPass, LintBuffer, FutureIncompatibleInfo};
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::lint::builtin::BuiltinLintDiagnostics;
|
|
|
|
use crate::lint::levels::{LintLevelSets, LintLevelsBuilder};
|
|
|
|
use crate::middle::privacy::AccessLevels;
|
2019-09-23 20:26:11 -04:00
|
|
|
use crate::session::Session;
|
2019-09-25 16:39:44 +01:00
|
|
|
use crate::ty::{self, print::Printer, subst::GenericArg, TyCtxt, Ty};
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
|
|
|
|
use crate::util::nodemap::FxHashMap;
|
|
|
|
use crate::util::common::time;
|
2014-06-06 15:49:48 -07:00
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
use errors::DiagnosticBuilder;
|
|
|
|
use std::slice;
|
2019-10-10 19:33:00 -04:00
|
|
|
use rustc_data_structures::sync::{self, ParallelIterator, join, par_iter};
|
2015-11-15 17:17:50 +01:00
|
|
|
use syntax::ast;
|
2018-12-19 13:51:52 -05:00
|
|
|
use syntax::util::lev_distance::find_best_match_for_name;
|
2015-09-10 16:40:59 +12:00
|
|
|
use syntax::visit as ast_visit;
|
2019-09-06 03:57:44 +01:00
|
|
|
use syntax_pos::{MultiSpan, Span, symbol::Symbol};
|
2014-06-06 15:49:48 -07:00
|
|
|
|
2019-11-11 22:46:56 +01:00
|
|
|
use rustc_error_codes::*;
|
|
|
|
|
2014-06-06 15:49:48 -07:00
|
|
|
/// Information about the registered lints.
|
|
|
|
///
|
|
|
|
/// This is basically the subset of `Context` that we can
|
|
|
|
/// build early in the compile pipeline.
|
|
|
|
pub struct LintStore {
|
2019-11-30 11:31:25 +03:00
|
|
|
/// Registered lints.
|
2019-10-07 16:52:53 -04:00
|
|
|
lints: Vec<&'static Lint>,
|
2014-06-06 15:49:48 -07:00
|
|
|
|
2019-10-07 18:23:16 -04:00
|
|
|
/// Constructor functions for each variety of lint pass.
|
|
|
|
///
|
|
|
|
/// These should only be called once, but since we want to avoid locks or
|
|
|
|
/// interior mutability, we don't enforce this (and lints should, in theory,
|
|
|
|
/// be compatible with being constructed more than once, though not
|
|
|
|
/// necessarily in a sane manner. This is safe though.)
|
2019-10-10 19:33:00 -04:00
|
|
|
pre_expansion_passes: Vec<Box<dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync>>,
|
|
|
|
early_passes: Vec<Box<dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync>>,
|
|
|
|
late_passes: Vec<Box<dyn Fn() -> LateLintPassObject + sync::Send + sync::Sync>>,
|
2019-10-07 18:23:16 -04:00
|
|
|
/// This is unique in that we construct them per-module, so not once.
|
2019-10-10 19:33:00 -04:00
|
|
|
late_module_passes: Vec<Box<dyn Fn() -> LateLintPassObject + sync::Send + sync::Sync>>,
|
2014-06-06 15:49:48 -07:00
|
|
|
|
|
|
|
/// Lints indexed by name.
|
2016-11-08 14:02:55 +11:00
|
|
|
by_name: FxHashMap<String, TargetLint>,
|
2014-06-06 15:49:48 -07:00
|
|
|
|
2018-09-15 17:32:24 +01:00
|
|
|
/// Map of registered lint groups to what lints they expand to.
|
|
|
|
lint_groups: FxHashMap<&'static str, LintGroup>,
|
2017-05-16 03:16:18 +08:00
|
|
|
}
|
|
|
|
|
2017-07-26 21:51:09 -07:00
|
|
|
/// Lints that are buffered up early on in the `Session` before the
|
|
|
|
/// `LintLevels` is calculated
|
2019-11-12 11:20:01 -05:00
|
|
|
#[derive(PartialEq, Debug)]
|
2017-07-26 21:51:09 -07:00
|
|
|
pub struct BufferedEarlyLint {
|
|
|
|
pub lint_id: LintId,
|
|
|
|
pub ast_id: ast::NodeId,
|
|
|
|
pub span: MultiSpan,
|
|
|
|
pub msg: String,
|
2018-02-22 22:34:06 -08:00
|
|
|
pub diagnostic: BuiltinLintDiagnostics,
|
2016-10-12 16:38:58 -04:00
|
|
|
}
|
2016-10-06 04:56:13 -04:00
|
|
|
|
2017-08-15 21:45:21 +02:00
|
|
|
/// The target of the `by_name` map, which accounts for renaming/deprecation.
|
2014-10-14 11:32:31 -07:00
|
|
|
enum TargetLint {
|
|
|
|
/// A direct lint target
|
|
|
|
Id(LintId),
|
|
|
|
|
|
|
|
/// Temporary renaming, used for easing migration pain; see #16545
|
|
|
|
Renamed(String, LintId),
|
2015-07-15 20:12:30 +03:00
|
|
|
|
|
|
|
/// Lint with this name existed previously, but has been removed/deprecated.
|
|
|
|
/// The string argument is the reason for removal.
|
|
|
|
Removed(String),
|
|
|
|
}
|
|
|
|
|
2017-07-26 21:51:09 -07:00
|
|
|
pub enum FindLintError {
|
2015-07-15 20:12:30 +03:00
|
|
|
NotFound,
|
2017-03-13 02:12:13 +02:00
|
|
|
Removed,
|
2014-10-14 11:32:31 -07:00
|
|
|
}
|
|
|
|
|
2018-09-15 17:32:24 +01:00
|
|
|
struct LintAlias {
|
|
|
|
name: &'static str,
|
|
|
|
/// Whether deprecation warnings should be suppressed for this alias.
|
|
|
|
silent: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct LintGroup {
|
|
|
|
lint_ids: Vec<LintId>,
|
|
|
|
from_plugin: bool,
|
|
|
|
depr: Option<LintAlias>,
|
|
|
|
}
|
|
|
|
|
2017-07-26 21:51:09 -07:00
|
|
|
pub enum CheckLintNameResult<'a> {
|
|
|
|
Ok(&'a [LintId]),
|
2018-12-19 13:51:52 -05:00
|
|
|
/// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
|
|
|
|
NoLint(Option<Symbol>),
|
2017-08-17 16:15:40 +02:00
|
|
|
/// The lint is either renamed or removed. This is the warning
|
2018-07-14 20:52:40 -07:00
|
|
|
/// message, and an optional new name (`None` if removed).
|
|
|
|
Warning(String, Option<String>),
|
2018-07-30 11:29:23 +02:00
|
|
|
/// The lint is from a tool. If the Option is None, then either
|
|
|
|
/// the lint does not exist in the tool or the code was not
|
|
|
|
/// compiled with the tool and therefore the lint was never
|
|
|
|
/// added to the `LintStore`. Otherwise the `LintId` will be
|
|
|
|
/// returned as if it where a rustc lint.
|
2018-08-27 23:25:31 +02:00
|
|
|
Tool(Result<&'a [LintId], (Option<&'a [LintId]>, String)>),
|
2017-07-26 21:51:09 -07:00
|
|
|
}
|
|
|
|
|
2014-06-06 15:49:48 -07:00
|
|
|
impl LintStore {
|
|
|
|
pub fn new() -> LintStore {
|
|
|
|
LintStore {
|
2016-10-29 22:54:04 +01:00
|
|
|
lints: vec![],
|
2019-10-07 18:23:16 -04:00
|
|
|
pre_expansion_passes: vec![],
|
|
|
|
early_passes: vec![],
|
|
|
|
late_passes: vec![],
|
2019-01-31 04:36:37 +01:00
|
|
|
late_module_passes: vec![],
|
2018-10-16 16:57:53 +02:00
|
|
|
by_name: Default::default(),
|
|
|
|
lint_groups: Default::default(),
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-07 16:52:53 -04:00
|
|
|
pub fn get_lints<'t>(&'t self) -> &'t [&'static Lint] {
|
2015-02-20 14:08:14 -05:00
|
|
|
&self.lints
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2014-07-21 15:27:59 +12:00
|
|
|
pub fn get_lint_groups<'t>(&'t self) -> Vec<(&'static str, Vec<LintId>, bool)> {
|
2018-09-15 15:26:45 +01:00
|
|
|
self.lint_groups.iter()
|
2018-09-15 17:32:24 +01:00
|
|
|
.filter(|(_, LintGroup { depr, .. })| {
|
|
|
|
// Don't display deprecated lint groups.
|
|
|
|
depr.is_none()
|
|
|
|
})
|
|
|
|
.map(|(k, LintGroup { lint_ids, from_plugin, .. })| {
|
|
|
|
(*k, lint_ids.clone(), *from_plugin)
|
|
|
|
})
|
|
|
|
.collect()
|
2014-07-21 15:27:59 +12:00
|
|
|
}
|
|
|
|
|
2019-10-22 16:53:28 -04:00
|
|
|
pub fn register_early_pass(
|
|
|
|
&mut self,
|
|
|
|
pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync
|
|
|
|
) {
|
2019-10-10 19:33:00 -04:00
|
|
|
self.early_passes.push(Box::new(pass));
|
2015-09-15 11:35:25 +12:00
|
|
|
}
|
|
|
|
|
2019-10-22 16:53:28 -04:00
|
|
|
pub fn register_pre_expansion_pass(
|
|
|
|
&mut self,
|
|
|
|
pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync,
|
|
|
|
) {
|
2019-10-10 19:33:00 -04:00
|
|
|
self.pre_expansion_passes.push(Box::new(pass));
|
2018-07-14 16:40:17 +02:00
|
|
|
}
|
|
|
|
|
2019-10-22 16:53:28 -04:00
|
|
|
pub fn register_late_pass(
|
|
|
|
&mut self,
|
|
|
|
pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync,
|
|
|
|
) {
|
2019-10-10 19:33:00 -04:00
|
|
|
self.late_passes.push(Box::new(pass));
|
2019-10-07 16:59:12 -04:00
|
|
|
}
|
|
|
|
|
2019-10-22 16:53:28 -04:00
|
|
|
pub fn register_late_mod_pass(
|
|
|
|
&mut self,
|
|
|
|
pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync,
|
|
|
|
) {
|
2019-10-10 19:33:00 -04:00
|
|
|
self.late_module_passes.push(Box::new(pass));
|
2015-09-15 11:35:25 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
// Helper method for register_early/late_pass
|
2019-10-07 17:21:50 -04:00
|
|
|
pub fn register_lints(&mut self, lints: &[&'static Lint]) {
|
2019-09-24 18:24:45 -04:00
|
|
|
for lint in lints {
|
2019-10-07 16:52:53 -04:00
|
|
|
self.lints.push(lint);
|
2014-06-06 15:49:48 -07:00
|
|
|
|
2018-06-21 09:04:50 +02:00
|
|
|
let id = LintId::of(lint);
|
2014-11-06 12:25:16 -05:00
|
|
|
if self.by_name.insert(lint.name_lower(), Id(id)).is_some() {
|
2019-09-23 20:13:02 -04:00
|
|
|
bug!("duplicate specification of lint {}", lint.name_lower())
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2019-10-08 21:49:21 -04:00
|
|
|
if let Some(FutureIncompatibleInfo { edition, .. }) = lint.future_incompatible {
|
|
|
|
if let Some(edition) = edition {
|
|
|
|
self.lint_groups.entry(edition.lint_name())
|
|
|
|
.or_insert(LintGroup {
|
|
|
|
lint_ids: vec![],
|
|
|
|
from_plugin: lint.is_plugin,
|
|
|
|
depr: None,
|
|
|
|
})
|
|
|
|
.lint_ids.push(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.lint_groups.entry("future_incompatible")
|
|
|
|
.or_insert(LintGroup {
|
|
|
|
lint_ids: vec![],
|
|
|
|
from_plugin: lint.is_plugin,
|
|
|
|
depr: None,
|
|
|
|
})
|
|
|
|
.lint_ids.push(id);
|
2018-02-22 16:51:42 -08:00
|
|
|
}
|
|
|
|
}
|
2016-01-08 17:53:44 -05:00
|
|
|
}
|
|
|
|
|
2018-09-15 15:26:45 +01:00
|
|
|
pub fn register_group_alias(
|
|
|
|
&mut self,
|
|
|
|
lint_name: &'static str,
|
|
|
|
alias: &'static str,
|
|
|
|
) {
|
2018-09-15 17:32:24 +01:00
|
|
|
self.lint_groups.insert(alias, LintGroup {
|
|
|
|
lint_ids: vec![],
|
|
|
|
from_plugin: false,
|
|
|
|
depr: Some(LintAlias { name: lint_name, silent: true }),
|
|
|
|
});
|
2018-09-15 15:26:45 +01:00
|
|
|
}
|
|
|
|
|
2018-08-27 23:24:42 +02:00
|
|
|
pub fn register_group(
|
|
|
|
&mut self,
|
|
|
|
from_plugin: bool,
|
|
|
|
name: &'static str,
|
|
|
|
deprecated_name: Option<&'static str>,
|
|
|
|
to: Vec<LintId>,
|
|
|
|
) {
|
|
|
|
let new = self
|
|
|
|
.lint_groups
|
2018-09-15 17:32:24 +01:00
|
|
|
.insert(name, LintGroup {
|
|
|
|
lint_ids: to,
|
|
|
|
from_plugin,
|
|
|
|
depr: None,
|
|
|
|
})
|
2018-08-27 23:24:42 +02:00
|
|
|
.is_none();
|
|
|
|
if let Some(deprecated) = deprecated_name {
|
2018-09-15 17:32:24 +01:00
|
|
|
self.lint_groups.insert(deprecated, LintGroup {
|
|
|
|
lint_ids: vec![],
|
|
|
|
from_plugin,
|
|
|
|
depr: Some(LintAlias { name, silent: false }),
|
|
|
|
});
|
2018-08-27 23:24:42 +02:00
|
|
|
}
|
2014-07-21 15:27:59 +12:00
|
|
|
|
|
|
|
if !new {
|
2019-09-23 20:13:02 -04:00
|
|
|
bug!("duplicate specification of lint group {}", name);
|
2014-07-21 15:27:59 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-25 22:44:44 +11:00
|
|
|
pub fn register_renamed(&mut self, old_name: &str, new_name: &str) {
|
2014-11-12 15:51:51 -08:00
|
|
|
let target = match self.by_name.get(new_name) {
|
2014-10-14 11:32:31 -07:00
|
|
|
Some(&Id(lint_id)) => lint_id.clone(),
|
2016-03-26 19:59:04 +01:00
|
|
|
_ => bug!("invalid lint renaming of {} to {}", old_name, new_name)
|
2014-10-14 11:32:31 -07:00
|
|
|
};
|
|
|
|
self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target));
|
|
|
|
}
|
|
|
|
|
2015-07-15 20:12:30 +03:00
|
|
|
pub fn register_removed(&mut self, name: &str, reason: &str) {
|
|
|
|
self.by_name.insert(name.into(), Removed(reason.into()));
|
|
|
|
}
|
|
|
|
|
2018-09-15 17:05:52 +01:00
|
|
|
pub fn find_lints(&self, mut lint_name: &str) -> Result<Vec<LintId>, FindLintError> {
|
2014-11-12 15:51:51 -08:00
|
|
|
match self.by_name.get(lint_name) {
|
2017-07-26 21:51:09 -07:00
|
|
|
Some(&Id(lint_id)) => Ok(vec![lint_id]),
|
2016-01-13 18:54:06 +00:00
|
|
|
Some(&Renamed(_, lint_id)) => {
|
2017-07-26 21:51:09 -07:00
|
|
|
Ok(vec![lint_id])
|
2015-07-15 20:12:30 +03:00
|
|
|
},
|
2017-06-23 18:29:30 -07:00
|
|
|
Some(&Removed(_)) => {
|
2015-07-15 20:12:30 +03:00
|
|
|
Err(FindLintError::Removed)
|
|
|
|
},
|
2017-07-26 21:51:09 -07:00
|
|
|
None => {
|
2018-09-15 17:05:52 +01:00
|
|
|
loop {
|
|
|
|
return match self.lint_groups.get(lint_name) {
|
2018-09-15 17:32:24 +01:00
|
|
|
Some(LintGroup {lint_ids, depr, .. }) => {
|
|
|
|
if let Some(LintAlias { name, .. }) = depr {
|
2018-09-15 17:05:52 +01:00
|
|
|
lint_name = name;
|
|
|
|
continue;
|
|
|
|
}
|
2018-09-15 17:32:24 +01:00
|
|
|
Ok(lint_ids.clone())
|
2018-09-15 17:05:52 +01:00
|
|
|
}
|
|
|
|
None => Err(FindLintError::Removed)
|
|
|
|
};
|
2014-07-21 15:27:59 +12:00
|
|
|
}
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
}
|
2017-05-16 03:16:18 +08:00
|
|
|
}
|
|
|
|
|
2017-08-17 16:21:55 +02:00
|
|
|
/// Checks the validity of lint names derived from the command line
|
2017-07-26 21:51:09 -07:00
|
|
|
pub fn check_lint_name_cmdline(&self,
|
|
|
|
sess: &Session,
|
|
|
|
lint_name: &str,
|
|
|
|
level: Level) {
|
2018-07-30 11:29:23 +02:00
|
|
|
let db = match self.check_lint_name(lint_name, None) {
|
2017-07-26 21:51:09 -07:00
|
|
|
CheckLintNameResult::Ok(_) => None,
|
2018-07-14 20:52:40 -07:00
|
|
|
CheckLintNameResult::Warning(ref msg, _) => {
|
2017-07-26 21:51:09 -07:00
|
|
|
Some(sess.struct_warn(msg))
|
|
|
|
},
|
2018-12-19 13:51:52 -05:00
|
|
|
CheckLintNameResult::NoLint(suggestion) => {
|
|
|
|
let mut err = struct_err!(sess, E0602, "unknown lint: `{}`", lint_name);
|
|
|
|
|
|
|
|
if let Some(suggestion) = suggestion {
|
|
|
|
err.help(&format!("did you mean: `{}`", suggestion));
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(err)
|
2017-07-26 21:51:09 -07:00
|
|
|
}
|
2018-09-01 17:43:14 +02:00
|
|
|
CheckLintNameResult::Tool(result) => match result {
|
|
|
|
Err((Some(_), new_name)) => Some(sess.struct_warn(&format!(
|
2018-09-01 21:45:44 +05:30
|
|
|
"lint name `{}` is deprecated \
|
2018-09-01 17:43:14 +02:00
|
|
|
and does not have an effect anymore. \
|
|
|
|
Use: {}",
|
|
|
|
lint_name, new_name
|
|
|
|
))),
|
|
|
|
_ => None,
|
|
|
|
},
|
2017-07-26 21:51:09 -07:00
|
|
|
};
|
2017-05-16 03:16:18 +08:00
|
|
|
|
2017-07-26 21:51:09 -07:00
|
|
|
if let Some(mut db) = db {
|
|
|
|
let msg = format!("requested on the command line with `{} {}`",
|
|
|
|
match level {
|
|
|
|
Level::Allow => "-A",
|
|
|
|
Level::Warn => "-W",
|
|
|
|
Level::Deny => "-D",
|
|
|
|
Level::Forbid => "-F",
|
|
|
|
},
|
|
|
|
lint_name);
|
|
|
|
db.note(&msg);
|
|
|
|
db.emit();
|
2017-05-16 03:16:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-26 21:51:09 -07:00
|
|
|
/// Checks the name of a lint for its existence, and whether it was
|
|
|
|
/// renamed or removed. Generates a DiagnosticBuilder containing a
|
|
|
|
/// warning for renamed and removed lints. This is over both lint
|
|
|
|
/// names from attributes and those passed on the command line. Since
|
|
|
|
/// it emits non-fatal warnings and there are *two* lint passes that
|
|
|
|
/// inspect attributes, this is only run from the late pass to avoid
|
|
|
|
/// printing duplicate warnings.
|
2018-07-30 11:29:23 +02:00
|
|
|
pub fn check_lint_name(
|
|
|
|
&self,
|
|
|
|
lint_name: &str,
|
2019-09-03 16:02:32 +10:00
|
|
|
tool_name: Option<Symbol>,
|
2018-08-29 22:02:42 -07:00
|
|
|
) -> CheckLintNameResult<'_> {
|
2018-07-30 11:29:23 +02:00
|
|
|
let complete_name = if let Some(tool_name) = tool_name {
|
|
|
|
format!("{}::{}", tool_name, lint_name)
|
|
|
|
} else {
|
|
|
|
lint_name.to_string()
|
|
|
|
};
|
2018-08-27 23:25:31 +02:00
|
|
|
// If the lint was scoped with `tool::` check if the tool lint exists
|
2018-07-30 11:29:23 +02:00
|
|
|
if let Some(_) = tool_name {
|
|
|
|
match self.by_name.get(&complete_name) {
|
|
|
|
None => match self.lint_groups.get(&*complete_name) {
|
2018-08-27 23:25:31 +02:00
|
|
|
None => return CheckLintNameResult::Tool(Err((None, String::new()))),
|
2018-09-15 17:32:24 +01:00
|
|
|
Some(LintGroup { lint_ids, .. }) => {
|
|
|
|
return CheckLintNameResult::Tool(Ok(&lint_ids));
|
|
|
|
}
|
2018-07-30 11:29:23 +02:00
|
|
|
},
|
2018-08-27 23:25:31 +02:00
|
|
|
Some(&Id(ref id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))),
|
2018-07-30 11:29:23 +02:00
|
|
|
// If the lint was registered as removed or renamed by the lint tool, we don't need
|
|
|
|
// to treat tool_lints and rustc lints different and can use the code below.
|
|
|
|
_ => {}
|
2015-07-23 22:19:12 -07:00
|
|
|
}
|
2018-07-30 11:29:23 +02:00
|
|
|
}
|
|
|
|
match self.by_name.get(&complete_name) {
|
|
|
|
Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning(
|
2018-08-27 23:25:31 +02:00
|
|
|
format!(
|
|
|
|
"lint `{}` has been renamed to `{}`",
|
|
|
|
complete_name, new_name
|
|
|
|
),
|
2018-07-30 11:29:23 +02:00
|
|
|
Some(new_name.to_owned()),
|
|
|
|
),
|
|
|
|
Some(&Removed(ref reason)) => CheckLintNameResult::Warning(
|
2018-08-27 23:25:31 +02:00
|
|
|
format!("lint `{}` has been removed: `{}`", complete_name, reason),
|
2018-07-30 11:29:23 +02:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
None => match self.lint_groups.get(&*complete_name) {
|
2018-08-27 23:25:31 +02:00
|
|
|
// If neither the lint, nor the lint group exists check if there is a `clippy::`
|
|
|
|
// variant of this lint
|
|
|
|
None => self.check_tool_name_for_backwards_compat(&complete_name, "clippy"),
|
2018-09-15 17:32:24 +01:00
|
|
|
Some(LintGroup { lint_ids, depr, .. }) => {
|
2018-08-27 23:25:31 +02:00
|
|
|
// Check if the lint group name is deprecated
|
2018-09-15 17:32:24 +01:00
|
|
|
if let Some(LintAlias { name, silent }) = depr {
|
|
|
|
let LintGroup { lint_ids, .. } = self.lint_groups.get(name).unwrap();
|
|
|
|
return if *silent {
|
|
|
|
CheckLintNameResult::Ok(&lint_ids)
|
2018-09-15 15:26:45 +01:00
|
|
|
} else {
|
|
|
|
CheckLintNameResult::Tool(Err((
|
2018-09-15 17:32:24 +01:00
|
|
|
Some(&lint_ids),
|
|
|
|
name.to_string(),
|
2018-09-15 15:26:45 +01:00
|
|
|
)))
|
|
|
|
};
|
2018-08-27 23:25:31 +02:00
|
|
|
}
|
2018-09-15 17:32:24 +01:00
|
|
|
CheckLintNameResult::Ok(&lint_ids)
|
2018-08-27 23:25:31 +02:00
|
|
|
}
|
2018-07-30 11:29:23 +02:00
|
|
|
},
|
2017-11-23 16:41:51 +02:00
|
|
|
Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
|
2015-07-23 22:19:12 -07:00
|
|
|
}
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
2018-08-27 23:25:31 +02:00
|
|
|
|
|
|
|
fn check_tool_name_for_backwards_compat(
|
|
|
|
&self,
|
|
|
|
lint_name: &str,
|
|
|
|
tool_name: &str,
|
2018-08-29 22:02:42 -07:00
|
|
|
) -> CheckLintNameResult<'_> {
|
2018-08-27 23:25:31 +02:00
|
|
|
let complete_name = format!("{}::{}", tool_name, lint_name);
|
|
|
|
match self.by_name.get(&complete_name) {
|
|
|
|
None => match self.lint_groups.get(&*complete_name) {
|
|
|
|
// Now we are sure, that this lint exists nowhere
|
2018-12-19 13:51:52 -05:00
|
|
|
None => {
|
|
|
|
let symbols = self.by_name.keys()
|
|
|
|
.map(|name| Symbol::intern(&name))
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
let suggestion =
|
|
|
|
find_best_match_for_name(symbols.iter(), &lint_name.to_lowercase(), None);
|
|
|
|
|
|
|
|
CheckLintNameResult::NoLint(suggestion)
|
|
|
|
}
|
2018-09-15 17:32:24 +01:00
|
|
|
Some(LintGroup { lint_ids, depr, .. }) => {
|
2018-09-15 15:26:45 +01:00
|
|
|
// Reaching this would be weird, but let's cover this case anyway
|
2018-09-15 17:32:24 +01:00
|
|
|
if let Some(LintAlias { name, silent }) = depr {
|
|
|
|
let LintGroup { lint_ids, .. } = self.lint_groups.get(name).unwrap();
|
|
|
|
return if *silent {
|
|
|
|
CheckLintNameResult::Tool(Err((Some(&lint_ids), complete_name)))
|
2018-09-15 15:26:45 +01:00
|
|
|
} else {
|
|
|
|
CheckLintNameResult::Tool(Err((
|
2018-09-15 17:32:24 +01:00
|
|
|
Some(&lint_ids),
|
|
|
|
name.to_string(),
|
2018-09-15 15:26:45 +01:00
|
|
|
)))
|
|
|
|
};
|
2018-08-27 23:25:31 +02:00
|
|
|
}
|
2018-09-15 17:32:24 +01:00
|
|
|
CheckLintNameResult::Tool(Err((Some(&lint_ids), complete_name)))
|
2018-08-27 23:25:31 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
Some(&Id(ref id)) => {
|
|
|
|
CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
|
|
|
|
}
|
2018-12-19 13:51:52 -05:00
|
|
|
_ => CheckLintNameResult::NoLint(None),
|
2018-08-27 23:25:31 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2015-09-10 16:40:59 +12:00
|
|
|
/// Context for lint checking after type checking.
|
2019-06-14 19:39:39 +03:00
|
|
|
pub struct LateContext<'a, 'tcx> {
|
2014-06-06 15:49:48 -07:00
|
|
|
/// Type context we're checking in.
|
2019-06-14 00:48:52 +03:00
|
|
|
pub tcx: TyCtxt<'tcx>,
|
2014-06-06 15:49:48 -07:00
|
|
|
|
2017-01-06 21:54:24 +02:00
|
|
|
/// Side-tables for the body we are in.
|
2018-06-11 08:48:15 +02:00
|
|
|
// FIXME: Make this lazy to avoid running the TypeckTables query?
|
2017-01-25 16:24:00 -05:00
|
|
|
pub tables: &'a ty::TypeckTables<'tcx>,
|
2017-01-06 21:54:24 +02:00
|
|
|
|
2017-06-07 15:21:55 +03:00
|
|
|
/// Parameter environment for the item we are in.
|
|
|
|
pub param_env: ty::ParamEnv<'tcx>,
|
|
|
|
|
2015-11-19 14:16:35 +03:00
|
|
|
/// Items accessible from the crate being checked.
|
|
|
|
pub access_levels: &'a AccessLevels,
|
2014-06-17 16:55:34 -07:00
|
|
|
|
2017-05-16 03:16:18 +08:00
|
|
|
/// The store of registered lints and the lint levels.
|
2019-10-09 09:53:13 -04:00
|
|
|
lint_store: &'tcx LintStore,
|
2017-07-26 21:51:09 -07:00
|
|
|
|
2019-02-06 14:16:11 +01:00
|
|
|
last_node_with_lint_attrs: hir::HirId,
|
2017-10-28 17:19:07 -04:00
|
|
|
|
|
|
|
/// Generic type parameters in scope for the item we are in.
|
|
|
|
pub generics: Option<&'tcx hir::Generics>,
|
2018-06-11 08:48:15 +02:00
|
|
|
|
|
|
|
/// We are only looking at one module
|
|
|
|
only_module: bool,
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2019-06-14 19:39:39 +03:00
|
|
|
pub struct LateContextAndPass<'a, 'tcx, T: LateLintPass<'a, 'tcx>> {
|
2019-01-31 01:36:11 +01:00
|
|
|
context: LateContext<'a, 'tcx>,
|
|
|
|
pass: T,
|
|
|
|
}
|
|
|
|
|
2015-09-10 16:40:59 +12:00
|
|
|
/// Context for lint checking of the AST, after expansion, before lowering to
|
|
|
|
/// HIR.
|
|
|
|
pub struct EarlyContext<'a> {
|
|
|
|
/// Type context we're checking in.
|
|
|
|
pub sess: &'a Session,
|
|
|
|
|
|
|
|
/// The crate being checked.
|
|
|
|
pub krate: &'a ast::Crate,
|
|
|
|
|
2017-07-26 21:51:09 -07:00
|
|
|
builder: LintLevelsBuilder<'a>,
|
|
|
|
|
2017-05-16 03:16:18 +08:00
|
|
|
/// The store of registered lints and the lint levels.
|
2019-10-09 08:46:11 -04:00
|
|
|
lint_store: &'a LintStore,
|
2017-07-26 21:51:09 -07:00
|
|
|
|
|
|
|
buffered: LintBuffer,
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2019-01-18 07:40:55 +01:00
|
|
|
pub struct EarlyContextAndPass<'a, T: EarlyLintPass> {
|
|
|
|
context: EarlyContext<'a>,
|
|
|
|
pass: T,
|
|
|
|
}
|
|
|
|
|
2018-07-14 16:40:17 +02:00
|
|
|
pub trait LintPassObject: Sized {}
|
2017-05-16 03:16:18 +08:00
|
|
|
|
2018-07-14 16:40:17 +02:00
|
|
|
impl LintPassObject for EarlyLintPassObject {}
|
2017-05-16 03:16:18 +08:00
|
|
|
|
2018-07-14 16:40:17 +02:00
|
|
|
impl LintPassObject for LateLintPassObject {}
|
2017-05-16 03:16:18 +08:00
|
|
|
|
2019-06-11 12:21:38 +03:00
|
|
|
pub trait LintContext: Sized {
|
2017-05-16 03:16:18 +08:00
|
|
|
type PassObject: LintPassObject;
|
|
|
|
|
2015-09-10 16:40:59 +12:00
|
|
|
fn sess(&self) -> &Session;
|
|
|
|
fn lints(&self) -> &LintStore;
|
2014-06-06 15:49:48 -07:00
|
|
|
|
2016-10-25 23:24:09 -07:00
|
|
|
fn lookup_and_emit<S: Into<MultiSpan>>(&self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
span: Option<S>,
|
|
|
|
msg: &str) {
|
2017-07-26 21:51:09 -07:00
|
|
|
self.lookup(lint, span, msg).emit();
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2018-02-22 22:34:06 -08:00
|
|
|
fn lookup_and_emit_with_diagnostics<S: Into<MultiSpan>>(&self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
span: Option<S>,
|
|
|
|
msg: &str,
|
|
|
|
diagnostic: BuiltinLintDiagnostics) {
|
|
|
|
let mut db = self.lookup(lint, span, msg);
|
|
|
|
diagnostic.run(self.sess(), &mut db);
|
|
|
|
db.emit();
|
|
|
|
}
|
|
|
|
|
2016-10-12 17:00:30 -04:00
|
|
|
fn lookup<S: Into<MultiSpan>>(&self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
span: Option<S>,
|
|
|
|
msg: &str)
|
2018-08-29 22:02:42 -07:00
|
|
|
-> DiagnosticBuilder<'_>;
|
2015-12-21 10:00:43 +13:00
|
|
|
|
2014-06-06 15:49:48 -07:00
|
|
|
/// Emit a lint at the appropriate level, for a particular span.
|
2016-10-25 23:24:09 -07:00
|
|
|
fn span_lint<S: Into<MultiSpan>>(&self, lint: &'static Lint, span: S, msg: &str) {
|
2014-06-06 15:49:48 -07:00
|
|
|
self.lookup_and_emit(lint, Some(span), msg);
|
|
|
|
}
|
|
|
|
|
2016-10-12 17:00:30 -04:00
|
|
|
fn struct_span_lint<S: Into<MultiSpan>>(&self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
span: S,
|
|
|
|
msg: &str)
|
2018-08-29 22:02:42 -07:00
|
|
|
-> DiagnosticBuilder<'_> {
|
2015-12-21 10:00:43 +13:00
|
|
|
self.lookup(lint, Some(span), msg)
|
|
|
|
}
|
|
|
|
|
2015-10-17 01:50:33 +05:30
|
|
|
/// Emit a lint and note at the appropriate level, for a particular span.
|
|
|
|
fn span_lint_note(&self, lint: &'static Lint, span: Span, msg: &str,
|
|
|
|
note_span: Span, note: &str) {
|
2015-12-23 19:27:20 +13:00
|
|
|
let mut err = self.lookup(lint, Some(span), msg);
|
2017-07-26 21:51:09 -07:00
|
|
|
if note_span == span {
|
|
|
|
err.note(note);
|
|
|
|
} else {
|
|
|
|
err.span_note(note_span, note);
|
2015-10-17 01:50:33 +05:30
|
|
|
}
|
2015-12-21 10:00:43 +13:00
|
|
|
err.emit();
|
2015-10-17 01:50:33 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/// Emit a lint and help at the appropriate level, for a particular span.
|
|
|
|
fn span_lint_help(&self, lint: &'static Lint, span: Span,
|
|
|
|
msg: &str, help: &str) {
|
2015-12-23 19:27:20 +13:00
|
|
|
let mut err = self.lookup(lint, Some(span), msg);
|
2015-10-17 01:50:33 +05:30
|
|
|
self.span_lint(lint, span, msg);
|
2017-07-26 21:51:09 -07:00
|
|
|
err.span_help(span, help);
|
2015-12-21 10:00:43 +13:00
|
|
|
err.emit();
|
2015-10-17 01:50:33 +05:30
|
|
|
}
|
|
|
|
|
2015-09-10 16:40:59 +12:00
|
|
|
/// Emit a lint at the appropriate level, with no associated span.
|
|
|
|
fn lint(&self, lint: &'static Lint, msg: &str) {
|
2016-10-25 23:24:09 -07:00
|
|
|
self.lookup_and_emit(lint, None as Option<Span>, msg);
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a> EarlyContext<'a> {
|
2018-07-14 16:40:17 +02:00
|
|
|
fn new(
|
|
|
|
sess: &'a Session,
|
2019-10-09 08:46:11 -04:00
|
|
|
lint_store: &'a LintStore,
|
2018-07-14 16:40:17 +02:00
|
|
|
krate: &'a ast::Crate,
|
|
|
|
buffered: LintBuffer,
|
2019-10-25 13:41:51 -04:00
|
|
|
warn_about_weird_lints: bool,
|
2018-07-14 16:40:17 +02:00
|
|
|
) -> EarlyContext<'a> {
|
2015-09-10 16:40:59 +12:00
|
|
|
EarlyContext {
|
2017-07-03 11:19:51 -07:00
|
|
|
sess,
|
|
|
|
krate,
|
2019-10-09 08:46:11 -04:00
|
|
|
lint_store,
|
2019-10-25 13:41:51 -04:00
|
|
|
builder: LintLevelSets::builder(sess, warn_about_weird_lints, lint_store),
|
2018-07-14 16:40:17 +02:00
|
|
|
buffered,
|
2017-07-26 21:51:09 -07:00
|
|
|
}
|
|
|
|
}
|
2019-01-18 07:40:55 +01:00
|
|
|
}
|
2017-07-26 21:51:09 -07:00
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
|
|
|
|
$cx.pass.$f(&$cx.context, $($args),*);
|
|
|
|
}) }
|
|
|
|
|
2019-01-18 07:40:55 +01:00
|
|
|
macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
|
|
|
|
$cx.pass.$f(&$cx.context, $($args),*);
|
|
|
|
}) }
|
|
|
|
|
|
|
|
impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
2017-07-26 21:51:09 -07:00
|
|
|
fn check_id(&mut self, id: ast::NodeId) {
|
2019-01-18 07:40:55 +01:00
|
|
|
for early_lint in self.context.buffered.take(id) {
|
|
|
|
self.context.lookup_and_emit_with_diagnostics(
|
|
|
|
early_lint.lint_id.lint,
|
|
|
|
Some(early_lint.span.clone()),
|
|
|
|
&early_lint.msg,
|
|
|
|
early_lint.diagnostic
|
|
|
|
);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
}
|
2019-01-18 07:40:55 +01:00
|
|
|
|
|
|
|
/// Merge the lints specified by any lint attributes into the
|
|
|
|
/// current lint context, call the provided function, then reset the
|
|
|
|
/// lints in effect to their previous state.
|
|
|
|
fn with_lint_attrs<F>(&mut self,
|
|
|
|
id: ast::NodeId,
|
|
|
|
attrs: &'a [ast::Attribute],
|
|
|
|
f: F)
|
|
|
|
where F: FnOnce(&mut Self)
|
|
|
|
{
|
2019-10-09 08:46:11 -04:00
|
|
|
let push = self.context.builder.push(attrs, &self.context.lint_store);
|
2019-01-18 07:40:55 +01:00
|
|
|
self.check_id(id);
|
|
|
|
self.enter_attrs(attrs);
|
|
|
|
f(self);
|
|
|
|
self.exit_attrs(attrs);
|
|
|
|
self.context.builder.pop(push);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn enter_attrs(&mut self, attrs: &'a [ast::Attribute]) {
|
|
|
|
debug!("early context: enter_attrs({:?})", attrs);
|
|
|
|
run_early_pass!(self, enter_lint_attrs, attrs);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn exit_attrs(&mut self, attrs: &'a [ast::Attribute]) {
|
|
|
|
debug!("early context: exit_attrs({:?})", attrs);
|
|
|
|
run_early_pass!(self, exit_lint_attrs, attrs);
|
|
|
|
}
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2019-06-11 12:21:38 +03:00
|
|
|
impl LintContext for LateContext<'_, '_> {
|
2017-05-16 03:16:18 +08:00
|
|
|
type PassObject = LateLintPassObject;
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Gets the overall compiler `Session` object.
|
2015-09-10 16:40:59 +12:00
|
|
|
fn sess(&self) -> &Session {
|
|
|
|
&self.tcx.sess
|
|
|
|
}
|
|
|
|
|
|
|
|
fn lints(&self) -> &LintStore {
|
2019-01-31 03:04:39 +01:00
|
|
|
&*self.lint_store
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2017-07-26 21:51:09 -07:00
|
|
|
fn lookup<S: Into<MultiSpan>>(&self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
span: Option<S>,
|
|
|
|
msg: &str)
|
2018-08-29 22:02:42 -07:00
|
|
|
-> DiagnosticBuilder<'_> {
|
2019-02-06 14:16:11 +01:00
|
|
|
let hir_id = self.last_node_with_lint_attrs;
|
|
|
|
|
2017-07-26 21:51:09 -07:00
|
|
|
match span {
|
2019-02-06 14:16:11 +01:00
|
|
|
Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, msg),
|
|
|
|
None => {
|
2019-02-26 11:48:34 +01:00
|
|
|
self.tcx.struct_lint_node(lint, hir_id, msg)
|
2019-02-06 14:16:11 +01:00
|
|
|
},
|
2017-07-26 21:51:09 -07:00
|
|
|
}
|
|
|
|
}
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2019-06-11 12:21:38 +03:00
|
|
|
impl LintContext for EarlyContext<'_> {
|
2017-05-16 03:16:18 +08:00
|
|
|
type PassObject = EarlyLintPassObject;
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Gets the overall compiler `Session` object.
|
2015-09-10 16:40:59 +12:00
|
|
|
fn sess(&self) -> &Session {
|
|
|
|
&self.sess
|
|
|
|
}
|
|
|
|
|
|
|
|
fn lints(&self) -> &LintStore {
|
2019-01-31 03:04:39 +01:00
|
|
|
&*self.lint_store
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2017-07-26 21:51:09 -07:00
|
|
|
fn lookup<S: Into<MultiSpan>>(&self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
span: Option<S>,
|
|
|
|
msg: &str)
|
2018-08-29 22:02:42 -07:00
|
|
|
-> DiagnosticBuilder<'_> {
|
2017-07-26 21:51:09 -07:00
|
|
|
self.builder.struct_lint(lint, span.map(|s| s.into()), msg)
|
|
|
|
}
|
2019-01-18 07:40:55 +01:00
|
|
|
}
|
2017-07-26 21:51:09 -07:00
|
|
|
|
2019-01-18 07:40:55 +01:00
|
|
|
impl<'a, 'tcx> LateContext<'a, 'tcx> {
|
2019-01-31 01:36:11 +01:00
|
|
|
pub fn current_lint_root(&self) -> hir::HirId {
|
|
|
|
self.last_node_with_lint_attrs
|
|
|
|
}
|
2019-04-05 23:04:56 +02:00
|
|
|
|
|
|
|
/// Check if a `DefId`'s path matches the given absolute type path usage.
|
2019-04-07 19:47:54 +02:00
|
|
|
///
|
2019-11-02 16:12:33 +01:00
|
|
|
/// Anonymous scopes such as `extern` imports are matched with `kw::Invalid`;
|
|
|
|
/// inherent `impl` blocks are matched with the name of the type.
|
|
|
|
///
|
2019-04-07 19:47:54 +02:00
|
|
|
/// # Examples
|
2019-05-02 12:33:59 -04:00
|
|
|
///
|
|
|
|
/// ```rust,ignore (no context or def id available)
|
2019-05-14 15:58:22 +02:00
|
|
|
/// if cx.match_def_path(def_id, &[sym::core, sym::option, sym::Option]) {
|
2019-04-07 19:47:54 +02:00
|
|
|
/// // The given `def_id` is that of an `Option` type
|
|
|
|
/// }
|
|
|
|
/// ```
|
2019-05-14 15:58:22 +02:00
|
|
|
pub fn match_def_path(&self, def_id: DefId, path: &[Symbol]) -> bool {
|
2019-04-07 19:47:54 +02:00
|
|
|
let names = self.get_def_path(def_id);
|
|
|
|
|
2019-05-14 15:58:22 +02:00
|
|
|
names.len() == path.len() && names.into_iter().zip(path.iter()).all(|(a, &b)| a == b)
|
2019-04-07 19:47:54 +02:00
|
|
|
}
|
|
|
|
|
2019-05-14 15:58:22 +02:00
|
|
|
/// Gets the absolute path of `def_id` as a vector of `Symbol`.
|
2019-04-07 19:47:54 +02:00
|
|
|
///
|
|
|
|
/// # Examples
|
2019-05-02 12:33:59 -04:00
|
|
|
///
|
|
|
|
/// ```rust,ignore (no context or def id available)
|
2019-04-07 19:47:54 +02:00
|
|
|
/// let def_path = cx.get_def_path(def_id);
|
2019-05-14 15:58:22 +02:00
|
|
|
/// if let &[sym::core, sym::option, sym::Option] = &def_path[..] {
|
2019-04-07 19:47:54 +02:00
|
|
|
/// // The given `def_id` is that of an `Option` type
|
|
|
|
/// }
|
|
|
|
/// ```
|
2019-05-14 15:58:22 +02:00
|
|
|
pub fn get_def_path(&self, def_id: DefId) -> Vec<Symbol> {
|
2019-06-11 22:03:44 +03:00
|
|
|
pub struct AbsolutePathPrinter<'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
pub tcx: TyCtxt<'tcx>,
|
2019-04-05 23:04:56 +02:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
2019-04-05 23:04:56 +02:00
|
|
|
type Error = !;
|
|
|
|
|
2019-05-14 15:58:22 +02:00
|
|
|
type Path = Vec<Symbol>;
|
2019-04-05 23:04:56 +02:00
|
|
|
type Region = ();
|
|
|
|
type Type = ();
|
|
|
|
type DynExistential = ();
|
2019-03-18 12:50:57 +02:00
|
|
|
type Const = ();
|
2019-04-05 23:04:56 +02:00
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
2019-04-05 23:04:56 +02:00
|
|
|
self.tcx
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print_dyn_existential(
|
|
|
|
self,
|
|
|
|
_predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
2019-03-18 12:50:57 +02:00
|
|
|
) -> Result<Self::DynExistential, Self::Error> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print_const(
|
|
|
|
self,
|
|
|
|
_ct: &'tcx ty::Const<'tcx>,
|
|
|
|
) -> Result<Self::Const, Self::Error> {
|
2019-04-05 23:04:56 +02:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
|
2019-05-14 15:58:22 +02:00
|
|
|
Ok(vec![self.tcx.original_crate_name(cnum)])
|
2019-04-05 23:04:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn path_qualified(
|
|
|
|
self,
|
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
trait_ref: Option<ty::TraitRef<'tcx>>,
|
2019-05-14 15:58:22 +02:00
|
|
|
) -> Result<Self::Path, Self::Error> {
|
2019-04-05 23:04:56 +02:00
|
|
|
if trait_ref.is_none() {
|
2019-09-16 19:08:35 +01:00
|
|
|
if let ty::Adt(def, substs) = self_ty.kind {
|
2019-04-05 23:04:56 +02:00
|
|
|
return self.print_def_path(def.did, substs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This shouldn't ever be needed, but just in case:
|
|
|
|
Ok(vec![match trait_ref {
|
2019-05-14 15:58:22 +02:00
|
|
|
Some(trait_ref) => Symbol::intern(&format!("{:?}", trait_ref)),
|
|
|
|
None => Symbol::intern(&format!("<{}>", self_ty)),
|
2019-04-05 23:04:56 +02:00
|
|
|
}])
|
|
|
|
}
|
|
|
|
|
|
|
|
fn path_append_impl(
|
|
|
|
self,
|
|
|
|
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
|
|
|
_disambiguated_data: &DisambiguatedDefPathData,
|
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
trait_ref: Option<ty::TraitRef<'tcx>>,
|
2019-05-14 15:58:22 +02:00
|
|
|
) -> Result<Self::Path, Self::Error> {
|
2019-04-05 23:04:56 +02:00
|
|
|
let mut path = print_prefix(self)?;
|
|
|
|
|
|
|
|
// This shouldn't ever be needed, but just in case:
|
|
|
|
path.push(match trait_ref {
|
|
|
|
Some(trait_ref) => {
|
2019-11-21 21:01:14 +03:00
|
|
|
Symbol::intern(
|
|
|
|
&format!(
|
|
|
|
"<impl {} for {}>",
|
|
|
|
trait_ref.print_only_trait_path(),
|
|
|
|
self_ty
|
|
|
|
)
|
|
|
|
)
|
2019-04-05 23:04:56 +02:00
|
|
|
},
|
2019-05-14 15:58:22 +02:00
|
|
|
None => Symbol::intern(&format!("<impl {}>", self_ty)),
|
2019-04-05 23:04:56 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
Ok(path)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn path_append(
|
|
|
|
self,
|
|
|
|
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
|
|
|
disambiguated_data: &DisambiguatedDefPathData,
|
2019-05-14 15:58:22 +02:00
|
|
|
) -> Result<Self::Path, Self::Error> {
|
2019-04-05 23:04:56 +02:00
|
|
|
let mut path = print_prefix(self)?;
|
|
|
|
|
|
|
|
// Skip `::{{constructor}}` on tuple/unit structs.
|
|
|
|
match disambiguated_data.data {
|
|
|
|
DefPathData::Ctor => return Ok(path),
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
2019-10-21 14:25:08 +11:00
|
|
|
path.push(disambiguated_data.data.as_symbol());
|
2019-04-05 23:04:56 +02:00
|
|
|
Ok(path)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn path_generic_args(
|
|
|
|
self,
|
|
|
|
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
2019-09-25 16:39:44 +01:00
|
|
|
_args: &[GenericArg<'tcx>],
|
2019-05-14 15:58:22 +02:00
|
|
|
) -> Result<Self::Path, Self::Error> {
|
2019-04-05 23:04:56 +02:00
|
|
|
print_prefix(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-07 19:47:54 +02:00
|
|
|
AbsolutePathPrinter { tcx: self.tcx }
|
|
|
|
.print_def_path(def_id, &[])
|
|
|
|
.unwrap()
|
2019-04-05 23:04:56 +02:00
|
|
|
}
|
2019-01-31 01:36:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'tcx> LayoutOf for LateContext<'a, 'tcx> {
|
|
|
|
type Ty = Ty<'tcx>;
|
|
|
|
type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
|
|
|
|
|
|
|
|
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
|
|
|
|
self.tcx.layout_of(self.param_env.and(ty))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> LateContextAndPass<'a, 'tcx, T> {
|
2019-01-18 07:40:55 +01:00
|
|
|
/// Merge the lints specified by any lint attributes into the
|
|
|
|
/// current lint context, call the provided function, then reset the
|
|
|
|
/// lints in effect to their previous state.
|
2017-07-26 21:51:09 -07:00
|
|
|
fn with_lint_attrs<F>(&mut self,
|
2019-02-06 14:16:11 +01:00
|
|
|
id: hir::HirId,
|
2019-01-18 07:40:55 +01:00
|
|
|
attrs: &'tcx [ast::Attribute],
|
2017-07-26 21:51:09 -07:00
|
|
|
f: F)
|
|
|
|
where F: FnOnce(&mut Self)
|
|
|
|
{
|
2019-01-31 01:36:11 +01:00
|
|
|
let prev = self.context.last_node_with_lint_attrs;
|
|
|
|
self.context.last_node_with_lint_attrs = id;
|
2017-07-26 21:51:09 -07:00
|
|
|
self.enter_attrs(attrs);
|
|
|
|
f(self);
|
|
|
|
self.exit_attrs(attrs);
|
2019-01-31 01:36:11 +01:00
|
|
|
self.context.last_node_with_lint_attrs = prev;
|
2017-07-26 21:51:09 -07:00
|
|
|
}
|
2015-09-10 16:40:59 +12:00
|
|
|
|
2019-02-26 11:04:58 +01:00
|
|
|
fn with_param_env<F>(&mut self, id: hir::HirId, f: F)
|
2017-06-07 15:21:55 +03:00
|
|
|
where F: FnOnce(&mut Self),
|
|
|
|
{
|
2019-01-31 01:36:11 +01:00
|
|
|
let old_param_env = self.context.param_env;
|
|
|
|
self.context.param_env = self.context.tcx.param_env(
|
2019-06-27 11:28:14 +02:00
|
|
|
self.context.tcx.hir().local_def_id(id)
|
2019-01-31 01:36:11 +01:00
|
|
|
);
|
2017-06-07 15:21:55 +03:00
|
|
|
f(self);
|
2019-01-31 01:36:11 +01:00
|
|
|
self.context.param_env = old_param_env;
|
2018-06-02 23:38:57 +02:00
|
|
|
}
|
2018-06-11 08:48:15 +02:00
|
|
|
|
|
|
|
fn process_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_mod, m, s, n);
|
2018-06-11 08:48:15 +02:00
|
|
|
hir_visit::walk_mod(self, m, n);
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_mod_post, m, s, n);
|
2018-06-11 08:48:15 +02:00
|
|
|
}
|
2017-06-07 15:21:55 +03:00
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
fn enter_attrs(&mut self, attrs: &'tcx [ast::Attribute]) {
|
|
|
|
debug!("late context: enter_attrs({:?})", attrs);
|
|
|
|
lint_callback!(self, enter_lint_attrs, attrs);
|
|
|
|
}
|
2017-09-13 02:19:11 +03:00
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
fn exit_attrs(&mut self, attrs: &'tcx [ast::Attribute]) {
|
|
|
|
debug!("late context: exit_attrs({:?})", attrs);
|
|
|
|
lint_callback!(self, exit_lint_attrs, attrs);
|
2017-09-13 02:19:11 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx>
|
|
|
|
for LateContextAndPass<'a, 'tcx, T> {
|
2015-11-17 18:56:13 -05:00
|
|
|
/// Because lints are scoped lexically, we want to walk nested
|
|
|
|
/// items in the context of the outer item, so enable
|
|
|
|
/// deep-walking.
|
2016-11-28 14:00:26 -05:00
|
|
|
fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'tcx> {
|
2019-01-31 01:36:11 +01:00
|
|
|
hir_visit::NestedVisitorMap::All(&self.context.tcx.hir())
|
2016-11-04 18:20:15 -04:00
|
|
|
}
|
|
|
|
|
2017-01-06 21:54:24 +02:00
|
|
|
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
2019-01-31 01:36:11 +01:00
|
|
|
let old_tables = self.context.tables;
|
|
|
|
self.context.tables = self.context.tcx.body_tables(body);
|
|
|
|
let body = self.context.tcx.hir().body(body);
|
2017-01-06 21:54:24 +02:00
|
|
|
self.visit_body(body);
|
2019-01-31 01:36:11 +01:00
|
|
|
self.context.tables = old_tables;
|
2017-01-06 21:54:24 +02:00
|
|
|
}
|
|
|
|
|
2019-08-27 13:24:32 +02:00
|
|
|
fn visit_param(&mut self, param: &'tcx hir::Param) {
|
|
|
|
self.with_lint_attrs(param.hir_id, ¶m.attrs, |cx| {
|
|
|
|
lint_callback!(cx, check_param, param);
|
|
|
|
hir_visit::walk_param(cx, param);
|
2019-07-26 19:52:37 -03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-03-07 12:51:09 +01:00
|
|
|
fn visit_body(&mut self, body: &'tcx hir::Body) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_body, body);
|
2017-03-07 12:51:09 +01:00
|
|
|
hir_visit::walk_body(self, body);
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_body_post, body);
|
2017-03-07 12:51:09 +01:00
|
|
|
}
|
|
|
|
|
2019-11-28 19:28:50 +01:00
|
|
|
fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
|
2019-01-31 01:36:11 +01:00
|
|
|
let generics = self.context.generics.take();
|
2019-09-26 17:51:36 +01:00
|
|
|
self.context.generics = it.kind.generics();
|
2019-02-06 14:16:11 +01:00
|
|
|
self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
|
2019-02-26 11:04:58 +01:00
|
|
|
cx.with_param_env(it.hir_id, |cx| {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_item, it);
|
2017-06-07 15:21:55 +03:00
|
|
|
hir_visit::walk_item(cx, it);
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_item_post, it);
|
2017-06-07 15:21:55 +03:00
|
|
|
});
|
2017-10-28 17:19:07 -04:00
|
|
|
});
|
2019-01-31 01:36:11 +01:00
|
|
|
self.context.generics = generics;
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2019-11-28 20:18:29 +01:00
|
|
|
fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
|
2019-02-06 14:16:11 +01:00
|
|
|
self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
|
2019-02-26 11:04:58 +01:00
|
|
|
cx.with_param_env(it.hir_id, |cx| {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_foreign_item, it);
|
2017-06-07 15:21:55 +03:00
|
|
|
hir_visit::walk_foreign_item(cx, it);
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_foreign_item_post, it);
|
2017-06-07 15:21:55 +03:00
|
|
|
});
|
2014-06-06 15:49:48 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_pat(&mut self, p: &'tcx hir::Pat) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_pat, p);
|
2015-09-10 16:40:59 +12:00
|
|
|
hir_visit::walk_pat(self, p);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_expr(&mut self, e: &'tcx hir::Expr) {
|
2019-02-06 14:16:11 +01:00
|
|
|
self.with_lint_attrs(e.hir_id, &e.attrs, |cx| {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_expr, e);
|
2015-11-03 17:39:51 +01:00
|
|
|
hir_visit::walk_expr(cx, e);
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_expr_post, e);
|
2015-11-03 17:39:51 +01:00
|
|
|
})
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_stmt(&mut self, s: &'tcx hir::Stmt) {
|
2015-11-03 17:39:51 +01:00
|
|
|
// statement attributes are actually just attributes on one of
|
|
|
|
// - item
|
|
|
|
// - local
|
|
|
|
// - expression
|
|
|
|
// so we keep track of lint levels there
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_stmt, s);
|
2015-09-10 16:40:59 +12:00
|
|
|
hir_visit::walk_stmt(self, s);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_fn(&mut self, fk: hir_visit::FnKind<'tcx>, decl: &'tcx hir::FnDecl,
|
2019-02-06 14:16:11 +01:00
|
|
|
body_id: hir::BodyId, span: Span, id: hir::HirId) {
|
2017-01-06 21:54:24 +02:00
|
|
|
// Wrap in tables here, not just in visit_nested_body,
|
|
|
|
// in order for `check_fn` to be able to use them.
|
2019-01-31 01:36:11 +01:00
|
|
|
let old_tables = self.context.tables;
|
|
|
|
self.context.tables = self.context.tcx.body_tables(body_id);
|
|
|
|
let body = self.context.tcx.hir().body(body_id);
|
|
|
|
lint_callback!(self, check_fn, fk, decl, body, span, id);
|
2016-10-28 22:58:32 +02:00
|
|
|
hir_visit::walk_fn(self, fk, decl, body_id, span, id);
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_fn_post, fk, decl, body, span, id);
|
|
|
|
self.context.tables = old_tables;
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2015-10-08 03:20:57 +03:00
|
|
|
fn visit_variant_data(&mut self,
|
2019-11-29 09:26:18 +01:00
|
|
|
s: &'tcx hir::VariantData<'tcx>,
|
2019-08-24 13:54:40 -03:00
|
|
|
_: ast::Name,
|
|
|
|
_: &'tcx hir::Generics,
|
|
|
|
_: hir::HirId,
|
2015-10-02 20:06:59 +03:00
|
|
|
_: Span) {
|
2019-08-24 13:54:40 -03:00
|
|
|
lint_callback!(self, check_struct_def, s);
|
2015-09-10 16:40:59 +12:00
|
|
|
hir_visit::walk_struct_def(self, s);
|
2019-08-24 13:54:40 -03:00
|
|
|
lint_callback!(self, check_struct_def_post, s);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2019-11-29 09:40:33 +01:00
|
|
|
fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
|
2019-02-06 14:16:11 +01:00
|
|
|
self.with_lint_attrs(s.hir_id, &s.attrs, |cx| {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_struct_field, s);
|
2015-09-10 16:40:59 +12:00
|
|
|
hir_visit::walk_struct_field(cx, s);
|
2014-06-06 15:49:48 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_variant(&mut self,
|
2019-11-29 09:26:18 +01:00
|
|
|
v: &'tcx hir::Variant<'tcx>,
|
2016-11-09 16:45:26 -05:00
|
|
|
g: &'tcx hir::Generics,
|
2019-02-06 14:16:11 +01:00
|
|
|
item_id: hir::HirId) {
|
2019-08-13 21:40:21 -03:00
|
|
|
self.with_lint_attrs(v.id, &v.attrs, |cx| {
|
2019-08-24 13:54:40 -03:00
|
|
|
lint_callback!(cx, check_variant, v);
|
2015-10-02 16:14:20 +03:00
|
|
|
hir_visit::walk_variant(cx, v, g, item_id);
|
2019-08-24 13:54:40 -03:00
|
|
|
lint_callback!(cx, check_variant_post, v);
|
2014-06-06 15:49:48 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_ty(&mut self, t: &'tcx hir::Ty) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_ty, t);
|
2015-09-10 16:40:59 +12:00
|
|
|
hir_visit::walk_ty(self, t);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2015-09-20 03:34:12 +03:00
|
|
|
fn visit_name(&mut self, sp: Span, name: ast::Name) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_name, sp, name);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2019-02-06 14:16:11 +01:00
|
|
|
fn visit_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) {
|
2019-01-31 01:36:11 +01:00
|
|
|
if !self.context.only_module {
|
2018-06-11 08:48:15 +02:00
|
|
|
self.process_mod(m, s, n);
|
|
|
|
}
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_local(&mut self, l: &'tcx hir::Local) {
|
2019-02-06 14:16:11 +01:00
|
|
|
self.with_lint_attrs(l.hir_id, &l.attrs, |cx| {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_local, l);
|
2015-11-03 17:39:51 +01:00
|
|
|
hir_visit::walk_local(cx, l);
|
|
|
|
})
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_block(&mut self, b: &'tcx hir::Block) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_block, b);
|
2015-09-10 16:40:59 +12:00
|
|
|
hir_visit::walk_block(self, b);
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_block_post, b);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_arm(&mut self, a: &'tcx hir::Arm) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_arm, a);
|
2015-09-10 16:40:59 +12:00
|
|
|
hir_visit::walk_arm(self, a);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2017-10-16 21:07:26 +02:00
|
|
|
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_generic_param, p);
|
2017-10-16 21:07:26 +02:00
|
|
|
hir_visit::walk_generic_param(self, p);
|
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_generics(&mut self, g: &'tcx hir::Generics) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_generics, g);
|
2015-09-10 16:40:59 +12:00
|
|
|
hir_visit::walk_generics(self, g);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2018-02-18 19:37:07 +01:00
|
|
|
fn visit_where_predicate(&mut self, p: &'tcx hir::WherePredicate) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_where_predicate, p);
|
2018-02-18 19:37:07 +01:00
|
|
|
hir_visit::walk_where_predicate(self, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_poly_trait_ref(&mut self, t: &'tcx hir::PolyTraitRef,
|
|
|
|
m: hir::TraitBoundModifier) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_poly_trait_ref, t, m);
|
2018-02-18 19:37:07 +01:00
|
|
|
hir_visit::walk_poly_trait_ref(self, t, m);
|
|
|
|
}
|
|
|
|
|
2019-11-28 21:47:10 +01:00
|
|
|
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
|
2019-01-31 01:36:11 +01:00
|
|
|
let generics = self.context.generics.take();
|
|
|
|
self.context.generics = Some(&trait_item.generics);
|
2019-02-06 14:16:11 +01:00
|
|
|
self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |cx| {
|
2019-02-26 11:04:58 +01:00
|
|
|
cx.with_param_env(trait_item.hir_id, |cx| {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_trait_item, trait_item);
|
2017-06-07 15:21:55 +03:00
|
|
|
hir_visit::walk_trait_item(cx, trait_item);
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_trait_item_post, trait_item);
|
2017-06-07 15:21:55 +03:00
|
|
|
});
|
2015-03-10 12:28:44 +02:00
|
|
|
});
|
2019-01-31 01:36:11 +01:00
|
|
|
self.context.generics = generics;
|
2015-03-10 12:28:44 +02:00
|
|
|
}
|
|
|
|
|
2019-11-28 22:16:44 +01:00
|
|
|
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
2019-01-31 01:36:11 +01:00
|
|
|
let generics = self.context.generics.take();
|
|
|
|
self.context.generics = Some(&impl_item.generics);
|
2019-02-06 14:16:11 +01:00
|
|
|
self.with_lint_attrs(impl_item.hir_id, &impl_item.attrs, |cx| {
|
2019-02-26 11:04:58 +01:00
|
|
|
cx.with_param_env(impl_item.hir_id, |cx| {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_impl_item, impl_item);
|
2017-06-07 15:21:55 +03:00
|
|
|
hir_visit::walk_impl_item(cx, impl_item);
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(cx, check_impl_item_post, impl_item);
|
2017-06-07 15:21:55 +03:00
|
|
|
});
|
2015-03-10 12:28:44 +02:00
|
|
|
});
|
2019-01-31 01:36:11 +01:00
|
|
|
self.context.generics = generics;
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2016-11-09 16:45:26 -05:00
|
|
|
fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_lifetime, lt);
|
Fix lint attributes on non-item nodes.
Currently, late lint checking uses two HIR visitors: LateContext and
IdVisitor. IdVisitor only overrides visit_id, and for each node searches
for builtin lints previously added to the session; LateContext overrides
a number of methods, and runs late lints. When LateContext encounters an
item, it first has IdVisitor walk everything in it except nested items
(OnlyBodies), then recurses into it itself - i.e. there are two separate
walks.
Aside from apparently being unnecessary, this separation prevents lint
attributes (allow/deny/warn) on non-item HIR nodes from working
properly. Test case:
// generates warning without this change
fn main() { #[allow(unreachable_code)] loop { break; break; } }
LateContext contains logic to merge attributes seen into the current lint
settings while walking (with_lint_attrs), but IdVisitor does not. So
such attributes will affect late lints (because they are called from
LateContext), and if the node contains any items within it, they will
affect builtin lints within those items (because that IdVisitor is run
while LateContext is within the attributed node), but otherwise the
attributes will be ignored for builtin lints.
This change simply removes IdVisitor and moves its visit_id into
LateContext itself. Hopefully this doesn't break anything...
Also added walk calls to visit_lifetime and visit_lifetime_def
respectively, so visit_lifetime_def will recurse into the lifetime and
visit_lifetime will recurse into the name. In principle this could
confuse lint plugins. This is "necessary" because walk_lifetime calls
visit_id on the lifetime; of course, an alternative would be directly
calling visit_id (which would require manually iterating over the
lifetimes in visit_lifetime_def), but that seems less clean.
2017-01-03 20:40:29 +01:00
|
|
|
hir_visit::walk_lifetime(self, lt);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2018-07-31 10:43:51 -06:00
|
|
|
fn visit_path(&mut self, p: &'tcx hir::Path, id: hir::HirId) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_path, p, id);
|
2015-09-10 16:40:59 +12:00
|
|
|
hir_visit::walk_path(self, p);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) {
|
2019-01-31 01:36:11 +01:00
|
|
|
lint_callback!(self, check_attribute, attr);
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-18 07:40:55 +01:00
|
|
|
impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
|
2019-08-27 13:24:32 +02:00
|
|
|
fn visit_param(&mut self, param: &'a ast::Param) {
|
|
|
|
self.with_lint_attrs(param.id, ¶m.attrs, |cx| {
|
|
|
|
run_early_pass!(cx, check_param, param);
|
|
|
|
ast_visit::walk_param(cx, param);
|
2019-07-26 19:52:37 -03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_item(&mut self, it: &'a ast::Item) {
|
2017-07-26 21:51:09 -07:00
|
|
|
self.with_lint_attrs(it.id, &it.attrs, |cx| {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_item, it);
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_item(cx, it);
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_item_post, it);
|
2015-09-10 16:40:59 +12:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_foreign_item(&mut self, it: &'a ast::ForeignItem) {
|
2017-07-26 21:51:09 -07:00
|
|
|
self.with_lint_attrs(it.id, &it.attrs, |cx| {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_foreign_item, it);
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_foreign_item(cx, it);
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_foreign_item_post, it);
|
2015-09-10 16:40:59 +12:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_pat(&mut self, p: &'a ast::Pat) {
|
2019-04-21 17:09:30 +03:00
|
|
|
run_early_pass!(self, check_pat, p);
|
2017-07-26 21:51:09 -07:00
|
|
|
self.check_id(p.id);
|
2019-04-21 17:09:30 +03:00
|
|
|
ast_visit::walk_pat(self, p);
|
|
|
|
run_early_pass!(self, check_pat_post, p);
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
2017-07-26 21:51:09 -07:00
|
|
|
self.with_lint_attrs(e.id, &e.attrs, |cx| {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_expr, e);
|
2015-12-19 23:33:45 +01:00
|
|
|
ast_visit::walk_expr(cx, e);
|
|
|
|
})
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_stmt(&mut self, s: &'a ast::Stmt) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_stmt, s);
|
2017-07-26 21:51:09 -07:00
|
|
|
self.check_id(s.id);
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_stmt(self, s);
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, decl: &'a ast::FnDecl,
|
2016-10-26 02:17:29 +03:00
|
|
|
span: Span, id: ast::NodeId) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_fn, fk, decl, span, id);
|
2017-07-26 21:51:09 -07:00
|
|
|
self.check_id(id);
|
2016-10-26 02:17:29 +03:00
|
|
|
ast_visit::walk_fn(self, fk, decl, span);
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_fn_post, fk, decl, span, id);
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2019-08-24 13:54:40 -03:00
|
|
|
fn visit_variant_data(&mut self, s: &'a ast::VariantData) {
|
|
|
|
run_early_pass!(self, check_struct_def, s);
|
2019-03-21 23:38:50 +01:00
|
|
|
if let Some(ctor_hir_id) = s.ctor_id() {
|
|
|
|
self.check_id(ctor_hir_id);
|
|
|
|
}
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_struct_def(self, s);
|
2019-08-24 13:54:40 -03:00
|
|
|
run_early_pass!(self, check_struct_def_post, s);
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_struct_field(&mut self, s: &'a ast::StructField) {
|
2017-07-26 21:51:09 -07:00
|
|
|
self.with_lint_attrs(s.id, &s.attrs, |cx| {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_struct_field, s);
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_struct_field(cx, s);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-08-24 13:54:40 -03:00
|
|
|
fn visit_variant(&mut self, v: &'a ast::Variant) {
|
|
|
|
self.with_lint_attrs(v.id, &v.attrs, |cx| {
|
|
|
|
run_early_pass!(cx, check_variant, v);
|
|
|
|
ast_visit::walk_variant(cx, v);
|
|
|
|
run_early_pass!(cx, check_variant_post, v);
|
2015-09-10 16:40:59 +12:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_ty(&mut self, t: &'a ast::Ty) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_ty, t);
|
2017-07-26 21:51:09 -07:00
|
|
|
self.check_id(t.id);
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_ty(self, t);
|
|
|
|
}
|
|
|
|
|
2018-03-19 03:54:56 +03:00
|
|
|
fn visit_ident(&mut self, ident: ast::Ident) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_ident, ident);
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2017-05-12 07:15:29 +12:00
|
|
|
fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, _a: &[ast::Attribute], n: ast::NodeId) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_mod, m, s, n);
|
2017-07-26 21:51:09 -07:00
|
|
|
self.check_id(n);
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_mod(self, m);
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_mod_post, m, s, n);
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_local(&mut self, l: &'a ast::Local) {
|
2017-07-26 21:51:09 -07:00
|
|
|
self.with_lint_attrs(l.id, &l.attrs, |cx| {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_local, l);
|
2015-12-19 23:33:45 +01:00
|
|
|
ast_visit::walk_local(cx, l);
|
|
|
|
})
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_block(&mut self, b: &'a ast::Block) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_block, b);
|
2017-07-26 21:51:09 -07:00
|
|
|
self.check_id(b.id);
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_block(self, b);
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_block_post, b);
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_arm(&mut self, a: &'a ast::Arm) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_arm, a);
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_arm(self, a);
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_expr_post(&mut self, e: &'a ast::Expr) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_expr_post, e);
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2017-10-16 21:07:26 +02:00
|
|
|
fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_generic_param, param);
|
2017-10-16 21:07:26 +02:00
|
|
|
ast_visit::walk_generic_param(self, param);
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_generics(&mut self, g: &'a ast::Generics) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_generics, g);
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_generics(self, g);
|
|
|
|
}
|
|
|
|
|
2018-02-18 19:37:07 +01:00
|
|
|
fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_where_predicate, p);
|
2018-02-18 19:37:07 +01:00
|
|
|
ast_visit::walk_where_predicate(self, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef, m: &'a ast::TraitBoundModifier) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_poly_trait_ref, t, m);
|
2018-02-18 19:37:07 +01:00
|
|
|
ast_visit::walk_poly_trait_ref(self, t, m);
|
|
|
|
}
|
|
|
|
|
2019-12-08 00:08:09 +01:00
|
|
|
fn visit_trait_item(&mut self, trait_item: &'a ast::AssocItem) {
|
2017-07-26 21:51:09 -07:00
|
|
|
self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_trait_item, trait_item);
|
2019-12-02 02:03:31 +01:00
|
|
|
ast_visit::walk_trait_item(cx, trait_item);
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_trait_item_post, trait_item);
|
2015-09-10 16:40:59 +12:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-08 00:08:09 +01:00
|
|
|
fn visit_impl_item(&mut self, impl_item: &'a ast::AssocItem) {
|
2017-07-26 21:51:09 -07:00
|
|
|
self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_impl_item, impl_item);
|
2019-12-02 02:03:31 +01:00
|
|
|
ast_visit::walk_impl_item(cx, impl_item);
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(cx, check_impl_item_post, impl_item);
|
2015-09-10 16:40:59 +12:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_lifetime, lt);
|
2017-07-26 21:51:09 -07:00
|
|
|
self.check_id(lt.id);
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_path, p, id);
|
2017-07-26 21:51:09 -07:00
|
|
|
self.check_id(id);
|
2015-09-10 16:40:59 +12:00
|
|
|
ast_visit::walk_path(self, p);
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_attribute, attr);
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
2017-05-12 08:10:52 +02:00
|
|
|
|
2018-07-14 16:40:17 +02:00
|
|
|
fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) {
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_mac_def, mac, id);
|
2017-07-26 21:51:09 -07:00
|
|
|
self.check_id(id);
|
2016-01-13 18:54:06 +00:00
|
|
|
}
|
2018-07-14 16:40:17 +02:00
|
|
|
|
2018-08-24 13:48:20 -07:00
|
|
|
fn visit_mac(&mut self, mac: &'a ast::Mac) {
|
2018-09-10 17:12:55 -04:00
|
|
|
// FIXME(#54110): So, this setup isn't really right. I think
|
|
|
|
// that (a) the libsyntax visitor ought to be doing this as
|
|
|
|
// part of `walk_mac`, and (b) we should be calling
|
|
|
|
// `visit_path`, *but* that would require a `NodeId`, and I
|
|
|
|
// want to get #53686 fixed quickly. -nmatsakis
|
2019-08-15 02:13:53 +03:00
|
|
|
ast_visit::walk_path(self, &mac.path);
|
2018-09-10 17:12:55 -04:00
|
|
|
|
2019-01-18 07:40:55 +01:00
|
|
|
run_early_pass!(self, check_mac, mac);
|
2018-07-14 16:40:17 +02:00
|
|
|
}
|
2016-01-13 18:54:06 +00:00
|
|
|
}
|
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
struct LateLintPassObjects<'a> {
|
|
|
|
lints: &'a mut [LateLintPassObject],
|
|
|
|
}
|
|
|
|
|
2019-08-11 12:55:14 -04:00
|
|
|
#[allow(rustc::lint_pass_impl_without_macro)]
|
2019-01-31 01:36:11 +01:00
|
|
|
impl LintPass for LateLintPassObjects<'_> {
|
|
|
|
fn name(&self) -> &'static str {
|
|
|
|
panic!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! expand_late_lint_pass_impl_methods {
|
|
|
|
([$a:tt, $hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
|
|
|
|
$(fn $name(&mut self, context: &LateContext<$a, $hir>, $($param: $arg),*) {
|
|
|
|
for obj in self.lints.iter_mut() {
|
|
|
|
obj.$name(context, $($param),*);
|
|
|
|
}
|
|
|
|
})*
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! late_lint_pass_impl {
|
|
|
|
([], [$hir:tt], $methods:tt) => (
|
|
|
|
impl LateLintPass<'a, $hir> for LateLintPassObjects<'_> {
|
|
|
|
expand_late_lint_pass_impl_methods!(['a, $hir], $methods);
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
late_lint_methods!(late_lint_pass_impl, [], ['tcx]);
|
|
|
|
|
|
|
|
fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2019-01-31 01:36:11 +01:00
|
|
|
module_def_id: DefId,
|
|
|
|
pass: T,
|
|
|
|
) {
|
2018-06-11 08:48:15 +02:00
|
|
|
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
|
2016-01-13 18:54:06 +00:00
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
let context = LateContext {
|
2018-06-11 08:48:15 +02:00
|
|
|
tcx,
|
|
|
|
tables: &ty::TypeckTables::empty(None),
|
|
|
|
param_env: ty::ParamEnv::empty(),
|
|
|
|
access_levels,
|
2019-10-09 09:53:13 -04:00
|
|
|
lint_store: &tcx.lint_store,
|
2018-06-11 08:48:15 +02:00
|
|
|
last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(),
|
|
|
|
generics: None,
|
|
|
|
only_module: true,
|
|
|
|
};
|
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
let mut cx = LateContextAndPass {
|
|
|
|
context,
|
|
|
|
pass
|
|
|
|
};
|
|
|
|
|
2018-06-11 08:48:15 +02:00
|
|
|
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
|
|
|
|
cx.process_mod(module, span, hir_id);
|
|
|
|
|
2019-03-03 18:47:54 +01:00
|
|
|
// Visit the crate attributes
|
|
|
|
if hir_id == hir::CRATE_HIR_ID {
|
2019-06-14 18:58:55 +02:00
|
|
|
walk_list!(cx, visit_attribute, tcx.hir().attrs(hir::CRATE_HIR_ID));
|
2019-03-03 18:47:54 +01:00
|
|
|
}
|
2018-06-11 08:48:15 +02:00
|
|
|
}
|
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2019-01-31 01:36:11 +01:00
|
|
|
module_def_id: DefId,
|
|
|
|
builtin_lints: T,
|
|
|
|
) {
|
2019-01-31 03:04:39 +01:00
|
|
|
if tcx.sess.opts.debugging_opts.no_interleave_lints {
|
|
|
|
// These passes runs in late_lint_crate with -Z no_interleave_lints
|
|
|
|
return;
|
|
|
|
}
|
2019-01-31 01:36:11 +01:00
|
|
|
|
|
|
|
late_lint_mod_pass(tcx, module_def_id, builtin_lints);
|
|
|
|
|
2019-10-09 09:53:13 -04:00
|
|
|
let mut passes: Vec<_> = tcx.lint_store.late_module_passes
|
2019-10-07 18:23:16 -04:00
|
|
|
.iter().map(|pass| (pass)()).collect();
|
2019-01-31 01:36:11 +01:00
|
|
|
|
|
|
|
if !passes.is_empty() {
|
|
|
|
late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] });
|
|
|
|
}
|
2018-06-11 08:48:15 +02:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, pass: T) {
|
2017-04-24 17:23:36 +03:00
|
|
|
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
|
2017-03-23 15:13:29 -04:00
|
|
|
|
2018-12-04 13:45:36 +01:00
|
|
|
let krate = tcx.hir().krate();
|
2014-06-06 15:49:48 -07:00
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
let context = LateContext {
|
|
|
|
tcx,
|
|
|
|
tables: &ty::TypeckTables::empty(None),
|
|
|
|
param_env: ty::ParamEnv::empty(),
|
|
|
|
access_levels,
|
2019-10-09 09:53:13 -04:00
|
|
|
lint_store: &tcx.lint_store,
|
2019-01-31 01:36:11 +01:00
|
|
|
last_node_with_lint_attrs: hir::CRATE_HIR_ID,
|
|
|
|
generics: None,
|
|
|
|
only_module: false,
|
|
|
|
};
|
2016-02-11 05:58:09 +01:00
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
let mut cx = LateContextAndPass {
|
|
|
|
context,
|
|
|
|
pass
|
2018-07-14 16:40:17 +02:00
|
|
|
};
|
2014-06-06 15:49:48 -07:00
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
// Visit the whole crate.
|
|
|
|
cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.attrs, |cx| {
|
|
|
|
// since the root module isn't visited as an item (because it isn't an
|
|
|
|
// item), warn for it here.
|
|
|
|
lint_callback!(cx, check_crate, krate);
|
|
|
|
|
|
|
|
hir_visit::walk_crate(cx, krate);
|
|
|
|
|
|
|
|
lint_callback!(cx, check_crate_post, krate);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-06-14 01:32:15 +03:00
|
|
|
fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
|
2019-10-09 09:53:13 -04:00
|
|
|
let mut passes = tcx.lint_store
|
2019-10-07 18:23:16 -04:00
|
|
|
.late_passes.iter().map(|p| (p)()).collect::<Vec<_>>();
|
2019-01-31 01:36:11 +01:00
|
|
|
|
|
|
|
if !tcx.sess.opts.debugging_opts.no_interleave_lints {
|
|
|
|
if !passes.is_empty() {
|
|
|
|
late_lint_pass_crate(tcx, LateLintPassObjects { lints: &mut passes[..] });
|
|
|
|
}
|
|
|
|
|
|
|
|
late_lint_pass_crate(tcx, builtin_lints);
|
|
|
|
} else {
|
|
|
|
for pass in &mut passes {
|
|
|
|
time(tcx.sess, &format!("running late lint: {}", pass.name()), || {
|
|
|
|
late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-10-09 09:53:13 -04:00
|
|
|
let mut passes: Vec<_> = tcx.lint_store.late_module_passes
|
2019-10-07 18:23:16 -04:00
|
|
|
.iter().map(|pass| (pass)()).collect();
|
2019-01-31 03:04:39 +01:00
|
|
|
|
2019-01-31 01:36:11 +01:00
|
|
|
for pass in &mut passes {
|
|
|
|
time(tcx.sess, &format!("running late module lint: {}", pass.name()), || {
|
|
|
|
late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2014-06-06 15:49:48 -07:00
|
|
|
}
|
2015-09-10 16:40:59 +12:00
|
|
|
|
2018-06-11 08:48:15 +02:00
|
|
|
/// Performs lint checking on a crate.
|
2019-01-31 01:36:11 +01:00
|
|
|
pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2019-01-31 03:04:39 +01:00
|
|
|
builtin_lints: impl FnOnce() -> T + Send,
|
2019-01-31 01:36:11 +01:00
|
|
|
) {
|
2019-01-31 03:04:39 +01:00
|
|
|
join(|| {
|
|
|
|
time(tcx.sess, "crate lints", || {
|
|
|
|
// Run whole crate non-incremental lints
|
|
|
|
late_lint_crate(tcx, builtin_lints());
|
|
|
|
});
|
|
|
|
}, || {
|
|
|
|
time(tcx.sess, "module lints", || {
|
|
|
|
// Run per-module lints
|
2019-01-31 04:36:37 +01:00
|
|
|
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
|
2019-07-10 12:22:07 +02:00
|
|
|
tcx.ensure().lint_mod(tcx.hir().local_def_id(module));
|
2019-01-31 04:36:37 +01:00
|
|
|
});
|
2019-01-31 03:04:39 +01:00
|
|
|
});
|
|
|
|
});
|
2018-06-11 08:48:15 +02:00
|
|
|
}
|
|
|
|
|
2019-01-18 07:40:55 +01:00
|
|
|
struct EarlyLintPassObjects<'a> {
|
|
|
|
lints: &'a mut [EarlyLintPassObject],
|
|
|
|
}
|
|
|
|
|
2019-08-11 12:55:14 -04:00
|
|
|
#[allow(rustc::lint_pass_impl_without_macro)]
|
2019-01-18 07:40:55 +01:00
|
|
|
impl LintPass for EarlyLintPassObjects<'_> {
|
|
|
|
fn name(&self) -> &'static str {
|
|
|
|
panic!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! expand_early_lint_pass_impl_methods {
|
|
|
|
([$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
|
|
|
|
$(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
|
|
|
|
for obj in self.lints.iter_mut() {
|
|
|
|
obj.$name(context, $($param),*);
|
|
|
|
}
|
|
|
|
})*
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! early_lint_pass_impl {
|
|
|
|
([], [$($methods:tt)*]) => (
|
|
|
|
impl EarlyLintPass for EarlyLintPassObjects<'_> {
|
|
|
|
expand_early_lint_pass_impl_methods!([$($methods)*]);
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
early_lint_methods!(early_lint_pass_impl, []);
|
|
|
|
|
|
|
|
fn early_lint_crate<T: EarlyLintPass>(
|
|
|
|
sess: &Session,
|
2019-10-09 08:46:11 -04:00
|
|
|
lint_store: &LintStore,
|
2019-01-18 07:40:55 +01:00
|
|
|
krate: &ast::Crate,
|
|
|
|
pass: T,
|
|
|
|
buffered: LintBuffer,
|
2019-10-25 13:41:51 -04:00
|
|
|
warn_about_weird_lints: bool,
|
2019-01-18 07:40:55 +01:00
|
|
|
) -> LintBuffer {
|
|
|
|
let mut cx = EarlyContextAndPass {
|
2019-10-25 13:41:51 -04:00
|
|
|
context: EarlyContext::new(sess, lint_store, krate, buffered, warn_about_weird_lints),
|
2019-01-18 07:40:55 +01:00
|
|
|
pass,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Visit the whole crate.
|
|
|
|
cx.with_lint_attrs(ast::CRATE_NODE_ID, &krate.attrs, |cx| {
|
|
|
|
// since the root module isn't visited as an item (because it isn't an
|
|
|
|
// item), warn for it here.
|
|
|
|
run_early_pass!(cx, check_crate, krate);
|
|
|
|
|
|
|
|
ast_visit::walk_crate(cx, krate);
|
|
|
|
|
|
|
|
run_early_pass!(cx, check_crate_post, krate);
|
|
|
|
});
|
|
|
|
cx.context.buffered
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn check_ast_crate<T: EarlyLintPass>(
|
2018-07-14 16:40:17 +02:00
|
|
|
sess: &Session,
|
2019-10-09 08:46:11 -04:00
|
|
|
lint_store: &LintStore,
|
2018-07-14 16:40:17 +02:00
|
|
|
krate: &ast::Crate,
|
|
|
|
pre_expansion: bool,
|
2019-10-25 13:41:51 -04:00
|
|
|
lint_buffer: Option<LintBuffer>,
|
2019-01-18 07:40:55 +01:00
|
|
|
builtin_lints: T,
|
2018-07-14 16:40:17 +02:00
|
|
|
) {
|
2019-10-25 13:41:51 -04:00
|
|
|
let mut passes: Vec<_> = if pre_expansion {
|
|
|
|
lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect()
|
2018-07-14 16:40:17 +02:00
|
|
|
} else {
|
2019-10-25 13:41:51 -04:00
|
|
|
lint_store.early_passes.iter().map(|p| (p)()).collect()
|
2018-07-14 16:40:17 +02:00
|
|
|
};
|
2019-10-25 13:41:51 -04:00
|
|
|
let mut buffered = lint_buffer.unwrap_or_default();
|
2015-09-10 16:40:59 +12:00
|
|
|
|
2019-01-18 07:40:55 +01:00
|
|
|
if !sess.opts.debugging_opts.no_interleave_lints {
|
2019-10-25 13:41:51 -04:00
|
|
|
buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered,
|
|
|
|
pre_expansion);
|
2015-09-10 16:40:59 +12:00
|
|
|
|
2019-01-18 07:40:55 +01:00
|
|
|
if !passes.is_empty() {
|
|
|
|
buffered = early_lint_crate(
|
|
|
|
sess,
|
2019-10-09 08:46:11 -04:00
|
|
|
lint_store,
|
2019-01-18 07:40:55 +01:00
|
|
|
krate,
|
|
|
|
EarlyLintPassObjects { lints: &mut passes[..] },
|
|
|
|
buffered,
|
2019-10-25 13:41:51 -04:00
|
|
|
pre_expansion,
|
2019-01-18 07:40:55 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for pass in &mut passes {
|
|
|
|
buffered = time(sess, &format!("running lint: {}", pass.name()), || {
|
|
|
|
early_lint_crate(
|
|
|
|
sess,
|
2019-10-09 08:46:11 -04:00
|
|
|
lint_store,
|
2019-01-18 07:40:55 +01:00
|
|
|
krate,
|
|
|
|
EarlyLintPassObjects { lints: slice::from_mut(pass) },
|
|
|
|
buffered,
|
2019-10-25 13:41:51 -04:00
|
|
|
pre_expansion,
|
2019-01-18 07:40:55 +01:00
|
|
|
)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2015-09-10 16:40:59 +12:00
|
|
|
|
2018-02-02 12:09:25 +05:30
|
|
|
// All of the buffered lints should have been emitted at this point.
|
|
|
|
// If not, that means that we somehow buffered a lint for a node id
|
|
|
|
// that was not lint-checked (perhaps it doesn't exist?). This is a bug.
|
|
|
|
//
|
|
|
|
// Rustdoc runs everybody-loops before the early lints and removes
|
|
|
|
// function bodies, so it's totally possible for linted
|
2018-11-27 02:59:49 +00:00
|
|
|
// node ids to not exist (e.g., macros defined within functions for the
|
2018-02-02 12:09:25 +05:30
|
|
|
// unused_macro lint) anymore. So we only run this check
|
|
|
|
// when we're not in rustdoc mode. (see issue #47639)
|
|
|
|
if !sess.opts.actually_rustdoc {
|
2018-07-14 16:40:17 +02:00
|
|
|
for (_id, lints) in buffered.map {
|
2018-02-02 12:09:25 +05:30
|
|
|
for early_lint in lints {
|
2018-02-23 00:10:37 -08:00
|
|
|
sess.delay_span_bug(early_lint.span, "failed to process buffered lint here");
|
2018-02-02 12:09:25 +05:30
|
|
|
}
|
2015-09-10 16:40:59 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|