Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make some lints incremental #57293

Merged
merged 4 commits into from
Mar 28, 2019
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Make some lints incremental
  • Loading branch information
Zoxc committed Mar 25, 2019
commit 7e156c2066bd9bf3a3d076ed32dd0d7b217c5857
1 change: 1 addition & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
@@ -474,6 +474,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
[] UnsafetyCheckResult(DefId),
[] UnsafeDeriveOnReprPacked(DefId),

[] LintMod(DefId),
[] CheckModAttrs(DefId),
[] CheckModLoops(DefId),
[] CheckModUnstableApiUsage(DefId),
8 changes: 4 additions & 4 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
@@ -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")
}
}
80 changes: 71 additions & 9 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
@@ -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],
}
1 change: 1 addition & 0 deletions src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 2 additions & 0 deletions src/librustc/ty/query/mod.rs
Original file line number Diff line number Diff line change
@@ -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) -> (),

1 change: 1 addition & 0 deletions src/librustc/ty/query/plumbing.rs
Original file line number Diff line number Diff line change
@@ -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!()); }
2 changes: 1 addition & 1 deletion src/librustc_interface/passes.rs
Original file line number Diff line number Diff line change
@@ -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 {
53 changes: 45 additions & 8 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
@@ -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",
3 changes: 1 addition & 2 deletions src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
@@ -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