]> git.lizzy.rs Git - rust.git/commitdiff
lint: extend `#[must_use]` to handle a message.
authorHuon Wilson <dbau.pp+github@gmail.com>
Wed, 9 Jul 2014 12:02:19 +0000 (22:02 +1000)
committerHuon Wilson <dbau.pp+github@gmail.com>
Wed, 9 Jul 2014 22:05:58 +0000 (08:05 +1000)
Similar to the stability attributes, a type annotated with `#[must_use =
"informative snippet"]` will print the normal warning message along with
"informative snippet". This allows the type author to provide some
guidance about why the type should be used.

src/librustc/lint/builtin.rs
src/test/compile-fail/unused-result.rs

index ae401b9d6f15c969a0e748ba58d5b5e4b47aa2ee..481187f7c2ce74b499592b24d761a729de28186b 100644 (file)
@@ -669,22 +669,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 +684,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
+        }
     }
 }
 
index 44058c1ddda190faec96844058b370847bc06605..ecc52c0ee7d58491b5f59f2d063b0ca078bcf7d4 100644 (file)
 #[must_use]
 enum MustUse { Test }
 
+#[must_use = "some message"]
+enum MustUseMsg { Test2 }
+
 fn foo<T>() -> T { fail!() }
 
 fn bar() -> int { return foo::<int>(); }
 fn baz() -> MustUse { return foo::<MustUse>(); }
+fn qux() -> MustUseMsg { return foo::<MustUseMsg>(); }
 
 #[allow(unused_result)]
 fn test() {
     foo::<int>();
     foo::<MustUse>(); //~ ERROR: unused result which must be used
+    foo::<MustUseMsg>(); //~ ERROR: unused result which must be used: some message
 }
 
 #[allow(unused_result, unused_must_use)]
 fn test2() {
     foo::<int>();
     foo::<MustUse>();
+    foo::<MustUseMsg>();
 }
 
 fn main() {
     foo::<int>(); //~ ERROR: unused result
     foo::<MustUse>(); //~ ERROR: unused result which must be used
+    foo::<MustUseMsg>(); //~ ERROR: unused result which must be used: some message
 
     let _ = foo::<int>();
     let _ = foo::<MustUse>();
+    let _ = foo::<MustUseMsg>();
 }