@@ -15,14 +15,16 @@ 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_span:: Symbol ;
19+ use rustc_attr_data_structures:: { AttributeKind , find_attr} ;
1820
1921use core:: ops:: ControlFlow ;
2022
2123use super :: { DOUBLE_MUST_USE , MUST_USE_CANDIDATE , MUST_USE_UNIT } ;
2224
2325pub ( super ) fn check_item < ' tcx > ( cx : & LateContext < ' tcx > , item : & ' tcx hir:: Item < ' _ > ) {
2426 let attrs = cx. tcx . hir_attrs ( item. hir_id ( ) ) ;
25- let attr = cx. tcx . get_attr ( item. owner_id , sym :: must_use ) ;
27+ let attr = find_attr ! ( cx. tcx. hir_attrs ( item. hir_id ( ) ) , AttributeKind :: MustUse { span , reason } => ( span , reason ) ) ;
2628 if let hir:: ItemKind :: Fn {
2729 ref sig,
2830 body : ref body_id,
@@ -31,9 +33,9 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
3133 {
3234 let is_public = cx. effective_visibilities . is_exported ( item. owner_id . def_id ) ;
3335 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) ;
36- } else if is_public && !is_proc_macro ( attrs) && !attrs . iter ( ) . any ( |a| a . has_name ( sym :: no_mangle ) ) {
36+ if let Some ( ( attr_span , reason ) ) = attr {
37+ check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, * attr_span , * reason , attrs, sig) ;
38+ } else if is_public && !is_proc_macro ( attrs) && !find_attr ! ( attrs , AttributeKind :: NoMangle ( .. ) ) {
3739 check_must_use_candidate (
3840 cx,
3941 sig. decl ,
@@ -52,9 +54,9 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
5254 let is_public = cx. effective_visibilities . is_exported ( item. owner_id . def_id ) ;
5355 let fn_header_span = item. span . with_hi ( sig. decl . output . span ( ) . hi ( ) ) ;
5456 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) ;
57+ let attr = find_attr ! ( cx. tcx. hir_attrs ( item. hir_id ( ) ) , AttributeKind :: MustUse { span , reason } => ( span , reason ) ) ;
58+ if let Some ( ( attr_span , reason ) ) = attr {
59+ check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, * attr_span , * reason , attrs, sig) ;
5860 } else if is_public && !is_proc_macro ( attrs) && trait_ref_of_method ( cx, item. owner_id ) . is_none ( ) {
5961 check_must_use_candidate (
6062 cx,
@@ -75,9 +77,9 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
7577 let fn_header_span = item. span . with_hi ( sig. decl . output . span ( ) . hi ( ) ) ;
7678
7779 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) ;
80+ let attr = find_attr ! ( cx. tcx. hir_attrs ( item. hir_id ( ) ) , AttributeKind :: MustUse { span , reason } => ( span , reason ) ) ;
81+ if let Some ( ( attr_span , reason ) ) = attr {
82+ check_needless_must_use ( cx, sig. decl , item. owner_id , item. span , fn_header_span, * attr_span , * reason , attrs, sig) ;
8183 } else if let hir:: TraitFn :: Provided ( eid) = * eid {
8284 let body = cx. tcx . hir_body ( eid) ;
8385 if attr. is_none ( ) && is_public && !is_proc_macro ( attrs) {
@@ -103,7 +105,8 @@ fn check_needless_must_use(
103105 item_id : hir:: OwnerId ,
104106 item_span : Span ,
105107 fn_header_span : Span ,
106- attr : & Attribute ,
108+ attr_span : Span ,
109+ reason : Option < Symbol > ,
107110 attrs : & [ Attribute ] ,
108111 sig : & FnSig < ' _ > ,
109112) {
@@ -119,7 +122,7 @@ fn check_needless_must_use(
119122 "this unit-returning function has a `#[must_use]` attribute" ,
120123 |diag| {
121124 diag. span_suggestion (
122- attr . span ( ) ,
125+ attr_span ,
123126 "remove the attribute" ,
124127 "" ,
125128 Applicability :: MachineApplicable ,
@@ -137,11 +140,11 @@ fn check_needless_must_use(
137140 MUST_USE_UNIT ,
138141 fn_header_span,
139142 "this unit-returning function has a `#[must_use]` attribute" ,
140- Some ( attr . span ( ) ) ,
143+ Some ( attr_span ) ,
141144 "remove `must_use`" ,
142145 ) ;
143146 }
144- } else if attr . value_str ( ) . is_none ( ) && is_must_use_ty ( cx, return_ty ( cx, item_id) ) {
147+ } else if reason . is_none ( ) && is_must_use_ty ( cx, return_ty ( cx, item_id) ) {
145148 // Ignore async functions unless Future::Output type is a must_use type
146149 if sig. header . is_async ( ) {
147150 let infcx = cx. tcx . infer_ctxt ( ) . build ( cx. typing_mode ( ) ) ;
0 commit comments