Skip to content

Commit

Permalink
rustc: track the current ty::ParamEnv in lint::LateContext.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Jun 9, 2017
1 parent 76a5070 commit 8b1b05b
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 24 deletions.
48 changes: 36 additions & 12 deletions src/librustc/lint/context.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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,

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
});
})
}

Expand Down Expand Up @@ -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);
});
});
}

Expand Down Expand Up @@ -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),
};
Expand Down
19 changes: 8 additions & 11 deletions src/librustc_lint/builtin.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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;
}
}
Expand All @@ -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,
}
Expand All @@ -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 {
Expand All @@ -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| {
Expand Down Expand Up @@ -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, \
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_lint/types.rs
Expand Up @@ -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)
Expand Down

0 comments on commit 8b1b05b

Please sign in to comment.