Skip to content

Commit

Permalink
warn on must_use use on async fn's
Browse files Browse the repository at this point in the history
  • Loading branch information
guswynn committed Nov 8, 2021
1 parent 495322d commit 958de5a
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
32 changes: 32 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Expand Up @@ -112,6 +112,7 @@ impl CheckAttrVisitor<'tcx> {
self.check_default_method_body_is_const(attr, span, target)
}
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
sym::must_use => self.check_must_use(hir_id, &attr, span, target),
sym::rustc_const_unstable
| sym::rustc_const_stable
| sym::unstable
Expand Down Expand Up @@ -1046,6 +1047,37 @@ impl CheckAttrVisitor<'tcx> {
is_valid
}

/// Warns against some misuses of `#[must_use]`
fn check_must_use(
&self,
hir_id: HirId,
attr: &Attribute,
span: &Span,
_target: Target,
) -> bool {
let node = self.tcx.hir().get(hir_id);
if let Some(fn_node) = node.fn_kind() {
if let rustc_hir::IsAsync::Async = fn_node.asyncness() {
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
lint.build(
"`must_use` attribute on `async` functions \
applies to the anonymous `Future` returned by the \
function, not the value within.",
)
.span_label(
*span,
"this attribute does nothing, the `Future`s \
returned by async functions are already `must_use`",
)
.emit();
});
}
}

// For now, its always valid
true
}

/// Checks if `#[must_not_suspend]` is applied to a function. Returns `true` if valid.
fn check_must_not_suspend(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
match target {
Expand Down
43 changes: 43 additions & 0 deletions src/test/ui/lint/unused/unused-async.rs
@@ -0,0 +1,43 @@
// edition:2018
// run-pass
#![allow(dead_code)]

#[must_use]
//~^ WARNING `must_use`
async fn test() -> i32 {
1
}


struct Wowee {}

impl Wowee {
#[must_use]
//~^ WARNING `must_use`
async fn test_method() -> i32 {
1
}
}

/* FIXME(guswynn) update this test when async-fn-in-traits works
trait Doer {
#[must_use]
async fn test_trait_method() -> i32;
WARNING must_use
async fn test_other_trait() -> i32;
}
impl Doer for Wowee {
async fn test_trait_method() -> i32 {
1
}
#[must_use]
async fn test_other_trait() -> i32 {
WARNING must_use
1
}
}
*/

fn main() {
}
26 changes: 26 additions & 0 deletions src/test/ui/lint/unused/unused-async.stderr
@@ -0,0 +1,26 @@
warning: `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within.
--> $DIR/unused-async.rs:5:1
|
LL | #[must_use]
| ^^^^^^^^^^^
LL |
LL | / async fn test() -> i32 {
LL | | 1
LL | | }
| |_- this attribute does nothing, the `Future`s returned by async functions are already `must_use`
|
= note: `#[warn(unused_attributes)]` on by default

warning: `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within.
--> $DIR/unused-async.rs:15:5
|
LL | #[must_use]
| ^^^^^^^^^^^
LL |
LL | / async fn test_method() -> i32 {
LL | | 1
LL | | }
| |_____- this attribute does nothing, the `Future`s returned by async functions are already `must_use`

warning: 2 warnings emitted

0 comments on commit 958de5a

Please sign in to comment.