1
+ use hir:: FnSig ;
1
2
use rustc_ast:: ast:: Attribute ;
2
3
use rustc_errors:: Applicability ;
3
4
use rustc_hir:: def_id:: DefIdSet ;
4
5
use rustc_hir:: { self as hir, def:: Res , QPath } ;
6
+ use rustc_infer:: infer:: TyCtxtInferExt ;
5
7
use rustc_lint:: { LateContext , LintContext } ;
6
8
use rustc_middle:: {
7
9
lint:: in_external_macro,
@@ -27,7 +29,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
27
29
let is_public = cx. effective_visibilities . is_exported ( item. owner_id . def_id ) ;
28
30
let fn_header_span = item. span . with_hi ( sig. decl . output . span ( ) . hi ( ) ) ;
29
31
if let Some ( attr) = attr {
30
- check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, attr) ;
32
+ check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, attr, sig ) ;
31
33
} else if is_public && !is_proc_macro ( attrs) && !attrs. iter ( ) . any ( |a| a. has_name ( sym:: no_mangle) ) {
32
34
check_must_use_candidate (
33
35
cx,
@@ -49,7 +51,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
49
51
let attrs = cx. tcx . hir ( ) . attrs ( item. hir_id ( ) ) ;
50
52
let attr = cx. tcx . get_attr ( item. owner_id , sym:: must_use) ;
51
53
if let Some ( attr) = attr {
52
- check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, attr) ;
54
+ check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, attr, sig ) ;
53
55
} else if is_public && !is_proc_macro ( attrs) && trait_ref_of_method ( cx, item. owner_id . def_id ) . is_none ( ) {
54
56
check_must_use_candidate (
55
57
cx,
@@ -72,7 +74,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
72
74
let attrs = cx. tcx . hir ( ) . attrs ( item. hir_id ( ) ) ;
73
75
let attr = cx. tcx . get_attr ( item. owner_id , sym:: must_use) ;
74
76
if let Some ( attr) = attr {
75
- check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, attr) ;
77
+ check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, attr, sig ) ;
76
78
} else if let hir:: TraitFn :: Provided ( eid) = * eid {
77
79
let body = cx. tcx . hir ( ) . body ( eid) ;
78
80
if attr. is_none ( ) && is_public && !is_proc_macro ( attrs) {
@@ -97,6 +99,7 @@ fn check_needless_must_use(
97
99
item_span : Span ,
98
100
fn_header_span : Span ,
99
101
attr : & Attribute ,
102
+ sig : & FnSig < ' _ > ,
100
103
) {
101
104
if in_external_macro ( cx. sess ( ) , item_span) {
102
105
return ;
@@ -112,6 +115,15 @@ fn check_needless_must_use(
112
115
} ,
113
116
) ;
114
117
} else if attr. value_str ( ) . is_none ( ) && is_must_use_ty ( cx, return_ty ( cx, item_id) ) {
118
+ // Ignore async functions unless Future::Output type is a must_use type
119
+ if sig. header . is_async ( ) {
120
+ let infcx = cx. tcx . infer_ctxt ( ) . build ( ) ;
121
+ if let Some ( future_ty) = infcx. get_impl_future_output_ty ( return_ty ( cx, item_id) )
122
+ && !is_must_use_ty ( cx, future_ty) {
123
+ return ;
124
+ }
125
+ }
126
+
115
127
span_lint_and_help (
116
128
cx,
117
129
DOUBLE_MUST_USE ,
0 commit comments