@@ -15,14 +15,17 @@ use clippy_utils::ty::is_must_use_ty;
1515use clippy_utils:: visitors:: for_each_expr_without_closures;
1616use clippy_utils:: { return_ty, trait_ref_of_method} ;
1717use rustc_trait_selection:: error_reporting:: InferCtxtErrorExt ;
18+ use rustc_attr_data_structures:: AttributeKind ;
19+ use rustc_span:: Symbol ;
20+ use rustc_attr_data_structures:: find_attr;
1821
1922use core:: ops:: ControlFlow ;
2023
2124use super :: { DOUBLE_MUST_USE , MUST_USE_CANDIDATE , MUST_USE_UNIT } ;
2225
2326pub ( super ) fn check_item < ' tcx > ( cx : & LateContext < ' tcx > , item : & ' tcx hir:: Item < ' _ > ) {
2427 let attrs = cx. tcx . hir_attrs ( item. hir_id ( ) ) ;
25- let attr = cx. tcx . get_attr ( item. owner_id , sym :: must_use ) ;
28+ let attr = find_attr ! ( cx. tcx. hir_attrs ( item. hir_id ( ) ) , AttributeKind :: MustUse { span , reason } => ( span , reason ) ) ;
2629 if let hir:: ItemKind :: Fn {
2730 ref sig,
2831 body : ref body_id,
@@ -31,8 +34,8 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
3134 {
3235 let is_public = cx. effective_visibilities . is_exported ( item. owner_id . def_id ) ;
3336 let fn_header_span = item. span . with_hi ( sig. decl . output . span ( ) . hi ( ) ) ;
34- if let Some ( attr ) = attr {
35- check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, attr , attrs, sig) ;
37+ if let Some ( ( attr_span , reason ) ) = attr {
38+ check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, * attr_span , * reason , attrs, sig) ;
3639 } else if is_public && !is_proc_macro ( attrs) && !attrs. iter ( ) . any ( |a| a. has_name ( sym:: no_mangle) ) {
3740 check_must_use_candidate (
3841 cx,
@@ -52,9 +55,9 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
5255 let is_public = cx. effective_visibilities . is_exported ( item. owner_id . def_id ) ;
5356 let fn_header_span = item. span . with_hi ( sig. decl . output . span ( ) . hi ( ) ) ;
5457 let attrs = cx. tcx . hir_attrs ( item. hir_id ( ) ) ;
55- let attr = cx. tcx . get_attr ( item. owner_id , sym :: must_use ) ;
56- if let Some ( attr ) = attr {
57- check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, attr , attrs, sig) ;
58+ let attr = find_attr ! ( cx. tcx. hir_attrs ( item. hir_id ( ) ) , AttributeKind :: MustUse { span , reason } => ( span , reason ) ) ;
59+ if let Some ( ( attr_span , reason ) ) = attr {
60+ check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, * attr_span , * reason , attrs, sig) ;
5861 } else if is_public && !is_proc_macro ( attrs) && trait_ref_of_method ( cx, item. owner_id ) . is_none ( ) {
5962 check_must_use_candidate (
6063 cx,
@@ -75,9 +78,9 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
7578 let fn_header_span = item. span . with_hi ( sig. decl . output . span ( ) . hi ( ) ) ;
7679
7780 let attrs = cx. tcx . hir_attrs ( item. hir_id ( ) ) ;
78- let attr = cx. tcx . get_attr ( item. owner_id , sym :: must_use ) ;
79- if let Some ( attr ) = attr {
80- check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, attr , attrs, sig) ;
81+ let attr = find_attr ! ( cx. tcx. hir_attrs ( item. hir_id ( ) ) , AttributeKind :: MustUse { span , reason } => ( span , reason ) ) ;
82+ if let Some ( ( attr_span , reason ) ) = attr {
83+ check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, * attr_span , * reason , attrs, sig) ;
8184 } else if let hir:: TraitFn :: Provided ( eid) = * eid {
8285 let body = cx. tcx . hir_body ( eid) ;
8386 if attr. is_none ( ) && is_public && !is_proc_macro ( attrs) {
@@ -103,7 +106,8 @@ fn check_needless_must_use(
103106 item_id : hir:: OwnerId ,
104107 item_span : Span ,
105108 fn_header_span : Span ,
106- attr : & Attribute ,
109+ attr_span : Span ,
110+ reason : Option < Symbol > ,
107111 attrs : & [ Attribute ] ,
108112 sig : & FnSig < ' _ > ,
109113) {
@@ -119,7 +123,7 @@ fn check_needless_must_use(
119123 "this unit-returning function has a `#[must_use]` attribute" ,
120124 |diag| {
121125 diag. span_suggestion (
122- attr . span ( ) ,
126+ attr_span ,
123127 "remove the attribute" ,
124128 "" ,
125129 Applicability :: MachineApplicable ,
@@ -137,11 +141,11 @@ fn check_needless_must_use(
137141 MUST_USE_UNIT ,
138142 fn_header_span,
139143 "this unit-returning function has a `#[must_use]` attribute" ,
140- Some ( attr . span ( ) ) ,
144+ Some ( attr_span ) ,
141145 "remove `must_use`" ,
142146 ) ;
143147 }
144- } else if attr . value_str ( ) . is_none ( ) && is_must_use_ty ( cx, return_ty ( cx, item_id) ) {
148+ } else if reason . is_none ( ) && is_must_use_ty ( cx, return_ty ( cx, item_id) ) {
145149 // Ignore async functions unless Future::Output type is a must_use type
146150 if sig. header . is_async ( ) {
147151 let infcx = cx. tcx . infer_ctxt ( ) . build ( cx. typing_mode ( ) ) ;
0 commit comments