Skip to content

Commit 7e156c2

Browse files
committed
Make some lints incremental
1 parent 4c27fb1 commit 7e156c2

File tree

9 files changed

+127
-24
lines changed

9 files changed

+127
-24
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
474474
[] UnsafetyCheckResult(DefId),
475475
[] UnsafeDeriveOnReprPacked(DefId),
476476

477+
[] LintMod(DefId),
477478
[] CheckModAttrs(DefId),
478479
[] CheckModLoops(DefId),
479480
[] CheckModUnstableApiUsage(DefId),

src/librustc/hir/map/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -580,17 +580,17 @@ impl<'hir> Map<'hir> {
580580
&self.forest.krate.attrs
581581
}
582582

583-
pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, NodeId)
584-
{
583+
pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) {
585584
let node_id = self.as_local_node_id(module).unwrap();
585+
let hir_id = self.node_to_hir_id(node_id);
586586
self.read(node_id);
587587
match self.find_entry(node_id).unwrap().node {
588588
Node::Item(&Item {
589589
span,
590590
node: ItemKind::Mod(ref m),
591591
..
592-
}) => (m, span, node_id),
593-
Node::Crate => (&self.forest.krate.module, self.forest.krate.span, node_id),
592+
}) => (m, span, hir_id),
593+
Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id),
594594
_ => panic!("not a module")
595595
}
596596
}

src/librustc/lint/context.rs

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use crate::rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
2727
use crate::session::{config, early_error, Session};
2828
use crate::ty::{self, TyCtxt, Ty};
2929
use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
30+
use crate::ty::query::Providers;
3031
use crate::util::nodemap::FxHashMap;
3132
use crate::util::common::time;
3233

@@ -36,7 +37,7 @@ use syntax::edition;
3637
use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}};
3738
use errors::DiagnosticBuilder;
3839
use crate::hir;
39-
use crate::hir::def_id::LOCAL_CRATE;
40+
use crate::hir::def_id::{DefId, LOCAL_CRATE};
4041
use crate::hir::intravisit as hir_visit;
4142
use syntax::util::lev_distance::find_best_match_for_name;
4243
use syntax::visit as ast_visit;
@@ -55,6 +56,7 @@ pub struct LintStore {
5556
pre_expansion_passes: Option<Vec<EarlyLintPassObject>>,
5657
early_passes: Option<Vec<EarlyLintPassObject>>,
5758
late_passes: Option<Vec<LateLintPassObject>>,
59+
late_module_passes: Option<Vec<LateLintPassObject>>,
5860

5961
/// Lints indexed by name.
6062
by_name: FxHashMap<String, TargetLint>,
@@ -150,6 +152,7 @@ impl LintStore {
150152
pre_expansion_passes: Some(vec![]),
151153
early_passes: Some(vec![]),
152154
late_passes: Some(vec![]),
155+
late_module_passes: Some(vec![]),
153156
by_name: Default::default(),
154157
future_incompatible: Default::default(),
155158
lint_groups: Default::default(),
@@ -199,9 +202,14 @@ impl LintStore {
199202
pub fn register_late_pass(&mut self,
200203
sess: Option<&Session>,
201204
from_plugin: bool,
205+
per_module: bool,
202206
pass: LateLintPassObject) {
203207
self.push_pass(sess, from_plugin, &pass);
204-
self.late_passes.as_mut().unwrap().push(pass);
208+
if per_module {
209+
self.late_module_passes.as_mut().unwrap().push(pass);
210+
} else {
211+
self.late_passes.as_mut().unwrap().push(pass);
212+
}
205213
}
206214

207215
// Helper method for register_early/late_pass
@@ -508,6 +516,7 @@ pub struct LateContext<'a, 'tcx: 'a> {
508516
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
509517

510518
/// Side-tables for the body we are in.
519+
// FIXME: Make this lazy to avoid running the TypeckTables query?
511520
pub tables: &'a ty::TypeckTables<'tcx>,
512521

513522
/// Parameter environment for the item we are in.
@@ -523,6 +532,9 @@ pub struct LateContext<'a, 'tcx: 'a> {
523532

524533
/// Generic type parameters in scope for the item we are in.
525534
pub generics: Option<&'tcx hir::Generics>,
535+
536+
/// We are only looking at one module
537+
only_module: bool,
526538
}
527539

528540
/// Context for lint checking of the AST, after expansion, before lowering to
@@ -803,6 +815,12 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
803815
pub fn current_lint_root(&self) -> hir::HirId {
804816
self.last_node_with_lint_attrs
805817
}
818+
819+
fn process_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) {
820+
run_lints!(self, check_mod, m, s, n);
821+
hir_visit::walk_mod(self, m, n);
822+
run_lints!(self, check_mod_post, m, s, n);
823+
}
806824
}
807825

808826
impl<'a, 'tcx> LayoutOf for LateContext<'a, 'tcx> {
@@ -934,9 +952,9 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
934952
}
935953

936954
fn visit_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) {
937-
run_lints!(self, check_mod, m, s, n);
938-
hir_visit::walk_mod(self, m, n);
939-
run_lints!(self, check_mod_post, m, s, n);
955+
if !self.only_module {
956+
self.process_mod(m, s, n);
957+
}
940958
}
941959

942960
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>
12031221
}
12041222
}
12051223

1224+
pub fn lint_mod<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
1225+
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
12061226

1207-
/// Performs lint checking on a crate.
1208-
///
1209-
/// Consumes the `lint_store` field of the `Session`.
1210-
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
1227+
let store = &tcx.sess.lint_store;
1228+
let passes = store.borrow_mut().late_module_passes.take();
1229+
1230+
let mut cx = LateContext {
1231+
tcx,
1232+
tables: &ty::TypeckTables::empty(None),
1233+
param_env: ty::ParamEnv::empty(),
1234+
access_levels,
1235+
lint_sess: LintSession {
1236+
lints: store.borrow(),
1237+
passes,
1238+
},
1239+
last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(),
1240+
generics: None,
1241+
only_module: true,
1242+
};
1243+
1244+
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
1245+
cx.process_mod(module, span, hir_id);
1246+
1247+
// Put the lint store levels and passes back in the session.
1248+
let passes = cx.lint_sess.passes;
1249+
drop(cx.lint_sess.lints);
1250+
store.borrow_mut().late_module_passes = passes;
1251+
}
1252+
1253+
pub(crate) fn provide(providers: &mut Providers<'_>) {
1254+
*providers = Providers {
1255+
lint_mod,
1256+
..*providers
1257+
};
1258+
}
1259+
1260+
fn lint_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
12111261
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
12121262

12131263
let krate = tcx.hir().krate();
@@ -1225,6 +1275,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
12251275
},
12261276
last_node_with_lint_attrs: hir::CRATE_HIR_ID,
12271277
generics: None,
1278+
only_module: false,
12281279
};
12291280

12301281
// Visit the whole crate.
@@ -1244,6 +1295,17 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
12441295
tcx.sess.lint_store.borrow_mut().late_passes = passes;
12451296
}
12461297

1298+
/// Performs lint checking on a crate.
1299+
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
1300+
// Run per-module lints
1301+
for &module in tcx.hir().krate().modules.keys() {
1302+
tcx.ensure().lint_mod(tcx.hir().local_def_id(module));
1303+
}
1304+
1305+
// Run whole crate non-incremental lints
1306+
lint_crate(tcx);
1307+
}
1308+
12471309
struct EarlyLintPassObjects<'a> {
12481310
lints: &'a mut [EarlyLintPassObject],
12491311
}

src/librustc/lint/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> {
824824

825825
pub fn provide(providers: &mut Providers<'_>) {
826826
providers.lint_levels = lint_levels;
827+
context::provide(providers);
827828
}
828829

829830
/// Returns whether `span` originates in a foreign crate's external macro.

src/librustc/ty/query/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ rustc_query_append! { [define_queries!][ <'tcx>
245245
},
246246

247247
Other {
248+
[] fn lint_mod: LintMod(DefId) -> (),
249+
248250
/// Checks the attributes in the module
249251
[] fn check_mod_attrs: CheckModAttrs(DefId) -> (),
250252

src/librustc/ty/query/plumbing.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,6 +1272,7 @@ pub fn force_from_dep_node<'tcx>(
12721272
DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
12731273
DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); }
12741274
DepKind::UnsafeDeriveOnReprPacked => { force!(unsafe_derive_on_repr_packed, def_id!()); }
1275+
DepKind::LintMod => { force!(lint_mod, def_id!()); }
12751276
DepKind::CheckModAttrs => { force!(check_mod_attrs, def_id!()); }
12761277
DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); }
12771278
DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); }

src/librustc_interface/passes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ pub fn register_plugins<'a>(
328328
ls.register_early_pass(Some(sess), true, false, pass);
329329
}
330330
for pass in late_lint_passes {
331-
ls.register_late_pass(Some(sess), true, pass);
331+
ls.register_late_pass(Some(sess), true, false, pass);
332332
}
333333

334334
for (name, (to, deprecated_name)) in lint_groups {

src/librustc_lint/lib.rs

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,37 +125,74 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
125125
store.register_early_pass(sess, false, true, box BuiltinCombinedEarlyLintPass::new());
126126
}
127127

128-
late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [
128+
// FIXME: Make a separate lint type which do not require typeck tables
129+
130+
late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedModuleLateLintPass, [
129131
HardwiredLints: HardwiredLints,
130132
WhileTrue: WhileTrue,
131133
ImproperCTypes: ImproperCTypes,
132134
VariantSizeDifferences: VariantSizeDifferences,
133135
BoxPointers: BoxPointers,
134-
UnusedAttributes: UnusedAttributes,
135136
PathStatements: PathStatements,
136137
UnusedResults: UnusedResults,
137-
NonSnakeCase: NonSnakeCase,
138138
NonUpperCaseGlobals: NonUpperCaseGlobals,
139139
NonShorthandFieldPatterns: NonShorthandFieldPatterns,
140140
UnusedAllocation: UnusedAllocation,
141+
142+
// Depends on types used in type definitions
141143
MissingCopyImplementations: MissingCopyImplementations,
142-
UnstableFeatures: UnstableFeatures,
143-
InvalidNoMangleItems: InvalidNoMangleItems,
144+
144145
PluginAsLibrary: PluginAsLibrary,
146+
147+
// Depends on referenced function signatures in expressions
145148
MutableTransmutes: MutableTransmutes,
149+
150+
// Depends on types of fields, checks if they implement Drop
146151
UnionsWithDropFields: UnionsWithDropFields,
147-
UnreachablePub: UnreachablePub,
148-
UnnameableTestItems: UnnameableTestItems::new(),
152+
149153
TypeAliasBounds: TypeAliasBounds,
154+
155+
// May Depend on constants elsewhere
150156
UnusedBrokenConst: UnusedBrokenConst,
157+
151158
TrivialConstraints: TrivialConstraints,
152159
TypeLimits: TypeLimits::new(),
160+
]], ['tcx]);
161+
162+
store.register_late_pass(sess, false, true, box BuiltinCombinedModuleLateLintPass::new());
163+
164+
late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [
165+
166+
// Uses attr::is_used which is untracked, can't be an incremental module pass.
167+
// Doesn't require type tables. Make a separate combined pass for that?
168+
UnusedAttributes: UnusedAttributes,
169+
170+
171+
// Checks crate attributes. Find out how that would work.
172+
NonSnakeCase: NonSnakeCase,
173+
174+
175+
// Needs to look at crate attributes. Make sure that works
176+
UnstableFeatures: UnstableFeatures,
177+
178+
// Depends on access levels
179+
InvalidNoMangleItems: InvalidNoMangleItems,
180+
181+
// Depends on access levels
182+
UnreachablePub: UnreachablePub,
183+
184+
UnnameableTestItems: UnnameableTestItems::new(),
185+
186+
// Tracks attributes of parents
153187
MissingDoc: MissingDoc::new(),
188+
189+
// Depends on access levels
154190
MissingDebugImplementations: MissingDebugImplementations::new(),
191+
155192
ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
156193
]], ['tcx]);
157194

158-
store.register_late_pass(sess, false, box BuiltinCombinedLateLintPass::new());
195+
store.register_late_pass(sess, false, false, box BuiltinCombinedLateLintPass::new());
159196

160197
add_lint_group!(sess,
161198
"nonstandard_style",

src/librustc_privacy/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,8 +1790,7 @@ fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
17901790
current_item: hir::DUMMY_HIR_ID,
17911791
empty_tables: &empty_tables,
17921792
};
1793-
let (module, span, node_id) = tcx.hir().get_module(module_def_id);
1794-
let hir_id = tcx.hir().node_to_hir_id(node_id);
1793+
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
17951794
intravisit::walk_mod(&mut visitor, module, hir_id);
17961795

17971796
// Check privacy of explicitly written types and traits as well as

0 commit comments

Comments
 (0)