Skip to content

Commit

Permalink
lint: extend #[must_use] to handle a message.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
huonw committed Jul 9, 2014
1 parent 66e1f11 commit b9e35a1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 11 deletions.
32 changes: 21 additions & 11 deletions src/librustc/lint/builtin.rs
Expand Up @@ -669,22 +669,13 @@ impl LintPass for UnusedResult {
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);
});
}
}
Expand All @@ -693,6 +684,25 @@ impl LintPass for UnusedResult {
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
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/test/compile-fail/unused-result.rs
Expand Up @@ -14,27 +14,35 @@
#[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>();
}

0 comments on commit b9e35a1

Please sign in to comment.