1
1
use clippy_utils:: consts:: { constant, Constant } ;
2
2
use clippy_utils:: diagnostics:: span_lint_and_then;
3
3
use clippy_utils:: higher:: IfLet ;
4
- use clippy_utils:: ty:: implements_trait ;
5
- use clippy_utils:: { in_macro , is_expn_of, is_lint_allowed, meets_msrv, msrvs, path_to_local} ;
4
+ use clippy_utils:: ty:: is_copy ;
5
+ use clippy_utils:: { is_expn_of, is_lint_allowed, meets_msrv, msrvs, path_to_local} ;
6
6
use if_chain:: if_chain;
7
7
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
8
8
use rustc_errors:: Applicability ;
@@ -46,21 +46,22 @@ declare_clippy_lint! {
46
46
/// println!("{}", first);
47
47
/// }
48
48
/// ```
49
+ #[ clippy:: version = "1.58.0" ]
49
50
pub INDEX_REFUTABLE_SLICE ,
50
51
nursery,
51
52
"avoid indexing on slices which could be destructed"
52
53
}
53
54
54
55
#[ derive( Copy , Clone ) ]
55
56
pub struct IndexRefutableSlice {
56
- indexing_limit : u64 ,
57
+ max_suggested_slice : u64 ,
57
58
msrv : Option < RustcVersion > ,
58
59
}
59
60
60
61
impl IndexRefutableSlice {
61
62
pub fn new ( max_suggested_slice_pattern_length : u64 , msrv : Option < RustcVersion > ) -> Self {
62
63
Self {
63
- indexing_limit : max_suggested_slice_pattern_length - 1 ,
64
+ max_suggested_slice : max_suggested_slice_pattern_length,
64
65
msrv,
65
66
}
66
67
}
@@ -71,14 +72,14 @@ impl_lint_pass!(IndexRefutableSlice => [INDEX_REFUTABLE_SLICE]);
71
72
impl LateLintPass < ' _ > for IndexRefutableSlice {
72
73
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx hir:: Expr < ' _ > ) {
73
74
if_chain ! {
74
- if !in_macro ( expr. span) || is_expn_of( expr. span, "if_chain" ) . is_some( ) ;
75
+ if !expr. span. from_expansion ( ) || is_expn_of( expr. span, "if_chain" ) . is_some( ) ;
75
76
if let Some ( IfLet { let_pat, if_then, ..} ) = IfLet :: hir( cx, expr) ;
76
77
if !is_lint_allowed( cx, INDEX_REFUTABLE_SLICE , expr. hir_id) ;
77
78
if meets_msrv( self . msrv. as_ref( ) , & msrvs:: SLICE_PATTERNS ) ;
78
79
79
80
let found_slices = find_slice_values( cx, let_pat) ;
80
81
if !found_slices. is_empty( ) ;
81
- let filtered_slices = filter_lintable_slices( cx, found_slices, self . indexing_limit , if_then) ;
82
+ let filtered_slices = filter_lintable_slices( cx, found_slices, self . max_suggested_slice , if_then) ;
82
83
if !filtered_slices. is_empty( ) ;
83
84
then {
84
85
for slice in filtered_slices. values( ) {
@@ -117,12 +118,7 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxHashMap<hir:
117
118
// The values need to use the `ref` keyword if they can't be copied.
118
119
// This will need to be adjusted if the lint want to support multable access in the future
119
120
let src_is_ref = bound_ty. is_ref ( ) && binding != hir:: BindingAnnotation :: Ref ;
120
- let is_copy = cx
121
- . tcx
122
- . lang_items ( )
123
- . copy_trait ( )
124
- . map_or ( false , |trait_id| implements_trait ( cx, inner_ty, trait_id, & [ ] ) ) ;
125
- let needs_ref = !( src_is_ref || is_copy) ;
121
+ let needs_ref = !( src_is_ref || is_copy ( cx, inner_ty) ) ;
126
122
127
123
let slice_info = slices
128
124
. entry ( value_hir_id)
@@ -183,10 +179,9 @@ fn lint_slice(cx: &LateContext<'_>, slice: &SliceLintInformation) {
183
179
Applicability :: MaybeIncorrect ,
184
180
) ;
185
181
186
- // I thought about adding a note to the lint message to inform the user that these
187
- // refactorings will remove the index expression. However, I decided against this,
188
- // as `filter_lintable_slices` will only return slices where all access indices are
189
- // known at compile time. The removal should therefore not have any side effects.
182
+ // The lint message doesn't contain a warning about the removed index expression,
183
+ // since `filter_lintable_slices` will only return slices where all access indices
184
+ // are known at compile time. Therefore, they can be removed without side effects.
190
185
} ,
191
186
) ;
192
187
}
@@ -214,13 +209,13 @@ impl SliceLintInformation {
214
209
fn filter_lintable_slices < ' a , ' tcx > (
215
210
cx : & ' a LateContext < ' tcx > ,
216
211
slice_lint_info : FxHashMap < hir:: HirId , SliceLintInformation > ,
217
- index_limit : u64 ,
212
+ max_suggested_slice : u64 ,
218
213
scope : & ' tcx hir:: Expr < ' tcx > ,
219
214
) -> FxHashMap < hir:: HirId , SliceLintInformation > {
220
215
let mut visitor = SliceIndexLintingVisitor {
221
216
cx,
222
217
slice_lint_info,
223
- index_limit ,
218
+ max_suggested_slice ,
224
219
} ;
225
220
226
221
intravisit:: walk_expr ( & mut visitor, scope) ;
@@ -234,7 +229,7 @@ fn filter_lintable_slices<'a, 'tcx>(
234
229
struct SliceIndexLintingVisitor < ' a , ' tcx > {
235
230
cx : & ' a LateContext < ' tcx > ,
236
231
slice_lint_info : FxHashMap < hir:: HirId , SliceLintInformation > ,
237
- index_limit : u64 ,
232
+ max_suggested_slice : u64 ,
238
233
}
239
234
240
235
impl < ' a , ' tcx > Visitor < ' tcx > for SliceIndexLintingVisitor < ' a , ' tcx > {
@@ -249,7 +244,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
249
244
let Self {
250
245
cx,
251
246
ref mut slice_lint_info,
252
- index_limit ,
247
+ max_suggested_slice ,
253
248
} = * self ;
254
249
255
250
if_chain ! {
@@ -264,7 +259,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
264
259
if let hir:: ExprKind :: Index ( _, index_expr) = parent_expr. kind;
265
260
if let Some ( ( Constant :: Int ( index_value) , _) ) = constant( cx, cx. typeck_results( ) , index_expr) ;
266
261
if let Ok ( index_value) = index_value. try_into( ) ;
267
- if index_value <= index_limit ;
262
+ if index_value < max_suggested_slice ;
268
263
269
264
// Make sure that this slice index is read only
270
265
let maybe_addrof_id = map. get_parent_node( parent_id) ;
0 commit comments