Skip to content

Commit

Permalink
Remove @no-rustfix for if_let_slice_binding and slice_indexing_in_macro
Browse files Browse the repository at this point in the history
  • Loading branch information
scottgerring committed Nov 29, 2024
1 parent 4f343ae commit c07474b
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 15 deletions.
177 changes: 177 additions & 0 deletions tests/ui/index_refutable_slice/if_let_slice_binding.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#![deny(clippy::index_refutable_slice)]
#![allow(clippy::uninlined_format_args, clippy::needless_lifetimes)]

enum SomeEnum<T> {
One(T),
Two(T),
Three(T),
Four(T),
}

fn lintable_examples() {
// Try with reference
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some([slice_0, ..]) = slice {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{}", slice_0);
}

// Try with copy
let slice: Option<[u32; 3]> = Some([1, 2, 3]);
if let Some([slice_0, ..]) = slice {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{}", slice_0);
}

// Try with long slice and small indices
let slice: Option<[u32; 9]> = Some([1, 2, 3, 4, 5, 6, 7, 8, 9]);
if let Some([slice_0, _, slice_2, ..]) = slice {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{}", slice_2);
println!("{}", slice_0);
}

// Multiple bindings
let slice_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([5, 6, 7]);
if let SomeEnum::One([slice_0, ..]) | SomeEnum::Three([slice_0, ..]) = slice_wrapped {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{}", slice_0);
}

// Two lintable slices in one if let
let a_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([9, 5, 1]);
let b_wrapped: Option<[u32; 2]> = Some([4, 6]);
if let (SomeEnum::Three([_, _, a_2, ..]), Some([_, b_1, ..])) = (a_wrapped, b_wrapped) {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
//~| ERROR: this binding can be a slice pattern to avoid indexing
println!("{} -> {}", a_2, b_1);
}

// This requires the slice values to be borrowed as the slice values can only be
// borrowed and `String` doesn't implement copy
let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]);
if let Some([_, ref slice_1, ..]) = slice {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{:?}", slice_1);
}
println!("{:?}", slice);

// This should not suggest using the `ref` keyword as the scrutinee is already
// a reference
let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]);
if let Some([slice_0, ..]) = &slice {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{:?}", slice_0);
}
println!("{:?}", slice);
}

fn slice_index_above_limit() {
let slice: Option<&[u32]> = Some(&[1, 2, 3]);

if let Some(slice) = slice {
// Would cause a panic, IDK
println!("{}", slice[7]);
}
}

fn slice_is_used() {
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some(slice) = slice {
println!("{:?}", slice.len());
}

let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some(slice) = slice {
println!("{:?}", slice.to_vec());
}

let opt: Option<[String; 2]> = Some([String::from("Hello"), String::from("world")]);
if let Some(slice) = opt {
if !slice.is_empty() {
println!("first: {}", slice[0]);
}
}
}

/// The slice is used by an external function and should therefore not be linted
fn check_slice_as_arg() {
fn is_interesting<T>(slice: &[T; 2]) -> bool {
!slice.is_empty()
}

let slice_wrapped: Option<[String; 2]> = Some([String::from("Hello"), String::from("world")]);
if let Some(slice) = &slice_wrapped {
if is_interesting(slice) {
println!("This is interesting {}", slice[0]);
}
}
println!("{:?}", slice_wrapped);
}

fn check_slice_in_struct() {
#[derive(Debug)]
struct Wrapper<'a> {
inner: Option<&'a [String]>,
is_awesome: bool,
}

impl<'a> Wrapper<'a> {
fn is_super_awesome(&self) -> bool {
self.is_awesome
}
}

let inner = &[String::from("New"), String::from("World")];
let wrap = Wrapper {
inner: Some(inner),
is_awesome: true,
};

// Test 1: Field access
if let Some([slice_0, ..]) = wrap.inner {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
if wrap.is_awesome {
println!("This is awesome! {}", slice_0);
}
}

// Test 2: function access
if let Some([slice_0, ..]) = wrap.inner {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
if wrap.is_super_awesome() {
println!("This is super awesome! {}", slice_0);
}
}
println!("Complete wrap: {:?}", wrap);
}

/// This would be a nice additional feature to have in the future, but adding it
/// now would make the PR too large. This is therefore only a test that we don't
/// lint cases we can't make a reasonable suggestion for
fn mutable_slice_index() {
// Mut access
let mut slice: Option<[String; 1]> = Some([String::from("Penguin")]);
if let Some(ref mut slice) = slice {
slice[0] = String::from("Mr. Penguin");
}
println!("Use after modification: {:?}", slice);

// Mut access on reference
let mut slice: Option<[String; 1]> = Some([String::from("Cat")]);
if let Some(slice) = &mut slice {
slice[0] = String::from("Lord Meow Meow");
}
println!("Use after modification: {:?}", slice);
}

/// The lint will ignore bindings with sub patterns as it would be hard
/// to build correct suggestions for these instances :)
fn binding_with_sub_pattern() {
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some(slice @ [_, _, _]) = slice {
println!("{:?}", slice[2]);
}
}

fn main() {}
2 changes: 0 additions & 2 deletions tests/ui/index_refutable_slice/if_let_slice_binding.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#![deny(clippy::index_refutable_slice)]
#![allow(clippy::uninlined_format_args, clippy::needless_lifetimes)]

//@no-rustfix: need to change the suggestion to a multipart suggestion

enum SomeEnum<T> {
One(T),
Two(T),
Expand Down
20 changes: 10 additions & 10 deletions tests/ui/index_refutable_slice/if_let_slice_binding.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:16:17
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:14:17
|
LL | if let Some(slice) = slice {
| ^^^^^
Expand All @@ -17,7 +17,7 @@ LL ~ println!("{}", slice_0);
|

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

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

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

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

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

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

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

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

error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:142:17
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:140:17
|
LL | if let Some(slice) = wrap.inner {
| ^^^^^
Expand Down
29 changes: 29 additions & 0 deletions tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#![deny(clippy::index_refutable_slice)]

extern crate if_chain;
use if_chain::if_chain;

macro_rules! if_let_slice_macro {
() => {
// This would normally be linted
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some(slice) = slice {
println!("{}", slice[0]);
}
};
}

fn main() {
// Don't lint this
if_let_slice_macro!();

// Do lint this
if_chain! {
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some([slice_0, ..]) = slice;
//~^ ERROR: this binding can be a slice pattern to avoid indexing
then {
println!("{}", slice_0);
}
}
}
2 changes: 0 additions & 2 deletions tests/ui/index_refutable_slice/slice_indexing_in_macro.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#![deny(clippy::index_refutable_slice)]

//@no-rustfix: need to change the suggestion to a multipart suggestion

extern crate if_chain;
use if_chain::if_chain;

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

0 comments on commit c07474b

Please sign in to comment.