提交 7e156c20 编写于 作者: J John Kåre Alsaker

Make some lints incremental

上级 4c27fb19
......@@ -474,6 +474,7 @@ pub fn to_dep_node(self, tcx: TyCtxt<'_, '_, '_>, kind: DepKind) -> DepNode {
[] UnsafetyCheckResult(DefId),
[] UnsafeDeriveOnReprPacked(DefId),
[] LintMod(DefId),
[] CheckModAttrs(DefId),
[] CheckModLoops(DefId),
[] CheckModUnstableApiUsage(DefId),
......
......@@ -580,17 +580,17 @@ pub fn krate_attrs(&self) -> &'hir [ast::Attribute] {
&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::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_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 @@ pub fn new() -> 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 @@ pub fn register_pre_expansion_pass(
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 @@ fn with_param_env<F>(&mut self, id: hir::HirId, f: F)
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 @@ fn visit_name(&mut self, sp: Span, name: ast::Name) {
}
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 @@ fn visit_mac(&mut self, mac: &'a ast::Mac) {
}
}
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 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
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 @@
},
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册