]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_lint/late.rs
New upstream version 1.46.0~beta.2+dfsg1
[rustc.git] / src / librustc_lint / late.rs
index c8f827b1f5cedf23681e876a2e8bff4a4551c4d2..5feb17af24f7cce740c99dacf6cd44a029288c4b 100644 (file)
@@ -30,6 +30,7 @@ use rustc_span::Span;
 
 use log::debug;
 use std::any::Any;
+use std::cell::Cell;
 use std::slice;
 
 /// Extract the `LintStore` from the query context.
@@ -43,12 +44,12 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
 }) }
 
-struct LateContextAndPass<'a, 'tcx, T: LateLintPass<'a, 'tcx>> {
-    context: LateContext<'a, 'tcx>,
+struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> {
+    context: LateContext<'tcx>,
     pass: T,
 }
 
-impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> LateContextAndPass<'a, 'tcx, T> {
+impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
     /// Merge the lints specified by any lint attributes into the
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
@@ -92,9 +93,7 @@ impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> LateContextAndPass<'a, 'tcx, T> {
     }
 }
 
-impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx>
-    for LateContextAndPass<'a, 'tcx, T>
-{
+impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPass<'tcx, T> {
     type Map = Map<'tcx>;
 
     /// Because lints are scoped lexically, we want to walk nested
@@ -104,12 +103,25 @@ impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx>
         hir_visit::NestedVisitorMap::All(self.context.tcx.hir())
     }
 
-    fn visit_nested_body(&mut self, body: hir::BodyId) {
-        let old_tables = self.context.tables;
-        self.context.tables = self.context.tcx.body_tables(body);
-        let body = self.context.tcx.hir().body(body);
+    fn visit_nested_body(&mut self, body_id: hir::BodyId) {
+        let old_enclosing_body = self.context.enclosing_body.replace(body_id);
+        let old_cached_typeck_tables = self.context.cached_typeck_tables.get();
+
+        // HACK(eddyb) avoid trashing `cached_typeck_tables` when we're
+        // nested in `visit_fn`, which may have already resulted in them
+        // being queried.
+        if old_enclosing_body != Some(body_id) {
+            self.context.cached_typeck_tables.set(None);
+        }
+
+        let body = self.context.tcx.hir().body(body_id);
         self.visit_body(body);
-        self.context.tables = old_tables;
+        self.context.enclosing_body = old_enclosing_body;
+
+        // See HACK comment above.
+        if old_enclosing_body != Some(body_id) {
+            self.context.cached_typeck_tables.set(old_cached_typeck_tables);
+        }
     }
 
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
@@ -181,13 +193,14 @@ impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx>
     ) {
         // Wrap in tables here, not just in visit_nested_body,
         // in order for `check_fn` to be able to use them.
-        let old_tables = self.context.tables;
-        self.context.tables = self.context.tcx.body_tables(body_id);
+        let old_enclosing_body = self.context.enclosing_body.replace(body_id);
+        let old_cached_typeck_tables = self.context.cached_typeck_tables.take();
         let body = self.context.tcx.hir().body(body_id);
         lint_callback!(self, check_fn, fk, decl, body, span, id);
         hir_visit::walk_fn(self, fk, decl, body_id, span, id);
         lint_callback!(self, check_fn_post, fk, decl, body, span, id);
-        self.context.tables = old_tables;
+        self.context.enclosing_body = old_enclosing_body;
+        self.context.cached_typeck_tables.set(old_cached_typeck_tables);
     }
 
     fn visit_variant_data(
@@ -333,8 +346,8 @@ impl LintPass for LateLintPassObjects<'_> {
 }
 
 macro_rules! expand_late_lint_pass_impl_methods {
-    ([$a:tt, $hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        $(fn $name(&mut self, context: &LateContext<$a, $hir>, $($param: $arg),*) {
+    ([$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        $(fn $name(&mut self, context: &LateContext<$hir>, $($param: $arg),*) {
             for obj in self.lints.iter_mut() {
                 obj.$name(context, $($param),*);
             }
@@ -343,16 +356,16 @@ macro_rules! expand_late_lint_pass_impl_methods {
 }
 
 macro_rules! late_lint_pass_impl {
-    ([], [$hir:tt], $methods:tt) => (
-        impl<'a, $hir> LateLintPass<'a, $hir> for LateLintPassObjects<'_> {
-            expand_late_lint_pass_impl_methods!(['a, $hir], $methods);
+    ([], [$hir:tt], $methods:tt) => {
+        impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_> {
+            expand_late_lint_pass_impl_methods!([$hir], $methods);
         }
-    )
+    };
 }
 
 crate::late_lint_methods!(late_lint_pass_impl, [], ['tcx]);
 
-fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
+fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>(
     tcx: TyCtxt<'tcx>,
     module_def_id: LocalDefId,
     pass: T,
@@ -361,7 +374,8 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
 
     let context = LateContext {
         tcx,
-        tables: &ty::TypeckTables::empty(None),
+        enclosing_body: None,
+        cached_typeck_tables: Cell::new(None),
         param_env: ty::ParamEnv::empty(),
         access_levels,
         lint_store: unerased_lint_store(tcx),
@@ -381,7 +395,7 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
     }
 }
 
-pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
+pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>(
     tcx: TyCtxt<'tcx>,
     module_def_id: LocalDefId,
     builtin_lints: T,
@@ -401,14 +415,15 @@ pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
     }
 }
 
-fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, pass: T) {
+fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) {
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
 
     let krate = tcx.hir().krate();
 
     let context = LateContext {
         tcx,
-        tables: &ty::TypeckTables::empty(None),
+        enclosing_body: None,
+        cached_typeck_tables: Cell::new(None),
         param_env: ty::ParamEnv::empty(),
         access_levels,
         lint_store: unerased_lint_store(tcx),
@@ -431,7 +446,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc
     })
 }
 
-fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
+fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
     let mut passes = unerased_lint_store(tcx).late_passes.iter().map(|p| (p)()).collect::<Vec<_>>();
 
     if !tcx.sess.opts.debugging_opts.no_interleave_lints {
@@ -461,7 +476,7 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b
 }
 
 /// Performs lint checking on a crate.
-pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
+pub fn check_crate<'tcx, T: LateLintPass<'tcx>>(
     tcx: TyCtxt<'tcx>,
     builtin_lints: impl FnOnce() -> T + Send,
 ) {