about summary refs log tree commit diff
path: root/src/librustc_lint
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2015-07-31 00:04:06 -0700
committerNick Cameron <ncameron@mozilla.com>2015-09-03 10:02:36 +1200
commitfacdf2ebb1dce9400a8c8ef0d85d7d278654effb (patch)
tree3ba46bd98df35b4b5d1bc5f1ba491d14adb6f373 /src/librustc_lint
parentcfd76b364cd01695517467299618ef63f1c0cc07 (diff)
downloadrust-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.rs182
-rw-r--r--src/librustc_lint/lib.rs1
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;