Make some lints incremental
This commit is contained in:
parent
4c27fb19ba
commit
7e156c2066
9 changed files with 127 additions and 24 deletions
|
@ -474,6 +474,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
|
|||
[] UnsafetyCheckResult(DefId),
|
||||
[] UnsafeDeriveOnReprPacked(DefId),
|
||||
|
||||
[] LintMod(DefId),
|
||||
[] CheckModAttrs(DefId),
|
||||
[] CheckModLoops(DefId),
|
||||
[] CheckModUnstableApiUsage(DefId),
|
||||
|
|
|
@ -580,17 +580,17 @@ impl<'hir> Map<'hir> {
|
|||
&self.forest.krate.attrs
|
||||
}
|
||||
|
||||
pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, NodeId)
|
||||
{
|
||||
pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) {
|
||||
let node_id = self.as_local_node_id(module).unwrap();
|
||||
let hir_id = self.node_to_hir_id(node_id);
|
||||
self.read(node_id);
|
||||
match self.find_entry(node_id).unwrap().node {
|
||||
Node::Item(&Item {
|
||||
span,
|
||||
node: ItemKind::Mod(ref m),
|
||||
..
|
||||
}) => (m, span, node_id),
|
||||
Node::Crate => (&self.forest.krate.module, self.forest.krate.span, node_id),
|
||||
}) => (m, span, hir_id),
|
||||
Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id),
|
||||
_ => panic!("not a module")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ use crate::rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
|
|||
use crate::session::{config, early_error, Session};
|
||||
use crate::ty::{self, TyCtxt, Ty};
|
||||
use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
|
||||
use crate::ty::query::Providers;
|
||||
use crate::util::nodemap::FxHashMap;
|
||||
use crate::util::common::time;
|
||||
|
||||
|
@ -36,7 +37,7 @@ use syntax::edition;
|
|||
use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}};
|
||||
use errors::DiagnosticBuilder;
|
||||
use crate::hir;
|
||||
use crate::hir::def_id::LOCAL_CRATE;
|
||||
use crate::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use crate::hir::intravisit as hir_visit;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use syntax::visit as ast_visit;
|
||||
|
@ -55,6 +56,7 @@ pub struct LintStore {
|
|||
pre_expansion_passes: Option<Vec<EarlyLintPassObject>>,
|
||||
early_passes: Option<Vec<EarlyLintPassObject>>,
|
||||
late_passes: Option<Vec<LateLintPassObject>>,
|
||||
late_module_passes: Option<Vec<LateLintPassObject>>,
|
||||
|
||||
/// Lints indexed by name.
|
||||
by_name: FxHashMap<String, TargetLint>,
|
||||
|
@ -150,6 +152,7 @@ impl LintStore {
|
|||
pre_expansion_passes: Some(vec![]),
|
||||
early_passes: Some(vec![]),
|
||||
late_passes: Some(vec![]),
|
||||
late_module_passes: Some(vec![]),
|
||||
by_name: Default::default(),
|
||||
future_incompatible: Default::default(),
|
||||
lint_groups: Default::default(),
|
||||
|
@ -199,9 +202,14 @@ impl LintStore {
|
|||
pub fn register_late_pass(&mut self,
|
||||
sess: Option<&Session>,
|
||||
from_plugin: bool,
|
||||
per_module: bool,
|
||||
pass: LateLintPassObject) {
|
||||
self.push_pass(sess, from_plugin, &pass);
|
||||
self.late_passes.as_mut().unwrap().push(pass);
|
||||
if per_module {
|
||||
self.late_module_passes.as_mut().unwrap().push(pass);
|
||||
} else {
|
||||
self.late_passes.as_mut().unwrap().push(pass);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method for register_early/late_pass
|
||||
|
@ -508,6 +516,7 @@ pub struct LateContext<'a, 'tcx: 'a> {
|
|||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
/// Side-tables for the body we are in.
|
||||
// FIXME: Make this lazy to avoid running the TypeckTables query?
|
||||
pub tables: &'a ty::TypeckTables<'tcx>,
|
||||
|
||||
/// Parameter environment for the item we are in.
|
||||
|
@ -523,6 +532,9 @@ pub struct LateContext<'a, 'tcx: 'a> {
|
|||
|
||||
/// Generic type parameters in scope for the item we are in.
|
||||
pub generics: Option<&'tcx hir::Generics>,
|
||||
|
||||
/// We are only looking at one module
|
||||
only_module: bool,
|
||||
}
|
||||
|
||||
/// Context for lint checking of the AST, after expansion, before lowering to
|
||||
|
@ -803,6 +815,12 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
|
|||
pub fn current_lint_root(&self) -> hir::HirId {
|
||||
self.last_node_with_lint_attrs
|
||||
}
|
||||
|
||||
fn process_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) {
|
||||
run_lints!(self, check_mod, m, s, n);
|
||||
hir_visit::walk_mod(self, m, n);
|
||||
run_lints!(self, check_mod_post, m, s, n);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LayoutOf for LateContext<'a, 'tcx> {
|
||||
|
@ -934,9 +952,9 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) {
|
||||
run_lints!(self, check_mod, m, s, n);
|
||||
hir_visit::walk_mod(self, m, n);
|
||||
run_lints!(self, check_mod_post, m, s, n);
|
||||
if !self.only_module {
|
||||
self.process_mod(m, s, n);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, l: &'tcx hir::Local) {
|
||||
|
@ -1203,11 +1221,43 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
}
|
||||
|
||||
pub fn lint_mod<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
|
||||
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
|
||||
|
||||
/// Performs lint checking on a crate.
|
||||
///
|
||||
/// Consumes the `lint_store` field of the `Session`.
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
let store = &tcx.sess.lint_store;
|
||||
let passes = store.borrow_mut().late_module_passes.take();
|
||||
|
||||
let mut cx = LateContext {
|
||||
tcx,
|
||||
tables: &ty::TypeckTables::empty(None),
|
||||
param_env: ty::ParamEnv::empty(),
|
||||
access_levels,
|
||||
lint_sess: LintSession {
|
||||
lints: store.borrow(),
|
||||
passes,
|
||||
},
|
||||
last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(),
|
||||
generics: None,
|
||||
only_module: true,
|
||||
};
|
||||
|
||||
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
|
||||
cx.process_mod(module, span, hir_id);
|
||||
|
||||
// Put the lint store levels and passes back in the session.
|
||||
let passes = cx.lint_sess.passes;
|
||||
drop(cx.lint_sess.lints);
|
||||
store.borrow_mut().late_module_passes = passes;
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers<'_>) {
|
||||
*providers = Providers {
|
||||
lint_mod,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
||||
fn lint_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
|
||||
|
||||
let krate = tcx.hir().krate();
|
||||
|
@ -1225,6 +1275,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
|||
},
|
||||
last_node_with_lint_attrs: hir::CRATE_HIR_ID,
|
||||
generics: None,
|
||||
only_module: false,
|
||||
};
|
||||
|
||||
// Visit the whole crate.
|
||||
|
@ -1244,6 +1295,17 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
|||
tcx.sess.lint_store.borrow_mut().late_passes = passes;
|
||||
}
|
||||
|
||||
/// Performs lint checking on a crate.
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
// Run per-module lints
|
||||
for &module in tcx.hir().krate().modules.keys() {
|
||||
tcx.ensure().lint_mod(tcx.hir().local_def_id(module));
|
||||
}
|
||||
|
||||
// Run whole crate non-incremental lints
|
||||
lint_crate(tcx);
|
||||
}
|
||||
|
||||
struct EarlyLintPassObjects<'a> {
|
||||
lints: &'a mut [EarlyLintPassObject],
|
||||
}
|
||||
|
|
|
@ -824,6 +824,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> {
|
|||
|
||||
pub fn provide(providers: &mut Providers<'_>) {
|
||||
providers.lint_levels = lint_levels;
|
||||
context::provide(providers);
|
||||
}
|
||||
|
||||
/// Returns whether `span` originates in a foreign crate's external macro.
|
||||
|
|
|
@ -245,6 +245,8 @@ rustc_query_append! { [define_queries!][ <'tcx>
|
|||
},
|
||||
|
||||
Other {
|
||||
[] fn lint_mod: LintMod(DefId) -> (),
|
||||
|
||||
/// Checks the attributes in the module
|
||||
[] fn check_mod_attrs: CheckModAttrs(DefId) -> (),
|
||||
|
||||
|
|
|
@ -1272,6 +1272,7 @@ pub fn force_from_dep_node<'tcx>(
|
|||
DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
|
||||
DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); }
|
||||
DepKind::UnsafeDeriveOnReprPacked => { force!(unsafe_derive_on_repr_packed, def_id!()); }
|
||||
DepKind::LintMod => { force!(lint_mod, def_id!()); }
|
||||
DepKind::CheckModAttrs => { force!(check_mod_attrs, def_id!()); }
|
||||
DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); }
|
||||
DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); }
|
||||
|
|
|
@ -328,7 +328,7 @@ pub fn register_plugins<'a>(
|
|||
ls.register_early_pass(Some(sess), true, false, pass);
|
||||
}
|
||||
for pass in late_lint_passes {
|
||||
ls.register_late_pass(Some(sess), true, pass);
|
||||
ls.register_late_pass(Some(sess), true, false, pass);
|
||||
}
|
||||
|
||||
for (name, (to, deprecated_name)) in lint_groups {
|
||||
|
|
|
@ -125,37 +125,74 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
|||
store.register_early_pass(sess, false, true, box BuiltinCombinedEarlyLintPass::new());
|
||||
}
|
||||
|
||||
late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [
|
||||
// FIXME: Make a separate lint type which do not require typeck tables
|
||||
|
||||
late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedModuleLateLintPass, [
|
||||
HardwiredLints: HardwiredLints,
|
||||
WhileTrue: WhileTrue,
|
||||
ImproperCTypes: ImproperCTypes,
|
||||
VariantSizeDifferences: VariantSizeDifferences,
|
||||
BoxPointers: BoxPointers,
|
||||
UnusedAttributes: UnusedAttributes,
|
||||
PathStatements: PathStatements,
|
||||
UnusedResults: UnusedResults,
|
||||
NonSnakeCase: NonSnakeCase,
|
||||
NonUpperCaseGlobals: NonUpperCaseGlobals,
|
||||
NonShorthandFieldPatterns: NonShorthandFieldPatterns,
|
||||
UnusedAllocation: UnusedAllocation,
|
||||
|
||||
// Depends on types used in type definitions
|
||||
MissingCopyImplementations: MissingCopyImplementations,
|
||||
UnstableFeatures: UnstableFeatures,
|
||||
InvalidNoMangleItems: InvalidNoMangleItems,
|
||||
|
||||
PluginAsLibrary: PluginAsLibrary,
|
||||
|
||||
// Depends on referenced function signatures in expressions
|
||||
MutableTransmutes: MutableTransmutes,
|
||||
|
||||
// Depends on types of fields, checks if they implement Drop
|
||||
UnionsWithDropFields: UnionsWithDropFields,
|
||||
UnreachablePub: UnreachablePub,
|
||||
UnnameableTestItems: UnnameableTestItems::new(),
|
||||
|
||||
TypeAliasBounds: TypeAliasBounds,
|
||||
|
||||
// May Depend on constants elsewhere
|
||||
UnusedBrokenConst: UnusedBrokenConst,
|
||||
|
||||
TrivialConstraints: TrivialConstraints,
|
||||
TypeLimits: TypeLimits::new(),
|
||||
]], ['tcx]);
|
||||
|
||||
store.register_late_pass(sess, false, true, box BuiltinCombinedModuleLateLintPass::new());
|
||||
|
||||
late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [
|
||||
|
||||
// Uses attr::is_used which is untracked, can't be an incremental module pass.
|
||||
// Doesn't require type tables. Make a separate combined pass for that?
|
||||
UnusedAttributes: UnusedAttributes,
|
||||
|
||||
|
||||
// Checks crate attributes. Find out how that would work.
|
||||
NonSnakeCase: NonSnakeCase,
|
||||
|
||||
|
||||
// Needs to look at crate attributes. Make sure that works
|
||||
UnstableFeatures: UnstableFeatures,
|
||||
|
||||
// Depends on access levels
|
||||
InvalidNoMangleItems: InvalidNoMangleItems,
|
||||
|
||||
// Depends on access levels
|
||||
UnreachablePub: UnreachablePub,
|
||||
|
||||
UnnameableTestItems: UnnameableTestItems::new(),
|
||||
|
||||
// Tracks attributes of parents
|
||||
MissingDoc: MissingDoc::new(),
|
||||
|
||||
// Depends on access levels
|
||||
MissingDebugImplementations: MissingDebugImplementations::new(),
|
||||
|
||||
ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
|
||||
]], ['tcx]);
|
||||
|
||||
store.register_late_pass(sess, false, box BuiltinCombinedLateLintPass::new());
|
||||
store.register_late_pass(sess, false, false, box BuiltinCombinedLateLintPass::new());
|
||||
|
||||
add_lint_group!(sess,
|
||||
"nonstandard_style",
|
||||
|
|
|
@ -1790,8 +1790,7 @@ fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
|
|||
current_item: hir::DUMMY_HIR_ID,
|
||||
empty_tables: &empty_tables,
|
||||
};
|
||||
let (module, span, node_id) = tcx.hir().get_module(module_def_id);
|
||||
let hir_id = tcx.hir().node_to_hir_id(node_id);
|
||||
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
|
||||
intravisit::walk_mod(&mut visitor, module, hir_id);
|
||||
|
||||
// Check privacy of explicitly written types and traits as well as
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue