about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-04-09 13:16:27 -0400
committerAlex Crichton <alex@alexcrichton.com>2013-04-09 13:48:44 -0400
commit3e67085d7a590ef360e7c85cc6c3931bae6df6a5 (patch)
tree0c70af514d73c4763f8549f77e14a3434397cfbe
parent5641777318239926363207f690bf265f7514a63c (diff)
downloadrust-3e67085d7a590ef360e7c85cc6c3931bae6df6a5.tar.gz
rust-3e67085d7a590ef360e7c85cc6c3931bae6df6a5.zip
Allow lint modes to be used on unused variables and dead assignments
-rw-r--r--src/librustc/middle/lint.rs19
-rw-r--r--src/librustc/middle/liveness.rs79
-rw-r--r--src/test/compile-fail/liveness-unused.rs44
3 files changed, 82 insertions, 60 deletions
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index b4aff91ed5b..0adf4b87f3a 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -83,9 +83,8 @@ pub enum lint {
 
     legacy_modes,
 
-    // FIXME(#3266)--make liveness warnings lintable
-    // unused_variable,
-    // dead_assignment
+    unused_variable,
+    dead_assignment,
 }
 
 pub fn level_to_str(lv: level) -> &'static str {
@@ -257,21 +256,19 @@ pub fn get_lint_dict() -> LintDict {
             default: deny
         }),
 
-        /* FIXME(#3266)--make liveness warnings lintable
-        (@~"unused_variable",
-         @LintSpec {
+        (~"unused_variable",
+         LintSpec {
             lint: unused_variable,
             desc: "detect variables which are not used in any way",
             default: warn
-         }),
+        }),
 
-        (@~"dead_assignment",
-         @LintSpec {
+        (~"dead_assignment",
+         LintSpec {
             lint: dead_assignment,
             desc: "detect assignments that will never be read",
             default: warn
-         }),
-        */
+        }),
     ];
     let mut map = HashMap::new();
     do vec::consume(v) |_, (k, v)| {
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 01598b11851..3a649e7cc3b 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -105,6 +105,7 @@
 
 use core::prelude::*;
 
+use middle::lint::{unused_variable, dead_assignment};
 use middle::pat_util;
 use middle::ty;
 use middle::typeck;
@@ -118,6 +119,7 @@ use core::ptr;
 use core::to_str;
 use core::uint;
 use core::vec;
+use core::util::with;
 use syntax::ast::*;
 use syntax::codemap::span;
 use syntax::parse::token::special_idents;
@@ -169,6 +171,7 @@ pub fn check_crate(tcx: ty::ctxt,
         visit_local: visit_local,
         visit_expr: visit_expr,
         visit_arm: visit_arm,
+        visit_item: visit_item,
         .. *visit::default_visitor()
     });
 
@@ -177,7 +180,8 @@ pub fn check_crate(tcx: ty::ctxt,
                                    method_map,
                                    variable_moves_map,
                                    capture_map,
-                                   last_use_map);
+                                   last_use_map,
+                                   0);
     visit::visit_crate(*crate, initial_maps, visitor);
     tcx.sess.abort_if_errors();
     return last_use_map;
@@ -269,13 +273,16 @@ struct IrMaps {
     capture_info_map: HashMap<node_id, @~[CaptureInfo]>,
     var_kinds: ~[VarKind],
     lnks: ~[LiveNodeKind],
+
+    cur_item: node_id,
 }
 
 fn IrMaps(tcx: ty::ctxt,
           method_map: typeck::method_map,
           variable_moves_map: moves::VariableMovesMap,
           capture_map: moves::CaptureMap,
-          last_use_map: last_use_map)
+          last_use_map: last_use_map,
+          cur_item: node_id)
        -> IrMaps {
     IrMaps {
         tcx: tcx,
@@ -289,7 +296,8 @@ fn IrMaps(tcx: ty::ctxt,
         variable_map: HashMap::new(),
         capture_info_map: HashMap::new(),
         var_kinds: ~[],
-        lnks: ~[]
+        lnks: ~[],
+        cur_item: cur_item,
     }
 }
 
@@ -394,6 +402,12 @@ pub impl IrMaps {
     }
 }
 
+fn visit_item(item: @item, &&self: @mut IrMaps, v: vt<@mut IrMaps>) {
+    do with(&mut self.cur_item, item.id) {
+        visit::visit_item(item, self, v)
+    }
+}
+
 fn visit_fn(fk: &visit::fn_kind,
             decl: &fn_decl,
             body: &blk,
@@ -409,7 +423,8 @@ fn visit_fn(fk: &visit::fn_kind,
                               self.method_map,
                               self.variable_moves_map,
                               self.capture_map,
-                              self.last_use_map);
+                              self.last_use_map,
+                              self.cur_item);
 
     debug!("creating fn_maps: %x", ptr::addr_of(&(*fn_maps)) as uint);
 
@@ -692,17 +707,19 @@ pub impl Liveness {
         }
     }
 
-    fn pat_bindings(&self, pat: @pat, f: &fn(LiveNode, Variable, span)) {
+    fn pat_bindings(&self, pat: @pat,
+                    f: &fn(LiveNode, Variable, span, node_id)) {
         let def_map = self.tcx.def_map;
         do pat_util::pat_bindings(def_map, pat) |_bm, p_id, sp, _n| {
             let ln = self.live_node(p_id, sp);
             let var = self.variable(p_id, sp);
-            f(ln, var, sp);
+            f(ln, var, sp, p_id);
         }
     }
 
     fn arm_pats_bindings(&self,
-                         pats: &[@pat], f: &fn(LiveNode, Variable, span)) {
+                         pats: &[@pat],
+                         f: &fn(LiveNode, Variable, span, node_id)) {
         // only consider the first pattern; any later patterns must have
         // the same bindings, and we also consider the first pattern to be
         // the "authoratative" set of ids
@@ -718,7 +735,7 @@ pub impl Liveness {
     fn define_bindings_in_arm_pats(&self, pats: &[@pat],
                                    succ: LiveNode) -> LiveNode {
         let mut succ = succ;
-        do self.arm_pats_bindings(pats) |ln, var, _sp| {
+        do self.arm_pats_bindings(pats) |ln, var, _sp, _id| {
             self.init_from_succ(ln, succ);
             self.define(ln, var);
             succ = ln;
@@ -1509,8 +1526,8 @@ fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) {
         // should not be live at this point.
 
         debug!("check_local() with no initializer");
-        do self.pat_bindings(local.node.pat) |ln, var, sp| {
-            if !self.warn_about_unused(sp, ln, var) {
+        do self.pat_bindings(local.node.pat) |ln, var, sp, id| {
+            if !self.warn_about_unused(sp, id, ln, var) {
                 match self.live_on_exit(ln, var) {
                   None => { /* not live: good */ }
                   Some(lnk) => {
@@ -1528,8 +1545,8 @@ fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) {
 }
 
 fn check_arm(arm: &arm, &&self: @Liveness, vt: vt<@Liveness>) {
-    do self.arm_pats_bindings(arm.pats) |ln, var, sp| {
-        self.warn_about_unused(sp, ln, var);
+    do self.arm_pats_bindings(arm.pats) |ln, var, sp, id| {
+        self.warn_about_unused(sp, id, ln, var);
     }
     visit::visit_arm(arm, self, vt);
 }
@@ -1691,14 +1708,14 @@ pub impl Liveness {
                 let ln = self.live_node(expr.id, expr.span);
                 let var = self.variable(nid, expr.span);
                 self.check_for_reassignment(ln, var, expr.span);
-                self.warn_about_dead_assign(expr.span, ln, var);
+                self.warn_about_dead_assign(expr.span, expr.id, ln, var);
               }
               def => {
                 match relevant_def(def) {
                   Some(nid) => {
                     let ln = self.live_node(expr.id, expr.span);
                     let var = self.variable(nid, expr.span);
-                    self.warn_about_dead_assign(expr.span, ln, var);
+                    self.warn_about_dead_assign(expr.span, expr.id, ln, var);
                   }
                   None => {}
                 }
@@ -1715,7 +1732,7 @@ pub impl Liveness {
     }
 
     fn check_for_reassignments_in_pat(@self, pat: @pat) {
-        do self.pat_bindings(pat) |ln, var, sp| {
+        do self.pat_bindings(pat) |ln, var, sp, _id| {
             self.check_for_reassignment(ln, var, sp);
         }
     }
@@ -1861,21 +1878,21 @@ pub impl Liveness {
             do pat_util::pat_bindings(self.tcx.def_map, arg.pat)
                     |_bm, p_id, sp, _n| {
                 let var = self.variable(p_id, sp);
-                self.warn_about_unused(sp, entry_ln, var);
+                self.warn_about_unused(sp, p_id, entry_ln, var);
             }
         }
     }
 
     fn warn_about_unused_or_dead_vars_in_pat(@self, pat: @pat) {
-        do self.pat_bindings(pat) |ln, var, sp| {
-            if !self.warn_about_unused(sp, ln, var) {
-                self.warn_about_dead_assign(sp, ln, var);
+        do self.pat_bindings(pat) |ln, var, sp, id| {
+            if !self.warn_about_unused(sp, id, ln, var) {
+                self.warn_about_dead_assign(sp, id, ln, var);
             }
         }
     }
 
-    fn warn_about_unused(@self, sp: span, ln: LiveNode, var: Variable)
-                        -> bool {
+    fn warn_about_unused(@self, sp: span, id: node_id,
+                         ln: LiveNode, var: Variable) -> bool {
         if !self.used_on_entry(ln, var) {
             for self.should_warn(var).each |name| {
 
@@ -1889,14 +1906,14 @@ pub impl Liveness {
                 };
 
                 if is_assigned {
-                    // FIXME(#3266)--make liveness warnings lintable
-                    self.tcx.sess.span_warn(
-                        sp, fmt!("variable `%s` is assigned to, \
+                    self.tcx.sess.span_lint(unused_variable, id,
+                        self.ir.cur_item, sp,
+                        fmt!("variable `%s` is assigned to, \
                                   but never used", **name));
                 } else {
-                    // FIXME(#3266)--make liveness warnings lintable
-                    self.tcx.sess.span_warn(
-                        sp, fmt!("unused variable: `%s`", **name));
+                    self.tcx.sess.span_lint(unused_variable, id,
+                        self.ir.cur_item, sp,
+                        fmt!("unused variable: `%s`", **name));
                 }
             }
             return true;
@@ -1904,12 +1921,12 @@ pub impl Liveness {
         return false;
     }
 
-    fn warn_about_dead_assign(@self, sp: span, ln: LiveNode, var: Variable) {
+    fn warn_about_dead_assign(@self, sp: span, id: node_id,
+                              ln: LiveNode, var: Variable) {
         if self.live_on_exit(ln, var).is_none() {
             for self.should_warn(var).each |name| {
-                // FIXME(#3266)--make liveness warnings lintable
-                self.tcx.sess.span_warn(
-                    sp,
+                self.tcx.sess.span_lint(dead_assignment, id,
+                    self.ir.cur_item, sp,
                     fmt!("value assigned to `%s` is never read", **name));
             }
         }
diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs
index 9e4d16f96e6..27db4ff5aaa 100644
--- a/src/test/compile-fail/liveness-unused.rs
+++ b/src/test/compile-fail/liveness-unused.rs
@@ -8,38 +8,57 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[deny(unused_variable)];
+#[deny(dead_assignment)];
+
 fn f1(x: int) {
-    //~^ WARNING unused variable: `x`
+    //~^ ERROR unused variable: `x`
 }
 
 fn f1b(x: &mut int) {
-    //~^ WARNING unused variable: `x`
+    //~^ ERROR unused variable: `x`
 }
 
+#[allow(unused_variable)]
+fn f1c(x: int) {}
+
 fn f2() {
     let x = 3;
-    //~^ WARNING unused variable: `x`
+    //~^ ERROR unused variable: `x`
 }
 
 fn f3() {
     let mut x = 3;
-    //~^ WARNING variable `x` is assigned to, but never used
+    //~^ ERROR variable `x` is assigned to, but never used
     x += 4;
-    //~^ WARNING value assigned to `x` is never read
+    //~^ ERROR value assigned to `x` is never read
 }
 
 fn f3b() {
     let mut z = 3;
-    //~^ WARNING variable `z` is assigned to, but never used
+    //~^ ERROR variable `z` is assigned to, but never used
     loop {
         z += 4;
     }
 }
 
+#[allow(unused_variable)]
+fn f3c() {
+    let mut z = 3;
+    loop { z += 4; }
+}
+
+#[allow(unused_variable)]
+#[allow(dead_assignment)]
+fn f3d() {
+    let mut x = 3;
+    x += 4;
+}
+
 fn f4() {
     match Some(3) {
       Some(i) => {
-        //~^ WARNING unused variable: `i`
+        //~^ ERROR unused variable: `i`
       }
       None => {}
     }
@@ -57,16 +76,5 @@ fn f4b() -> int {
     }
 }
 
-// leave this in here just to trigger compile-fail:
-struct r {
-    x: (),
-}
-
-impl Drop for r {
-    fn finalize(&self) {}
-}
-
 fn main() {
-    let x = r { x: () };
-    || { copy x; }; //~ ERROR copying a value of non-copyable type
 }