about summary refs log tree commit diff
path: root/src/librustc/lint
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-06-11 08:48:15 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-03-25 23:00:34 +0100
commit7e156c2066bd9bf3a3d076ed32dd0d7b217c5857 (patch)
tree5406cd654488f8f90814a432a736c1126cd05878 /src/librustc/lint
parent4c27fb19ba15a2e45485e601a79914c6280196b0 (diff)
downloadrust-7e156c2066bd9bf3a3d076ed32dd0d7b217c5857.tar.gz
rust-7e156c2066bd9bf3a3d076ed32dd0d7b217c5857.zip
Make some lints incremental
Diffstat (limited to 'src/librustc/lint')
-rw-r--r--src/librustc/lint/context.rs80
-rw-r--r--src/librustc/lint/mod.rs1
2 files changed, 72 insertions, 9 deletions
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 94f1d9c2710..6df3409d080 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -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],
 }
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index ae44210bcff..cf1c5d50000 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -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.