]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/lint/builtin.rs
auto merge of #15999 : Kimundi/rust/fix_folder, r=nikomatsakis
[rust.git] / src / librustc / lint / builtin.rs
index 0ab3d50cfbc3da3b9b7db5edb600dcba316ba235..1667f2b6d5f0a7ec9cc17f1cc5e6f3ec27bc4661 100644 (file)
 use middle::typeck::astconv::ast_ty_to_ty;
 use middle::typeck::infer;
 use middle::{typeck, ty, def, pat_util, stability};
-use util::ppaux::{ty_to_str};
+use util::ppaux::{ty_to_string};
 use util::nodemap::NodeSet;
 use lint::{Context, LintPass, LintArray};
 
 use std::cmp;
 use std::collections::HashMap;
-use std::i16;
-use std::i32;
-use std::i64;
-use std::i8;
-use std::u16;
-use std::u32;
-use std::u64;
-use std::u8;
+use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
 use std::gc::Gc;
 use syntax::abi;
 use syntax::ast_map;
@@ -214,7 +207,21 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
                                          "literal out of range for its type");
                         }
                     },
-
+                    ty::ty_float(t) => {
+                        let (min, max) = float_ty_range(t);
+                        let lit_val: f64 = match lit.node {
+                            ast::LitFloat(ref v, _) |
+                            ast::LitFloatUnsuffixed(ref v) => match from_str(v.get()) {
+                                Some(f) => f,
+                                None => return
+                            },
+                            _ => fail!()
+                        };
+                        if lit_val < min || lit_val > max {
+                            cx.span_lint(TYPE_OVERFLOW, e.span,
+                                         "literal out of range for its type");
+                        }
+                    },
                     _ => ()
                 };
             },
@@ -265,6 +272,13 @@ fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) {
             }
         }
 
+        fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) {
+            match float_ty {
+                ast::TyF32  => (f32::MIN_VALUE as f64, f32::MAX_VALUE as f64),
+                ast::TyF64  => (f64::MIN_VALUE,        f64::MAX_VALUE)
+            }
+        }
+
         fn check_limits(tcx: &ty::ctxt, binop: ast::BinOp,
                         l: &ast::Expr, r: &ast::Expr) -> bool {
             let (lit, expr, swap) = match (&l.node, &r.node) {
@@ -344,9 +358,9 @@ fn check_ty(cx: &Context, ty: &ast::Ty) {
                         def::DefTy(def_id) => {
                             if !adt::is_ffi_safe(cx.tcx, def_id) {
                                 cx.span_lint(CTYPES, ty.span,
-                                             "found enum type without foreign-function-safe \
-                                              representation annotation in foreign module");
-                                // hmm... this message could be more helpful
+                                             "found enum type without foreign-function-safe
+                                             representation annotation in foreign module, consider \
+                                             adding a #[repr(...)] attribute to the enumeration");
                             }
                         }
                         _ => ()
@@ -412,14 +426,14 @@ fn check_heap_type(&self, cx: &Context, span: Span, ty: ty::t) {
         });
 
         if n_uniq > 0 {
-            let s = ty_to_str(cx.tcx, ty);
+            let s = ty_to_string(cx.tcx, ty);
             let m = format!("type uses owned (Box type) pointers: {}", s);
             cx.span_lint(OWNED_HEAP_MEMORY, span, m.as_slice());
             cx.span_lint(HEAP_MEMORY, span, m.as_slice());
         }
 
         if n_box > 0 {
-            let s = ty_to_str(cx.tcx, ty);
+            let s = ty_to_string(cx.tcx, ty);
             let m = format!("type uses managed (@ type) pointers: {}", s);
             cx.span_lint(MANAGED_HEAP_MEMORY, span, m.as_slice());
             cx.span_lint(HEAP_MEMORY, span, m.as_slice());
@@ -575,12 +589,12 @@ fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) {
         ];
 
         static CRATE_ATTRS: &'static [&'static str] = &[
+            "crate_name",
             "crate_type",
             "feature",
             "no_start",
             "no_main",
             "no_std",
-            "crate_id",
             "desc",
             "comment",
             "license",
@@ -669,22 +683,13 @@ fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
                 if ast_util::is_local(did) {
                     match cx.tcx.map.get(did.node) {
                         ast_map::NodeItem(it) => {
-                            if attr::contains_name(it.attrs.as_slice(),
-                                                   "must_use") {
-                                cx.span_lint(UNUSED_MUST_USE, s.span,
-                                             "unused result which must be used");
-                                warned = true;
-                            }
+                            warned |= check_must_use(cx, it.attrs.as_slice(), s.span);
                         }
                         _ => {}
                     }
                 } else {
                     csearch::get_item_attrs(&cx.sess().cstore, did, |attrs| {
-                        if attr::contains_name(attrs.as_slice(), "must_use") {
-                            cx.span_lint(UNUSED_MUST_USE, s.span,
-                                         "unused result which must be used");
-                            warned = true;
-                        }
+                        warned |= check_must_use(cx, attrs.as_slice(), s.span);
                     });
                 }
             }
@@ -693,6 +698,25 @@ fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
         if !warned {
             cx.span_lint(UNUSED_RESULT, s.span, "unused result");
         }
+
+        fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool {
+            for attr in attrs.iter() {
+                if attr.check_name("must_use") {
+                    let mut msg = "unused result which must be used".to_string();
+                    // check for #[must_use="..."]
+                    match attr.value_str() {
+                        None => {}
+                        Some(s) => {
+                            msg.push_str(": ");
+                            msg.push_str(s.get());
+                        }
+                    }
+                    cx.span_lint(UNUSED_MUST_USE, sp, msg.as_slice());
+                    return true;
+                }
+            }
+            false
+        }
     }
 }
 
@@ -734,6 +758,11 @@ fn check_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
             }
         }
 
+        let has_extern_repr = it.attrs.iter().fold(attr::ReprAny, |acc, attr| {
+            attr::find_repr_attr(cx.tcx.sess.diagnostic(), attr, acc)
+        }) == attr::ReprExtern;
+        if has_extern_repr { return }
+
         match it.node {
             ast::ItemTy(..) | ast::ItemStruct(..) => {
                 check_case(cx, "type", it.ident, it.span)
@@ -1114,7 +1143,7 @@ fn check_unused_mut_pat(&self, cx: &Context, pats: &[Gc<ast::Pat>]) {
                 match mode {
                     ast::BindByValue(ast::MutMutable) => {
                         if !token::get_ident(ident).get().starts_with("_") {
-                            mutables.insert_or_update_with(ident.name as uint,
+                            mutables.insert_or_update_with(ident.name.uint(),
                                 vec!(id), |_, old| { old.push(id); });
                         }
                     }
@@ -1404,6 +1433,9 @@ fn get_lints(&self) -> LintArray {
     }
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        // if the expression was produced by a macro expansion,
+        if e.span.expn_info.is_some() { return }
+
         let id = match e.node {
             ast::ExprPath(..) | ast::ExprStruct(..) => {
                 match cx.tcx.def_map.borrow().find(&e.id) {
@@ -1419,6 +1451,9 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
                             typeck::MethodStatic(def_id) => {
                                 def_id
                             }
+                            typeck::MethodStaticUnboxedClosure(def_id) => {
+                                def_id
+                            }
                             typeck::MethodParam(typeck::MethodParam {
                                 trait_id: trait_id,
                                 method_num: index,