diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /src/tools/clippy/tests/ui/index_refutable_slice | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/clippy/tests/ui/index_refutable_slice')
4 files changed, 374 insertions, 0 deletions
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs new file mode 100644 index 000000000..c2c0c520d --- /dev/null +++ b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs @@ -0,0 +1,166 @@ +#![deny(clippy::index_refutable_slice)] + +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) = slice { + println!("{}", slice[0]); + } + + // Try with copy + let slice: Option<[u32; 3]> = Some([1, 2, 3]); + if let Some(slice) = slice { + 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) = slice { + println!("{}", slice[2]); + println!("{}", slice[0]); + } + + // Multiple bindings + let slice_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([5, 6, 7]); + if let SomeEnum::One(slice) | SomeEnum::Three(slice) = slice_wrapped { + 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), Some(b)) = (a_wrapped, b_wrapped) { + 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) = slice { + 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) = &slice { + 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) = wrap.inner { + if wrap.is_awesome { + println!("This is awesome! {}", slice[0]); + } + } + + // Test 2: function access + if let Some(slice) = wrap.inner { + 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() {} diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr new file mode 100644 index 000000000..a607df9b8 --- /dev/null +++ b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr @@ -0,0 +1,158 @@ +error: this binding can be a slice pattern to avoid indexing + --> $DIR/if_let_slice_binding.rs:13:17 + | +LL | if let Some(slice) = slice { + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/if_let_slice_binding.rs:1:9 + | +LL | #![deny(clippy::index_refutable_slice)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a slice pattern here + | +LL | if let Some([slice_0, ..]) = slice { + | ~~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL | println!("{}", slice_0); + | ~~~~~~~ + +error: this binding can be a slice pattern to avoid indexing + --> $DIR/if_let_slice_binding.rs:19:17 + | +LL | if let Some(slice) = slice { + | ^^^^^ + | +help: try using a slice pattern here + | +LL | if let Some([slice_0, ..]) = slice { + | ~~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL | println!("{}", slice_0); + | ~~~~~~~ + +error: this binding can be a slice pattern to avoid indexing + --> $DIR/if_let_slice_binding.rs:25:17 + | +LL | if let Some(slice) = slice { + | ^^^^^ + | +help: try using a slice pattern here + | +LL | if let Some([slice_0, _, slice_2, ..]) = slice { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL ~ println!("{}", slice_2); +LL ~ println!("{}", slice_0); + | + +error: this binding can be a slice pattern to avoid indexing + --> $DIR/if_let_slice_binding.rs:32:26 + | +LL | if let SomeEnum::One(slice) | SomeEnum::Three(slice) = slice_wrapped { + | ^^^^^ + | +help: try using a slice pattern here + | +LL | if let SomeEnum::One([slice_0, ..]) | SomeEnum::Three([slice_0, ..]) = slice_wrapped { + | ~~~~~~~~~~~~~ ~~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL | println!("{}", slice_0); + | ~~~~~~~ + +error: this binding can be a slice pattern to avoid indexing + --> $DIR/if_let_slice_binding.rs:39:29 + | +LL | if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) { + | ^ + | +help: try using a slice pattern here + | +LL | if let (SomeEnum::Three([_, _, a_2, ..]), Some(b)) = (a_wrapped, b_wrapped) { + | ~~~~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL | println!("{} -> {}", a_2, b[1]); + | ~~~ + +error: this binding can be a slice pattern to avoid indexing + --> $DIR/if_let_slice_binding.rs:39:38 + | +LL | if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) { + | ^ + | +help: try using a slice pattern here + | +LL | if let (SomeEnum::Three(a), Some([_, b_1, ..])) = (a_wrapped, b_wrapped) { + | ~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL | println!("{} -> {}", a[2], b_1); + | ~~~ + +error: this binding can be a slice pattern to avoid indexing + --> $DIR/if_let_slice_binding.rs:46:21 + | +LL | if let Some(ref slice) = slice { + | ^^^^^ + | +help: try using a slice pattern here + | +LL | if let Some([_, ref slice_1, ..]) = slice { + | ~~~~~~~~~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL | println!("{:?}", slice_1); + | ~~~~~~~ + +error: this binding can be a slice pattern to avoid indexing + --> $DIR/if_let_slice_binding.rs:54:17 + | +LL | if let Some(slice) = &slice { + | ^^^^^ + | +help: try using a slice pattern here + | +LL | if let Some([slice_0, ..]) = &slice { + | ~~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL | println!("{:?}", slice_0); + | ~~~~~~~ + +error: this binding can be a slice pattern to avoid indexing + --> $DIR/if_let_slice_binding.rs:123:17 + | +LL | if let Some(slice) = wrap.inner { + | ^^^^^ + | +help: try using a slice pattern here + | +LL | if let Some([slice_0, ..]) = wrap.inner { + | ~~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL | println!("This is awesome! {}", slice_0); + | ~~~~~~~ + +error: this binding can be a slice pattern to avoid indexing + --> $DIR/if_let_slice_binding.rs:130:17 + | +LL | if let Some(slice) = wrap.inner { + | ^^^^^ + | +help: try using a slice pattern here + | +LL | if let Some([slice_0, ..]) = wrap.inner { + | ~~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL | println!("This is super awesome! {}", slice_0); + | ~~~~~~~ + +error: aborting due to 10 previous errors + diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs new file mode 100644 index 000000000..406e82083 --- /dev/null +++ b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs @@ -0,0 +1,28 @@ +#![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) = slice; + then { + println!("{}", slice[0]); + } + } +} diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr new file mode 100644 index 000000000..11b19428b --- /dev/null +++ b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr @@ -0,0 +1,22 @@ +error: this binding can be a slice pattern to avoid indexing + --> $DIR/slice_indexing_in_macro.rs:23:21 + | +LL | if let Some(slice) = slice; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/slice_indexing_in_macro.rs:1:9 + | +LL | #![deny(clippy::index_refutable_slice)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a slice pattern here + | +LL | if let Some([slice_0, ..]) = slice; + | ~~~~~~~~~~~~~ +help: and replace the index expressions here + | +LL | println!("{}", slice_0); + | ~~~~~~~ + +error: aborting due to previous error + |