diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2015-07-31 00:04:06 -0700 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2015-09-03 10:02:36 +1200 |
| commit | facdf2ebb1dce9400a8c8ef0d85d7d278654effb (patch) | |
| tree | 3ba46bd98df35b4b5d1bc5f1ba491d14adb6f373 /src/librustc_lint | |
| parent | cfd76b364cd01695517467299618ef63f1c0cc07 (diff) | |
| download | rust-facdf2ebb1dce9400a8c8ef0d85d7d278654effb.tar.gz rust-facdf2ebb1dce9400a8c8ef0d85d7d278654effb.zip | |
Add an intital HIR and lowering step
Diffstat (limited to 'src/librustc_lint')
| -rw-r--r-- | src/librustc_lint/builtin.rs | 182 | ||||
| -rw-r--r-- | src/librustc_lint/lib.rs | 1 |
2 files changed, 109 insertions, 74 deletions
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c723bad5265..40f7fbbdef7 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -35,7 +35,7 @@ use middle::subst::Substs; use middle::ty::{self, Ty}; use middle::const_eval::{eval_const_expr_partial, ConstVal}; use middle::const_eval::EvalHint::ExprTypeChecked; -use rustc::ast_map; +use rustc::front::map as hir_map; use util::nodemap::{FnvHashMap, FnvHashSet, NodeSet}; use lint::{Level, Context, LintPass, LintArray, Lint}; @@ -53,6 +53,14 @@ use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU use syntax::ptr::P; use syntax::visit::{self, FnKind, Visitor}; +use rustc_front::lowering::{lower_expr, lower_block, lower_item, lower_path, lower_pat, + lower_trait_ref}; +use rustc_front::hir; +use rustc_front::attr as front_attr; +use rustc_front::attr::AttrMetaMethods as FrontAttrMetaMethods; +use rustc_front::visit::Visitor as HirVisitor; +use rustc_front::visit as hir_visit; + // hardwired lints from librustc pub use lint::builtin::*; @@ -129,7 +137,7 @@ impl LintPass for TypeLimits { check_unsigned_negation_feature(cx, e.span); }, ast::LitInt(_, ast::UnsuffixedIntLit(_)) => { - if let ty::TyUint(_) = cx.tcx.expr_ty(e).sty { + if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty { check_unsigned_negation_feature(cx, e.span); } }, @@ -137,7 +145,7 @@ impl LintPass for TypeLimits { } }, _ => { - let t = cx.tcx.expr_ty(&**expr); + let t = cx.tcx.node_id_to_type(expr.id); match t.sty { ty::TyUint(_) => { check_unsigned_negation_feature(cx, e.span); @@ -161,7 +169,7 @@ impl LintPass for TypeLimits { } if is_shift_binop(binop.node) { - let opt_ty_bits = match cx.tcx.expr_ty(&**l).sty { + let opt_ty_bits = match cx.tcx.node_id_to_type(l.id).sty { ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)), ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)), _ => None @@ -172,7 +180,8 @@ impl LintPass for TypeLimits { if let ast::LitInt(shift, _) = lit.node { shift >= bits } else { false } } else { - match eval_const_expr_partial(cx.tcx, &**r, ExprTypeChecked) { + let r = lower_expr(r); + match eval_const_expr_partial(cx.tcx, &r, ExprTypeChecked) { Ok(ConstVal::Int(shift)) => { shift as u64 >= bits }, Ok(ConstVal::Uint(shift)) => { shift >= bits }, _ => { false } @@ -186,12 +195,12 @@ impl LintPass for TypeLimits { } }, ast::ExprLit(ref lit) => { - match cx.tcx.expr_ty(e).sty { + match cx.tcx.node_id_to_type(e.id).sty { ty::TyInt(t) => { match lit.node { ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) | ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => { - let int_type = if let ast::TyIs = t { + let int_type = if let hir::TyIs = t { cx.sess().target.int_type } else { t @@ -212,7 +221,7 @@ impl LintPass for TypeLimits { }; }, ty::TyUint(t) => { - let uint_type = if let ast::TyUs = t { + let uint_type = if let hir::TyUs = t { cx.sess().target.uint_type } else { t @@ -275,50 +284,50 @@ impl LintPass for TypeLimits { // for isize & usize, be conservative with the warnings, so that the // warnings are consistent between 32- and 64-bit platforms - fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) { + fn int_ty_range(int_ty: hir::IntTy) -> (i64, i64) { match int_ty { - ast::TyIs => (i64::MIN, i64::MAX), - ast::TyI8 => (i8::MIN as i64, i8::MAX as i64), - ast::TyI16 => (i16::MIN as i64, i16::MAX as i64), - ast::TyI32 => (i32::MIN as i64, i32::MAX as i64), - ast::TyI64 => (i64::MIN, i64::MAX) + hir::TyIs => (i64::MIN, i64::MAX), + hir::TyI8 => (i8::MIN as i64, i8::MAX as i64), + hir::TyI16 => (i16::MIN as i64, i16::MAX as i64), + hir::TyI32 => (i32::MIN as i64, i32::MAX as i64), + hir::TyI64 => (i64::MIN, i64::MAX) } } - fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) { + fn uint_ty_range(uint_ty: hir::UintTy) -> (u64, u64) { match uint_ty { - ast::TyUs => (u64::MIN, u64::MAX), - ast::TyU8 => (u8::MIN as u64, u8::MAX as u64), - ast::TyU16 => (u16::MIN as u64, u16::MAX as u64), - ast::TyU32 => (u32::MIN as u64, u32::MAX as u64), - ast::TyU64 => (u64::MIN, u64::MAX) + hir::TyUs => (u64::MIN, u64::MAX), + hir::TyU8 => (u8::MIN as u64, u8::MAX as u64), + hir::TyU16 => (u16::MIN as u64, u16::MAX as u64), + hir::TyU32 => (u32::MIN as u64, u32::MAX as u64), + hir::TyU64 => (u64::MIN, u64::MAX) } } - fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) { + fn float_ty_range(float_ty: hir::FloatTy) -> (f64, f64) { match float_ty { - ast::TyF32 => (f32::MIN as f64, f32::MAX as f64), - ast::TyF64 => (f64::MIN, f64::MAX) + hir::TyF32 => (f32::MIN as f64, f32::MAX as f64), + hir::TyF64 => (f64::MIN, f64::MAX) } } - fn int_ty_bits(int_ty: ast::IntTy, target_int_ty: ast::IntTy) -> u64 { + fn int_ty_bits(int_ty: hir::IntTy, target_int_ty: hir::IntTy) -> u64 { match int_ty { - ast::TyIs => int_ty_bits(target_int_ty, target_int_ty), - ast::TyI8 => i8::BITS as u64, - ast::TyI16 => i16::BITS as u64, - ast::TyI32 => i32::BITS as u64, - ast::TyI64 => i64::BITS as u64 + hir::TyIs => int_ty_bits(target_int_ty, target_int_ty), + hir::TyI8 => i8::BITS as u64, + hir::TyI16 => i16::BITS as u64, + hir::TyI32 => i32::BITS as u64, + hir::TyI64 => i64::BITS as u64 } } - fn uint_ty_bits(uint_ty: ast::UintTy, target_uint_ty: ast::UintTy) -> u64 { + fn uint_ty_bits(uint_ty: hir::UintTy, target_uint_ty: hir::UintTy) -> u64 { match uint_ty { - ast::TyUs => uint_ty_bits(target_uint_ty, target_uint_ty), - ast::TyU8 => u8::BITS as u64, - ast::TyU16 => u16::BITS as u64, - ast::TyU32 => u32::BITS as u64, - ast::TyU64 => u64::BITS as u64 + hir::TyUs => uint_ty_bits(target_uint_ty, target_uint_ty), + hir::TyU8 => u8::BITS as u64, + hir::TyU16 => u16::BITS as u64, + hir::TyU32 => u32::BITS as u64, + hir::TyU64 => u64::BITS as u64 } } @@ -336,7 +345,7 @@ impl LintPass for TypeLimits { } else { binop }; - match tcx.expr_ty(expr).sty { + match tcx.node_id_to_type(expr.id).sty { ty::TyInt(int_ty) => { let (min, max) = int_ty_range(int_ty); let lit_val: i64 = match lit.node { @@ -466,7 +475,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match ty.sty { ty::TyStruct(def, substs) => { - if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) { + if !cx.lookup_repr_hints(def.did).contains(&front_attr::ReprExtern) { return FfiUnsafe( "found struct without foreign-function-safe \ representation annotation in foreign module, \ @@ -550,11 +559,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } - ty::TyInt(ast::TyIs) => { + ty::TyInt(hir::TyIs) => { FfiUnsafe("found Rust type `isize` in foreign module, while \ `libc::c_int` or `libc::c_long` should be used") } - ty::TyUint(ast::TyUs) => { + ty::TyUint(hir::TyUs) => { FfiUnsafe("found Rust type `usize` in foreign module, while \ `libc::c_uint` or `libc::c_ulong` should be used") } @@ -784,7 +793,7 @@ impl LintPass for BoxPointers { } fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - let ty = cx.tcx.expr_ty(e); + let ty = cx.tcx.node_id_to_type(e.id); self.check_heap_type(cx, e.span, ty); } } @@ -799,17 +808,17 @@ struct RawPtrDeriveVisitor<'a, 'tcx: 'a> { cx: &'a Context<'a, 'tcx> } -impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: &ast::Ty) { +impl<'a, 'tcx, 'v> HirVisitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> { + fn visit_ty(&mut self, ty: &hir::Ty) { const MSG: &'static str = "use of `#[derive]` with a raw pointer"; - if let ast::TyPtr(..) = ty.node { + if let hir::TyPtr(..) = ty.node { self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG); } - visit::walk_ty(self, ty); + hir_visit::walk_ty(self, ty); } // explicit override to a no-op to reduce code bloat - fn visit_expr(&mut self, _: &ast::Expr) {} - fn visit_block(&mut self, _: &ast::Block) {} + fn visit_expr(&mut self, _: &hir::Expr) {} + fn visit_block(&mut self, _: &hir::Block) {} } pub struct RawPointerDerive { @@ -833,8 +842,9 @@ impl LintPass for RawPointerDerive { if !attr::contains_name(&item.attrs, "automatically_derived") { return; } + let item = lower_item(item); let did = match item.node { - ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => { + hir::ItemImpl(_, _, _, ref t_ref_opt, _, _) => { // Deriving the Copy trait does not cause a warning if let &Some(ref trait_ref) = t_ref_opt { let def_id = cx.tcx.trait_ref_to_def_id(trait_ref); @@ -855,16 +865,16 @@ impl LintPass for RawPointerDerive { return; } let item = match cx.tcx.map.find(did.node) { - Some(ast_map::NodeItem(item)) => item, + Some(hir_map::NodeItem(item)) => item, _ => return, }; if !self.checked_raw_pointers.insert(item.id) { return; } match item.node { - ast::ItemStruct(..) | ast::ItemEnum(..) => { + hir::ItemStruct(..) | hir::ItemEnum(..) => { let mut visitor = RawPtrDeriveVisitor { cx: cx }; - visit::walk_item(&mut visitor, &*item); + hir_visit::walk_item(&mut visitor, &item); } _ => {} } @@ -989,14 +999,15 @@ impl LintPass for UnusedResults { return; } - let t = cx.tcx.expr_ty(expr); + let expr = lower_expr(expr); + let t = cx.tcx.expr_ty(&expr); let warned = match t.sty { ty::TyTuple(ref tys) if tys.is_empty() => return, ty::TyBool => return, ty::TyStruct(def, _) | ty::TyEnum(def, _) => { if def.did.is_local() { - if let ast_map::NodeItem(it) = cx.tcx.map.get(def.did.node) { + if let hir_map::NodeItem(it) = cx.tcx.map.get(def.did.node) { check_must_use(cx, &it.attrs, s.span) } else { false @@ -1012,7 +1023,7 @@ impl LintPass for UnusedResults { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } - fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool { + fn check_must_use(cx: &Context, attrs: &[hir::Attribute], sp: Span) -> bool { for attr in attrs { if attr.check_name("must_use") { let mut msg = "unused result which must be used".to_string(); @@ -1642,9 +1653,9 @@ impl UnusedMut { let mut mutables = FnvHashMap(); for p in pats { - pat_util::pat_bindings(&cx.tcx.def_map, &**p, |mode, id, _, path1| { + pat_util::pat_bindings(&cx.tcx.def_map, &lower_pat(p), |mode, id, _, path1| { let ident = path1.node; - if let ast::BindByValue(ast::MutMutable) = mode { + if let hir::BindByValue(hir::MutMutable) = mode { if !ident.name.as_str().starts_with("_") { match mutables.entry(ident.name.usize()) { Vacant(entry) => { entry.insert(vec![id]); }, @@ -1718,11 +1729,11 @@ impl LintPass for UnusedAllocation { if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) { if let ty::AdjustDerefRef(ty::AutoDerefRef { ref autoref, .. }) = *adjustment { match autoref { - &Some(ty::AutoPtr(_, ast::MutImmutable)) => { + &Some(ty::AutoPtr(_, hir::MutImmutable)) => { cx.span_lint(UNUSED_ALLOCATION, e.span, "unnecessary allocation, use & instead"); } - &Some(ty::AutoPtr(_, ast::MutMutable)) => { + &Some(ty::AutoPtr(_, hir::MutMutable)) => { cx.span_lint(UNUSED_ALLOCATION, e.span, "unnecessary allocation, use &mut instead"); } @@ -1862,9 +1873,9 @@ impl LintPass for MissingDoc { ast::ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) => { // If the trait is private, add the impl items to private_traits so they don't get // reported for missing docs. - let real_trait = cx.tcx.trait_ref_to_def_id(trait_ref); + let real_trait = cx.tcx.trait_ref_to_def_id(&lower_trait_ref(trait_ref)); match cx.tcx.map.find(real_trait.node) { - Some(ast_map::NodeItem(item)) => if item.vis == ast::Visibility::Inherited { + Some(hir_map::NodeItem(item)) => if item.vis == hir::Visibility::Inherited { for itm in impl_items { self.private_traits.insert(itm.id); } @@ -2087,29 +2098,51 @@ impl Stability { } } +fn hir_to_ast_stability(stab: &front_attr::Stability) -> attr::Stability { + attr::Stability { + level: match stab.level { + front_attr::Unstable => attr::Unstable, + front_attr::Stable => attr::Stable, + }, + feature: stab.feature.clone(), + since: stab.since.clone(), + deprecated_since: stab.deprecated_since.clone(), + reason: stab.reason.clone(), + issue: stab.issue, + } +} + impl LintPass for Stability { fn get_lints(&self) -> LintArray { lint_array!(DEPRECATED) } fn check_item(&mut self, cx: &Context, item: &ast::Item) { - stability::check_item(cx.tcx, item, false, - &mut |id, sp, stab| self.lint(cx, id, sp, stab)); + stability::check_item(cx.tcx, &lower_item(item), false, + &mut |id, sp, stab| + self.lint(cx, id, sp, + &stab.map(|s| hir_to_ast_stability(s)).as_ref())); } fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - stability::check_expr(cx.tcx, e, - &mut |id, sp, stab| self.lint(cx, id, sp, stab)); + stability::check_expr(cx.tcx, &lower_expr(e), + &mut |id, sp, stab| + self.lint(cx, id, sp, + &stab.map(|s| hir_to_ast_stability(s)).as_ref())); } fn check_path(&mut self, cx: &Context, path: &ast::Path, id: ast::NodeId) { - stability::check_path(cx.tcx, path, id, - &mut |id, sp, stab| self.lint(cx, id, sp, stab)); + stability::check_path(cx.tcx, &lower_path(path), id, + &mut |id, sp, stab| + self.lint(cx, id, sp, + &stab.map(|s| hir_to_ast_stability(s)).as_ref())); } fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) { - stability::check_pat(cx.tcx, pat, - &mut |id, sp, stab| self.lint(cx, id, sp, stab)) + stability::check_pat(cx.tcx, &lower_pat(pat), + &mut |id, sp, stab| + self.lint(cx, id, sp, + &stab.map(|s| hir_to_ast_stability(s)).as_ref())); } } @@ -2168,7 +2201,7 @@ impl LintPass for UnconditionalRecursion { // to have behaviour like the above, rather than // e.g. accidentally recurring after an assert. - let cfg = cfg::CFG::new(cx.tcx, blk); + let cfg = cfg::CFG::new(cx.tcx, &lower_block(blk)); let mut work_queue = vec![cfg.entry]; let mut reached_exit_without_self_call = false; @@ -2248,7 +2281,7 @@ impl LintPass for UnconditionalRecursion { fn_id: ast::NodeId, id: ast::NodeId) -> bool { match tcx.map.get(id) { - ast_map::NodeExpr(&ast::Expr { node: ast::ExprCall(ref callee, _), .. }) => { + hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => { tcx.def_map.borrow().get(&callee.id) .map_or(false, |def| def.def_id() == DefId::local(fn_id)) } @@ -2283,7 +2316,7 @@ impl LintPass for UnconditionalRecursion { // Check for calls to methods via explicit paths (e.g. `T::method()`). match tcx.map.get(id) { - ast_map::NodeExpr(&ast::Expr { node: ast::ExprCall(ref callee, _), .. }) => { + hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => { match tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()) { Some(def::DefMethod(def_id)) => { let no_substs = &ty::ItemSubsts::empty(); @@ -2479,12 +2512,13 @@ impl LintPass for MutableTransmutes { fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) { use syntax::abi::RustIntrinsic; + let msg = "mutating transmuted &mut T from &T may cause undefined behavior,\ consider instead using an UnsafeCell"; match get_transmute_from_to(cx, expr) { Some((&ty::TyRef(_, from_mt), &ty::TyRef(_, to_mt))) => { - if to_mt.mutbl == ast::Mutability::MutMutable - && from_mt.mutbl == ast::Mutability::MutImmutable { + if to_mt.mutbl == hir::Mutability::MutMutable + && from_mt.mutbl == hir::Mutability::MutImmutable { cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg); } } @@ -2497,7 +2531,7 @@ impl LintPass for MutableTransmutes { ast::ExprPath(..) => (), _ => return None } - if let def::DefFn(did, _) = cx.tcx.resolve_expr(expr) { + if let def::DefFn(did, _) = cx.tcx.resolve_expr(&lower_expr(expr)) { if !def_id_is_transmute(cx, did) { return None; } @@ -2584,7 +2618,7 @@ impl LintPass for DropWithReprExtern { ty::TyStruct(self_type_def, _) => { let self_type_did = self_type_def.did; let hints = ctx.tcx.lookup_repr_hints(self_type_did); - if hints.iter().any(|attr| *attr == attr::ReprExtern) && + if hints.iter().any(|attr| *attr == front_attr::ReprExtern) && self_type_def.dtor_kind().has_drop_flag() { let drop_impl_span = ctx.tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP); diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index d97f3dbb79b..517a3d13ddf 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -47,6 +47,7 @@ extern crate syntax; extern crate rustc; #[macro_use] extern crate log; +extern crate rustc_front; pub use rustc::lint as lint; pub use rustc::metadata as metadata; |
