@@ -8,7 +8,6 @@ use clippy_utils::ty::is_copy;
8
8
use clippy_utils:: visitors:: for_each_local_use_after_expr;
9
9
use clippy_utils:: { get_parent_expr, higher, is_trait_method} ;
10
10
use if_chain:: if_chain;
11
- use rustc_ast:: BindingAnnotation ;
12
11
use rustc_errors:: Applicability ;
13
12
use rustc_hir:: { BorrowKind , Expr , ExprKind , Mutability , Node , PatKind } ;
14
13
use rustc_lint:: { LateContext , LateLintPass } ;
@@ -54,11 +53,7 @@ declare_clippy_lint! {
54
53
impl_lint_pass ! ( UselessVec => [ USELESS_VEC ] ) ;
55
54
56
55
fn adjusts_to_slice ( cx : & LateContext < ' _ > , e : & Expr < ' _ > ) -> bool {
57
- if let ty:: Ref ( _, ty, _) = cx. typeck_results ( ) . expr_ty_adjusted ( e) . kind ( ) {
58
- ty. is_slice ( )
59
- } else {
60
- false
61
- }
56
+ matches ! ( cx. typeck_results( ) . expr_ty_adjusted( e) . kind( ) , ty:: Ref ( _, ty, _) if ty. is_slice( ) )
62
57
}
63
58
64
59
/// Checks if the given expression is a method call to a `Vec` method
@@ -76,13 +71,21 @@ fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
76
71
77
72
impl < ' tcx > LateLintPass < ' tcx > for UselessVec {
78
73
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
79
- // search for `&vec![_]` expressions where the adjusted type is `&[_]`
74
+ // search for `&vec![_]` or `vec![_]` expressions where the adjusted type is `&[_]`
80
75
if_chain ! {
81
76
if adjusts_to_slice( cx, expr) ;
82
- if let ExprKind :: AddrOf ( BorrowKind :: Ref , mutability, addressee) = expr. kind;
83
- if let Some ( vec_args) = higher:: VecArgs :: hir( cx, addressee) ;
77
+ if let Some ( vec_args) = higher:: VecArgs :: hir( cx, expr. peel_borrows( ) ) ;
84
78
then {
85
- self . check_vec_macro( cx, & vec_args, mutability, expr. span, SuggestSlice :: Yes ) ;
79
+ let ( suggest_slice, span) = if let ExprKind :: AddrOf ( BorrowKind :: Ref , mutability, _) = expr. kind {
80
+ // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.)
81
+ ( SuggestedType :: SliceRef ( mutability) , expr. span)
82
+ } else {
83
+ // `expr` is the `vec![_]` expansion, so suggest `[_]`
84
+ // and also use the span of the actual `vec![_]` expression
85
+ ( SuggestedType :: Array , expr. span. ctxt( ) . outer_expn_data( ) . call_site)
86
+ } ;
87
+
88
+ self . check_vec_macro( cx, & vec_args, span, suggest_slice) ;
86
89
}
87
90
}
88
91
@@ -93,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
93
96
// for now ignore locals with type annotations.
94
97
// this is to avoid compile errors when doing the suggestion here: let _: Vec<_> = vec![..];
95
98
&& local. ty . is_none ( )
96
- && let PatKind :: Binding ( BindingAnnotation ( _ , mutbl ) , id, ..) = local. pat . kind
99
+ && let PatKind :: Binding ( _ , id, ..) = local. pat . kind
97
100
&& is_copy ( cx, vec_type ( cx. typeck_results ( ) . expr_ty_adjusted ( expr) ) )
98
101
{
99
102
let only_slice_uses = for_each_local_use_after_expr ( cx, id, expr. hir_id , |expr| {
@@ -113,9 +116,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
113
116
self . check_vec_macro (
114
117
cx,
115
118
& vec_args,
116
- mutbl,
117
119
expr. span . ctxt ( ) . outer_expn_data ( ) . call_site ,
118
- SuggestSlice :: No
120
+ SuggestedType :: Array
119
121
) ;
120
122
}
121
123
}
@@ -128,7 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
128
130
then {
129
131
// report the error around the `vec!` not inside `<std macros>:`
130
132
let span = arg. span. ctxt( ) . outer_expn_data( ) . call_site;
131
- self . check_vec_macro( cx, & vec_args, Mutability :: Not , span, SuggestSlice :: No ) ;
133
+ self . check_vec_macro( cx, & vec_args, span, SuggestedType :: Array ) ;
132
134
}
133
135
}
134
136
}
@@ -137,29 +139,23 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
137
139
}
138
140
139
141
#[ derive( Copy , Clone ) ]
140
- enum SuggestSlice {
142
+ enum SuggestedType {
141
143
/// Suggest using a slice `&[..]` / `&mut [..]`
142
- Yes ,
144
+ SliceRef ( Mutability ) ,
143
145
/// Suggest using an array: `[..]`
144
- No ,
146
+ Array ,
145
147
}
146
148
147
149
impl UselessVec {
148
150
fn check_vec_macro < ' tcx > (
149
151
& mut self ,
150
152
cx : & LateContext < ' tcx > ,
151
153
vec_args : & higher:: VecArgs < ' tcx > ,
152
- mutability : Mutability ,
153
154
span : Span ,
154
- suggest_slice : SuggestSlice ,
155
+ suggest_slice : SuggestedType ,
155
156
) {
156
157
let mut applicability = Applicability :: MachineApplicable ;
157
158
158
- let ( borrow_prefix_mut, borrow_prefix) = match suggest_slice {
159
- SuggestSlice :: Yes => ( "&mut " , "&" ) ,
160
- SuggestSlice :: No => ( "" , "" ) ,
161
- } ;
162
-
163
159
let snippet = match * vec_args {
164
160
higher:: VecArgs :: Repeat ( elem, len) => {
165
161
if let Some ( Constant :: Int ( len_constant) ) = constant ( cx, cx. typeck_results ( ) , len) {
@@ -168,21 +164,13 @@ impl UselessVec {
168
164
return ;
169
165
}
170
166
171
- match mutability {
172
- Mutability :: Mut => {
173
- format ! (
174
- "{borrow_prefix_mut}[{}; {}]" ,
175
- snippet_with_applicability( cx, elem. span, "elem" , & mut applicability) ,
176
- snippet_with_applicability( cx, len. span, "len" , & mut applicability)
177
- )
178
- } ,
179
- Mutability :: Not => {
180
- format ! (
181
- "{borrow_prefix}[{}; {}]" ,
182
- snippet_with_applicability( cx, elem. span, "elem" , & mut applicability) ,
183
- snippet_with_applicability( cx, len. span, "len" , & mut applicability)
184
- )
185
- } ,
167
+ let elem = snippet_with_applicability ( cx, elem. span , "elem" , & mut applicability) ;
168
+ let len = snippet_with_applicability ( cx, len. span , "len" , & mut applicability) ;
169
+
170
+ match suggest_slice {
171
+ SuggestedType :: SliceRef ( Mutability :: Mut ) => format ! ( "&mut [{elem}; {len}]" ) ,
172
+ SuggestedType :: SliceRef ( Mutability :: Not ) => format ! ( "&[{elem}; {len}]" ) ,
173
+ SuggestedType :: Array => format ! ( "[{elem}; {len}]" ) ,
186
174
}
187
175
} else {
188
176
return ;
@@ -194,25 +182,24 @@ impl UselessVec {
194
182
return ;
195
183
}
196
184
let span = args[ 0 ] . span . to ( last. span ) ;
185
+ let args = snippet_with_applicability ( cx, span, ".." , & mut applicability) ;
197
186
198
- match mutability {
199
- Mutability :: Mut => {
200
- format ! (
201
- "{borrow_prefix_mut}[{}]" ,
202
- snippet_with_applicability ( cx , span , ".." , & mut applicability )
203
- )
187
+ match suggest_slice {
188
+ SuggestedType :: SliceRef ( Mutability :: Mut ) => {
189
+ format ! ( "&mut [{args}]" )
190
+ } ,
191
+ SuggestedType :: SliceRef ( Mutability :: Not ) => {
192
+ format ! ( "&[{args}]" )
204
193
} ,
205
- Mutability :: Not => {
206
- format ! (
207
- "{borrow_prefix}[{}]" ,
208
- snippet_with_applicability( cx, span, ".." , & mut applicability)
209
- )
194
+ SuggestedType :: Array => {
195
+ format ! ( "[{args}]" )
210
196
} ,
211
197
}
212
198
} else {
213
- match mutability {
214
- Mutability :: Mut => format ! ( "{borrow_prefix_mut}[]" ) ,
215
- Mutability :: Not => format ! ( "{borrow_prefix}[]" ) ,
199
+ match suggest_slice {
200
+ SuggestedType :: SliceRef ( Mutability :: Mut ) => "&mut []" . to_owned ( ) ,
201
+ SuggestedType :: SliceRef ( Mutability :: Not ) => "&[]" . to_owned ( ) ,
202
+ SuggestedType :: Array => "[]" . to_owned ( ) ,
216
203
}
217
204
}
218
205
} ,
@@ -226,8 +213,8 @@ impl UselessVec {
226
213
& format ! (
227
214
"you can use {} directly" ,
228
215
match suggest_slice {
229
- SuggestSlice :: Yes => "a slice" ,
230
- SuggestSlice :: No => "an array" ,
216
+ SuggestedType :: SliceRef ( _ ) => "a slice" ,
217
+ SuggestedType :: Array => "an array" ,
231
218
}
232
219
) ,
233
220
snippet,
0 commit comments