Skip to content

Commit 978e7ab

Browse files
authored
Rollup merge of #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 #78149.
2 parents b7b7f27 + f57713b commit 978e7ab

28 files changed

+159
-105
lines changed

compiler/rustc_lint/src/unused.rs

+23-7
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

+2-12
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

+2-2
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

+1-1
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

+2-2
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

+1-1
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

+1-1
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

+1-1
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

+1-1
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

+1-1
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

src/test/ui/generator/yield-in-box.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | | let _t = box (&x, yield 0, &y);
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/yield-in-initializer.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | | // See https://github.com/rust-lang/rust/issues/52792
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/yield-subtype.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | / || {
55
LL | | yield a;
66
LL | | 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

src/test/ui/issues/issue-1460.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ warning: unused closure that must be used
22
--> $DIR/issue-1460.rs:6:5
33
|
44
LL | {|i: u32| if 1 == i { }};
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: closures are lazy and do nothing unless called
88
= note: `#[warn(unused_must_use)]` on by default

src/test/ui/issues/issue-16256.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ warning: unused closure that must be used
22
--> $DIR/issue-16256.rs:6:5
33
|
44
LL | |c: u8| buf.push(c);
5-
| ^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^
66
|
77
= note: closures are lazy and do nothing unless called
88
= note: `#[warn(unused_must_use)]` on by default

src/test/ui/lint/fn_must_use.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ warning: unused return value of `need_to_use_this_value` that must be used
22
--> $DIR/fn_must_use.rs:55:5
33
|
44
LL | need_to_use_this_value();
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: it's important
88
note: the lint level is defined here
@@ -15,33 +15,33 @@ warning: unused return value of `MyStruct::need_to_use_this_method_value` that m
1515
--> $DIR/fn_must_use.rs:60:5
1616
|
1717
LL | m.need_to_use_this_method_value();
18-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1919

2020
warning: unused return value of `EvenNature::is_even` that must be used
2121
--> $DIR/fn_must_use.rs:61:5
2222
|
2323
LL | m.is_even(); // trait method!
24-
| ^^^^^^^^^^^^
24+
| ^^^^^^^^^^^
2525
|
2626
= note: no side effects
2727

2828
warning: unused return value of `MyStruct::need_to_use_this_associated_function_value` that must be used
2929
--> $DIR/fn_must_use.rs:64:5
3030
|
3131
LL | MyStruct::need_to_use_this_associated_function_value();
32-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3333

3434
warning: unused return value of `std::cmp::PartialEq::eq` that must be used
3535
--> $DIR/fn_must_use.rs:70:5
3636
|
3737
LL | 2.eq(&3);
38-
| ^^^^^^^^^
38+
| ^^^^^^^^
3939

4040
warning: unused return value of `std::cmp::PartialEq::eq` that must be used
4141
--> $DIR/fn_must_use.rs:71:5
4242
|
4343
LL | m.eq(&n);
44-
| ^^^^^^^^^
44+
| ^^^^^^^^
4545

4646
warning: unused comparison that must be used
4747
--> $DIR/fn_must_use.rs:74:5

src/test/ui/lint/unused/must-use-box-from-raw.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ warning: unused return value of `Box::<T>::from_raw` that must be used
22
--> $DIR/must-use-box-from-raw.rs:8:5
33
|
44
LL | Box::from_raw(ptr);
5-
| ^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^
66
|
77
= note: call `drop(from_raw(ptr))` if you intend to drop the `Box`
88
note: the lint level is defined here

src/test/ui/lint/unused/must_use-array.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: unused array of `S` that must be used
22
--> $DIR/must_use-array.rs:39:5
33
|
44
LL | singleton();
5-
| ^^^^^^^^^^^^
5+
| ^^^^^^^^^^^
66
|
77
note: the lint level is defined here
88
--> $DIR/must_use-array.rs:1:9
@@ -14,7 +14,7 @@ error: unused array of `S` that must be used
1414
--> $DIR/must_use-array.rs:40:5
1515
|
1616
LL | many();
17-
| ^^^^^^^
17+
| ^^^^^^
1818

1919
error: unused array of `S` in tuple element 0 that must be used
2020
--> $DIR/must_use-array.rs:41:6
@@ -26,7 +26,7 @@ error: unused array of implementers of `T` that must be used
2626
--> $DIR/must_use-array.rs:42:5
2727
|
2828
LL | array_of_impl_trait();
29-
| ^^^^^^^^^^^^^^^^^^^^^^
29+
| ^^^^^^^^^^^^^^^^^^^^^
3030

3131
error: unused array of boxed `T` trait objects in tuple element 1 that must be used
3232
--> $DIR/must_use-array.rs:43:5
@@ -38,7 +38,7 @@ error: unused array of arrays of arrays of `S` that must be used
3838
--> $DIR/must_use-array.rs:45:5
3939
|
4040
LL | array_of_arrays_of_arrays();
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
4242

4343
error: aborting due to 6 previous errors
4444

src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: unused implementer of `Iterator` that must be used
22
--> $DIR/must_use-in-stdlib-traits.rs:42:4
33
|
44
LL | iterator();
5-
| ^^^^^^^^^^^
5+
| ^^^^^^^^^^
66
|
77
= note: iterators are lazy and do nothing unless consumed
88
note: the lint level is defined here
@@ -15,31 +15,31 @@ error: unused implementer of `Future` that must be used
1515
--> $DIR/must_use-in-stdlib-traits.rs:43:4
1616
|
1717
LL | future();
18-
| ^^^^^^^^^
18+
| ^^^^^^^^
1919
|
2020
= note: futures do nothing unless you `.await` or poll them
2121

2222
error: unused implementer of `FnOnce` that must be used
2323
--> $DIR/must_use-in-stdlib-traits.rs:44:4
2424
|
2525
LL | square_fn_once();
26-
| ^^^^^^^^^^^^^^^^^
26+
| ^^^^^^^^^^^^^^^^
2727
|
2828
= note: closures are lazy and do nothing unless called
2929

3030
error: unused implementer of `FnMut` that must be used
3131
--> $DIR/must_use-in-stdlib-traits.rs:45:4
3232
|
3333
LL | square_fn_mut();
34-
| ^^^^^^^^^^^^^^^^
34+
| ^^^^^^^^^^^^^^^
3535
|
3636
= note: closures are lazy and do nothing unless called
3737

3838
error: unused implementer of `Fn` that must be used
3939
--> $DIR/must_use-in-stdlib-traits.rs:46:4
4040
|
4141
LL | square_fn();
42-
| ^^^^^^^^^^^^
42+
| ^^^^^^^^^^^
4343
|
4444
= note: closures are lazy and do nothing unless called
4545

src/test/ui/lint/unused/must_use-trait.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: unused implementer of `Critical` that must be used
22
--> $DIR/must_use-trait.rs:33:5
33
|
44
LL | get_critical();
5-
| ^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^
66
|
77
note: the lint level is defined here
88
--> $DIR/must_use-trait.rs:1:9
@@ -14,13 +14,13 @@ error: unused boxed `Critical` trait object that must be used
1414
--> $DIR/must_use-trait.rs:34:5
1515
|
1616
LL | get_boxed_critical();
17-
| ^^^^^^^^^^^^^^^^^^^^^
17+
| ^^^^^^^^^^^^^^^^^^^^
1818

1919
error: unused boxed boxed `Critical` trait object that must be used
2020
--> $DIR/must_use-trait.rs:35:5
2121
|
2222
LL | get_nested_boxed_critical();
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
2424

2525
error: unused boxed `Critical` trait object in tuple element 1 that must be used
2626
--> $DIR/must_use-trait.rs:37:5

0 commit comments

Comments
 (0)