Skip to content

Commit c78a1f4

Browse files
committed
Remove @no-rustfix for if_let_slice_binding and slice_indexing_in_macro
1 parent d983222 commit c78a1f4

6 files changed

+217
-15
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#![deny(clippy::index_refutable_slice)]
2+
#![allow(clippy::uninlined_format_args, clippy::needless_lifetimes)]
3+
4+
enum SomeEnum<T> {
5+
One(T),
6+
Two(T),
7+
Three(T),
8+
Four(T),
9+
}
10+
11+
fn lintable_examples() {
12+
// Try with reference
13+
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
14+
if let Some([slice_0, ..]) = slice {
15+
//~^ ERROR: this binding can be a slice pattern to avoid indexing
16+
println!("{}", slice_0);
17+
}
18+
19+
// Try with copy
20+
let slice: Option<[u32; 3]> = Some([1, 2, 3]);
21+
if let Some([slice_0, ..]) = slice {
22+
//~^ ERROR: this binding can be a slice pattern to avoid indexing
23+
println!("{}", slice_0);
24+
}
25+
26+
// Try with long slice and small indices
27+
let slice: Option<[u32; 9]> = Some([1, 2, 3, 4, 5, 6, 7, 8, 9]);
28+
if let Some([slice_0, _, slice_2, ..]) = slice {
29+
//~^ ERROR: this binding can be a slice pattern to avoid indexing
30+
println!("{}", slice_2);
31+
println!("{}", slice_0);
32+
}
33+
34+
// Multiple bindings
35+
let slice_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([5, 6, 7]);
36+
if let SomeEnum::One([slice_0, ..]) | SomeEnum::Three([slice_0, ..]) = slice_wrapped {
37+
//~^ ERROR: this binding can be a slice pattern to avoid indexing
38+
println!("{}", slice_0);
39+
}
40+
41+
// Two lintable slices in one if let
42+
let a_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([9, 5, 1]);
43+
let b_wrapped: Option<[u32; 2]> = Some([4, 6]);
44+
if let (SomeEnum::Three([_, _, a_2, ..]), Some([_, b_1, ..])) = (a_wrapped, b_wrapped) {
45+
//~^ ERROR: this binding can be a slice pattern to avoid indexing
46+
//~| ERROR: this binding can be a slice pattern to avoid indexing
47+
println!("{} -> {}", a_2, b_1);
48+
}
49+
50+
// This requires the slice values to be borrowed as the slice values can only be
51+
// borrowed and `String` doesn't implement copy
52+
let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]);
53+
if let Some([_, ref slice_1, ..]) = slice {
54+
//~^ ERROR: this binding can be a slice pattern to avoid indexing
55+
println!("{:?}", slice_1);
56+
}
57+
println!("{:?}", slice);
58+
59+
// This should not suggest using the `ref` keyword as the scrutinee is already
60+
// a reference
61+
let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]);
62+
if let Some([slice_0, ..]) = &slice {
63+
//~^ ERROR: this binding can be a slice pattern to avoid indexing
64+
println!("{:?}", slice_0);
65+
}
66+
println!("{:?}", slice);
67+
}
68+
69+
fn slice_index_above_limit() {
70+
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
71+
72+
if let Some(slice) = slice {
73+
// Would cause a panic, IDK
74+
println!("{}", slice[7]);
75+
}
76+
}
77+
78+
fn slice_is_used() {
79+
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
80+
if let Some(slice) = slice {
81+
println!("{:?}", slice.len());
82+
}
83+
84+
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
85+
if let Some(slice) = slice {
86+
println!("{:?}", slice.to_vec());
87+
}
88+
89+
let opt: Option<[String; 2]> = Some([String::from("Hello"), String::from("world")]);
90+
if let Some(slice) = opt {
91+
if !slice.is_empty() {
92+
println!("first: {}", slice[0]);
93+
}
94+
}
95+
}
96+
97+
/// The slice is used by an external function and should therefore not be linted
98+
fn check_slice_as_arg() {
99+
fn is_interesting<T>(slice: &[T; 2]) -> bool {
100+
!slice.is_empty()
101+
}
102+
103+
let slice_wrapped: Option<[String; 2]> = Some([String::from("Hello"), String::from("world")]);
104+
if let Some(slice) = &slice_wrapped {
105+
if is_interesting(slice) {
106+
println!("This is interesting {}", slice[0]);
107+
}
108+
}
109+
println!("{:?}", slice_wrapped);
110+
}
111+
112+
fn check_slice_in_struct() {
113+
#[derive(Debug)]
114+
struct Wrapper<'a> {
115+
inner: Option<&'a [String]>,
116+
is_awesome: bool,
117+
}
118+
119+
impl<'a> Wrapper<'a> {
120+
fn is_super_awesome(&self) -> bool {
121+
self.is_awesome
122+
}
123+
}
124+
125+
let inner = &[String::from("New"), String::from("World")];
126+
let wrap = Wrapper {
127+
inner: Some(inner),
128+
is_awesome: true,
129+
};
130+
131+
// Test 1: Field access
132+
if let Some([slice_0, ..]) = wrap.inner {
133+
//~^ ERROR: this binding can be a slice pattern to avoid indexing
134+
if wrap.is_awesome {
135+
println!("This is awesome! {}", slice_0);
136+
}
137+
}
138+
139+
// Test 2: function access
140+
if let Some([slice_0, ..]) = wrap.inner {
141+
//~^ ERROR: this binding can be a slice pattern to avoid indexing
142+
if wrap.is_super_awesome() {
143+
println!("This is super awesome! {}", slice_0);
144+
}
145+
}
146+
println!("Complete wrap: {:?}", wrap);
147+
}
148+
149+
/// This would be a nice additional feature to have in the future, but adding it
150+
/// now would make the PR too large. This is therefore only a test that we don't
151+
/// lint cases we can't make a reasonable suggestion for
152+
fn mutable_slice_index() {
153+
// Mut access
154+
let mut slice: Option<[String; 1]> = Some([String::from("Penguin")]);
155+
if let Some(ref mut slice) = slice {
156+
slice[0] = String::from("Mr. Penguin");
157+
}
158+
println!("Use after modification: {:?}", slice);
159+
160+
// Mut access on reference
161+
let mut slice: Option<[String; 1]> = Some([String::from("Cat")]);
162+
if let Some(slice) = &mut slice {
163+
slice[0] = String::from("Lord Meow Meow");
164+
}
165+
println!("Use after modification: {:?}", slice);
166+
}
167+
168+
/// The lint will ignore bindings with sub patterns as it would be hard
169+
/// to build correct suggestions for these instances :)
170+
fn binding_with_sub_pattern() {
171+
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
172+
if let Some(slice @ [_, _, _]) = slice {
173+
println!("{:?}", slice[2]);
174+
}
175+
}
176+
177+
fn main() {}

tests/ui/index_refutable_slice/if_let_slice_binding.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#![deny(clippy::index_refutable_slice)]
22
#![allow(clippy::uninlined_format_args, clippy::needless_lifetimes)]
33

4-
//@no-rustfix: need to change the suggestion to a multipart suggestion
5-
64
enum SomeEnum<T> {
75
One(T),
86
Two(T),

tests/ui/index_refutable_slice/if_let_slice_binding.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: this binding can be a slice pattern to avoid indexing
2-
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:16:17
2+
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:14:17
33
|
44
LL | if let Some(slice) = slice {
55
| ^^^^^
@@ -17,7 +17,7 @@ LL ~ println!("{}", slice_0);
1717
|
1818

1919
error: this binding can be a slice pattern to avoid indexing
20-
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:23:17
20+
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:21:17
2121
|
2222
LL | if let Some(slice) = slice {
2323
| ^^^^^
@@ -30,7 +30,7 @@ LL ~ println!("{}", slice_0);
3030
|
3131

3232
error: this binding can be a slice pattern to avoid indexing
33-
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:30:17
33+
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:28:17
3434
|
3535
LL | if let Some(slice) = slice {
3636
| ^^^^^
@@ -44,7 +44,7 @@ LL ~ println!("{}", slice_0);
4444
|
4545

4646
error: this binding can be a slice pattern to avoid indexing
47-
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:38:26
47+
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:36:26
4848
|
4949
LL | if let SomeEnum::One(slice) | SomeEnum::Three(slice) = slice_wrapped {
5050
| ^^^^^
@@ -57,7 +57,7 @@ LL ~ println!("{}", slice_0);
5757
|
5858

5959
error: this binding can be a slice pattern to avoid indexing
60-
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:46:29
60+
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:44:29
6161
|
6262
LL | if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) {
6363
| ^
@@ -71,7 +71,7 @@ LL ~ println!("{} -> {}", a_2, b[1]);
7171
|
7272

7373
error: this binding can be a slice pattern to avoid indexing
74-
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:46:38
74+
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:44:38
7575
|
7676
LL | if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) {
7777
| ^
@@ -85,7 +85,7 @@ LL ~ println!("{} -> {}", a[2], b_1);
8585
|
8686

8787
error: this binding can be a slice pattern to avoid indexing
88-
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:55:21
88+
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:53:21
8989
|
9090
LL | if let Some(ref slice) = slice {
9191
| ^^^^^
@@ -98,7 +98,7 @@ LL ~ println!("{:?}", slice_1);
9898
|
9999

100100
error: this binding can be a slice pattern to avoid indexing
101-
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:64:17
101+
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:62:17
102102
|
103103
LL | if let Some(slice) = &slice {
104104
| ^^^^^
@@ -111,7 +111,7 @@ LL ~ println!("{:?}", slice_0);
111111
|
112112

113113
error: this binding can be a slice pattern to avoid indexing
114-
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:134:17
114+
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:132:17
115115
|
116116
LL | if let Some(slice) = wrap.inner {
117117
| ^^^^^
@@ -125,7 +125,7 @@ LL ~ println!("This is awesome! {}", slice_0);
125125
|
126126

127127
error: this binding can be a slice pattern to avoid indexing
128-
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:142:17
128+
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:140:17
129129
|
130130
LL | if let Some(slice) = wrap.inner {
131131
| ^^^^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#![deny(clippy::index_refutable_slice)]
2+
3+
extern crate if_chain;
4+
use if_chain::if_chain;
5+
6+
macro_rules! if_let_slice_macro {
7+
() => {
8+
// This would normally be linted
9+
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
10+
if let Some(slice) = slice {
11+
println!("{}", slice[0]);
12+
}
13+
};
14+
}
15+
16+
fn main() {
17+
// Don't lint this
18+
if_let_slice_macro!();
19+
20+
// Do lint this
21+
if_chain! {
22+
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
23+
if let Some([slice_0, ..]) = slice;
24+
//~^ ERROR: this binding can be a slice pattern to avoid indexing
25+
then {
26+
println!("{}", slice_0);
27+
}
28+
}
29+
}

tests/ui/index_refutable_slice/slice_indexing_in_macro.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#![deny(clippy::index_refutable_slice)]
22

3-
//@no-rustfix: need to change the suggestion to a multipart suggestion
4-
53
extern crate if_chain;
64
use if_chain::if_chain;
75

tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: this binding can be a slice pattern to avoid indexing
2-
--> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:25:21
2+
--> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:23:21
33
|
44
LL | if let Some(slice) = slice;
55
| ^^^^^

0 commit comments

Comments
 (0)