Skip to content

Commit 26419e6

Browse files
committed
Ignore slices with sub patterns in avoidable_slice_indexing
1 parent d403a4a commit 26419e6

File tree

3 files changed

+39
-25
lines changed

3 files changed

+39
-25
lines changed

clippy_lints/src/avoidable_slice_indexing.rs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -87,32 +87,44 @@ impl LateLintPass<'_> for AvoidableSliceIndexing {
8787
}
8888

8989
fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> Option<FxHashMap<hir::HirId, SliceLintInformation>> {
90-
// TODO xFrednet 2021-08-31: Test with sub pattern stuff
91-
90+
let mut removed_pat: FxHashSet<Symbol> = FxHashSet::default();
9291
let mut ident_to_id: FxHashMap<Symbol, hir::HirId> = FxHashMap::default();
9392
let mut slices: FxHashMap<hir::HirId, SliceLintInformation> = FxHashMap::default();
94-
pat.each_binding(|binding, hir_id, span, ident| {
95-
// We'll just ignore mut and ref mut for simplicity sake right now
96-
if let hir::BindingAnnotation::Mutable | hir::BindingAnnotation::RefMut = binding {
97-
return;
98-
}
93+
pat.walk_always(|pat| {
94+
if let hir::PatKind::Binding(binding, _, ident, sub_pat) = pat.kind {
95+
// We'll just ignore mut and ref mut for simplicity sake right now
96+
if let hir::BindingAnnotation::Mutable | hir::BindingAnnotation::RefMut = binding {
97+
return;
98+
}
99+
100+
// This block catches bindings with sub patterns. It would be hard to build a correct suggestion
101+
// for them and it's likely that the user knows what they are doing in such a case.
102+
if removed_pat.contains(&ident.name) {
103+
return;
104+
}
105+
if sub_pat.is_some() {
106+
removed_pat.insert(ident.name);
107+
ident_to_id.remove(&ident.name).map(|key| slices.remove(&key));
108+
return;
109+
}
99110

100-
let bound_ty = cx.typeck_results().node_type(hir_id);
101-
if let ty::Slice(inner_ty) | ty::Array(inner_ty, _) = bound_ty.peel_refs().kind() {
102-
// The values need to use the `ref` keyword if they can't be coppied.
103-
// This will need to be adjusted if the lint want to support multable access in the future
104-
let needs_ref = !bound_ty.is_ref()
105-
|| !cx
106-
.tcx
107-
.lang_items()
108-
.copy_trait()
109-
.map_or(false, |trait_id| implements_trait(cx, inner_ty, trait_id, &[]));
111+
let bound_ty = cx.typeck_results().node_type(pat.hir_id);
112+
if let ty::Slice(inner_ty) | ty::Array(inner_ty, _) = bound_ty.peel_refs().kind() {
113+
// The values need to use the `ref` keyword if they can't be coppied.
114+
// This will need to be adjusted if the lint want to support multable access in the future
115+
let needs_ref = !bound_ty.is_ref()
116+
|| !cx
117+
.tcx
118+
.lang_items()
119+
.copy_trait()
120+
.map_or(false, |trait_id| implements_trait(cx, inner_ty, trait_id, &[]));
110121

111-
let key = *ident_to_id.entry(ident.name).or_insert(hir_id);
112-
let slice_info = slices
113-
.entry(key)
114-
.or_insert_with(|| SliceLintInformation::new(ident, needs_ref));
115-
slice_info.pattern_spans.push(span);
122+
let key = *ident_to_id.entry(ident.name).or_insert(pat.hir_id);
123+
let slice_info = slices
124+
.entry(key)
125+
.or_insert_with(|| SliceLintInformation::new(ident, needs_ref));
126+
slice_info.pattern_spans.push(pat.span);
127+
}
116128
}
117129
});
118130

tests/ui/avoidable_slice_indexing/if_let_slice_destruction.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,12 @@ fn mutable_slice_index() {
9797
println!("Use after modification: {:?}", slice);
9898
}
9999

100-
fn complex_binding() {
100+
/// The lint will ignore bindings with sub patterns as it would be hard
101+
/// to build correct suggestions for these instances :)
102+
fn binding_with_sub_pattern() {
101103
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
102104
if let Some(slice @ [_, _, _]) = slice {
103-
println!("{:?}", slice[8]);
105+
println!("{:?}", slice[2]);
104106
}
105107
}
106108

tests/ui/avoidable_slice_indexing/slice_indexing_in_macro.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: this slice can be deconstructured to avoid indexing
2-
--> $DIR/slice_indexing_in_macro.rs:24:21
2+
--> $DIR/slice_indexing_in_macro.rs:23:21
33
|
44
LL | if let Some(slice) = slice;
55
| ^^^^^

0 commit comments

Comments
 (0)