@@ -15,14 +15,17 @@ use clippy_utils::ty::is_must_use_ty;
15
15
use clippy_utils:: visitors:: for_each_expr_without_closures;
16
16
use clippy_utils:: { return_ty, trait_ref_of_method} ;
17
17
use 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;
18
21
19
22
use core:: ops:: ControlFlow ;
20
23
21
24
use super :: { DOUBLE_MUST_USE , MUST_USE_CANDIDATE , MUST_USE_UNIT } ;
22
25
23
26
pub ( super ) fn check_item < ' tcx > ( cx : & LateContext < ' tcx > , item : & ' tcx hir:: Item < ' _ > ) {
24
27
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 ) ) ;
26
29
if let hir:: ItemKind :: Fn {
27
30
ref sig,
28
31
body : ref body_id,
@@ -31,8 +34,8 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
31
34
{
32
35
let is_public = cx. effective_visibilities . is_exported ( item. owner_id . def_id ) ;
33
36
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) ;
36
39
} else if is_public && !is_proc_macro ( attrs) && !attrs. iter ( ) . any ( |a| a. has_name ( sym:: no_mangle) ) {
37
40
check_must_use_candidate (
38
41
cx,
@@ -52,9 +55,9 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
52
55
let is_public = cx. effective_visibilities . is_exported ( item. owner_id . def_id ) ;
53
56
let fn_header_span = item. span . with_hi ( sig. decl . output . span ( ) . hi ( ) ) ;
54
57
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) ;
58
61
} else if is_public && !is_proc_macro ( attrs) && trait_ref_of_method ( cx, item. owner_id ) . is_none ( ) {
59
62
check_must_use_candidate (
60
63
cx,
@@ -75,9 +78,9 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
75
78
let fn_header_span = item. span . with_hi ( sig. decl . output . span ( ) . hi ( ) ) ;
76
79
77
80
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) ;
81
84
} else if let hir:: TraitFn :: Provided ( eid) = * eid {
82
85
let body = cx. tcx . hir_body ( eid) ;
83
86
if attr. is_none ( ) && is_public && !is_proc_macro ( attrs) {
@@ -103,7 +106,8 @@ fn check_needless_must_use(
103
106
item_id : hir:: OwnerId ,
104
107
item_span : Span ,
105
108
fn_header_span : Span ,
106
- attr : & Attribute ,
109
+ attr_span : Span ,
110
+ reason : Option < Symbol > ,
107
111
attrs : & [ Attribute ] ,
108
112
sig : & FnSig < ' _ > ,
109
113
) {
@@ -119,7 +123,7 @@ fn check_needless_must_use(
119
123
"this unit-returning function has a `#[must_use]` attribute" ,
120
124
|diag| {
121
125
diag. span_suggestion (
122
- attr . span ( ) ,
126
+ attr_span ,
123
127
"remove the attribute" ,
124
128
"" ,
125
129
Applicability :: MachineApplicable ,
@@ -137,11 +141,11 @@ fn check_needless_must_use(
137
141
MUST_USE_UNIT ,
138
142
fn_header_span,
139
143
"this unit-returning function has a `#[must_use]` attribute" ,
140
- Some ( attr . span ( ) ) ,
144
+ Some ( attr_span ) ,
141
145
"remove `must_use`" ,
142
146
) ;
143
147
}
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) ) {
145
149
// Ignore async functions unless Future::Output type is a must_use type
146
150
if sig. header . is_async ( ) {
147
151
let infcx = cx. tcx . infer_ctxt ( ) . build ( cx. typing_mode ( ) ) ;
0 commit comments