about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-06-07 15:21:55 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-06-09 12:27:56 +0300
commit8b1b05bcebc1c6c8c2a7acdaa1970167c5b98cb4 (patch)
treecc03b3870ce8fc531c476239d48127b3acd061b0
parent76a50706a8e19ecc253bb2a5749b1a3f4f5dc89d (diff)
downloadrust-8b1b05bcebc1c6c8c2a7acdaa1970167c5b98cb4.tar.gz
rust-8b1b05bcebc1c6c8c2a7acdaa1970167c5b98cb4.zip
rustc: track the current ty::ParamEnv in lint::LateContext.
-rw-r--r--src/librustc/lint/context.rs48
-rw-r--r--src/librustc_lint/builtin.rs19
-rw-r--r--src/librustc_lint/types.rs2
3 files changed, 45 insertions, 24 deletions
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index b14f549cbf6..40734469718 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -27,6 +27,7 @@ use self::TargetLint::*;
 
 use dep_graph::DepNode;
 use middle::privacy::AccessLevels;
+use traits::Reveal;
 use ty::{self, TyCtxt};
 use session::{config, early_error, Session};
 use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource};
@@ -411,6 +412,9 @@ pub struct LateContext<'a, 'tcx: 'a> {
     /// Side-tables for the body we are in.
     pub tables: &'a ty::TypeckTables<'tcx>,
 
+    /// Parameter environment for the item we are in.
+    pub param_env: ty::ParamEnv<'tcx>,
+
     /// Items accessible from the crate being checked.
     pub access_levels: &'a AccessLevels,
 
@@ -866,6 +870,17 @@ impl<'a> LintContext<'a> for EarlyContext<'a> {
     }
 }
 
+impl<'a, 'tcx> LateContext<'a, 'tcx> {
+    fn with_param_env<F>(&mut self, id: ast::NodeId, f: F)
+        where F: FnOnce(&mut Self),
+    {
+        let old_param_env = self.param_env;
+        self.param_env = self.tcx.param_env(self.tcx.hir.local_def_id(id));
+        f(self);
+        self.param_env = old_param_env;
+    }
+}
+
 impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
     /// Because lints are scoped lexically, we want to walk nested
     /// items in the context of the outer item, so enable
@@ -899,17 +914,21 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
 
     fn visit_item(&mut self, it: &'tcx hir::Item) {
         self.with_lint_attrs(&it.attrs, |cx| {
-            run_lints!(cx, check_item, late_passes, it);
-            hir_visit::walk_item(cx, it);
-            run_lints!(cx, check_item_post, late_passes, it);
+            cx.with_param_env(it.id, |cx| {
+                run_lints!(cx, check_item, late_passes, it);
+                hir_visit::walk_item(cx, it);
+                run_lints!(cx, check_item_post, late_passes, it);
+            });
         })
     }
 
     fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) {
         self.with_lint_attrs(&it.attrs, |cx| {
-            run_lints!(cx, check_foreign_item, late_passes, it);
-            hir_visit::walk_foreign_item(cx, it);
-            run_lints!(cx, check_foreign_item_post, late_passes, it);
+            cx.with_param_env(it.id, |cx| {
+                run_lints!(cx, check_foreign_item, late_passes, it);
+                hir_visit::walk_foreign_item(cx, it);
+                run_lints!(cx, check_foreign_item_post, late_passes, it);
+            });
         })
     }
 
@@ -1023,17 +1042,21 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
         self.with_lint_attrs(&trait_item.attrs, |cx| {
-            run_lints!(cx, check_trait_item, late_passes, trait_item);
-            hir_visit::walk_trait_item(cx, trait_item);
-            run_lints!(cx, check_trait_item_post, late_passes, trait_item);
+            cx.with_param_env(trait_item.id, |cx| {
+                run_lints!(cx, check_trait_item, late_passes, trait_item);
+                hir_visit::walk_trait_item(cx, trait_item);
+                run_lints!(cx, check_trait_item_post, late_passes, trait_item);
+            });
         });
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         self.with_lint_attrs(&impl_item.attrs, |cx| {
-            run_lints!(cx, check_impl_item, late_passes, impl_item);
-            hir_visit::walk_impl_item(cx, impl_item);
-            run_lints!(cx, check_impl_item_post, late_passes, impl_item);
+            cx.with_param_env(impl_item.id, |cx| {
+                run_lints!(cx, check_impl_item, late_passes, impl_item);
+                hir_visit::walk_impl_item(cx, impl_item);
+                run_lints!(cx, check_impl_item_post, late_passes, impl_item);
+            });
         });
     }
 
@@ -1327,6 +1350,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut cx = LateContext {
         tcx: tcx,
         tables: &ty::TypeckTables::empty(),
+        param_env: ty::ParamEnv::empty(Reveal::UserFacing),
         access_levels: access_levels,
         lint_sess: LintSession::new(&tcx.sess.lint_store),
     };
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 3a4729e6454..bccdac91423 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -32,7 +32,7 @@ use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
 use rustc::cfg;
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty};
 use rustc::traits::{self, Reveal};
 use rustc::hir::map as hir_map;
 use util::nodemap::NodeSet;
@@ -893,7 +893,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
             for adjustment in cx.tables.expr_adjustments(expr) {
                 if let Adjust::Deref(Some(deref)) = adjustment.kind {
                     let (def_id, substs) = deref.method_call(cx.tcx, source);
-                    if method_call_refers_to_method(cx.tcx, method, def_id, substs, id) {
+                    if method_call_refers_to_method(cx, method, def_id, substs, id) {
                         return true;
                     }
                 }
@@ -904,7 +904,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
             if cx.tables.is_method_call(expr) {
                 let def_id = cx.tables.type_dependent_defs[&id].def_id();
                 let substs = cx.tables.node_substs(id);
-                if method_call_refers_to_method(cx.tcx, method, def_id, substs, id) {
+                if method_call_refers_to_method(cx, method, def_id, substs, id) {
                     return true;
                 }
             }
@@ -920,8 +920,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
                     match def {
                         Def::Method(def_id) => {
                             let substs = cx.tables.node_substs(callee.id);
-                            method_call_refers_to_method(
-                                cx.tcx, method, def_id, substs, id)
+                            method_call_refers_to_method(cx, method, def_id, substs, id)
                         }
                         _ => false,
                     }
@@ -932,12 +931,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
 
         // Check if the method call to the method with the ID `callee_id`
         // and instantiated with `callee_substs` refers to method `method`.
-        fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        fn method_call_refers_to_method<'a, 'tcx>(cx: &LateContext<'a, 'tcx>,
                                                   method: &ty::AssociatedItem,
                                                   callee_id: DefId,
                                                   callee_substs: &Substs<'tcx>,
                                                   expr_id: ast::NodeId)
                                                   -> bool {
+            let tcx = cx.tcx;
             let callee_item = tcx.associated_item(callee_id);
 
             match callee_item.container {
@@ -951,10 +951,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
                     let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs);
                     let trait_ref = ty::Binder(trait_ref);
                     let span = tcx.hir.span(expr_id);
-                    let param_env = tcx.param_env(method.def_id);
                     let obligation =
                         traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
-                                                param_env,
+                                                cx.param_env,
                                                 trait_ref.to_poly_trait_predicate());
 
                     tcx.infer_ctxt(()).enter(|infcx| {
@@ -1224,11 +1223,9 @@ impl LintPass for UnionsWithDropFields {
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
     fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) {
         if let hir::ItemUnion(ref vdata, _) = item.node {
-            let item_def_id = ctx.tcx.hir.local_def_id(item.id);
-            let param_env = ctx.tcx.param_env(item_def_id);
             for field in vdata.fields() {
                 let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id));
-                if field_ty.needs_drop(ctx.tcx, param_env) {
+                if field_ty.needs_drop(ctx.tcx, ctx.param_env) {
                     ctx.span_lint(UNIONS_WITH_DROP_FIELDS,
                                   field.span,
                                   "union contains a field with possibly non-trivial drop code, \
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 3019165bfbf..32bde42b526 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -725,7 +725,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
                 // sizes only make sense for non-generic types
                 let item_def_id = cx.tcx.hir.local_def_id(it.id);
                 let t = cx.tcx.type_of(item_def_id);
-                let param_env = cx.tcx.param_env(item_def_id).reveal_all();
+                let param_env = cx.param_env.reveal_all();
                 let ty = cx.tcx.erase_regions(&t);
                 let layout = ty.layout(cx.tcx, param_env).unwrap_or_else(|e| {
                     bug!("failed to get layout for `{}`: {}", t, e)