1+ use hir:: FnSig ;
12use rustc_ast:: ast:: Attribute ;
23use rustc_errors:: Applicability ;
34use rustc_hir:: def_id:: DefIdSet ;
45use rustc_hir:: { self as hir, def:: Res , QPath } ;
6+ use rustc_infer:: infer:: TyCtxtInferExt ;
57use rustc_lint:: { LateContext , LintContext } ;
68use rustc_middle:: {
79 lint:: in_external_macro,
@@ -27,7 +29,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
2729 let is_public = cx. effective_visibilities . is_exported ( item. owner_id . def_id ) ;
2830 let fn_header_span = item. span . with_hi ( sig. decl . output . span ( ) . hi ( ) ) ;
2931 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 ) ;
3133 } else if is_public && !is_proc_macro ( attrs) && !attrs. iter ( ) . any ( |a| a. has_name ( sym:: no_mangle) ) {
3234 check_must_use_candidate (
3335 cx,
@@ -49,7 +51,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
4951 let attrs = cx. tcx . hir ( ) . attrs ( item. hir_id ( ) ) ;
5052 let attr = cx. tcx . get_attr ( item. owner_id , sym:: must_use) ;
5153 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 ) ;
5355 } else if is_public && !is_proc_macro ( attrs) && trait_ref_of_method ( cx, item. owner_id . def_id ) . is_none ( ) {
5456 check_must_use_candidate (
5557 cx,
@@ -72,7 +74,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
7274 let attrs = cx. tcx . hir ( ) . attrs ( item. hir_id ( ) ) ;
7375 let attr = cx. tcx . get_attr ( item. owner_id , sym:: must_use) ;
7476 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 ) ;
7678 } else if let hir:: TraitFn :: Provided ( eid) = * eid {
7779 let body = cx. tcx . hir ( ) . body ( eid) ;
7880 if attr. is_none ( ) && is_public && !is_proc_macro ( attrs) {
@@ -97,6 +99,7 @@ fn check_needless_must_use(
9799 item_span : Span ,
98100 fn_header_span : Span ,
99101 attr : & Attribute ,
102+ sig : & FnSig < ' _ > ,
100103) {
101104 if in_external_macro ( cx. sess ( ) , item_span) {
102105 return ;
@@ -112,6 +115,15 @@ fn check_needless_must_use(
112115 } ,
113116 ) ;
114117 } 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+
115127 span_lint_and_help (
116128 cx,
117129 DOUBLE_MUST_USE ,
0 commit comments