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};
/// 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,
}
}
+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
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);
+ });
})
}
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);
+ });
});
}
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),
};
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;
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;
}
}
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;
}
}
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,
}
// 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 {
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| {
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, \