@@ -4,7 +4,7 @@ use std::ops::ControlFlow;
4
4
use clippy_config:: msrvs:: { self , Msrv } ;
5
5
use clippy_utils:: consts:: { constant, Constant } ;
6
6
use clippy_utils:: diagnostics:: span_lint_hir_and_then;
7
- use clippy_utils:: source:: snippet_with_applicability ;
7
+ use clippy_utils:: source:: snippet_opt ;
8
8
use clippy_utils:: ty:: is_copy;
9
9
use clippy_utils:: visitors:: for_each_local_use_after_expr;
10
10
use clippy_utils:: { get_parent_expr, higher, is_trait_method} ;
@@ -57,6 +57,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
57
57
let Some ( vec_args) = higher:: VecArgs :: hir ( cx, expr. peel_borrows ( ) ) else {
58
58
return ;
59
59
} ;
60
+ // the parent callsite of this `vec!` expression, or span to the borrowed one such as `&vec!`
61
+ let callsite = expr. span . parent_callsite ( ) . unwrap_or ( expr. span ) ;
60
62
61
63
match cx. tcx . parent_hir_node ( expr. hir_id ) {
62
64
// search for `let foo = vec![_]` expressions where all uses of `foo`
@@ -84,41 +86,31 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
84
86
} )
85
87
. is_continue ( ) ;
86
88
87
- let span = expr. span . ctxt ( ) . outer_expn_data ( ) . call_site ;
88
89
if only_slice_uses {
89
- self . check_vec_macro ( cx, & vec_args, span , expr. hir_id , SuggestedType :: Array ) ;
90
+ self . check_vec_macro ( cx, & vec_args, callsite , expr. hir_id , SuggestedType :: Array ) ;
90
91
} else {
91
- self . span_to_lint_map . insert ( span , None ) ;
92
+ self . span_to_lint_map . insert ( callsite , None ) ;
92
93
}
93
94
} ,
94
95
// if the local pattern has a specified type, do not lint.
95
96
Node :: Local ( Local { ty : Some ( _) , .. } ) if higher:: VecArgs :: hir ( cx, expr) . is_some ( ) => {
96
- let span = expr. span . ctxt ( ) . outer_expn_data ( ) . call_site ;
97
- self . span_to_lint_map . insert ( span, None ) ;
97
+ self . span_to_lint_map . insert ( callsite, None ) ;
98
98
} ,
99
99
// search for `for _ in vec![...]`
100
100
Node :: Expr ( Expr { span, .. } )
101
101
if span. is_desugaring ( DesugaringKind :: ForLoop ) && self . msrv . meets ( msrvs:: ARRAY_INTO_ITERATOR ) =>
102
102
{
103
- // report the error around the `vec!` not inside `<std macros>:`
104
- let span = expr. span . ctxt ( ) . outer_expn_data ( ) . call_site ;
105
- self . check_vec_macro ( cx, & vec_args, span, expr. hir_id , SuggestedType :: Array ) ;
103
+ let suggest_slice = suggest_type ( expr) ;
104
+ self . check_vec_macro ( cx, & vec_args, callsite, expr. hir_id , suggest_slice) ;
106
105
} ,
107
106
// search for `&vec![_]` or `vec![_]` expressions where the adjusted type is `&[_]`
108
107
_ => {
109
- let ( suggest_slice, span) = if let ExprKind :: AddrOf ( BorrowKind :: Ref , mutability, _) = expr. kind {
110
- // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.)
111
- ( SuggestedType :: SliceRef ( mutability) , expr. span )
112
- } else {
113
- // `expr` is the `vec![_]` expansion, so suggest `[_]`
114
- // and also use the span of the actual `vec![_]` expression
115
- ( SuggestedType :: Array , expr. span . ctxt ( ) . outer_expn_data ( ) . call_site )
116
- } ;
108
+ let suggest_slice = suggest_type ( expr) ;
117
109
118
110
if adjusts_to_slice ( cx, expr) {
119
- self . check_vec_macro ( cx, & vec_args, span , expr. hir_id , suggest_slice) ;
111
+ self . check_vec_macro ( cx, & vec_args, callsite , expr. hir_id , suggest_slice) ;
120
112
} else {
121
- self . span_to_lint_map . insert ( span , None ) ;
113
+ self . span_to_lint_map . insert ( callsite , None ) ;
122
114
}
123
115
} ,
124
116
}
@@ -151,8 +143,6 @@ impl UselessVec {
151
143
return ;
152
144
}
153
145
154
- let mut applicability = Applicability :: MachineApplicable ;
155
-
156
146
let snippet = match * vec_args {
157
147
higher:: VecArgs :: Repeat ( elem, len) => {
158
148
if let Some ( Constant :: Int ( len_constant) ) = constant ( cx, cx. typeck_results ( ) , len) {
@@ -166,7 +156,7 @@ impl UselessVec {
166
156
return ;
167
157
}
168
158
169
- suggest_slice. snippet ( cx, Some ( elem. span ) , Some ( len. span ) , & mut applicability )
159
+ suggest_slice. snippet ( cx, Some ( elem. span ) , Some ( len. span ) )
170
160
} else {
171
161
return ;
172
162
}
@@ -180,13 +170,16 @@ impl UselessVec {
180
170
} else {
181
171
None
182
172
} ;
183
- suggest_slice. snippet ( cx, args_span, None , & mut applicability )
173
+ suggest_slice. snippet ( cx, args_span, None )
184
174
} ,
185
175
} ;
186
176
187
- self . span_to_lint_map
188
- . entry ( span)
189
- . or_insert ( Some ( ( hir_id, suggest_slice, snippet, applicability) ) ) ;
177
+ self . span_to_lint_map . entry ( span) . or_insert ( Some ( (
178
+ hir_id,
179
+ suggest_slice,
180
+ snippet,
181
+ Applicability :: MachineApplicable ,
182
+ ) ) ) ;
190
183
}
191
184
}
192
185
@@ -206,24 +199,16 @@ impl SuggestedType {
206
199
}
207
200
}
208
201
209
- fn snippet (
210
- self ,
211
- cx : & LateContext < ' _ > ,
212
- args_span : Option < Span > ,
213
- len_span : Option < Span > ,
214
- app : & mut Applicability ,
215
- ) -> String {
216
- let args = args_span
217
- . map ( |sp| snippet_with_applicability ( cx, sp, ".." , app) )
218
- . unwrap_or_default ( ) ;
202
+ fn snippet ( self , cx : & LateContext < ' _ > , args_span : Option < Span > , len_span : Option < Span > ) -> String {
203
+ let maybe_args = args_span. and_then ( |sp| snippet_opt ( cx, sp) ) . unwrap_or_default ( ) ;
219
204
let maybe_len = len_span
220
- . map ( |sp| format ! ( "; {}" , snippet_with_applicability ( cx , sp , "len" , app ) ) )
205
+ . and_then ( |sp| snippet_opt ( cx , sp ) . map ( |s| format ! ( "; {s}" ) ) )
221
206
. unwrap_or_default ( ) ;
222
207
223
208
match self {
224
- Self :: SliceRef ( Mutability :: Mut ) => format ! ( "&mut [{args }{maybe_len}]" ) ,
225
- Self :: SliceRef ( Mutability :: Not ) => format ! ( "&[{args }{maybe_len}]" ) ,
226
- Self :: Array => format ! ( "[{args }{maybe_len}]" ) ,
209
+ Self :: SliceRef ( Mutability :: Mut ) => format ! ( "&mut [{maybe_args }{maybe_len}]" ) ,
210
+ Self :: SliceRef ( Mutability :: Not ) => format ! ( "&[{maybe_args }{maybe_len}]" ) ,
211
+ Self :: Array => format ! ( "[{maybe_args }{maybe_len}]" ) ,
227
212
}
228
213
}
229
214
}
@@ -249,3 +234,13 @@ pub fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
249
234
is_trait_method ( cx, e, sym:: IntoIterator )
250
235
}
251
236
}
237
+
238
+ fn suggest_type ( expr : & Expr < ' _ > ) -> SuggestedType {
239
+ if let ExprKind :: AddrOf ( BorrowKind :: Ref , mutability, _) = expr. kind {
240
+ // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.)
241
+ SuggestedType :: SliceRef ( mutability)
242
+ } else {
243
+ // `expr` is the `vec![_]` expansion, so suggest `[_]`
244
+ SuggestedType :: Array
245
+ }
246
+ }
0 commit comments