Skip to content

Commit 37c5efa

Browse files
authored
Rollup merge of rust-lang#100633 - estebank:must_use_async_fn_return, r=tmandry
Consider `#[must_use]` annotation on `async fn` as also affecting the `Future::Output` No longer lint against `#[must_use] async fn foo()`. When encountering a statement that awaits on a `Future`, check if the `Future`'s parent item is annotated with `#[must_use]` and emit a lint if so. This effectively makes `must_use` an annotation on the `Future::Output` instead of only the `Future` itself. Fix rust-lang#78149.
2 parents c1a859b + f57713b commit 37c5efa

28 files changed

+159
-105
lines changed

compiler/rustc_lint/src/unused.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_hir::def::{DefKind, Res};
99
use rustc_hir::def_id::DefId;
1010
use rustc_infer::traits::util::elaborate_predicates_with_span;
1111
use rustc_middle::ty::adjustment;
12-
use rustc_middle::ty::{self, Ty};
12+
use rustc_middle::ty::{self, DefIdTree, Ty};
1313
use rustc_span::symbol::Symbol;
1414
use rustc_span::symbol::{kw, sym};
1515
use rustc_span::{BytePos, Span};
@@ -87,17 +87,33 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
8787

8888
impl<'tcx> LateLintPass<'tcx> for UnusedResults {
8989
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
90-
let expr = match s.kind {
91-
hir::StmtKind::Semi(ref expr) => &**expr,
92-
_ => return,
93-
};
90+
let hir::StmtKind::Semi(expr) = s.kind else { return; };
9491

9592
if let hir::ExprKind::Ret(..) = expr.kind {
9693
return;
9794
}
9895

96+
if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind
97+
&& let ty = cx.typeck_results().expr_ty(&await_expr)
98+
&& let ty::Opaque(future_def_id, _) = ty.kind()
99+
&& cx.tcx.ty_is_opaque_future(ty)
100+
// FIXME: This also includes non-async fns that return `impl Future`.
101+
&& let async_fn_def_id = cx.tcx.parent(*future_def_id)
102+
&& check_must_use_def(
103+
cx,
104+
async_fn_def_id,
105+
expr.span,
106+
"output of future returned by ",
107+
"",
108+
)
109+
{
110+
// We have a bare `foo().await;` on an opaque type from an async function that was
111+
// annotated with `#[must_use]`.
112+
return;
113+
}
114+
99115
let ty = cx.typeck_results().expr_ty(&expr);
100-
let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", 1);
116+
let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, expr.span, "", "", 1);
101117

102118
let mut fn_warned = false;
103119
let mut op_warned = false;
@@ -119,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
119135
_ => None,
120136
};
121137
if let Some(def_id) = maybe_def_id {
122-
fn_warned = check_must_use_def(cx, def_id, s.span, "return value of ", "");
138+
fn_warned = check_must_use_def(cx, def_id, expr.span, "return value of ", "");
123139
} else if type_permits_lack_of_use {
124140
// We don't warn about unused unit or uninhabited types.
125141
// (See https://github.com/rust-lang/rust/issues/43806 for details.)

compiler/rustc_passes/src/check_attr.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ impl CheckAttrVisitor<'_> {
139139
sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target),
140140
sym::const_trait => self.check_const_trait(attr, span, target),
141141
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
142-
sym::must_use => self.check_must_use(hir_id, &attr, span, target),
142+
sym::must_use => self.check_must_use(hir_id, &attr, target),
143143
sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target),
144144
sym::rustc_allow_incoherent_impl => {
145145
self.check_allow_incoherent_impl(&attr, span, target)
@@ -1163,17 +1163,7 @@ impl CheckAttrVisitor<'_> {
11631163
}
11641164

11651165
/// Warns against some misuses of `#[must_use]`
1166-
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
1167-
let node = self.tcx.hir().get(hir_id);
1168-
if let Some(kind) = node.fn_kind() && let rustc_hir::IsAsync::Async = kind.asyncness() {
1169-
self.tcx.emit_spanned_lint(
1170-
UNUSED_ATTRIBUTES,
1171-
hir_id,
1172-
attr.span,
1173-
errors::MustUseAsync { span }
1174-
);
1175-
}
1176-
1166+
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
11771167
if !matches!(
11781168
target,
11791169
Target::Fn

src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ LL | / || match out_ref {
1616
LL | | Variant::A => (),
1717
LL | | Variant::B => (),
1818
LL | | };
19-
| |______^
19+
| |_____^
2020
|
2121
= note: closures are lazy and do nothing unless called
2222
= note: `#[warn(unused_must_use)]` on by default
@@ -28,7 +28,7 @@ LL | / || match here.field {
2828
LL | | Variant::A => (),
2929
LL | | Variant::B => (),
3030
LL | | };
31-
| |______^
31+
| |_____^
3232
|
3333
= note: closures are lazy and do nothing unless called
3434

src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ warning: unused `MustUseDeprecated` that must be used
2828
--> $DIR/cfg-attr-multi-true.rs:19:5
2929
|
3030
LL | MustUseDeprecated::new();
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^
3232
|
3333
note: the lint level is defined here
3434
--> $DIR/cfg-attr-multi-true.rs:7:9

src/test/ui/generator/issue-52398.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ warning: unused generator that must be used
44
LL | / move || {
55
LL | | A.test(yield);
66
LL | | };
7-
| |______^
7+
| |_____^
88
|
99
= note: generators are lazy and do nothing unless resumed
1010
= note: `#[warn(unused_must_use)]` on by default
@@ -16,7 +16,7 @@ LL | / static move || {
1616
LL | | yield *y.borrow();
1717
LL | | return "Done";
1818
LL | | };
19-
| |______^
19+
| |_____^
2020
|
2121
= note: generators are lazy and do nothing unless resumed
2222

src/test/ui/generator/issue-57084.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | | loop {
77
LL | | yield
88
LL | | }
99
LL | | };
10-
| |______^
10+
| |_____^
1111
|
1212
= note: generators are lazy and do nothing unless resumed
1313
= note: `#[warn(unused_must_use)]` on by default

src/test/ui/generator/match-bindings.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | | match Enum::A(String::new()) {
88
... |
99
LL | | }
1010
LL | | };
11-
| |______^
11+
| |_____^
1212
|
1313
= note: generators are lazy and do nothing unless resumed
1414
= note: `#[warn(unused_must_use)]` on by default

src/test/ui/generator/reborrow-mut-upvar.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | | yield;
88
... |
99
LL | | *bar = 2;
1010
LL | | };
11-
| |______^
11+
| |_____^
1212
|
1313
= note: generators are lazy and do nothing unless resumed
1414
= note: `#[warn(unused_must_use)]` on by default

src/test/ui/generator/too-live-local-in-immovable-gen.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | | // and it should also find out that `a` is not live.
88
... |
99
LL | | let _ = &a;
1010
LL | | };
11-
| |__________^
11+
| |_________^
1212
|
1313
= note: generators are lazy and do nothing unless resumed
1414
= note: `#[warn(unused_must_use)]` on by default

src/test/ui/generator/yield-in-args-rev.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | / || {
55
LL | | let b = true;
66
LL | | foo(yield, &b);
77
LL | | };
8-
| |______^
8+
| |_____^
99
|
1010
= note: generators are lazy and do nothing unless resumed
1111
= note: `#[warn(unused_must_use)]` on by default

0 commit comments

Comments
 (0)