-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix: fixed multipart_suggestion in index_refutable_slice uitest (#13727)
This should address #13099 for the derivable_impls test. As this combines everything into a single multipart_suggestion, the feedback message is a little less "targeted" than it was before, but now it provides a complete`--fix`able suggestion - e.g.: ``` error: this binding can be a slice pattern to avoid indexing --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:5:17 | LL | if let Some(slice) = slice { | ^^^^^ | note: the lint level is defined here --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:1:9 | LL | #![deny(clippy::index_refutable_slice)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the binding and indexed access with a slice pattern | LL ~ if let Some([_, _, _, _, _, _, _, slice_7, ..]) = slice { LL | LL | // This would usually not be linted but is included now due to the LL | // index limit in the config file LL ~ println!("{}", slice_7); | ``` changelog: [index_refutable_slice]: Fixed multipart_suggestions to provide correct rustfix-able lint
- Loading branch information
Showing
10 changed files
with
311 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#![deny(clippy::index_refutable_slice)] | ||
|
||
fn below_limit() { | ||
let slice: Option<&[u32]> = Some(&[1, 2, 3]); | ||
if let Some([_, _, _, _, _, _, _, slice_7, ..]) = slice { | ||
//~^ ERROR: binding can be a slice pattern | ||
// This would usually not be linted but is included now due to the | ||
// index limit in the config file | ||
println!("{}", slice_7); | ||
} | ||
} | ||
|
||
fn above_limit() { | ||
let slice: Option<&[u32]> = Some(&[1, 2, 3]); | ||
if let Some(slice) = slice { | ||
// This will not be linted as 8 is above the limit | ||
println!("{}", slice[8]); | ||
} | ||
} | ||
|
||
fn main() { | ||
below_limit(); | ||
above_limit(); | ||
} |
2 changes: 0 additions & 2 deletions
2
tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
tests/ui/index_refutable_slice/if_let_slice_binding.fixed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.