diff options
| author | bors <bors@rust-lang.org> | 2022-03-14 16:24:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-03-14 16:24:12 +0000 |
| commit | 285fa7ecd05dcbfdaf2faaf20400f5f92b39b3c6 (patch) | |
| tree | a8b13585116a678e07763e47514130459f5e4347 /src/tools/clippy/tests | |
| parent | bce19cf7f19ee5729defaccc86b068cc3c206c9c (diff) | |
| parent | 706fa54456f42086a943992e03354c75e1754307 (diff) | |
| download | rust-285fa7ecd05dcbfdaf2faaf20400f5f92b39b3c6.tar.gz rust-285fa7ecd05dcbfdaf2faaf20400f5f92b39b3c6.zip | |
Auto merge of #94929 - flip1995:clippyup, r=Manishearth
Update Clippy r? `@Manishearth` A few days delayed, because I recovered from a cold last week and couldn't get myself to do the sync, sorry. :upside_down_face:
Diffstat (limited to 'src/tools/clippy/tests')
44 files changed, 1394 insertions, 56 deletions
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 6bc74bc1e9a..c9710e3db8e 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -34,6 +34,7 @@ static TEST_DEPENDENCIES: &[&str] = &[ "syn", "tokio", "parking_lot", + "rustc_semver", ]; // Test dependencies may need an `extern crate` here to ensure that they show up @@ -53,6 +54,8 @@ extern crate parking_lot; #[allow(unused_extern_crates)] extern crate quote; #[allow(unused_extern_crates)] +extern crate rustc_semver; +#[allow(unused_extern_crates)] extern crate syn; #[allow(unused_extern_crates)] extern crate tokio; @@ -165,7 +168,11 @@ fn run_ui() { let _threads = VarGuard::set( "RUST_TEST_THREADS", // if RUST_TEST_THREADS is set, adhere to it, otherwise override it - env::var("RUST_TEST_THREADS").unwrap_or_else(|_| num_cpus::get().to_string()), + env::var("RUST_TEST_THREADS").unwrap_or_else(|_| { + std::thread::available_parallelism() + .map_or(1, std::num::NonZeroUsize::get) + .to_string() + }), ); compiletest::run_tests(&config); } diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed new file mode 100644 index 00000000000..900a8fffd40 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed @@ -0,0 +1,40 @@ +// run-rustfix + +#![deny(clippy::internal)] +#![allow(clippy::missing_clippy_version_attribute)] +#![feature(rustc_private)] + +extern crate rustc_ast; +extern crate rustc_hir; +extern crate rustc_lint; +extern crate rustc_middle; +#[macro_use] +extern crate rustc_session; +use clippy_utils::extract_msrv_attr; +use rustc_hir::Expr; +use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; +use rustc_semver::RustcVersion; + +declare_lint! { + pub TEST_LINT, + Warn, + "" +} + +struct Pass { + msrv: Option<RustcVersion>, +} + +impl_lint_pass!(Pass => [TEST_LINT]); + +impl LateLintPass<'_> for Pass { + extract_msrv_attr!(LateContext); + fn check_expr(&mut self, _: &LateContext<'_>, _: &Expr<'_>) {} +} + +impl EarlyLintPass for Pass { + extract_msrv_attr!(EarlyContext); + fn check_expr(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Expr) {} +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs new file mode 100644 index 00000000000..4bc8164db67 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs @@ -0,0 +1,38 @@ +// run-rustfix + +#![deny(clippy::internal)] +#![allow(clippy::missing_clippy_version_attribute)] +#![feature(rustc_private)] + +extern crate rustc_ast; +extern crate rustc_hir; +extern crate rustc_lint; +extern crate rustc_middle; +#[macro_use] +extern crate rustc_session; +use clippy_utils::extract_msrv_attr; +use rustc_hir::Expr; +use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; +use rustc_semver::RustcVersion; + +declare_lint! { + pub TEST_LINT, + Warn, + "" +} + +struct Pass { + msrv: Option<RustcVersion>, +} + +impl_lint_pass!(Pass => [TEST_LINT]); + +impl LateLintPass<'_> for Pass { + fn check_expr(&mut self, _: &LateContext<'_>, _: &Expr<'_>) {} +} + +impl EarlyLintPass for Pass { + fn check_expr(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Expr) {} +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr new file mode 100644 index 00000000000..ddc06f0be1b --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr @@ -0,0 +1,32 @@ +error: `extract_msrv_attr!` macro missing from `LateLintPass` implementation + --> $DIR/invalid_msrv_attr_impl.rs:30:1 + | +LL | impl LateLintPass<'_> for Pass { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/invalid_msrv_attr_impl.rs:3:9 + | +LL | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(clippy::missing_msrv_attr_impl)]` implied by `#[deny(clippy::internal)]` +help: add `extract_msrv_attr!(LateContext)` to the `LateLintPass` implementation + | +LL + impl LateLintPass<'_> for Pass { +LL + extract_msrv_attr!(LateContext); + | + +error: `extract_msrv_attr!` macro missing from `EarlyLintPass` implementation + --> $DIR/invalid_msrv_attr_impl.rs:34:1 + | +LL | impl EarlyLintPass for Pass { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `extract_msrv_attr!(EarlyContext)` to the `EarlyLintPass` implementation + | +LL + impl EarlyLintPass for Pass { +LL + extract_msrv_attr!(EarlyContext); + | + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs b/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs new file mode 100644 index 00000000000..1a0d4e88657 --- /dev/null +++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs @@ -0,0 +1,14 @@ +#![feature(lint_reasons)] +#![deny(clippy::allow_attributes_without_reason)] + +// These should trigger the lint +#[allow(dead_code)] +#[allow(dead_code, deprecated)] +// These should be fine +#[allow(dead_code, reason = "This should be allowed")] +#[warn(dyn_drop, reason = "Warnings can also have reasons")] +#[warn(deref_nullptr)] +#[deny(deref_nullptr)] +#[forbid(deref_nullptr)] + +fn main() {} diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr new file mode 100644 index 00000000000..cd040a144aa --- /dev/null +++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr @@ -0,0 +1,23 @@ +error: `allow` attribute without specifying a reason + --> $DIR/allow_attributes_without_reason.rs:5:1 + | +LL | #[allow(dead_code)] + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/allow_attributes_without_reason.rs:2:9 + | +LL | #![deny(clippy::allow_attributes_without_reason)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: try adding a reason at the end with `, reason = ".."` + +error: `allow` attribute without specifying a reason + --> $DIR/allow_attributes_without_reason.rs:6:1 + | +LL | #[allow(dead_code, deprecated)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a reason at the end with `, reason = ".."` + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs b/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs new file mode 100644 index 00000000000..cfe1cca2eba --- /dev/null +++ b/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs @@ -0,0 +1,39 @@ +fn main() { + let x: [i32; 3] = [1_i32, 2, 3]; + let r_x = &x; + // Check casting through multiple bindings + // Because it's separate, it does not check the cast back to something of the same size + let a = r_x as *const [i32]; + let b = a as *const [u8]; + let c = b as *const [u32]; + + // loses data + let loss = r_x as *const [i32] as *const [u8]; + + // Cast back to same size but different type loses no data, just type conversion + // This is weird code but there's no reason for this lint specifically to fire *twice* on it + let restore = r_x as *const [i32] as *const [u8] as *const [u32]; + + // Check casting through blocks is detected + let loss_block_1 = { r_x as *const [i32] } as *const [u8]; + let loss_block_2 = { + let _ = (); + r_x as *const [i32] + } as *const [u8]; + + // Check that resores of the same size are detected through blocks + let restore_block_1 = { r_x as *const [i32] } as *const [u8] as *const [u32]; + let restore_block_2 = { ({ r_x as *const [i32] }) as *const [u8] } as *const [u32]; + let restore_block_3 = { + let _ = (); + ({ + let _ = (); + r_x as *const [i32] + }) as *const [u8] + } as *const [u32]; + + // Check that the result of a long chain of casts is detected + let long_chain_loss = r_x as *const [i32] as *const [u32] as *const [u16] as *const [i8] as *const [u8]; + let long_chain_restore = + r_x as *const [i32] as *const [u32] as *const [u16] as *const [i8] as *const [u8] as *const [u32]; +} diff --git a/src/tools/clippy/tests/ui/cast_slice_different_sizes.stderr b/src/tools/clippy/tests/ui/cast_slice_different_sizes.stderr new file mode 100644 index 00000000000..a37cec7cb3b --- /dev/null +++ b/src/tools/clippy/tests/ui/cast_slice_different_sizes.stderr @@ -0,0 +1,52 @@ +error: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (element size 1) does not adjust the count + --> $DIR/cast_slice_different_sizes.rs:7:13 + | +LL | let b = a as *const [u8]; + | ^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts(a as *const u8, ..)` + | + = note: `#[deny(clippy::cast_slice_different_sizes)]` on by default + +error: casting between raw pointers to `[u8]` (element size 1) and `[u32]` (element size 4) does not adjust the count + --> $DIR/cast_slice_different_sizes.rs:8:13 + | +LL | let c = b as *const [u32]; + | ^^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts(b as *const u32, ..)` + +error: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (element size 1) does not adjust the count + --> $DIR/cast_slice_different_sizes.rs:11:16 + | +LL | let loss = r_x as *const [i32] as *const [u8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts(r_x as *const [i32] as *const u8, ..)` + +error: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (element size 1) does not adjust the count + --> $DIR/cast_slice_different_sizes.rs:18:24 + | +LL | let loss_block_1 = { r_x as *const [i32] } as *const [u8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts({ r_x as *const [i32] } as *const u8, ..)` + +error: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (element size 1) does not adjust the count + --> $DIR/cast_slice_different_sizes.rs:19:24 + | +LL | let loss_block_2 = { + | ________________________^ +LL | | let _ = (); +LL | | r_x as *const [i32] +LL | | } as *const [u8]; + | |____________________^ + | +help: replace with `ptr::slice_from_raw_parts` + | +LL ~ let loss_block_2 = core::ptr::slice_from_raw_parts({ +LL + let _ = (); +LL + r_x as *const [i32] +LL ~ } as *const u8, ..); + | + +error: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (element size 1) does not adjust the count + --> $DIR/cast_slice_different_sizes.rs:36:27 + | +LL | let long_chain_loss = r_x as *const [i32] as *const [u32] as *const [u16] as *const [i8] as *const [u8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts(r_x as *const [i32] as *const [u32] as *const [u16] as *const [i8] as *const u8, ..)` + +error: aborting due to 6 previous errors + diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs index be4348e2bb7..4a5c597dda5 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs +++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -12,12 +12,12 @@ static N: AtomicUsize = AtomicUsize::new(0); #[warn(clippy::main_recursion)] #[start] -fn main(argc: isize, argv: *const *const u8) -> isize { +fn main(_argc: isize, _argv: *const *const u8) -> isize { let x = N.load(Ordering::Relaxed); N.store(x + 1, Ordering::Relaxed); if x < 3 { - main(argc, argv); + main(_argc, _argv); } 0 diff --git a/src/tools/clippy/tests/ui/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro.rs index 9b03c9b4783..baf01174b67 100644 --- a/src/tools/clippy/tests/ui/dbg_macro.rs +++ b/src/tools/clippy/tests/ui/dbg_macro.rs @@ -1,3 +1,4 @@ +// compile-flags: --test #![warn(clippy::dbg_macro)] fn foo(n: u32) -> u32 { @@ -40,3 +41,8 @@ mod issue7274 { dbg!(2); }); } + +#[test] +pub fn issue8481() { + dbg!(1); +} diff --git a/src/tools/clippy/tests/ui/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro.stderr index 8ee1b328720..a3e7a7162e5 100644 --- a/src/tools/clippy/tests/ui/dbg_macro.stderr +++ b/src/tools/clippy/tests/ui/dbg_macro.stderr @@ -1,5 +1,5 @@ error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:4:22 + --> $DIR/dbg_macro.rs:5:22 | LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(n) = n.checked_sub(4) { n } else { n } | ~~~~~~~~~~~~~~~~ error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:8:8 + --> $DIR/dbg_macro.rs:9:8 | LL | if dbg!(n <= 1) { | ^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if n <= 1 { | ~~~~~~ error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:9:9 + --> $DIR/dbg_macro.rs:10:9 | LL | dbg!(1) | ^^^^^^^ @@ -33,7 +33,7 @@ LL | 1 | error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:11:9 + --> $DIR/dbg_macro.rs:12:9 | LL | dbg!(n * factorial(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | n * factorial(n - 1) | error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:16:5 + --> $DIR/dbg_macro.rs:17:5 | LL | dbg!(42); | ^^^^^^^^ @@ -55,7 +55,7 @@ LL | 42; | ~~ error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:17:5 + --> $DIR/dbg_macro.rs:18:5 | LL | dbg!(dbg!(dbg!(42))); | ^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | dbg!(dbg!(42)); | ~~~~~~~~~~~~~~ error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:18:14 + --> $DIR/dbg_macro.rs:19:14 | LL | foo(3) + dbg!(factorial(4)); | ^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | foo(3) + factorial(4); | ~~~~~~~~~~~~ error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:19:5 + --> $DIR/dbg_macro.rs:20:5 | LL | dbg!(1, 2, dbg!(3, 4)); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | (1, 2, dbg!(3, 4)); | ~~~~~~~~~~~~~~~~~~ error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:20:5 + --> $DIR/dbg_macro.rs:21:5 | LL | dbg!(1, 2, 3, 4, 5); | ^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | (1, 2, 3, 4, 5); | ~~~~~~~~~~~~~~~ error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:40:9 + --> $DIR/dbg_macro.rs:41:9 | LL | dbg!(2); | ^^^^^^^ diff --git a/src/tools/clippy/tests/ui/extend_with_drain.fixed b/src/tools/clippy/tests/ui/extend_with_drain.fixed index e863870e7d6..71ebad24c16 100644 --- a/src/tools/clippy/tests/ui/extend_with_drain.fixed +++ b/src/tools/clippy/tests/ui/extend_with_drain.fixed @@ -1,11 +1,11 @@ // run-rustfix #![warn(clippy::extend_with_drain)] +#![allow(clippy::iter_with_drain)] use std::collections::BinaryHeap; fn main() { //gets linted let mut vec1 = vec![0u8; 1024]; let mut vec2: std::vec::Vec<u8> = Vec::new(); - vec2.append(&mut vec1); let mut vec3 = vec![0u8; 1024]; @@ -17,7 +17,7 @@ fn main() { vec11.append(&mut return_vector()); - //won't get linted it dosen't move the entire content of a vec into another + //won't get linted it doesn't move the entire content of a vec into another let mut test1 = vec![0u8, 10]; let mut test2: std::vec::Vec<u8> = Vec::new(); diff --git a/src/tools/clippy/tests/ui/extend_with_drain.rs b/src/tools/clippy/tests/ui/extend_with_drain.rs index dcb36b5951c..e9f011abb0e 100644 --- a/src/tools/clippy/tests/ui/extend_with_drain.rs +++ b/src/tools/clippy/tests/ui/extend_with_drain.rs @@ -1,11 +1,11 @@ // run-rustfix #![warn(clippy::extend_with_drain)] +#![allow(clippy::iter_with_drain)] use std::collections::BinaryHeap; fn main() { //gets linted let mut vec1 = vec![0u8; 1024]; let mut vec2: std::vec::Vec<u8> = Vec::new(); - vec2.extend(vec1.drain(..)); let mut vec3 = vec![0u8; 1024]; @@ -17,7 +17,7 @@ fn main() { vec11.extend(return_vector().drain(..)); - //won't get linted it dosen't move the entire content of a vec into another + //won't get linted it doesn't move the entire content of a vec into another let mut test1 = vec![0u8, 10]; let mut test2: std::vec::Vec<u8> = Vec::new(); diff --git a/src/tools/clippy/tests/ui/iter_with_drain.fixed b/src/tools/clippy/tests/ui/iter_with_drain.fixed new file mode 100644 index 00000000000..aea4dba9dd5 --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_with_drain.fixed @@ -0,0 +1,56 @@ +// run-rustfix +// will emits unused mut warnings after fixing +#![allow(unused_mut)] +// will emits needless collect warnings after fixing +#![allow(clippy::needless_collect)] +#![warn(clippy::iter_with_drain)] +use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; + +fn full() { + let mut a = vec!["aaa".to_string(), "bbb".to_string()]; + let mut a: BinaryHeap<_> = a.into_iter().collect(); + let mut a: HashSet<_> = a.drain().collect(); + let mut a: VecDeque<_> = a.drain().collect(); + let mut a: Vec<_> = a.into_iter().collect(); + let mut a: HashMap<_, _> = a.into_iter().map(|x| (x.clone(), x)).collect(); + let _: Vec<(String, String)> = a.drain().collect(); +} + +fn closed() { + let mut a = vec!["aaa".to_string(), "bbb".to_string()]; + let mut a: BinaryHeap<_> = a.into_iter().collect(); + let mut a: HashSet<_> = a.drain().collect(); + let mut a: VecDeque<_> = a.drain().collect(); + let mut a: Vec<_> = a.into_iter().collect(); + let mut a: HashMap<_, _> = a.into_iter().map(|x| (x.clone(), x)).collect(); + let _: Vec<(String, String)> = a.drain().collect(); +} + +fn should_not_help() { + let mut a = vec!["aaa".to_string(), "bbb".to_string()]; + let mut a: BinaryHeap<_> = a.drain(1..).collect(); + let mut a: HashSet<_> = a.drain().collect(); + let mut a: VecDeque<_> = a.drain().collect(); + let mut a: Vec<_> = a.drain(..a.len() - 1).collect(); + let mut a: HashMap<_, _> = a.drain(1..a.len() - 1).map(|x| (x.clone(), x)).collect(); + let _: Vec<(String, String)> = a.drain().collect(); + + let mut b = vec!["aaa".to_string(), "bbb".to_string()]; + let _: Vec<_> = b.drain(0..a.len()).collect(); +} + +#[derive(Default)] +struct Bomb { + fire: Vec<u8>, +} + +fn should_not_help_0(bomb: &mut Bomb) { + let _: Vec<u8> = bomb.fire.drain(..).collect(); +} + +fn main() { + full(); + closed(); + should_not_help(); + should_not_help_0(&mut Bomb::default()); +} diff --git a/src/tools/clippy/tests/ui/iter_with_drain.rs b/src/tools/clippy/tests/ui/iter_with_drain.rs new file mode 100644 index 00000000000..271878cffb4 --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_with_drain.rs @@ -0,0 +1,56 @@ +// run-rustfix +// will emits unused mut warnings after fixing +#![allow(unused_mut)] +// will emits needless collect warnings after fixing +#![allow(clippy::needless_collect)] +#![warn(clippy::iter_with_drain)] +use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; + +fn full() { + let mut a = vec!["aaa".to_string(), "bbb".to_string()]; + let mut a: BinaryHeap<_> = a.drain(..).collect(); + let mut a: HashSet<_> = a.drain().collect(); + let mut a: VecDeque<_> = a.drain().collect(); + let mut a: Vec<_> = a.drain(..).collect(); + let mut a: HashMap<_, _> = a.drain(..).map(|x| (x.clone(), x)).collect(); + let _: Vec<(String, String)> = a.drain().collect(); +} + +fn closed() { + let mut a = vec!["aaa".to_string(), "bbb".to_string()]; + let mut a: BinaryHeap<_> = a.drain(0..).collect(); + let mut a: HashSet<_> = a.drain().collect(); + let mut a: VecDeque<_> = a.drain().collect(); + let mut a: Vec<_> = a.drain(..a.len()).collect(); + let mut a: HashMap<_, _> = a.drain(0..a.len()).map(|x| (x.clone(), x)).collect(); + let _: Vec<(String, String)> = a.drain().collect(); +} + +fn should_not_help() { + let mut a = vec!["aaa".to_string(), "bbb".to_string()]; + let mut a: BinaryHeap<_> = a.drain(1..).collect(); + let mut a: HashSet<_> = a.drain().collect(); + let mut a: VecDeque<_> = a.drain().collect(); + let mut a: Vec<_> = a.drain(..a.len() - 1).collect(); + let mut a: HashMap<_, _> = a.drain(1..a.len() - 1).map(|x| (x.clone(), x)).collect(); + let _: Vec<(String, String)> = a.drain().collect(); + + let mut b = vec!["aaa".to_string(), "bbb".to_string()]; + let _: Vec<_> = b.drain(0..a.len()).collect(); +} + +#[derive(Default)] +struct Bomb { + fire: Vec<u8>, +} + +fn should_not_help_0(bomb: &mut Bomb) { + let _: Vec<u8> = bomb.fire.drain(..).collect(); +} + +fn main() { + full(); + closed(); + should_not_help(); + should_not_help_0(&mut Bomb::default()); +} diff --git a/src/tools/clippy/tests/ui/iter_with_drain.stderr b/src/tools/clippy/tests/ui/iter_with_drain.stderr new file mode 100644 index 00000000000..aa394439fa6 --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_with_drain.stderr @@ -0,0 +1,40 @@ +error: `drain(..)` used on a `Vec` + --> $DIR/iter_with_drain.rs:11:34 + | +LL | let mut a: BinaryHeap<_> = a.drain(..).collect(); + | ^^^^^^^^^ help: try this: `into_iter()` + | + = note: `-D clippy::iter-with-drain` implied by `-D warnings` + +error: `drain(..)` used on a `VecDeque` + --> $DIR/iter_with_drain.rs:14:27 + | +LL | let mut a: Vec<_> = a.drain(..).collect(); + | ^^^^^^^^^ help: try this: `into_iter()` + +error: `drain(..)` used on a `Vec` + --> $DIR/iter_with_drain.rs:15:34 + | +LL | let mut a: HashMap<_, _> = a.drain(..).map(|x| (x.clone(), x)).collect(); + | ^^^^^^^^^ help: try this: `into_iter()` + +error: `drain(..)` used on a `Vec` + --> $DIR/iter_with_drain.rs:21:34 + | +LL | let mut a: BinaryHeap<_> = a.drain(0..).collect(); + | ^^^^^^^^^^ help: try this: `into_iter()` + +error: `drain(..)` used on a `VecDeque` + --> $DIR/iter_with_drain.rs:24:27 + | +LL | let mut a: Vec<_> = a.drain(..a.len()).collect(); + | ^^^^^^^^^^^^^^^^ help: try this: `into_iter()` + +error: `drain(..)` used on a `Vec` + --> $DIR/iter_with_drain.rs:25:34 + | +LL | let mut a: HashMap<_, _> = a.drain(0..a.len()).map(|x| (x.clone(), x)).collect(); + | ^^^^^^^^^^^^^^^^^ help: try this: `into_iter()` + +error: aborting due to 6 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_map_option.fixed b/src/tools/clippy/tests/ui/manual_map_option.fixed index 294d79abc04..fc6a7abca0e 100644 --- a/src/tools/clippy/tests/ui/manual_map_option.fixed +++ b/src/tools/clippy/tests/ui/manual_map_option.fixed @@ -148,6 +148,7 @@ fn main() { // #7077 let s = &String::new(); + #[allow(clippy::needless_match)] let _: Option<&str> = match Some(s) { Some(s) => Some(s), None => None, diff --git a/src/tools/clippy/tests/ui/manual_map_option.rs b/src/tools/clippy/tests/ui/manual_map_option.rs index d11bf5ecb82..16508270f64 100644 --- a/src/tools/clippy/tests/ui/manual_map_option.rs +++ b/src/tools/clippy/tests/ui/manual_map_option.rs @@ -214,6 +214,7 @@ fn main() { // #7077 let s = &String::new(); + #[allow(clippy::needless_match)] let _: Option<&str> = match Some(s) { Some(s) => Some(s), None => None, diff --git a/src/tools/clippy/tests/ui/missing_spin_loop.fixed b/src/tools/clippy/tests/ui/missing_spin_loop.fixed new file mode 100644 index 00000000000..aa89e04d26e --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_spin_loop.fixed @@ -0,0 +1,28 @@ +// run-rustfix +#![warn(clippy::missing_spin_loop)] +#![allow(clippy::bool_comparison)] +#![allow(unused_braces)] + +use core::sync::atomic::{AtomicBool, Ordering}; + +fn main() { + let b = AtomicBool::new(true); + // Those should lint + while b.load(Ordering::Acquire) { std::hint::spin_loop() } + + while !b.load(Ordering::SeqCst) { std::hint::spin_loop() } + + while b.load(Ordering::Acquire) == false { std::hint::spin_loop() } + + while { true == b.load(Ordering::Acquire) } { std::hint::spin_loop() } + + while b.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) != Ok(true) { std::hint::spin_loop() } + + while Ok(false) != b.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) { std::hint::spin_loop() } + + // This is OK, as the body is not empty + while b.load(Ordering::Acquire) { + std::hint::spin_loop() + } + // TODO: also match on loop+match or while let +} diff --git a/src/tools/clippy/tests/ui/missing_spin_loop.rs b/src/tools/clippy/tests/ui/missing_spin_loop.rs new file mode 100644 index 00000000000..88745e47732 --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_spin_loop.rs @@ -0,0 +1,28 @@ +// run-rustfix +#![warn(clippy::missing_spin_loop)] +#![allow(clippy::bool_comparison)] +#![allow(unused_braces)] + +use core::sync::atomic::{AtomicBool, Ordering}; + +fn main() { + let b = AtomicBool::new(true); + // Those should lint + while b.load(Ordering::Acquire) {} + + while !b.load(Ordering::SeqCst) {} + + while b.load(Ordering::Acquire) == false {} + + while { true == b.load(Ordering::Acquire) } {} + + while b.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) != Ok(true) {} + + while Ok(false) != b.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {} + + // This is OK, as the body is not empty + while b.load(Ordering::Acquire) { + std::hint::spin_loop() + } + // TODO: also match on loop+match or while let +} diff --git a/src/tools/clippy/tests/ui/missing_spin_loop.stderr b/src/tools/clippy/tests/ui/missing_spin_loop.stderr new file mode 100644 index 00000000000..485da00dc64 --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_spin_loop.stderr @@ -0,0 +1,40 @@ +error: busy-waiting loop should at least have a spin loop hint + --> $DIR/missing_spin_loop.rs:11:37 + | +LL | while b.load(Ordering::Acquire) {} + | ^^ help: try this: `{ std::hint::spin_loop() }` + | + = note: `-D clippy::missing-spin-loop` implied by `-D warnings` + +error: busy-waiting loop should at least have a spin loop hint + --> $DIR/missing_spin_loop.rs:13:37 + | +LL | while !b.load(Ordering::SeqCst) {} + | ^^ help: try this: `{ std::hint::spin_loop() }` + +error: busy-waiting loop should at least have a spin loop hint + --> $DIR/missing_spin_loop.rs:15:46 + | +LL | while b.load(Ordering::Acquire) == false {} + | ^^ help: try this: `{ std::hint::spin_loop() }` + +error: busy-waiting loop should at least have a spin loop hint + --> $DIR/missing_spin_loop.rs:17:49 + | +LL | while { true == b.load(Ordering::Acquire) } {} + | ^^ help: try this: `{ std::hint::spin_loop() }` + +error: busy-waiting loop should at least have a spin loop hint + --> $DIR/missing_spin_loop.rs:19:93 + | +LL | while b.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) != Ok(true) {} + | ^^ help: try this: `{ std::hint::spin_loop() }` + +error: busy-waiting loop should at least have a spin loop hint + --> $DIR/missing_spin_loop.rs:21:94 + | +LL | while Ok(false) != b.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {} + | ^^ help: try this: `{ std::hint::spin_loop() }` + +error: aborting due to 6 previous errors + diff --git a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed new file mode 100644 index 00000000000..bb4b4795516 --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed @@ -0,0 +1,23 @@ +// run-rustfix +#![warn(clippy::missing_spin_loop)] +#![feature(lang_items, start, libc)] +#![no_std] + +use core::sync::atomic::{AtomicBool, Ordering}; + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + // This should trigger the lint + let b = AtomicBool::new(true); + // This should lint with `core::hint::spin_loop()` + while b.load(Ordering::Acquire) { core::hint::spin_loop() } + 0 +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs new file mode 100644 index 00000000000..a19bc72baf8 --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs @@ -0,0 +1,23 @@ +// run-rustfix +#![warn(clippy::missing_spin_loop)] +#![feature(lang_items, start, libc)] +#![no_std] + +use core::sync::atomic::{AtomicBool, Ordering}; + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + // This should trigger the lint + let b = AtomicBool::new(true); + // This should lint with `core::hint::spin_loop()` + while b.load(Ordering::Acquire) {} + 0 +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr new file mode 100644 index 00000000000..2b3b6873c3c --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr @@ -0,0 +1,10 @@ +error: busy-waiting loop should at least have a spin loop hint + --> $DIR/missing_spin_loop_no_std.rs:13:37 + | +LL | while b.load(Ordering::Acquire) {} + | ^^ help: try this: `{ core::hint::spin_loop() }` + | + = note: `-D clippy::missing-spin-loop` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/needless_match.fixed b/src/tools/clippy/tests/ui/needless_match.fixed new file mode 100644 index 00000000000..ece18ad737f --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_match.fixed @@ -0,0 +1,83 @@ +// run-rustfix +#![warn(clippy::needless_match)] +#![allow(clippy::manual_map)] +#![allow(dead_code)] + +#[derive(Clone, Copy)] +enum Choice { + A, + B, + C, + D, +} + +#[allow(unused_mut)] +fn useless_match() { + let mut i = 10; + let _: i32 = i; + let _: i32 = i; + let mut _i_mut = i; + + let s = "test"; + let _: &str = s; +} + +fn custom_type_match(se: Choice) { + let _: Choice = se; + // Don't trigger + let _: Choice = match se { + Choice::A => Choice::A, + Choice::B => Choice::B, + _ => Choice::C, + }; + // Mingled, don't trigger + let _: Choice = match se { + Choice::A => Choice::B, + Choice::B => Choice::C, + Choice::C => Choice::D, + Choice::D => Choice::A, + }; +} + +fn option_match(x: Option<i32>) { + let _: Option<i32> = x; + // Don't trigger, this is the case for manual_map_option + let _: Option<i32> = match x { + Some(a) => Some(-a), + None => None, + }; +} + +fn func_ret_err<T>(err: T) -> Result<i32, T> { + Err(err) +} + +fn result_match() { + let _: Result<i32, i32> = Ok(1); + let _: Result<i32, i32> = func_ret_err(0_i32); +} + +fn if_let_option() -> Option<i32> { + Some(1) +} + +fn if_let_result(x: Result<(), i32>) { + let _: Result<(), i32> = x; + let _: Result<(), i32> = x; + // Input type mismatch, don't trigger + let _: Result<(), i32> = if let Err(e) = Ok(1) { Err(e) } else { x }; +} + +fn if_let_custom_enum(x: Choice) { + let _: Choice = x; + // Don't trigger + let _: Choice = if let Choice::A = x { + Choice::A + } else if true { + Choice::B + } else { + x + }; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_match.rs b/src/tools/clippy/tests/ui/needless_match.rs new file mode 100644 index 00000000000..36649de35a6 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_match.rs @@ -0,0 +1,122 @@ +// run-rustfix +#![warn(clippy::needless_match)] +#![allow(clippy::manual_map)] +#![allow(dead_code)] + +#[derive(Clone, Copy)] +enum Choice { + A, + B, + C, + D, +} + +#[allow(unused_mut)] +fn useless_match() { + let mut i = 10; + let _: i32 = match i { + 0 => 0, + 1 => 1, + 2 => 2, + _ => i, + }; + let _: i32 = match i { + 0 => 0, + 1 => 1, + ref i => *i, + }; + let mut _i_mut = match i { + 0 => 0, + 1 => 1, + ref mut i => *i, + }; + + let s = "test"; + let _: &str = match s { + "a" => "a", + "b" => "b", + s => s, + }; +} + +fn custom_type_match(se: Choice) { + let _: Choice = match se { + Choice::A => Choice::A, + Choice::B => Choice::B, + Choice::C => Choice::C, + Choice::D => Choice::D, + }; + // Don't trigger + let _: Choice = match se { + Choice::A => Choice::A, + Choice::B => Choice::B, + _ => Choice::C, + }; + // Mingled, don't trigger + let _: Choice = match se { + Choice::A => Choice::B, + Choice::B => Choice::C, + Choice::C => Choice::D, + Choice::D => Choice::A, + }; +} + +fn option_match(x: Option<i32>) { + let _: Option<i32> = match x { + Some(a) => Some(a), + None => None, + }; + // Don't trigger, this is the case for manual_map_option + let _: Option<i32> = match x { + Some(a) => Some(-a), + None => None, + }; +} + +fn func_ret_err<T>(err: T) -> Result<i32, T> { + Err(err) +} + +fn result_match() { + let _: Result<i32, i32> = match Ok(1) { + Ok(a) => Ok(a), + Err(err) => Err(err), + }; + let _: Result<i32, i32> = match func_ret_err(0_i32) { + Err(err) => Err(err), + Ok(a) => Ok(a), + }; +} + +fn if_let_option() -> Option<i32> { + if let Some(a) = Some(1) { Some(a) } else { None } +} + +fn if_let_result(x: Result<(), i32>) { + let _: Result<(), i32> = if let Err(e) = x { Err(e) } else { x }; + let _: Result<(), i32> = if let Ok(val) = x { Ok(val) } else { x }; + // Input type mismatch, don't trigger + let _: Result<(), i32> = if let Err(e) = Ok(1) { Err(e) } else { x }; +} + +fn if_let_custom_enum(x: Choice) { + let _: Choice = if let Choice::A = x { + Choice::A + } else if let Choice::B = x { + Choice::B + } else if let Choice::C = x { + Choice::C + } else { + x + }; + // Don't trigger + let _: Choice = if let Choice::A = x { + Choice::A + } else if true { + Choice::B + } else { + x + }; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_match.stderr b/src/tools/clippy/tests/ui/needless_match.stderr new file mode 100644 index 00000000000..ad1525406ad --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_match.stderr @@ -0,0 +1,122 @@ +error: this match expression is unnecessary + --> $DIR/needless_match.rs:17:18 + | +LL | let _: i32 = match i { + | __________________^ +LL | | 0 => 0, +LL | | 1 => 1, +LL | | 2 => 2, +LL | | _ => i, +LL | | }; + | |_____^ help: replace it with: `i` + | + = note: `-D clippy::needless-match` implied by `-D warnings` + +error: this match expression is unnecessary + --> $DIR/needless_match.rs:23:18 + | +LL | let _: i32 = match i { + | __________________^ +LL | | 0 => 0, +LL | | 1 => 1, +LL | | ref i => *i, +LL | | }; + | |_____^ help: replace it with: `i` + +error: this match expression is unnecessary + --> $DIR/needless_match.rs:28:22 + | +LL | let mut _i_mut = match i { + | ______________________^ +LL | | 0 => 0, +LL | | 1 => 1, +LL | | ref mut i => *i, +LL | | }; + | |_____^ help: replace it with: `i` + +error: this match expression is unnecessary + --> $DIR/needless_match.rs:35:19 + | +LL | let _: &str = match s { + | ___________________^ +LL | | "a" => "a", +LL | | "b" => "b", +LL | | s => s, +LL | | }; + | |_____^ help: replace it with: `s` + +error: this match expression is unnecessary + --> $DIR/needless_match.rs:43:21 + | +LL | let _: Choice = match se { + | _____________________^ +LL | | Choice::A => Choice::A, +LL | | Choice::B => Choice::B, +LL | | Choice::C => Choice::C, +LL | | Choice::D => Choice::D, +LL | | }; + | |_____^ help: replace it with: `se` + +error: this match expression is unnecessary + --> $DIR/needless_match.rs:65:26 + | +LL | let _: Option<i32> = match x { + | __________________________^ +LL | | Some(a) => Some(a), +LL | | None => None, +LL | | }; + | |_____^ help: replace it with: `x` + +error: this match expression is unnecessary + --> $DIR/needless_match.rs:81:31 + | +LL | let _: Result<i32, i32> = match Ok(1) { + | _______________________________^ +LL | | Ok(a) => Ok(a), +LL | | Err(err) => Err(err), +LL | | }; + | |_____^ help: replace it with: `Ok(1)` + +error: this match expression is unnecessary + --> $DIR/needless_match.rs:85:31 + | +LL | let _: Result<i32, i32> = match func_ret_err(0_i32) { + | _______________________________^ +LL | | Err(err) => Err(err), +LL | | Ok(a) => Ok(a), +LL | | }; + | |_____^ help: replace it with: `func_ret_err(0_i32)` + +error: this if-let expression is unnecessary + --> $DIR/needless_match.rs:92:5 + | +LL | if let Some(a) = Some(1) { Some(a) } else { None } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `Some(1)` + +error: this if-let expression is unnecessary + --> $DIR/needless_match.rs:96:30 + | +LL | let _: Result<(), i32> = if let Err(e) = x { Err(e) } else { x }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x` + +error: this if-let expression is unnecessary + --> $DIR/needless_match.rs:97:30 + | +LL | let _: Result<(), i32> = if let Ok(val) = x { Ok(val) } else { x }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x` + +error: this if-let expression is unnecessary + --> $DIR/needless_match.rs:103:21 + | +LL | let _: Choice = if let Choice::A = x { + | _____________________^ +LL | | Choice::A +LL | | } else if let Choice::B = x { +LL | | Choice::B +... | +LL | | x +LL | | }; + | |_____^ help: replace it with: `x` + +error: aborting due to 12 previous errors + diff --git a/src/tools/clippy/tests/ui/only_used_in_recursion.rs b/src/tools/clippy/tests/ui/only_used_in_recursion.rs new file mode 100644 index 00000000000..5768434f988 --- /dev/null +++ b/src/tools/clippy/tests/ui/only_used_in_recursion.rs @@ -0,0 +1,122 @@ +#![warn(clippy::only_used_in_recursion)] + +fn simple(a: usize, b: usize) -> usize { + if a == 0 { 1 } else { simple(a - 1, b) } +} + +fn with_calc(a: usize, b: isize) -> usize { + if a == 0 { 1 } else { with_calc(a - 1, -b + 1) } +} + +fn tuple((a, b): (usize, usize)) -> usize { + if a == 0 { 1 } else { tuple((a - 1, b + 1)) } +} + +fn let_tuple(a: usize, b: usize) -> usize { + let (c, d) = (a, b); + if c == 0 { 1 } else { let_tuple(c - 1, d + 1) } +} + +fn array([a, b]: [usize; 2]) -> usize { + if a == 0 { 1 } else { array([a - 1, b + 1]) } +} + +fn index(a: usize, mut b: &[usize], c: usize) -> usize { + if a == 0 { 1 } else { index(a - 1, b, c + b[0]) } +} + +fn break_(a: usize, mut b: usize, mut c: usize) -> usize { + let c = loop { + b += 1; + c += 1; + if c == 10 { + break b; + } + }; + + if a == 0 { 1 } else { break_(a - 1, c, c) } +} + +// this has a side effect +fn mut_ref(a: usize, b: &mut usize) -> usize { + *b = 1; + if a == 0 { 1 } else { mut_ref(a - 1, b) } +} + +fn mut_ref2(a: usize, b: &mut usize) -> usize { + let mut c = *b; + if a == 0 { 1 } else { mut_ref2(a - 1, &mut c) } +} + +fn not_primitive(a: usize, b: String) -> usize { + if a == 0 { 1 } else { not_primitive(a - 1, b) } +} + +// this doesn't have a side effect, +// but `String` is not primitive. +fn not_primitive_op(a: usize, b: String, c: &str) -> usize { + if a == 1 { 1 } else { not_primitive_op(a, b + c, c) } +} + +struct A; + +impl A { + fn method(a: usize, b: usize) -> usize { + if a == 0 { 1 } else { A::method(a - 1, b - 1) } + } + + fn method2(&self, a: usize, b: usize) -> usize { + if a == 0 { 1 } else { self.method2(a - 1, b + 1) } + } +} + +trait B { + fn hello(a: usize, b: usize) -> usize; + + fn hello2(&self, a: usize, b: usize) -> usize; +} + +impl B for A { + fn hello(a: usize, b: usize) -> usize { + if a == 0 { 1 } else { A::hello(a - 1, b + 1) } + } + + fn hello2(&self, a: usize, b: usize) -> usize { + if a == 0 { 1 } else { self.hello2(a - 1, b + 1) } + } +} + +trait C { + fn hello(a: usize, b: usize) -> usize { + if a == 0 { 1 } else { Self::hello(a - 1, b + 1) } + } + + fn hello2(&self, a: usize, b: usize) -> usize { + if a == 0 { 1 } else { self.hello2(a - 1, b + 1) } + } +} + +fn ignore(a: usize, _: usize) -> usize { + if a == 1 { 1 } else { ignore(a - 1, 0) } +} + +fn ignore2(a: usize, _b: usize) -> usize { + if a == 1 { 1 } else { ignore2(a - 1, _b) } +} + +fn f1(a: u32) -> u32 { + a +} + +fn f2(a: u32) -> u32 { + f1(a) +} + +fn inner_fn(a: u32) -> u32 { + fn inner_fn(a: u32) -> u32 { + a + } + inner_fn(a) +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/only_used_in_recursion.stderr b/src/tools/clippy/tests/ui/only_used_in_recursion.stderr new file mode 100644 index 00000000000..6fe9361bf5f --- /dev/null +++ b/src/tools/clippy/tests/ui/only_used_in_recursion.stderr @@ -0,0 +1,82 @@ +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:3:21 + | +LL | fn simple(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_b` + | + = note: `-D clippy::only-used-in-recursion` implied by `-D warnings` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:7:24 + | +LL | fn with_calc(a: usize, b: isize) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_b` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:11:14 + | +LL | fn tuple((a, b): (usize, usize)) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_b` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:15:24 + | +LL | fn let_tuple(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_b` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:20:14 + | +LL | fn array([a, b]: [usize; 2]) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_b` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:24:20 + | +LL | fn index(a: usize, mut b: &[usize], c: usize) -> usize { + | ^^^^^ help: if this is intentional, prefix with an underscore: `_b` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:24:37 + | +LL | fn index(a: usize, mut b: &[usize], c: usize) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_c` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:28:21 + | +LL | fn break_(a: usize, mut b: usize, mut c: usize) -> usize { + | ^^^^^ help: if this is intentional, prefix with an underscore: `_b` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:46:23 + | +LL | fn mut_ref2(a: usize, b: &mut usize) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_b` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:51:28 + | +LL | fn not_primitive(a: usize, b: String) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_b` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:68:33 + | +LL | fn method2(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_b` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:90:24 + | +LL | fn hello(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_b` + +error: parameter is only used in recursion + --> $DIR/only_used_in_recursion.rs:94:32 + | +LL | fn hello2(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix with an underscore: `_b` + +error: aborting due to 13 previous errors + diff --git a/src/tools/clippy/tests/ui/range_plus_minus_one.fixed b/src/tools/clippy/tests/ui/range_plus_minus_one.fixed index 19b253b0fe2..40d7791df28 100644 --- a/src/tools/clippy/tests/ui/range_plus_minus_one.fixed +++ b/src/tools/clippy/tests/ui/range_plus_minus_one.fixed @@ -1,7 +1,7 @@ // run-rustfix #![allow(unused_parens)] - +#![allow(clippy::iter_with_drain)] fn f() -> usize { 42 } diff --git a/src/tools/clippy/tests/ui/range_plus_minus_one.rs b/src/tools/clippy/tests/ui/range_plus_minus_one.rs index 7d034117547..a8ddd9b5f75 100644 --- a/src/tools/clippy/tests/ui/range_plus_minus_one.rs +++ b/src/tools/clippy/tests/ui/range_plus_minus_one.rs @@ -1,7 +1,7 @@ // run-rustfix #![allow(unused_parens)] - +#![allow(clippy::iter_with_drain)] fn f() -> usize { 42 } diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed index 9ae0ed0b13f..b425cdd6cbf 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -25,8 +25,8 @@ fn main() { let slice_ptr = &[0, 1, 2, 3] as *const [i32]; // ... or pointer_kind(T) = pointer_kind(U_0); ptr-ptr-cast - let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u16] }; - let _ptr_to_unsized = slice_ptr as *const [u16]; + let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u32] }; + let _ptr_to_unsized = slice_ptr as *const [u32]; // TODO: We could try testing vtable casts here too, but maybe // we should wait until std::raw::TraitObject is stabilized? diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index 985cf9a075d..8fd57c59652 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -25,8 +25,8 @@ fn main() { let slice_ptr = &[0, 1, 2, 3] as *const [i32]; // ... or pointer_kind(T) = pointer_kind(U_0); ptr-ptr-cast - let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u16]>(slice_ptr) }; - let _ptr_to_unsized = slice_ptr as *const [u16]; + let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u32]>(slice_ptr) }; + let _ptr_to_unsized = slice_ptr as *const [u32]; // TODO: We could try testing vtable casts here too, but maybe // we should wait until std::raw::TraitObject is stabilized? diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr index e8496a325d6..d9b64a0ed7b 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -17,8 +17,8 @@ LL | let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr error: transmute from a pointer to a pointer --> $DIR/transmutes_expressible_as_ptr_casts.rs:28:46 | -LL | let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u16]>(slice_ptr) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice_ptr as *const [u16]` +LL | let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u32]>(slice_ptr) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice_ptr as *const [u32]` error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead --> $DIR/transmutes_expressible_as_ptr_casts.rs:34:50 diff --git a/src/tools/clippy/tests/ui/unnecessary_filter_map.rs b/src/tools/clippy/tests/ui/unnecessary_filter_map.rs index c58181f518d..8e01c2674f1 100644 --- a/src/tools/clippy/tests/ui/unnecessary_filter_map.rs +++ b/src/tools/clippy/tests/ui/unnecessary_filter_map.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + fn main() { let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); let _ = (0..4).filter_map(|x| { @@ -19,3 +21,130 @@ fn main() { fn filter_map_none_changes_item_type() -> impl Iterator<Item = bool> { "".chars().filter_map(|_| None) } + +// https://github.com/rust-lang/rust-clippy/issues/4433#issue-483920107 +mod comment_483920107 { + enum Severity { + Warning, + Other, + } + + struct ServerError; + + impl ServerError { + fn severity(&self) -> Severity { + Severity::Warning + } + } + + struct S { + warnings: Vec<ServerError>, + } + + impl S { + fn foo(&mut self, server_errors: Vec<ServerError>) { + #[allow(unused_variables)] + let errors: Vec<ServerError> = server_errors + .into_iter() + .filter_map(|se| match se.severity() { + Severity::Warning => { + self.warnings.push(se); + None + }, + _ => Some(se), + }) + .collect(); + } + } +} + +// https://github.com/rust-lang/rust-clippy/issues/4433#issuecomment-611006622 +mod comment_611006622 { + struct PendingRequest { + reply_to: u8, + token: u8, + expires: u8, + group_id: u8, + } + + enum Value { + Null, + } + + struct Node; + + impl Node { + fn send_response(&self, _reply_to: u8, _token: u8, _value: Value) -> &Self { + self + } + fn on_error_warn(&self) -> &Self { + self + } + } + + struct S { + pending_requests: Vec<PendingRequest>, + } + + impl S { + fn foo(&mut self, node: Node, now: u8, group_id: u8) { + // "drain_filter" + self.pending_requests = self + .pending_requests + .drain(..) + .filter_map(|pending| { + if pending.expires <= now { + return None; // Expired, remove + } + + if pending.group_id == group_id { + // Matched - reuse strings and remove + node.send_response(pending.reply_to, pending.token, Value::Null) + .on_error_warn(); + None + } else { + // Keep waiting + Some(pending) + } + }) + .collect(); + } + } +} + +// https://github.com/rust-lang/rust-clippy/issues/4433#issuecomment-621925270 +// This extrapolation doesn't reproduce the false positive. Additional context seems necessary. +mod comment_621925270 { + struct Signature(u8); + + fn foo(sig_packets: impl Iterator<Item = Result<Signature, ()>>) -> impl Iterator<Item = u8> { + sig_packets.filter_map(|res| match res { + Ok(Signature(sig_packet)) => Some(sig_packet), + _ => None, + }) + } +} + +// https://github.com/rust-lang/rust-clippy/issues/4433#issuecomment-1052978898 +mod comment_1052978898 { + #![allow(clippy::redundant_closure)] + + pub struct S(u8); + + impl S { + pub fn consume(self) { + println!("yum"); + } + } + + pub fn filter_owned() -> impl Iterator<Item = S> { + (0..10).map(|i| S(i)).filter_map(|s| { + if s.0 & 1 == 0 { + s.consume(); + None + } else { + Some(s) + } + }) + } +} diff --git a/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr b/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr index 041829c3c78..5585b10ab90 100644 --- a/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr @@ -1,5 +1,5 @@ error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:2:13 + --> $DIR/unnecessary_filter_map.rs:4:13 | LL | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:3:13 + --> $DIR/unnecessary_filter_map.rs:5:13 | LL | let _ = (0..4).filter_map(|x| { | _____________^ @@ -19,7 +19,7 @@ LL | | }); | |______^ error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:9:13 + --> $DIR/unnecessary_filter_map.rs:11:13 | LL | let _ = (0..4).filter_map(|x| match x { | _____________^ @@ -29,7 +29,7 @@ LL | | }); | |______^ error: this `.filter_map` can be written more simply using `.map` - --> $DIR/unnecessary_filter_map.rs:14:13 + --> $DIR/unnecessary_filter_map.rs:16:13 | LL | let _ = (0..4).filter_map(|x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/unnecessary_find_map.rs b/src/tools/clippy/tests/ui/unnecessary_find_map.rs new file mode 100644 index 00000000000..a52390861b4 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_find_map.rs @@ -0,0 +1,23 @@ +#![allow(dead_code)] + +fn main() { + let _ = (0..4).find_map(|x| if x > 1 { Some(x) } else { None }); + let _ = (0..4).find_map(|x| { + if x > 1 { + return Some(x); + }; + None + }); + let _ = (0..4).find_map(|x| match x { + 0 | 1 => None, + _ => Some(x), + }); + + let _ = (0..4).find_map(|x| Some(x + 1)); + + let _ = (0..4).find_map(i32::checked_abs); +} + +fn find_map_none_changes_item_type() -> Option<bool> { + "".chars().find_map(|_| None) +} diff --git a/src/tools/clippy/tests/ui/unnecessary_find_map.stderr b/src/tools/clippy/tests/ui/unnecessary_find_map.stderr new file mode 100644 index 00000000000..fb33c122fe3 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_find_map.stderr @@ -0,0 +1,38 @@ +error: this `.find_map` can be written more simply using `.find` + --> $DIR/unnecessary_find_map.rs:4:13 + | +LL | let _ = (0..4).find_map(|x| if x > 1 { Some(x) } else { None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unnecessary-find-map` implied by `-D warnings` + +error: this `.find_map` can be written more simply using `.find` + --> $DIR/unnecessary_find_map.rs:5:13 + | +LL | let _ = (0..4).find_map(|x| { + | _____________^ +LL | | if x > 1 { +LL | | return Some(x); +LL | | }; +LL | | None +LL | | }); + | |______^ + +error: this `.find_map` can be written more simply using `.find` + --> $DIR/unnecessary_find_map.rs:11:13 + | +LL | let _ = (0..4).find_map(|x| match x { + | _____________^ +LL | | 0 | 1 => None, +LL | | _ => Some(x), +LL | | }); + | |______^ + +error: this `.find_map` can be written more simply using `.map(..).next()` + --> $DIR/unnecessary_find_map.rs:16:13 + | +LL | let _ = (0..4).find_map(|x| Some(x + 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed b/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed index d806d620b17..21e2da474a8 100644 --- a/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed @@ -3,7 +3,6 @@ #![allow(clippy::stable_sort_primitive)] use std::cell::Ref; -use std::cmp::Reverse; fn unnecessary_sort_by() { fn id(x: isize) -> isize { @@ -18,8 +17,8 @@ fn unnecessary_sort_by() { vec.sort_unstable_by_key(|a| id(-a)); // Reverse examples vec.sort_by(|a, b| b.cmp(a)); // not linted to avoid suggesting `Reverse(b)` which would borrow - vec.sort_by_key(|b| Reverse((b + 5).abs())); - vec.sort_unstable_by_key(|b| Reverse(id(-b))); + vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs())); + vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b))); // Negative examples (shouldn't be changed) let c = &7; vec.sort_by(|a, b| (b - a).cmp(&(a - b))); @@ -76,7 +75,6 @@ mod issue_5754 { // The closure parameter is not dereferenced anymore, so non-Copy types can be linted mod issue_6001 { - use super::*; struct Test(String); impl Test { @@ -93,8 +91,8 @@ mod issue_6001 { args.sort_by_key(|a| a.name()); args.sort_unstable_by_key(|a| a.name()); // Reverse - args.sort_by_key(|b| Reverse(b.name())); - args.sort_unstable_by_key(|b| Reverse(b.name())); + args.sort_by_key(|b| std::cmp::Reverse(b.name())); + args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name())); } } diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.rs b/src/tools/clippy/tests/ui/unnecessary_sort_by.rs index 6ee9c3af455..3365bf6e119 100644 --- a/src/tools/clippy/tests/ui/unnecessary_sort_by.rs +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.rs @@ -3,7 +3,6 @@ #![allow(clippy::stable_sort_primitive)] use std::cell::Ref; -use std::cmp::Reverse; fn unnecessary_sort_by() { fn id(x: isize) -> isize { @@ -76,7 +75,6 @@ mod issue_5754 { // The closure parameter is not dereferenced anymore, so non-Copy types can be linted mod issue_6001 { - use super::*; struct Test(String); impl Test { diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr b/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr index ca9641e8803..89da5e7ea8b 100644 --- a/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr @@ -1,5 +1,5 @@ error: use Vec::sort here instead - --> $DIR/unnecessary_sort_by.rs:15:5 + --> $DIR/unnecessary_sort_by.rs:14:5 | LL | vec.sort_by(|a, b| a.cmp(b)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort()` @@ -7,70 +7,70 @@ LL | vec.sort_by(|a, b| a.cmp(b)); = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` error: use Vec::sort here instead - --> $DIR/unnecessary_sort_by.rs:16:5 + --> $DIR/unnecessary_sort_by.rs:15:5 | LL | vec.sort_unstable_by(|a, b| a.cmp(b)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable()` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:17:5 + --> $DIR/unnecessary_sort_by.rs:16:5 | LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (a + 5).abs())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:18:5 + --> $DIR/unnecessary_sort_by.rs:17:5 | LL | vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| id(-a))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:21:5 + --> $DIR/unnecessary_sort_by.rs:20:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| Reverse((b + 5).abs()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs()))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:22:5 + --> $DIR/unnecessary_sort_by.rs:21:5 | LL | vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|b| Reverse(id(-b)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b)))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:32:5 + --> $DIR/unnecessary_sort_by.rs:31:5 | LL | vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (***a).abs())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:33:5 + --> $DIR/unnecessary_sort_by.rs:32:5 | LL | vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| (***a).abs())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:93:9 + --> $DIR/unnecessary_sort_by.rs:91:9 | LL | args.sort_by(|a, b| a.name().cmp(&b.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|a| a.name())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:94:9 + --> $DIR/unnecessary_sort_by.rs:92:9 | LL | args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|a| a.name())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:96:9 + --> $DIR/unnecessary_sort_by.rs:94:9 | LL | args.sort_by(|a, b| b.name().cmp(&a.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| Reverse(b.name()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| std::cmp::Reverse(b.name()))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:97:9 + --> $DIR/unnecessary_sort_by.rs:95:9 | LL | args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|b| Reverse(b.name()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name()))` error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed index 4e33e343ce0..9d216f56ae6 100644 --- a/src/tools/clippy/tests/ui/use_self.fixed +++ b/src/tools/clippy/tests/ui/use_self.fixed @@ -2,7 +2,7 @@ // aux-build:proc_macro_derive.rs #![warn(clippy::use_self)] -#![allow(dead_code)] +#![allow(dead_code, unreachable_code)] #![allow( clippy::should_implement_trait, clippy::upper_case_acronyms, @@ -519,3 +519,26 @@ mod self_is_ty_param { } } } + +mod use_self_in_pat { + enum Foo { + Bar, + Baz, + } + + impl Foo { + fn do_stuff(self) { + match self { + Self::Bar => unimplemented!(), + Self::Baz => unimplemented!(), + } + match Some(1) { + Some(_) => unimplemented!(), + None => unimplemented!(), + } + if let Self::Bar = self { + unimplemented!() + } + } + } +} diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs index 7b621ff9bca..5f604fe25e4 100644 --- a/src/tools/clippy/tests/ui/use_self.rs +++ b/src/tools/clippy/tests/ui/use_self.rs @@ -2,7 +2,7 @@ // aux-build:proc_macro_derive.rs #![warn(clippy::use_self)] -#![allow(dead_code)] +#![allow(dead_code, unreachable_code)] #