@@ -4,7 +4,7 @@ use std::ops::ControlFlow;
44use clippy_config:: msrvs:: { self , Msrv } ;
55use clippy_utils:: consts:: { constant, Constant } ;
66use clippy_utils:: diagnostics:: span_lint_hir_and_then;
7- use clippy_utils:: source:: snippet_with_applicability ;
7+ use clippy_utils:: source:: snippet_opt ;
88use clippy_utils:: ty:: is_copy;
99use clippy_utils:: visitors:: for_each_local_use_after_expr;
1010use clippy_utils:: { get_parent_expr, higher, is_trait_method} ;
@@ -57,6 +57,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
5757 let Some ( vec_args) = higher:: VecArgs :: hir ( cx, expr. peel_borrows ( ) ) else {
5858 return ;
5959 } ;
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 ) ;
6062
6163 match cx. tcx . parent_hir_node ( expr. hir_id ) {
6264 // search for `let foo = vec![_]` expressions where all uses of `foo`
@@ -84,41 +86,31 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
8486 } )
8587 . is_continue ( ) ;
8688
87- let span = expr. span . ctxt ( ) . outer_expn_data ( ) . call_site ;
8889 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 ) ;
9091 } else {
91- self . span_to_lint_map . insert ( span , None ) ;
92+ self . span_to_lint_map . insert ( callsite , None ) ;
9293 }
9394 } ,
9495 // if the local pattern has a specified type, do not lint.
9596 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 ) ;
9898 } ,
9999 // search for `for _ in vec![...]`
100100 Node :: Expr ( Expr { span, .. } )
101101 if span. is_desugaring ( DesugaringKind :: ForLoop ) && self . msrv . meets ( msrvs:: ARRAY_INTO_ITERATOR ) =>
102102 {
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) ;
106105 } ,
107106 // search for `&vec![_]` or `vec![_]` expressions where the adjusted type is `&[_]`
108107 _ => {
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) ;
117109
118110 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) ;
120112 } else {
121- self . span_to_lint_map . insert ( span , None ) ;
113+ self . span_to_lint_map . insert ( callsite , None ) ;
122114 }
123115 } ,
124116 }
@@ -151,8 +143,6 @@ impl UselessVec {
151143 return ;
152144 }
153145
154- let mut applicability = Applicability :: MachineApplicable ;
155-
156146 let snippet = match * vec_args {
157147 higher:: VecArgs :: Repeat ( elem, len) => {
158148 if let Some ( Constant :: Int ( len_constant) ) = constant ( cx, cx. typeck_results ( ) , len) {
@@ -166,7 +156,7 @@ impl UselessVec {
166156 return ;
167157 }
168158
169- suggest_slice. snippet ( cx, Some ( elem. span ) , Some ( len. span ) , & mut applicability )
159+ suggest_slice. snippet ( cx, Some ( elem. span ) , Some ( len. span ) )
170160 } else {
171161 return ;
172162 }
@@ -180,13 +170,16 @@ impl UselessVec {
180170 } else {
181171 None
182172 } ;
183- suggest_slice. snippet ( cx, args_span, None , & mut applicability )
173+ suggest_slice. snippet ( cx, args_span, None )
184174 } ,
185175 } ;
186176
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+ ) ) ) ;
190183 }
191184}
192185
@@ -206,24 +199,16 @@ impl SuggestedType {
206199 }
207200 }
208201
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 ( ) ;
219204 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}" ) ) )
221206 . unwrap_or_default ( ) ;
222207
223208 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}]" ) ,
227212 }
228213 }
229214}
@@ -249,3 +234,13 @@ pub fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
249234 is_trait_method ( cx, e, sym:: IntoIterator )
250235 }
251236}
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