From d30fe88099a08805394475b7a095ae7549b2a6b4 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Tue, 20 May 2025 22:07:24 +0500 Subject: [PATCH 01/38] if let guard stabilize --- clippy_lints/src/lib.rs | 2 +- clippy_utils/src/lib.rs | 2 +- .../match_like_matches_macro_if_let_guard.rs | 1 - tests/ui/redundant_guards.fixed | 1 - tests/ui/redundant_guards.rs | 1 - tests/ui/redundant_guards.stderr | 60 ++++++++-------- .../redundant_pattern_matching_option.fixed | 1 - tests/ui/redundant_pattern_matching_option.rs | 1 - .../redundant_pattern_matching_option.stderr | 70 +++++++++---------- 9 files changed, 67 insertions(+), 72 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 40b7c3a3fc22..653c1cc7280f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,9 +1,9 @@ +#![cfg_attr(bootstrap, feature(if_let_guard))] #![feature(box_patterns)] #![feature(control_flow_into_value)] #![feature(exact_div)] #![feature(f128)] #![feature(f16)] -#![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(iter_partition_in_place)] #![feature(macro_metavar_expr_concat)] diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index c479ea59b884..d8b2b22dd09d 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1,5 +1,5 @@ +#![cfg_attr(bootstrap, feature(if_let_guard))] #![feature(box_patterns)] -#![feature(if_let_guard)] #![feature(macro_metavar_expr)] #![feature(never_type)] #![feature(rustc_private)] diff --git a/tests/ui/match_like_matches_macro_if_let_guard.rs b/tests/ui/match_like_matches_macro_if_let_guard.rs index b596d36072e5..4b3b53d83f5e 100644 --- a/tests/ui/match_like_matches_macro_if_let_guard.rs +++ b/tests/ui/match_like_matches_macro_if_let_guard.rs @@ -1,6 +1,5 @@ //@check-pass #![warn(clippy::match_like_matches_macro)] -#![feature(if_let_guard)] #[expect(clippy::option_option)] fn issue15841(opt: Option>>, value: i32) { diff --git a/tests/ui/redundant_guards.fixed b/tests/ui/redundant_guards.fixed index 9dd9d341db2e..f433d8263023 100644 --- a/tests/ui/redundant_guards.fixed +++ b/tests/ui/redundant_guards.fixed @@ -1,5 +1,4 @@ //@aux-build:proc_macros.rs -#![feature(if_let_guard)] #![allow(clippy::no_effect, unused, clippy::single_match, invalid_nan_comparisons)] #![warn(clippy::redundant_guards)] diff --git a/tests/ui/redundant_guards.rs b/tests/ui/redundant_guards.rs index e9950d3bbd1d..02115af75ed0 100644 --- a/tests/ui/redundant_guards.rs +++ b/tests/ui/redundant_guards.rs @@ -1,5 +1,4 @@ //@aux-build:proc_macros.rs -#![feature(if_let_guard)] #![allow(clippy::no_effect, unused, clippy::single_match, invalid_nan_comparisons)] #![warn(clippy::redundant_guards)] diff --git a/tests/ui/redundant_guards.stderr b/tests/ui/redundant_guards.stderr index cb7b9b119e20..c889d5a5697d 100644 --- a/tests/ui/redundant_guards.stderr +++ b/tests/ui/redundant_guards.stderr @@ -1,5 +1,5 @@ error: redundant guard - --> tests/ui/redundant_guards.rs:22:14 + --> tests/ui/redundant_guards.rs:21:14 | LL | x if x == 0.0 => todo!(), | ^^^^^^^^ @@ -13,7 +13,7 @@ LL + 0.0 => todo!(), | error: redundant guard - --> tests/ui/redundant_guards.rs:29:14 + --> tests/ui/redundant_guards.rs:28:14 | LL | x if x == FloatWrapper(0.0) => todo!(), | ^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + FloatWrapper(0.0) => todo!(), | error: redundant guard - --> tests/ui/redundant_guards.rs:45:20 + --> tests/ui/redundant_guards.rs:44:20 | LL | C(x, y) if let 1 = y => .., | ^^^^^^^^^ @@ -37,7 +37,7 @@ LL + C(x, 1) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:52:20 + --> tests/ui/redundant_guards.rs:51:20 | LL | Some(x) if matches!(x, Some(1) if true) => .., | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + Some(Some(1)) if true => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:54:20 + --> tests/ui/redundant_guards.rs:53:20 | LL | Some(x) if matches!(x, Some(1)) => { | ^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + Some(Some(1)) => { | error: redundant guard - --> tests/ui/redundant_guards.rs:59:20 + --> tests/ui/redundant_guards.rs:58:20 | LL | Some(x) if let Some(1) = x => .., | ^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + Some(Some(1)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:61:20 + --> tests/ui/redundant_guards.rs:60:20 | LL | Some(x) if x == Some(2) => .., | ^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + Some(Some(2)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:63:20 + --> tests/ui/redundant_guards.rs:62:20 | LL | Some(x) if Some(2) == x => .., | ^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + Some(Some(2)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:89:20 + --> tests/ui/redundant_guards.rs:88:20 | LL | B { e } if matches!(e, Some(A(2))) => .., | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + B { e: Some(A(2)) } => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:127:20 + --> tests/ui/redundant_guards.rs:126:20 | LL | E::A(y) if y == "not from an or pattern" => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + E::A("not from an or pattern") => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:135:14 + --> tests/ui/redundant_guards.rs:134:14 | LL | x if matches!(x, Some(0)) => .., | ^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + Some(0) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:143:14 + --> tests/ui/redundant_guards.rs:142:14 | LL | i if i == -1 => {}, | ^^^^^^^ @@ -145,7 +145,7 @@ LL + -1 => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:145:14 + --> tests/ui/redundant_guards.rs:144:14 | LL | i if i == 1 => {}, | ^^^^^^ @@ -157,7 +157,7 @@ LL + 1 => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:208:28 + --> tests/ui/redundant_guards.rs:207:28 | LL | Some(ref x) if x == &1 => {}, | ^^^^^^^ @@ -169,7 +169,7 @@ LL + Some(1) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:210:28 + --> tests/ui/redundant_guards.rs:209:28 | LL | Some(ref x) if &1 == x => {}, | ^^^^^^^ @@ -181,7 +181,7 @@ LL + Some(1) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:212:28 + --> tests/ui/redundant_guards.rs:211:28 | LL | Some(ref x) if let &2 = x => {}, | ^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + Some(2) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:214:28 + --> tests/ui/redundant_guards.rs:213:28 | LL | Some(ref x) if matches!(x, &3) => {}, | ^^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + Some(3) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:235:32 + --> tests/ui/redundant_guards.rs:234:32 | LL | B { ref c, .. } if c == &1 => {}, | ^^^^^^^ @@ -217,7 +217,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:237:32 + --> tests/ui/redundant_guards.rs:236:32 | LL | B { ref c, .. } if &1 == c => {}, | ^^^^^^^ @@ -229,7 +229,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:239:32 + --> tests/ui/redundant_guards.rs:238:32 | LL | B { ref c, .. } if let &1 = c => {}, | ^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:241:32 + --> tests/ui/redundant_guards.rs:240:32 | LL | B { ref c, .. } if matches!(c, &1) => {}, | ^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:252:26 + --> tests/ui/redundant_guards.rs:251:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -265,7 +265,7 @@ LL + Some(Some("")) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:264:26 + --> tests/ui/redundant_guards.rs:263:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL + Some(Some([])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:270:26 + --> tests/ui/redundant_guards.rs:269:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -289,7 +289,7 @@ LL + Some(Some([])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:282:26 + --> tests/ui/redundant_guards.rs:281:26 | LL | Some(Some(x)) if x.starts_with(&[]) => {}, | ^^^^^^^^^^^^^^^^^^ @@ -301,7 +301,7 @@ LL + Some(Some([..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:288:26 + --> tests/ui/redundant_guards.rs:287:26 | LL | Some(Some(x)) if x.starts_with(&[1]) => {}, | ^^^^^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL + Some(Some([1, ..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:294:26 + --> tests/ui/redundant_guards.rs:293:26 | LL | Some(Some(x)) if x.starts_with(&[1, 2]) => {}, | ^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +325,7 @@ LL + Some(Some([1, 2, ..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:300:26 + --> tests/ui/redundant_guards.rs:299:26 | LL | Some(Some(x)) if x.ends_with(&[1, 2]) => {}, | ^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL + Some(Some([.., 1, 2])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:323:18 + --> tests/ui/redundant_guards.rs:322:18 | LL | y if y.is_empty() => {}, | ^^^^^^^^^^^^ @@ -349,7 +349,7 @@ LL + "" => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:342:22 + --> tests/ui/redundant_guards.rs:341:22 | LL | y if y.is_empty() => {}, | ^^^^^^^^^^^^ diff --git a/tests/ui/redundant_pattern_matching_option.fixed b/tests/ui/redundant_pattern_matching_option.fixed index b44009446640..dbebc4e9793a 100644 --- a/tests/ui/redundant_pattern_matching_option.fixed +++ b/tests/ui/redundant_pattern_matching_option.fixed @@ -1,4 +1,3 @@ -#![feature(if_let_guard)] #![warn(clippy::redundant_pattern_matching)] #![allow( clippy::needless_bool, diff --git a/tests/ui/redundant_pattern_matching_option.rs b/tests/ui/redundant_pattern_matching_option.rs index c13cf993e786..b3bb74428a54 100644 --- a/tests/ui/redundant_pattern_matching_option.rs +++ b/tests/ui/redundant_pattern_matching_option.rs @@ -1,4 +1,3 @@ -#![feature(if_let_guard)] #![warn(clippy::redundant_pattern_matching)] #![allow( clippy::needless_bool, diff --git a/tests/ui/redundant_pattern_matching_option.stderr b/tests/ui/redundant_pattern_matching_option.stderr index 5c9edfd4c50a..62ead95235ab 100644 --- a/tests/ui/redundant_pattern_matching_option.stderr +++ b/tests/ui/redundant_pattern_matching_option.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:12:5 + --> tests/ui/redundant_pattern_matching_option.rs:11:5 | LL | matches!(maybe_some, None if !boolean) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `maybe_some.is_none() && (!boolean)` @@ -8,55 +8,55 @@ LL | matches!(maybe_some, None if !boolean) = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:17:13 + --> tests/ui/redundant_pattern_matching_option.rs:16:13 | LL | let _ = matches!(maybe_some, None if boolean || boolean2); // guard needs parentheses | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `maybe_some.is_none() && (boolean || boolean2)` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:33:12 + --> tests/ui/redundant_pattern_matching_option.rs:32:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:36:12 + --> tests/ui/redundant_pattern_matching_option.rs:35:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:39:12 + --> tests/ui/redundant_pattern_matching_option.rs:38:12 | LL | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:46:15 + --> tests/ui/redundant_pattern_matching_option.rs:45:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:49:15 + --> tests/ui/redundant_pattern_matching_option.rs:48:15 | LL | while let None = Some(42) {} | ----------^^^^----------- help: try: `while Some(42).is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:52:15 + --> tests/ui/redundant_pattern_matching_option.rs:51:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:56:15 + --> tests/ui/redundant_pattern_matching_option.rs:55:15 | LL | while let Some(_) = v.pop() { | ----------^^^^^^^---------- help: try: `while v.pop().is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:65:5 + --> tests/ui/redundant_pattern_matching_option.rs:64:5 | LL | / match Some(42) { LL | | @@ -66,7 +66,7 @@ LL | | }; | |_____^ help: try: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:71:5 + --> tests/ui/redundant_pattern_matching_option.rs:70:5 | LL | / match None::<()> { LL | | @@ -76,7 +76,7 @@ LL | | }; | |_____^ help: try: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:77:13 + --> tests/ui/redundant_pattern_matching_option.rs:76:13 | LL | let _ = match None::<()> { | _____________^ @@ -87,55 +87,55 @@ LL | | }; | |_____^ help: try: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:84:20 + --> tests/ui/redundant_pattern_matching_option.rs:83:20 | LL | let _ = if let Some(_) = opt { true } else { false }; | -------^^^^^^^------ help: try: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:91:20 + --> tests/ui/redundant_pattern_matching_option.rs:90:20 | LL | let _ = if let Some(_) = gen_opt() { | -------^^^^^^^------------ help: try: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:94:19 + --> tests/ui/redundant_pattern_matching_option.rs:93:19 | LL | } else if let None = gen_opt() { | -------^^^^------------ help: try: `if gen_opt().is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:101:12 + --> tests/ui/redundant_pattern_matching_option.rs:100:12 | LL | if let Some(..) = gen_opt() {} | -------^^^^^^^^------------ help: try: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:117:12 + --> tests/ui/redundant_pattern_matching_option.rs:116:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:120:12 + --> tests/ui/redundant_pattern_matching_option.rs:119:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:123:15 + --> tests/ui/redundant_pattern_matching_option.rs:122:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:126:15 + --> tests/ui/redundant_pattern_matching_option.rs:125:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:129:5 + --> tests/ui/redundant_pattern_matching_option.rs:128:5 | LL | / match Some(42) { LL | | @@ -145,7 +145,7 @@ LL | | }; | |_____^ help: try: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:135:5 + --> tests/ui/redundant_pattern_matching_option.rs:134:5 | LL | / match None::<()> { LL | | @@ -155,19 +155,19 @@ LL | | }; | |_____^ help: try: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:144:12 + --> tests/ui/redundant_pattern_matching_option.rs:143:12 | LL | if let None = *(&None::<()>) {} | -------^^^^----------------- help: try: `if (&None::<()>).is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:146:12 + --> tests/ui/redundant_pattern_matching_option.rs:145:12 | LL | if let None = *&None::<()> {} | -------^^^^--------------- help: try: `if (&None::<()>).is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:153:5 + --> tests/ui/redundant_pattern_matching_option.rs:152:5 | LL | / match x { LL | | @@ -177,7 +177,7 @@ LL | | }; | |_____^ help: try: `x.is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:159:5 + --> tests/ui/redundant_pattern_matching_option.rs:158:5 | LL | / match x { LL | | @@ -187,7 +187,7 @@ LL | | }; | |_____^ help: try: `x.is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:165:5 + --> tests/ui/redundant_pattern_matching_option.rs:164:5 | LL | / match x { LL | | @@ -197,7 +197,7 @@ LL | | }; | |_____^ help: try: `x.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:171:5 + --> tests/ui/redundant_pattern_matching_option.rs:170:5 | LL | / match x { LL | | @@ -207,43 +207,43 @@ LL | | }; | |_____^ help: try: `x.is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:187:13 + --> tests/ui/redundant_pattern_matching_option.rs:186:13 | LL | let _ = matches!(x, Some(_)); | ^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:190:13 + --> tests/ui/redundant_pattern_matching_option.rs:189:13 | LL | let _ = matches!(x, None); | ^^^^^^^^^^^^^^^^^ help: try: `x.is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:201:17 + --> tests/ui/redundant_pattern_matching_option.rs:200:17 | LL | let _ = matches!(*p, None); | ^^^^^^^^^^^^^^^^^^ help: try: `(*p).is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:209:16 + --> tests/ui/redundant_pattern_matching_option.rs:208:16 | LL | if let Some(_) = x? { | -------^^^^^^^----- help: try: `if x?.is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:229:16 + --> tests/ui/redundant_pattern_matching_option.rs:228:16 | LL | if let Some(_) = x.await { | -------^^^^^^^---------- help: try: `if x.await.is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:242:12 + --> tests/ui/redundant_pattern_matching_option.rs:241:12 | LL | if let Some(_) = (x! {}) {}; | -------^^^^^^^---------- help: try: `if x! {}.is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:244:15 + --> tests/ui/redundant_pattern_matching_option.rs:243:15 | LL | while let Some(_) = (x! {}) {} | ----------^^^^^^^---------- help: try: `while x! {}.is_some()` From f79b6a1f602e2a69052d6923060b977161093da2 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 18 Feb 2026 16:12:14 +0100 Subject: [PATCH 02/38] docs: add `<>` around Markdown link --- book/src/development/the_team.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/development/the_team.md b/book/src/development/the_team.md index d22123231868..a663158c949b 100644 --- a/book/src/development/the_team.md +++ b/book/src/development/the_team.md @@ -51,7 +51,7 @@ this group to help with triaging, which can include: busy or wants to abandon it. If the reviewer is busy, the PR can be reassigned to someone else. - Checkout: https://triage.rust-lang.org/triage/rust-lang/rust-clippy to + Checkout: to monitor PRs. While not part of their duties, contributors are encouraged to review PRs From 5fef4429d1949f49d6cd64636e757f121fb2966f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 14 Feb 2026 00:14:02 +0000 Subject: [PATCH 03/38] Make all multipart suggestions verbose The ShowAlways style of suggestions is usually easier to understand than the inline style. --- clippy_lints/src/create_dir.rs | 2 +- clippy_lints/src/duration_suboptimal_units.rs | 2 +- clippy_lints/src/empty_line_after.rs | 6 +- clippy_lints/src/loops/never_loop.rs | 2 +- clippy_lints/src/matches/match_same_arms.rs | 4 +- clippy_lints/src/matches/redundant_guards.rs | 2 +- clippy_lints/src/methods/io_other_error.rs | 2 +- clippy_lints/src/methods/ip_constant.rs | 2 +- .../methods/suspicious_command_arg_space.rs | 2 +- .../src/methods/unnecessary_map_or.rs | 2 +- .../src/needless_arbitrary_self_type.rs | 2 +- clippy_lints/src/raw_strings.rs | 2 +- clippy_lints/src/returns/needless_return.rs | 2 +- .../src/significant_drop_tightening.rs | 2 +- clippy_lints/src/unit_types/let_unit_value.rs | 4 +- .../src/repeated_is_diagnostic_item.rs | 8 +- .../ui-toml/ref_option/ref_option.all.stderr | 114 ++++++---- .../ref_option/ref_option.private.stderr | 83 +++++--- .../ref_option/ref_option_traits.all.stderr | 39 ++-- .../ref_option_traits.private.stderr | 19 +- .../renamed_function_params.default.stderr | 39 +++- .../renamed_function_params.extend.stderr | 23 +- .../default_constructed_unit_structs.stderr | 59 ++++-- tests/ui/double_ended_iterator_last.stderr | 19 +- tests/ui/extra_unused_type_parameters.stderr | 47 ++++- tests/ui/manual_is_ascii_check.stderr | 199 +++++++++++++++--- tests/ui/mutex_atomic.stderr | 77 ++++++- tests/ui/needless_borrow_pat.stderr | 47 ++++- .../ui/non_canonical_partial_ord_impl.stderr | 86 +++++--- ...nonical_partial_ord_impl_fully_qual.stderr | 47 +++-- tests/ui/ptr_arg.stderr | 159 ++++++++++++-- tests/ui/range.stderr | 7 +- tests/ui/range_unfixable.stderr | 7 +- tests/ui/unit_arg_fixable.stderr | 39 ++-- ...sary_fallible_conversions_unfixable.stderr | 42 +++- tests/ui/unnecessary_iter_cloned.stderr | 8 +- tests/ui/unnecessary_literal_unwrap.stderr | 32 ++- ...nnecessary_literal_unwrap_unfixable.stderr | 16 +- tests/ui/useless_conversion.stderr | 81 ++++--- 39 files changed, 1023 insertions(+), 312 deletions(-) diff --git a/clippy_lints/src/create_dir.rs b/clippy_lints/src/create_dir.rs index 695b25aeb0b7..f68c0b3a1ddc 100644 --- a/clippy_lints/src/create_dir.rs +++ b/clippy_lints/src/create_dir.rs @@ -51,7 +51,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { suggestions.push((path.span.shrink_to_lo(), "std::fs::".to_owned())); } - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( "consider calling `std::fs::create_dir_all` instead", suggestions, Applicability::MaybeIncorrect, diff --git a/clippy_lints/src/duration_suboptimal_units.rs b/clippy_lints/src/duration_suboptimal_units.rs index 19f44f8e959d..6ad432c2659a 100644 --- a/clippy_lints/src/duration_suboptimal_units.rs +++ b/clippy_lints/src/duration_suboptimal_units.rs @@ -98,7 +98,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { (func_name.ident.span, promoted_constructor.to_string()), (arg.span, promoted_value.to_string()), ]; - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( format!("try using {promoted_constructor}"), suggestions, Applicability::MachineApplicable, diff --git a/clippy_lints/src/empty_line_after.rs b/clippy_lints/src/empty_line_after.rs index 76e67b1154be..12dcf9252f73 100644 --- a/clippy_lints/src/empty_line_after.rs +++ b/clippy_lints/src/empty_line_after.rs @@ -367,7 +367,7 @@ fn check_gaps(&self, cx: &EarlyContext<'_>, gaps: &[Gap<'_>], id: NodeId) { Some(name) => format!("{} `{name}`", info.kind).into(), None => Cow::from("the following item"), }; - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( format!("if the doc comment should not document {name} then comment it out"), suggestions, Applicability::MaybeIncorrect, @@ -384,7 +384,7 @@ fn check_gaps(&self, cx: &EarlyContext<'_>, gaps: &[Gap<'_>], id: NodeId) { // Commentless empty gaps between line doc comments, possibly intended to be part of the markdown let indent = snippet_indent(cx, first_gap.prev_stop.span).unwrap_or_default(); - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( format!("if the documentation should include the empty {lines} include {them} in the comment"), empty_lines() .map(|empty_line| (empty_line, format!("{indent}///"))) @@ -414,7 +414,7 @@ fn suggest_inner(&self, diag: &mut Diag<'_, ()>, kind: StopKind, gaps: &[Gap<'_> } else { parent.kind }; - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( match kind { StopKind::Attr => format!("if the attribute should apply to the {desc} use an inner attribute"), StopKind::Doc(_) => format!("if the comment should document the {desc} use an inner doc comment"), diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index 231388e7379a..ff0ac575550c 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -56,7 +56,7 @@ pub(super) fn check<'tcx>( )]; // Make sure to clear up the diverging sites when we remove a loopp. suggestions.extend(break_spans.iter().map(|span| (*span, String::new()))); - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( "if you need the first element of the iterator, try writing", suggestions, app, diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index c20217563d62..5b0de80e67fd 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -129,7 +129,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { diag.span_label(last.span, "the wildcard arm"); let s = if prev.len() > 1 { "s" } else { "" }; - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( format!("otherwise remove the non-wildcard arm{s}"), prev.iter() .map(|(_, arm)| (adjusted_arm_span(cx, arm.span), String::new())) @@ -158,7 +158,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { .chain([(dest.pat.span, pat_snippets.iter().join(" | "))]) .collect_vec(); - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( "otherwise merge the patterns into a single arm", suggs, Applicability::MaybeIncorrect, diff --git a/clippy_lints/src/matches/redundant_guards.rs b/clippy_lints/src/matches/redundant_guards.rs index 757ecf75ed45..fa8b6a65a203 100644 --- a/clippy_lints/src/matches/redundant_guards.rs +++ b/clippy_lints/src/matches/redundant_guards.rs @@ -226,7 +226,7 @@ fn emit_redundant_guards<'tcx>( } => (span.shrink_to_hi(), format!(": {binding_replacement}")), PatBindingInfo { span, .. } => (span, binding_replacement.into_owned()), }; - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( "try", vec![ suggestion_span, diff --git a/clippy_lints/src/methods/io_other_error.rs b/clippy_lints/src/methods/io_other_error.rs index b081e804859a..d9735f294140 100644 --- a/clippy_lints/src/methods/io_other_error.rs +++ b/clippy_lints/src/methods/io_other_error.rs @@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, path: &Expr<'_>, args expr.span, "this can be `std::io::Error::other(_)`", |diag| { - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( "use `std::io::Error::other`", vec![ (new_segment.ident.span, "other".to_owned()), diff --git a/clippy_lints/src/methods/ip_constant.rs b/clippy_lints/src/methods/ip_constant.rs index d5e4dac5e452..7c24cf03fd97 100644 --- a/clippy_lints/src/methods/ip_constant.rs +++ b/clippy_lints/src/methods/ip_constant.rs @@ -45,7 +45,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args } span_lint_and_then(cx, IP_CONSTANT, expr.span, "hand-coded well-known IP address", |diag| { - diag.multipart_suggestion_verbose("use", sugg, Applicability::MachineApplicable); + diag.multipart_suggestion("use", sugg, Applicability::MachineApplicable); }); } } diff --git a/clippy_lints/src/methods/suspicious_command_arg_space.rs b/clippy_lints/src/methods/suspicious_command_arg_space.rs index 3e9c677fe34a..be733c5d3514 100644 --- a/clippy_lints/src/methods/suspicious_command_arg_space.rs +++ b/clippy_lints/src/methods/suspicious_command_arg_space.rs @@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx hir::Expr<'_>, arg arg.span, "single argument that looks like it should be multiple arguments", |diag: &mut Diag<'_, ()>| { - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( "consider splitting the argument", vec![(span, "args".to_string()), (arg.span, format!("[{arg1:?}, {arg2:?}]"))], Applicability::MaybeIncorrect, diff --git a/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs index 21e112360aaf..b9af39184387 100644 --- a/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/clippy_lints/src/methods/unnecessary_map_or.rs @@ -154,7 +154,7 @@ pub(super) fn check<'a>( expr.span, "this `map_or` can be simplified", |diag| { - diag.multipart_suggestion_verbose(format!("use {method} instead"), sugg, applicability); + diag.multipart_suggestion(format!("use {method} instead"), sugg, applicability); }, ); } diff --git a/clippy_lints/src/needless_arbitrary_self_type.rs b/clippy_lints/src/needless_arbitrary_self_type.rs index 691d9035d02c..0d9e0bcff48e 100644 --- a/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/clippy_lints/src/needless_arbitrary_self_type.rs @@ -117,7 +117,7 @@ fn check_param(&mut self, cx: &EarlyContext<'_>, p: &Param) { if !add.is_empty() { sugg.push((p.span.shrink_to_lo(), add)); } - diag.multipart_suggestion_verbose("remove the type", sugg, applicability); + diag.multipart_suggestion("remove the type", sugg, applicability); }, ); } diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs index 943e662479e9..63b9a38eef1e 100644 --- a/clippy_lints/src/raw_strings.rs +++ b/clippy_lints/src/raw_strings.rs @@ -123,7 +123,7 @@ fn check_raw_string(&self, cx: &EarlyContext<'_>, str: &str, lit_span: Span, pre remove.push((end, String::new())); } - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( format!("use a plain {descr} literal instead"), remove, Applicability::MachineApplicable, diff --git a/clippy_lints/src/returns/needless_return.rs b/clippy_lints/src/returns/needless_return.rs index 7d836b610e5f..04e4f379e37c 100644 --- a/clippy_lints/src/returns/needless_return.rs +++ b/clippy_lints/src/returns/needless_return.rs @@ -251,7 +251,7 @@ fn emit_return_lint( .chain(semi_spans.into_iter().map(|span| (span, String::new()))) .collect(); - diag.multipart_suggestion_verbose(replacement.sugg_help(), suggestions, replacement.applicability()); + diag.multipart_suggestion(replacement.sugg_help(), suggestions, replacement.applicability()); }, ); } diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index 8557e8d18d10..c2c1778882d3 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -104,7 +104,7 @@ fn check_fn( format!("\n{indent}{init_method}.{usage_method};") }; - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( "merge the temporary construction with its single usage", vec![(apa.first_stmt_span, stmt), (apa.last_stmt_span, String::new())], Applicability::MaybeIncorrect, diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs index 2645e94358e1..2a23e5329e9e 100644 --- a/clippy_lints/src/unit_types/let_unit_value.rs +++ b/clippy_lints/src/unit_types/let_unit_value.rs @@ -118,7 +118,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, format_args: &FormatArgsStorag init_new_span.shrink_to_lo(), format!("();\n{}", snippet_indent(cx, local.span).as_deref().unwrap_or("")), )); - diag.multipart_suggestion_verbose("replace variable usages with `()`", suggestions, app); + diag.multipart_suggestion("replace variable usages with `()`", suggestions, app); return; } } @@ -131,7 +131,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, format_args: &FormatArgsStorag } else { "omit the `let` binding and replace variable usages with `()`" }; - diag.multipart_suggestion_verbose(message, suggestions, app); + diag.multipart_suggestion(message, suggestions, app); }, ); } diff --git a/clippy_lints_internal/src/repeated_is_diagnostic_item.rs b/clippy_lints_internal/src/repeated_is_diagnostic_item.rs index 55fb78b1e296..8644ea1fc907 100644 --- a/clippy_lints_internal/src/repeated_is_diagnostic_item.rs +++ b/clippy_lints_internal/src/repeated_is_diagnostic_item.rs @@ -190,7 +190,7 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { })) .collect(); - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( format!("call `{recv_ty}::opt_diag_name`, and reuse the results"), sugg, app, @@ -234,7 +234,7 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { })) .collect(); - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( "call `TyCtxt::get_diagnostic_name`, and reuse the results", sugg, app, @@ -437,7 +437,7 @@ fn check_if_chains<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, conds: Vec<&'t })) .collect(); - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( format!("call `{recv_ty}::opt_diag_name`, and reuse the results"), sugg, app, @@ -489,7 +489,7 @@ fn check_if_chains<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, conds: Vec<&'t })) .collect(); - diag.multipart_suggestion_verbose( + diag.multipart_suggestion( "call `TyCtxt::get_diagnostic_name`, and reuse the results", sugg, app, diff --git a/tests/ui-toml/ref_option/ref_option.all.stderr b/tests/ui-toml/ref_option/ref_option.all.stderr index 45ce105e0308..333942c58543 100644 --- a/tests/ui-toml/ref_option/ref_option.all.stderr +++ b/tests/ui-toml/ref_option/ref_option.all.stderr @@ -2,52 +2,69 @@ error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:9:1 | LL | fn opt_u8(a: &Option) {} - | ^^^^^^^^^^^^^-----------^^^^ - | | - | help: change this to: `Option<&u8>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::ref-option` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::ref_option)]` +help: change this to + | +LL - fn opt_u8(a: &Option) {} +LL + fn opt_u8(a: Option<&u8>) {} + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:11:1 | LL | fn opt_gen(a: &Option) {} - | ^^^^^^^^^^^^^^^^^----------^^^^ - | | - | help: change this to: `Option<&T>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn opt_gen(a: &Option) {} +LL + fn opt_gen(a: Option<&T>) {} + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:13:1 | LL | fn opt_string(a: &std::option::Option) {} - | ^^^^^^^^^^^^^^^^^----------------------------^^^^ - | | - | help: change this to: `std::option::Option<&String>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn opt_string(a: &std::option::Option) {} +LL + fn opt_string(a: std::option::Option<&String>) {} + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:15:1 | -LL | fn ret_u8<'a>(p: &'a str) -> &'a Option { - | ^ -------------- help: change this to: `Option<&'a u8>` - | _| - | | +LL | / fn ret_u8<'a>(p: &'a str) -> &'a Option { LL | | LL | | panic!() LL | | } | |_^ + | +help: change this to + | +LL - fn ret_u8<'a>(p: &'a str) -> &'a Option { +LL + fn ret_u8<'a>(p: &'a str) -> Option<&'a u8> { + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:19:1 | -LL | fn ret_u8_static() -> &'static Option { - | ^ ------------------- help: change this to: `Option<&'static u8>` - | _| - | | +LL | / fn ret_u8_static() -> &'static Option { LL | | LL | | panic!() LL | | } | |_^ + | +help: change this to + | +LL - fn ret_u8_static() -> &'static Option { +LL + fn ret_u8_static() -> Option<&'static u8> { + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:23:1 @@ -64,22 +81,29 @@ LL + fn mult_string(a: Option<&String>, b: Option<&Vec>) {} error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:25:1 | -LL | fn ret_box<'a>() -> &'a Option> { - | ^ ------------------- help: change this to: `Option<&'a Box>` - | _| - | | +LL | / fn ret_box<'a>() -> &'a Option> { LL | | LL | | panic!() LL | | } | |_^ + | +help: change this to + | +LL - fn ret_box<'a>() -> &'a Option> { +LL + fn ret_box<'a>() -> Option<&'a Box> { + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:30:1 | LL | pub fn pub_opt_string(a: &Option) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ - | | - | help: change this to: `Option<&String>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - pub fn pub_opt_string(a: &Option) {} +LL + pub fn pub_opt_string(a: Option<&String>) {} + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:32:1 @@ -97,41 +121,55 @@ error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:38:5 | LL | pub fn pub_opt_params(&self, a: &Option<()>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ - | | - | help: change this to: `Option<&()>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - pub fn pub_opt_params(&self, a: &Option<()>) {} +LL + pub fn pub_opt_params(&self, a: Option<&()>) {} + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:40:5 | -LL | pub fn pub_opt_ret(&self) -> &Option { - | ^ --------------- help: change this to: `Option<&String>` - | _____| - | | +LL | / pub fn pub_opt_ret(&self) -> &Option { LL | | LL | | panic!() LL | | } | |_____^ + | +help: change this to + | +LL - pub fn pub_opt_ret(&self) -> &Option { +LL + pub fn pub_opt_ret(&self) -> Option<&String> { + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:45:5 | LL | fn private_opt_params(&self, a: &Option<()>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ - | | - | help: change this to: `Option<&()>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn private_opt_params(&self, a: &Option<()>) {} +LL + fn private_opt_params(&self, a: Option<&()>) {} + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:47:5 | -LL | fn private_opt_ret(&self) -> &Option { - | ^ --------------- help: change this to: `Option<&String>` - | _____| - | | +LL | / fn private_opt_ret(&self) -> &Option { LL | | LL | | panic!() LL | | } | |_____^ + | +help: change this to + | +LL - fn private_opt_ret(&self) -> &Option { +LL + fn private_opt_ret(&self) -> Option<&String> { + | error: aborting due to 13 previous errors diff --git a/tests/ui-toml/ref_option/ref_option.private.stderr b/tests/ui-toml/ref_option/ref_option.private.stderr index a63efd60a036..0702e54fd9f0 100644 --- a/tests/ui-toml/ref_option/ref_option.private.stderr +++ b/tests/ui-toml/ref_option/ref_option.private.stderr @@ -2,52 +2,69 @@ error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:9:1 | LL | fn opt_u8(a: &Option) {} - | ^^^^^^^^^^^^^-----------^^^^ - | | - | help: change this to: `Option<&u8>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::ref-option` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::ref_option)]` +help: change this to + | +LL - fn opt_u8(a: &Option) {} +LL + fn opt_u8(a: Option<&u8>) {} + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:11:1 | LL | fn opt_gen(a: &Option) {} - | ^^^^^^^^^^^^^^^^^----------^^^^ - | | - | help: change this to: `Option<&T>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn opt_gen(a: &Option) {} +LL + fn opt_gen(a: Option<&T>) {} + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:13:1 | LL | fn opt_string(a: &std::option::Option) {} - | ^^^^^^^^^^^^^^^^^----------------------------^^^^ - | | - | help: change this to: `std::option::Option<&String>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn opt_string(a: &std::option::Option) {} +LL + fn opt_string(a: std::option::Option<&String>) {} + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:15:1 | -LL | fn ret_u8<'a>(p: &'a str) -> &'a Option { - | ^ -------------- help: change this to: `Option<&'a u8>` - | _| - | | +LL | / fn ret_u8<'a>(p: &'a str) -> &'a Option { LL | | LL | | panic!() LL | | } | |_^ + | +help: change this to + | +LL - fn ret_u8<'a>(p: &'a str) -> &'a Option { +LL + fn ret_u8<'a>(p: &'a str) -> Option<&'a u8> { + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:19:1 | -LL | fn ret_u8_static() -> &'static Option { - | ^ ------------------- help: change this to: `Option<&'static u8>` - | _| - | | +LL | / fn ret_u8_static() -> &'static Option { LL | | LL | | panic!() LL | | } | |_^ + | +help: change this to + | +LL - fn ret_u8_static() -> &'static Option { +LL + fn ret_u8_static() -> Option<&'static u8> { + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:23:1 @@ -64,34 +81,44 @@ LL + fn mult_string(a: Option<&String>, b: Option<&Vec>) {} error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:25:1 | -LL | fn ret_box<'a>() -> &'a Option> { - | ^ ------------------- help: change this to: `Option<&'a Box>` - | _| - | | +LL | / fn ret_box<'a>() -> &'a Option> { LL | | LL | | panic!() LL | | } | |_^ + | +help: change this to + | +LL - fn ret_box<'a>() -> &'a Option> { +LL + fn ret_box<'a>() -> Option<&'a Box> { + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:45:5 | LL | fn private_opt_params(&self, a: &Option<()>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ - | | - | help: change this to: `Option<&()>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn private_opt_params(&self, a: &Option<()>) {} +LL + fn private_opt_params(&self, a: Option<&()>) {} + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option.rs:47:5 | -LL | fn private_opt_ret(&self) -> &Option { - | ^ --------------- help: change this to: `Option<&String>` - | _____| - | | +LL | / fn private_opt_ret(&self) -> &Option { LL | | LL | | panic!() LL | | } | |_____^ + | +help: change this to + | +LL - fn private_opt_ret(&self) -> &Option { +LL + fn private_opt_ret(&self) -> Option<&String> { + | error: aborting due to 9 previous errors diff --git a/tests/ui-toml/ref_option/ref_option_traits.all.stderr b/tests/ui-toml/ref_option/ref_option_traits.all.stderr index 602e148be601..0d4657246f29 100644 --- a/tests/ui-toml/ref_option/ref_option_traits.all.stderr +++ b/tests/ui-toml/ref_option/ref_option_traits.all.stderr @@ -2,36 +2,51 @@ error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option_traits.rs:10:5 | LL | fn pub_trait_opt(&self, a: &Option>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------^^ - | | - | help: change this to: `Option<&Vec>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::ref-option` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::ref_option)]` +help: change this to + | +LL - fn pub_trait_opt(&self, a: &Option>); +LL + fn pub_trait_opt(&self, a: Option<&Vec>); + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option_traits.rs:12:5 | LL | fn pub_trait_ret(&self) -> &Option>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------^ - | | - | help: change this to: `Option<&Vec>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn pub_trait_ret(&self) -> &Option>; +LL + fn pub_trait_ret(&self) -> Option<&Vec>; + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option_traits.rs:17:5 | LL | fn trait_opt(&self, a: &Option); - | ^^^^^^^^^^^^^^^^^^^^^^^---------------^^ - | | - | help: change this to: `Option<&String>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn trait_opt(&self, a: &Option); +LL + fn trait_opt(&self, a: Option<&String>); + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option_traits.rs:19:5 | LL | fn trait_ret(&self) -> &Option; - | ^^^^^^^^^^^^^^^^^^^^^^^---------------^ - | | - | help: change this to: `Option<&String>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn trait_ret(&self) -> &Option; +LL + fn trait_ret(&self) -> Option<&String>; + | error: aborting due to 4 previous errors diff --git a/tests/ui-toml/ref_option/ref_option_traits.private.stderr b/tests/ui-toml/ref_option/ref_option_traits.private.stderr index 20bea400edfe..64f69c1bed8d 100644 --- a/tests/ui-toml/ref_option/ref_option_traits.private.stderr +++ b/tests/ui-toml/ref_option/ref_option_traits.private.stderr @@ -2,20 +2,27 @@ error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option_traits.rs:17:5 | LL | fn trait_opt(&self, a: &Option); - | ^^^^^^^^^^^^^^^^^^^^^^^---------------^^ - | | - | help: change this to: `Option<&String>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::ref-option` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::ref_option)]` +help: change this to + | +LL - fn trait_opt(&self, a: &Option); +LL + fn trait_opt(&self, a: Option<&String>); + | error: it is more idiomatic to use `Option<&T>` instead of `&Option` --> tests/ui-toml/ref_option/ref_option_traits.rs:19:5 | LL | fn trait_ret(&self) -> &Option; - | ^^^^^^^^^^^^^^^^^^^^^^^---------------^ - | | - | help: change this to: `Option<&String>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn trait_ret(&self) -> &Option; +LL + fn trait_ret(&self) -> Option<&String>; + | error: aborting due to 2 previous errors diff --git a/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr b/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr index 7fdaa4420450..a950ede89f87 100644 --- a/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr +++ b/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr @@ -2,28 +2,51 @@ error: renamed function parameter of trait impl --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:30:18 | LL | fn eq(&self, rhs: &Self) -> bool { - | ^^^ help: consider using the default name: `other` + | ^^^ | = note: `-D clippy::renamed-function-params` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::renamed_function_params)]` +help: consider using the default name + | +LL - fn eq(&self, rhs: &Self) -> bool { +LL + fn eq(&self, other: &Self) -> bool { + | error: renamed function parameter of trait impl --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:34:18 | LL | fn ne(&self, rhs: &Self) -> bool { - | ^^^ help: consider using the default name: `other` + | ^^^ + | +help: consider using the default name + | +LL - fn ne(&self, rhs: &Self) -> bool { +LL + fn ne(&self, other: &Self) -> bool { + | error: renamed function parameter of trait impl --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:48:19 | LL | fn foo(&self, i_dont_wanna_use_your_name: u8) {} // only lint in `extend` - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the default name: `val` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using the default name + | +LL - fn foo(&self, i_dont_wanna_use_your_name: u8) {} // only lint in `extend` +LL + fn foo(&self, val: u8) {} // only lint in `extend` + | error: renamed function parameter of trait impl --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:57:31 | LL | fn hash(&self, states: &mut H) { - | ^^^^^^ help: consider using the default name: `state` + | ^^^^^^ + | +help: consider using the default name + | +LL - fn hash(&self, states: &mut H) { +LL + fn hash(&self, state: &mut H) { + | error: renamed function parameters of trait impl --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:61:30 @@ -41,7 +64,13 @@ error: renamed function parameter of trait impl --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:82:18 | LL | fn add(self, b: B) -> C { - | ^ help: consider using the default name: `rhs` + | ^ + | +help: consider using the default name + | +LL - fn add(self, b: B) -> C { +LL + fn add(self, rhs: B) -> C { + | error: aborting due to 6 previous errors diff --git a/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr b/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr index d670026b5411..dd5fa2ba2870 100644 --- a/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr +++ b/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr @@ -2,22 +2,39 @@ error: renamed function parameter of trait impl --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:30:18 | LL | fn eq(&self, rhs: &Self) -> bool { - | ^^^ help: consider using the default name: `other` + | ^^^ | = note: `-D clippy::renamed-function-params` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::renamed_function_params)]` +help: consider using the default name + | +LL - fn eq(&self, rhs: &Self) -> bool { +LL + fn eq(&self, other: &Self) -> bool { + | error: renamed function parameter of trait impl --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:34:18 | LL | fn ne(&self, rhs: &Self) -> bool { - | ^^^ help: consider using the default name: `other` + | ^^^ + | +help: consider using the default name + | +LL - fn ne(&self, rhs: &Self) -> bool { +LL + fn ne(&self, other: &Self) -> bool { + | error: renamed function parameter of trait impl --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:57:31 | LL | fn hash(&self, states: &mut H) { - | ^^^^^^ help: consider using the default name: `state` + | ^^^^^^ + | +help: consider using the default name + | +LL - fn hash(&self, states: &mut H) { +LL + fn hash(&self, state: &mut H) { + | error: renamed function parameters of trait impl --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:61:30 diff --git a/tests/ui/default_constructed_unit_structs.stderr b/tests/ui/default_constructed_unit_structs.stderr index 97fad792e4f7..7b30c18dc3cf 100644 --- a/tests/ui/default_constructed_unit_structs.stderr +++ b/tests/ui/default_constructed_unit_structs.stderr @@ -2,52 +2,75 @@ error: use of `default` to create a unit struct --> tests/ui/default_constructed_unit_structs.rs:11:9 | LL | Self::default() - | ^^^^----------- - | | - | help: remove this call to `default` + | ^^^^^^^^^^^^^^^ | = note: `-D clippy::default-constructed-unit-structs` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::default_constructed_unit_structs)]` +help: remove this call to `default` + | +LL - Self::default() +LL + Self + | error: use of `default` to create a unit struct --> tests/ui/default_constructed_unit_structs.rs:54:20 | LL | inner: PhantomData::default(), - | ^^^^^^^^^^^----------- - | | - | help: remove this call to `default` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove this call to `default` + | +LL - inner: PhantomData::default(), +LL + inner: PhantomData, + | error: use of `default` to create a unit struct --> tests/ui/default_constructed_unit_structs.rs:128:13 | LL | let _ = PhantomData::::default(); - | ^^^^^^^^^^^^^^^^^^^^----------- - | | - | help: remove this call to `default` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove this call to `default` + | +LL - let _ = PhantomData::::default(); +LL + let _ = PhantomData::; + | error: use of `default` to create a unit struct --> tests/ui/default_constructed_unit_structs.rs:130:31 | LL | let _: PhantomData = PhantomData::default(); - | ^^^^^^^^^^^----------- - | | - | help: remove this call to `default` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove this call to `default` + | +LL - let _: PhantomData = PhantomData::default(); +LL + let _: PhantomData = PhantomData; + | error: use of `default` to create a unit struct --> tests/ui/default_constructed_unit_structs.rs:132:31 | LL | let _: PhantomData = std::marker::PhantomData::default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^----------- - | | - | help: remove this call to `default` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove this call to `default` + | +LL - let _: PhantomData = std::marker::PhantomData::default(); +LL + let _: PhantomData = std::marker::PhantomData; + | error: use of `default` to create a unit struct --> tests/ui/default_constructed_unit_structs.rs:134:13 | LL | let _ = UnitStruct::default(); - | ^^^^^^^^^^----------- - | | - | help: remove this call to `default` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: remove this call to `default` + | +LL - let _ = UnitStruct::default(); +LL + let _ = UnitStruct; + | error: use of `default` to create a unit struct --> tests/ui/default_constructed_unit_structs.rs:172:7 diff --git a/tests/ui/double_ended_iterator_last.stderr b/tests/ui/double_ended_iterator_last.stderr index 0f0056be3769..1a1f18fab1ed 100644 --- a/tests/ui/double_ended_iterator_last.stderr +++ b/tests/ui/double_ended_iterator_last.stderr @@ -2,20 +2,27 @@ error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly --> tests/ui/double_ended_iterator_last.rs:5:5 | LL | s.split(' ').last() - | ^^^^^^^^^^^^^------ - | | - | help: try: `next_back()` + | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::double-ended-iterator-last` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::double_ended_iterator_last)]` +help: try + | +LL - s.split(' ').last() +LL + s.split(' ').next_back() + | error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator --> tests/ui/double_ended_iterator_last.rs:22:13 | LL | let _ = DeIterator.last(); - | ^^^^^^^^^^^------ - | | - | help: try: `next_back()` + | ^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - let _ = DeIterator.last(); +LL + let _ = DeIterator.next_back(); + | error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator --> tests/ui/double_ended_iterator_last.rs:114:36 diff --git a/tests/ui/extra_unused_type_parameters.stderr b/tests/ui/extra_unused_type_parameters.stderr index 5086826ae5c0..61083a44b6c2 100644 --- a/tests/ui/extra_unused_type_parameters.stderr +++ b/tests/ui/extra_unused_type_parameters.stderr @@ -2,22 +2,39 @@ error: type parameter `T` goes unused in function definition --> tests/ui/extra_unused_type_parameters.rs:9:13 | LL | fn unused_ty(x: u8) { - | ^^^ help: consider removing the parameter + | ^^^ | = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::extra_unused_type_parameters)]` +help: consider removing the parameter + | +LL - fn unused_ty(x: u8) { +LL + fn unused_ty(x: u8) { + | error: type parameters go unused in function definition: T, U --> tests/ui/extra_unused_type_parameters.rs:14:16 | LL | fn unused_multi(x: u8) { - | ^^^^^^ help: consider removing the parameters + | ^^^^^^ + | +help: consider removing the parameters + | +LL - fn unused_multi(x: u8) { +LL + fn unused_multi(x: u8) { + | error: type parameter `T` goes unused in function definition --> tests/ui/extra_unused_type_parameters.rs:19:21 | LL | fn unused_with_lt<'a, T>(x: &'a u8) { - | ^^^ help: consider removing the parameter + | ^^^ + | +help: consider removing the parameter + | +LL - fn unused_with_lt<'a, T>(x: &'a u8) { +LL + fn unused_with_lt<'a>(x: &'a u8) { + | error: type parameters go unused in function definition: T, V --> tests/ui/extra_unused_type_parameters.rs:32:19 @@ -47,19 +64,37 @@ error: type parameter `T` goes unused in function definition --> tests/ui/extra_unused_type_parameters.rs:63:22 | LL | fn unused_ty_impl(&self) { - | ^^^ help: consider removing the parameter + | ^^^ + | +help: consider removing the parameter + | +LL - fn unused_ty_impl(&self) { +LL + fn unused_ty_impl(&self) { + | error: type parameters go unused in function definition: A, B --> tests/ui/extra_unused_type_parameters.rs:86:17 | LL | fn unused_opaque(dummy: impl Default) { - | ^^^^^^ help: consider removing the parameters + | ^^^^^^ + | +help: consider removing the parameters + | +LL - fn unused_opaque(dummy: impl Default) { +LL + fn unused_opaque(dummy: impl Default) { + | error: type parameter `U` goes unused in function definition --> tests/ui/extra_unused_type_parameters.rs:100:56 | LL | fn unused_with_priv_trait_bound() { - | ^^^ help: consider removing the parameter + | ^^^ + | +help: consider removing the parameter + | +LL - fn unused_with_priv_trait_bound() { +LL + fn unused_with_priv_trait_bound() { + | error: aborting due to 8 previous errors diff --git a/tests/ui/manual_is_ascii_check.stderr b/tests/ui/manual_is_ascii_check.stderr index cb2548ea7316..28128d79d9ac 100644 --- a/tests/ui/manual_is_ascii_check.stderr +++ b/tests/ui/manual_is_ascii_check.stderr @@ -2,148 +2,291 @@ error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:5:13 | LL | assert!(matches!('x', 'a'..='z')); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_lowercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::manual-is-ascii-check` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_is_ascii_check)]` +help: try + | +LL - assert!(matches!('x', 'a'..='z')); +LL + assert!('x'.is_ascii_lowercase()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:7:13 | LL | assert!(matches!('X', 'A'..='Z')); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - assert!(matches!('X', 'A'..='Z')); +LL + assert!('X'.is_ascii_uppercase()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:9:13 | LL | assert!(matches!(b'x', b'a'..=b'z')); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'x'.is_ascii_lowercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - assert!(matches!(b'x', b'a'..=b'z')); +LL + assert!(b'x'.is_ascii_lowercase()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:11:13 | LL | assert!(matches!(b'X', b'A'..=b'Z')); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'X'.is_ascii_uppercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - assert!(matches!(b'X', b'A'..=b'Z')); +LL + assert!(b'X'.is_ascii_uppercase()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:15:13 | LL | assert!(matches!(num, '0'..='9')); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.is_ascii_digit()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - assert!(matches!(num, '0'..='9')); +LL + assert!(num.is_ascii_digit()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:17:13 | LL | assert!(matches!(b'1', b'0'..=b'9')); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - assert!(matches!(b'1', b'0'..=b'9')); +LL + assert!(b'1'.is_ascii_digit()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:19:13 | LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z')); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - assert!(matches!('x', 'A'..='Z' | 'a'..='z')); +LL + assert!('x'.is_ascii_alphabetic()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:24:5 | LL | (b'0'..=b'9').contains(&b'0'); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'0'.is_ascii_digit()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - (b'0'..=b'9').contains(&b'0'); +LL + b'0'.is_ascii_digit(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:26:5 | LL | (b'a'..=b'z').contains(&b'a'); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'a'.is_ascii_lowercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - (b'a'..=b'z').contains(&b'a'); +LL + b'a'.is_ascii_lowercase(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:28:5 | LL | (b'A'..=b'Z').contains(&b'A'); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'A'.is_ascii_uppercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - (b'A'..=b'Z').contains(&b'A'); +LL + b'A'.is_ascii_uppercase(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:31:5 | LL | ('0'..='9').contains(&'0'); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'0'.is_ascii_digit()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - ('0'..='9').contains(&'0'); +LL + '0'.is_ascii_digit(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:33:5 | LL | ('a'..='z').contains(&'a'); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'a'.is_ascii_lowercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - ('a'..='z').contains(&'a'); +LL + 'a'.is_ascii_lowercase(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:35:5 | LL | ('A'..='Z').contains(&'A'); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'A'.is_ascii_uppercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - ('A'..='Z').contains(&'A'); +LL + 'A'.is_ascii_uppercase(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:39:5 | LL | ('0'..='9').contains(cool_letter); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_digit()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - ('0'..='9').contains(cool_letter); +LL + cool_letter.is_ascii_digit(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:41:5 | LL | ('a'..='z').contains(cool_letter); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_lowercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - ('a'..='z').contains(cool_letter); +LL + cool_letter.is_ascii_lowercase(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:43:5 | LL | ('A'..='Z').contains(cool_letter); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_uppercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - ('A'..='Z').contains(cool_letter); +LL + cool_letter.is_ascii_uppercase(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:57:13 | LL | assert!(matches!(b'1', b'0'..=b'9')); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - assert!(matches!(b'1', b'0'..=b'9')); +LL + assert!(b'1'.is_ascii_digit()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:59:13 | LL | assert!(matches!('X', 'A'..='Z')); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - assert!(matches!('X', 'A'..='Z')); +LL + assert!('X'.is_ascii_uppercase()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:61:13 | LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z')); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - assert!(matches!('x', 'A'..='Z' | 'a'..='z')); +LL + assert!('x'.is_ascii_alphabetic()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:63:13 | LL | assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F')); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_hexdigit()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F')); +LL + assert!('x'.is_ascii_hexdigit()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:75:23 | LL | const FOO: bool = matches!('x', '0'..='9'); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - const FOO: bool = matches!('x', '0'..='9'); +LL + const FOO: bool = 'x'.is_ascii_digit(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:77:23 | LL | const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_hexdigit()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'); +LL + const BAR: bool = 'x'.is_ascii_hexdigit(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:84:5 | LL | ('0'..='9').contains(&&cool_letter); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_digit()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - ('0'..='9').contains(&&cool_letter); +LL + cool_letter.is_ascii_digit(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:86:5 | LL | ('a'..='z').contains(*cool_letter); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_lowercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - ('a'..='z').contains(*cool_letter); +LL + cool_letter.is_ascii_lowercase(); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:105:20 @@ -173,7 +316,13 @@ error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:109:26 | LL | take_while(|c: char| ('A'..='Z').contains(&c)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `c.is_ascii_uppercase()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - take_while(|c: char| ('A'..='Z').contains(&c)); +LL + take_while(|c: char| c.is_ascii_uppercase()); + | error: manual check for common ascii range --> tests/ui/manual_is_ascii_check.rs:111:20 diff --git a/tests/ui/mutex_atomic.stderr b/tests/ui/mutex_atomic.stderr index 56d94035583c..c1391e0111c8 100644 --- a/tests/ui/mutex_atomic.stderr +++ b/tests/ui/mutex_atomic.stderr @@ -2,69 +2,109 @@ error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:8:13 | LL | let _ = Mutex::new(true); - | ^^^^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicBool::new(true)` + | ^^^^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` = note: `-D clippy::mutex-atomic` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::mutex_atomic)]` +help: try + | +LL - let _ = Mutex::new(true); +LL + let _ = std::sync::atomic::AtomicBool::new(true); + | error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:11:13 | LL | let _ = Mutex::new(5usize); - | ^^^^^^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicUsize::new(5usize)` + | ^^^^^^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` +help: try + | +LL - let _ = Mutex::new(5usize); +LL + let _ = std::sync::atomic::AtomicUsize::new(5usize); + | error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:14:13 | LL | let _ = Mutex::new(9isize); - | ^^^^^^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicIsize::new(9isize)` + | ^^^^^^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` +help: try + | +LL - let _ = Mutex::new(9isize); +LL + let _ = std::sync::atomic::AtomicIsize::new(9isize); + | error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:21:13 | LL | let _ = Mutex::new(&mut x as *mut u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicPtr::new(&mut x as *mut u32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` +help: try + | +LL - let _ = Mutex::new(&mut x as *mut u32); +LL + let _ = std::sync::atomic::AtomicPtr::new(&mut x as *mut u32); + | error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:24:13 | LL | let _ = Mutex::new(0u32); - | ^^^^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicU32::new(0u32)` + | ^^^^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` = note: `-D clippy::mutex-integer` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::mutex_integer)]` +help: try + | +LL - let _ = Mutex::new(0u32); +LL + let _ = std::sync::atomic::AtomicU32::new(0u32); + | error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:27:13 | LL | let _ = Mutex::new(0i32); - | ^^^^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicI32::new(0i32)` + | ^^^^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` +help: try + | +LL - let _ = Mutex::new(0i32); +LL + let _ = std::sync::atomic::AtomicI32::new(0i32); + | error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:31:13 | LL | let _ = Mutex::new(0u8); - | ^^^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicU8::new(0u8)` + | ^^^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` +help: try + | +LL - let _ = Mutex::new(0u8); +LL + let _ = std::sync::atomic::AtomicU8::new(0u8); + | error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:34:13 | LL | let _ = Mutex::new(0i16); - | ^^^^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicI16::new(0i16)` + | ^^^^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` +help: try + | +LL - let _ = Mutex::new(0i16); +LL + let _ = std::sync::atomic::AtomicI16::new(0i16); + | error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:37:25 @@ -83,9 +123,14 @@ error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:41:13 | LL | let _ = Mutex::new(X); - | ^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicI64::new(X)` + | ^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` +help: try + | +LL - let _ = Mutex::new(X); +LL + let _ = std::sync::atomic::AtomicI64::new(X); + | error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:53:30 @@ -104,9 +149,14 @@ error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:56:15 | LL | let mtx = Mutex::new(0); - | ^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicI32::new(0)` + | ^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` +help: try + | +LL - let mtx = Mutex::new(0); +LL + let mtx = std::sync::atomic::AtomicI32::new(0); + | error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:60:22 @@ -134,9 +184,14 @@ error: using a `Mutex` where an atomic would do --> tests/ui/mutex_atomic.rs:76:13 | LL | let _ = Mutex::new(test_expr!(1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::sync::atomic::AtomicBool::new(test_expr!(1))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>` +help: try + | +LL - let _ = Mutex::new(test_expr!(1)); +LL + let _ = std::sync::atomic::AtomicBool::new(test_expr!(1)); + | error: aborting due to 15 previous errors diff --git a/tests/ui/needless_borrow_pat.stderr b/tests/ui/needless_borrow_pat.stderr index 34f167cca223..c99625f7d1e5 100644 --- a/tests/ui/needless_borrow_pat.stderr +++ b/tests/ui/needless_borrow_pat.stderr @@ -2,10 +2,15 @@ error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:57:14 | LL | Some(ref x) => x, - | ^^^^^ help: try: `x` + | ^^^^^ | = note: `-D clippy::needless-borrow` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_borrow)]` +help: try + | +LL - Some(ref x) => x, +LL + Some(x) => x, + | error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:64:14 @@ -38,13 +43,25 @@ error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:83:14 | LL | Some(ref x) => m1!(x), - | ^^^^^ help: try: `x` + | ^^^^^ + | +help: try + | +LL - Some(ref x) => m1!(x), +LL + Some(x) => m1!(x), + | error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:89:15 | LL | let _ = |&ref x: &&String| { - | ^^^^^ help: try: `x` + | ^^^^^ + | +help: try + | +LL - let _ = |&ref x: &&String| { +LL + let _ = |&x: &&String| { + | error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:96:10 @@ -64,7 +81,13 @@ error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:108:14 | LL | Some(ref x) => x.0, - | ^^^^^ help: try: `x` + | ^^^^^ + | +help: try + | +LL - Some(ref x) => x.0, +LL + Some(x) => x.0, + | error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:119:14 @@ -82,7 +105,13 @@ error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:126:21 | LL | if let Some(ref x) = Some(&String::new()); - | ^^^^^ help: try: `x` + | ^^^^^ + | +help: try + | +LL - if let Some(ref x) = Some(&String::new()); +LL + if let Some(x) = Some(&String::new()); + | error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:136:12 @@ -103,7 +132,13 @@ error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:145:11 | LL | fn f(&ref x: &&String) { - | ^^^^^ help: try: `x` + | ^^^^^ + | +help: try + | +LL - fn f(&ref x: &&String) { +LL + fn f(&x: &&String) { + | error: this pattern creates a reference to a reference --> tests/ui/needless_borrow_pat.rs:155:11 diff --git a/tests/ui/non_canonical_partial_ord_impl.stderr b/tests/ui/non_canonical_partial_ord_impl.stderr index a134df17691e..36f68ae897d3 100644 --- a/tests/ui/non_canonical_partial_ord_impl.stderr +++ b/tests/ui/non_canonical_partial_ord_impl.stderr @@ -1,18 +1,23 @@ error: non-canonical implementation of `partial_cmp` on an `Ord` type --> tests/ui/non_canonical_partial_ord_impl.rs:20:1 | -LL | / impl PartialOrd for A { +LL | / impl PartialOrd for A { LL | | -LL | | fn partial_cmp(&self, other: &Self) -> Option { - | | _____________________________________________________________- -LL | || todo!(); -LL | || } - | ||_____- help: change this to: `{ Some(self.cmp(other)) }` -LL | | } - | |__^ +LL | | fn partial_cmp(&self, other: &Self) -> Option { +LL | | todo!(); +LL | | } +LL | | } + | |_^ | = note: `-D clippy::non-canonical-partial-ord-impl` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::non_canonical_partial_ord_impl)]` +help: change this to + | +LL - fn partial_cmp(&self, other: &Self) -> Option { +LL - todo!(); +LL - } +LL + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } + | error: non-canonical implementation of `partial_cmp` on an `Ord` type --> tests/ui/non_canonical_partial_ord_impl.rs:55:1 @@ -36,43 +41,60 @@ LL + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp error: non-canonical implementation of `partial_cmp` on an `Ord` type --> tests/ui/non_canonical_partial_ord_impl.rs:191:9 | -LL | / impl PartialOrd for A { +LL | / impl PartialOrd for A { LL | | -LL | | fn partial_cmp(&self, other: &Self) -> Option { - | | _____________________________________________________________________- -LL | || todo!(); -LL | || } - | ||_____________- help: change this to: `{ Some(self.cmp(other)) }` -LL | | } - | |__________^ +LL | | fn partial_cmp(&self, other: &Self) -> Option { +LL | | todo!(); +LL | | } +LL | | } + | |_________^ | = note: this error originates in the macro `__inline_mac_mod_issue12788` (in Nightly builds, run with -Z macro-backtrace for more info) +help: change this to + | +LL - fn partial_cmp(&self, other: &Self) -> Option { +LL - todo!(); +LL - } +LL + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } + | error: non-canonical implementation of `partial_cmp` on an `Ord` type --> tests/ui/non_canonical_partial_ord_impl.rs:271:1 | -LL | / impl PartialOrd for K { +LL | / impl PartialOrd for K { LL | | -LL | | fn partial_cmp(&self, other: &Self) -> Option { - | | _____________________________________________________________- -LL | || Ordering::Greater.into() -LL | || } - | ||_____- help: change this to: `{ Some(self.cmp(other)) }` -LL | | } - | |__^ +LL | | fn partial_cmp(&self, other: &Self) -> Option { +LL | | Ordering::Greater.into() +LL | | } +LL | | } + | |_^ + | +help: change this to + | +LL - fn partial_cmp(&self, other: &Self) -> Option { +LL - Ordering::Greater.into() +LL - } +LL + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } + | error: non-canonical implementation of `partial_cmp` on an `Ord` type --> tests/ui/non_canonical_partial_ord_impl.rs:289:1 | -LL | / impl PartialOrd for L { +LL | / impl PartialOrd for L { LL | | -LL | | fn partial_cmp(&self, other: &Self) -> Option { - | | _____________________________________________________________- -LL | || Some(other.cmp(self)) -LL | || } - | ||_____- help: change this to: `{ Some(self.cmp(other)) }` -LL | | } - | |__^ +LL | | fn partial_cmp(&self, other: &Self) -> Option { +LL | | Some(other.cmp(self)) +LL | | } +LL | | } + | |_^ + | +help: change this to + | +LL - fn partial_cmp(&self, other: &Self) -> Option { +LL - Some(other.cmp(self)) +LL - } +LL + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } + | error: aborting due to 5 previous errors diff --git a/tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr b/tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr index 392b81dc8d74..83ca78bbb59e 100644 --- a/tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr +++ b/tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr @@ -1,34 +1,43 @@ error: non-canonical implementation of `partial_cmp` on an `Ord` type --> tests/ui/non_canonical_partial_ord_impl_fully_qual.rs:23:1 | -LL | / impl PartialOrd for A { +LL | / impl PartialOrd for A { LL | | -LL | | fn partial_cmp(&self, other: &Self) -> Option { - | | _____________________________________________________________- -LL | || // NOTE: This suggestion is wrong, as `Ord` is not in scope. But this should be fine as it isn't -LL | || // automatically applied -LL | || todo!(); -LL | || } - | ||_____- help: change this to: `{ Some(self.cmp(other)) }` -LL | | } - | |__^ +LL | | fn partial_cmp(&self, other: &Self) -> Option { +... | +LL | | } + | |_^ | = note: `-D clippy::non-canonical-partial-ord-impl` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::non_canonical_partial_ord_impl)]` +help: change this to + | +LL - fn partial_cmp(&self, other: &Self) -> Option { +LL - // NOTE: This suggestion is wrong, as `Ord` is not in scope. But this should be fine as it isn't +LL - // automatically applied +LL - todo!(); +LL - } +LL + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } + | error: non-canonical implementation of `partial_cmp` on an `Ord` type --> tests/ui/non_canonical_partial_ord_impl_fully_qual.rs:47:1 | -LL | / impl PartialOrd for B { +LL | / impl PartialOrd for B { LL | | -LL | | fn partial_cmp(&self, other: &Self) -> Option { - | | _____________________________________________________________- -LL | || // This calls `B.cmp`, not `Ord::cmp`! -LL | || Some(self.cmp(other)) -LL | || } - | ||_____- help: change this to: `{ Some(std::cmp::Ord::cmp(self, other)) }` -LL | | } - | |__^ +LL | | fn partial_cmp(&self, other: &Self) -> Option { +... | +LL | | } + | |_^ + | +help: change this to + | +LL - fn partial_cmp(&self, other: &Self) -> Option { +LL - // This calls `B.cmp`, not `Ord::cmp`! +LL - Some(self.cmp(other)) +LL - } +LL + fn partial_cmp(&self, other: &Self) -> Option { Some(std::cmp::Ord::cmp(self, other)) } + | error: aborting due to 2 previous errors diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index f32e83d8b818..08746460add1 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -2,46 +2,87 @@ error: writing `&Vec` instead of `&[_]` involves a new object where a slice will --> tests/ui/ptr_arg.rs:13:14 | LL | fn do_vec(x: &Vec) { - | ^^^^^^^^^ help: change this to: `&[i64]` + | ^^^^^^^^^ | = note: `-D clippy::ptr-arg` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::ptr_arg)]` +help: change this to + | +LL - fn do_vec(x: &Vec) { +LL + fn do_vec(x: &[i64]) { + | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:19:18 | LL | fn do_vec_mut(x: &mut Vec) { - | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` + | ^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn do_vec_mut(x: &mut Vec) { +LL + fn do_vec_mut(x: &mut [i64]) { + | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:25:19 | LL | fn do_vec_mut2(x: &mut Vec) { - | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` + | ^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn do_vec_mut2(x: &mut Vec) { +LL + fn do_vec_mut2(x: &mut [i64]) { + | error: writing `&String` instead of `&str` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:32:14 | LL | fn do_str(x: &String) { - | ^^^^^^^ help: change this to: `&str` + | ^^^^^^^ + | +help: change this to + | +LL - fn do_str(x: &String) { +LL + fn do_str(x: &str) { + | error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:38:18 | LL | fn do_str_mut(x: &mut String) { - | ^^^^^^^^^^^ help: change this to: `&mut str` + | ^^^^^^^^^^^ + | +help: change this to + | +LL - fn do_str_mut(x: &mut String) { +LL + fn do_str_mut(x: &mut str) { + | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:44:15 | LL | fn do_path(x: &PathBuf) { - | ^^^^^^^^ help: change this to: `&Path` + | ^^^^^^^^ + | +help: change this to + | +LL - fn do_path(x: &PathBuf) { +LL + fn do_path(x: &Path) { + | error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:50:19 | LL | fn do_path_mut(x: &mut PathBuf) { - | ^^^^^^^^^^^^ help: change this to: `&mut Path` + | ^^^^^^^^^^^^ + | +help: change this to + | +LL - fn do_path_mut(x: &mut PathBuf) { +LL + fn do_path_mut(x: &mut Path) { + | error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:60:18 @@ -130,7 +171,13 @@ error: writing `&String` instead of `&str` involves a new object where a slice w --> tests/ui/ptr_arg.rs:152:64 | LL | fn some_allowed(#[allow(clippy::ptr_arg)] v: &Vec, s: &String) {} - | ^^^^^^^ help: change this to: `&str` + | ^^^^^^^ + | +help: change this to + | +LL - fn some_allowed(#[allow(clippy::ptr_arg)] v: &Vec, s: &String) {} +LL + fn some_allowed(#[allow(clippy::ptr_arg)] v: &Vec, s: &str) {} + | error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:182:21 @@ -181,25 +228,49 @@ error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a sl --> tests/ui/ptr_arg.rs:204:29 | LL | fn mut_vec_slice_methods(v: &mut Vec) { - | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` + | ^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn mut_vec_slice_methods(v: &mut Vec) { +LL + fn mut_vec_slice_methods(v: &mut [u32]) { + | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:268:17 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { - | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` + | ^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { +LL + fn dyn_trait(a: &mut [u32], b: &mut String, c: &mut PathBuf) { + | error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:268:35 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { - | ^^^^^^^^^^^ help: change this to: `&mut str` + | ^^^^^^^^^^^ + | +help: change this to + | +LL - fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { +LL + fn dyn_trait(a: &mut Vec, b: &mut str, c: &mut PathBuf) { + | error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:268:51 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { - | ^^^^^^^^^^^^ help: change this to: `&mut Path` + | ^^^^^^^^^^^^ + | +help: change this to + | +LL - fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { +LL + fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut Path) { + | error: using a reference to `Cow` is not recommended --> tests/ui/ptr_arg.rs:295:39 @@ -223,49 +294,97 @@ error: writing `&String` instead of `&str` involves a new object where a slice w --> tests/ui/ptr_arg.rs:347:17 | LL | fn good(v1: &String, v2: &String) { - | ^^^^^^^ help: change this to: `&str` + | ^^^^^^^ + | +help: change this to + | +LL - fn good(v1: &String, v2: &String) { +LL + fn good(v1: &str, v2: &String) { + | error: writing `&String` instead of `&str` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:347:30 | LL | fn good(v1: &String, v2: &String) { - | ^^^^^^^ help: change this to: `&str` + | ^^^^^^^ + | +help: change this to + | +LL - fn good(v1: &String, v2: &String) { +LL + fn good(v1: &String, v2: &str) { + | error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:363:20 | LL | fn foo_used(x: &Vec) { - | ^^^^^^^^^ help: change this to: `&[i32]` + | ^^^^^^^^^ + | +help: change this to + | +LL - fn foo_used(x: &Vec) { +LL + fn foo_used(x: &[i32]) { + | error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:377:26 | LL | fn foo_local_used(x: &Vec) { - | ^^^^^^^^^ help: change this to: `&[i32]` + | ^^^^^^^^^ + | +help: change this to + | +LL - fn foo_local_used(x: &Vec) { +LL + fn foo_local_used(x: &[i32]) { + | error: writing `&String` instead of `&str` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:386:33 | LL | fn foofoo(_x: &Vec, y: &String) { - | ^^^^^^^ help: change this to: `&str` + | ^^^^^^^ + | +help: change this to + | +LL - fn foofoo(_x: &Vec, y: &String) { +LL + fn foofoo(_x: &Vec, y: &str) { + | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:407:20 | LL | fn bar_used(x: &mut Vec) { - | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` + | ^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn bar_used(x: &mut Vec) { +LL + fn bar_used(x: &mut [u32]) { + | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:421:26 | LL | fn bar_local_used(x: &mut Vec) { - | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` + | ^^^^^^^^^^^^^ + | +help: change this to + | +LL - fn bar_local_used(x: &mut Vec) { +LL + fn bar_local_used(x: &mut [u32]) { + | error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:430:37 | LL | fn barbar(_x: &mut Vec, y: &mut String) { - | ^^^^^^^^^^^ help: change this to: `&mut str` + | ^^^^^^^^^^^ + | +help: change this to + | +LL - fn barbar(_x: &mut Vec, y: &mut String) { +LL + fn barbar(_x: &mut Vec, y: &mut str) { + | error: eliding a lifetime that's named elsewhere is confusing --> tests/ui/ptr_arg.rs:314:56 diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index b0a852a69fc5..e3b2e3c90058 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -2,11 +2,16 @@ error: using `.zip()` with a range and `.len()` --> tests/ui/range.rs:6:14 | LL | let _x = v1.iter().zip(0..v1.len()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `v1.iter().enumerate()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the order of the element and the index will be swapped = note: `-D clippy::range-zip-with-len` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::range_zip_with_len)]` +help: use + | +LL - let _x = v1.iter().zip(0..v1.len()); +LL + let _x = v1.iter().enumerate(); + | error: using `.zip()` with a range and `.len()` --> tests/ui/range.rs:10:19 diff --git a/tests/ui/range_unfixable.stderr b/tests/ui/range_unfixable.stderr index fb03ea2c05f6..3ddb0c2a991b 100644 --- a/tests/ui/range_unfixable.stderr +++ b/tests/ui/range_unfixable.stderr @@ -2,11 +2,16 @@ error: using `.zip()` with a range and `.len()` --> tests/ui/range_unfixable.rs:10:5 | LL | v1.iter().zip(0..v1.len()).filter(|(_, i)| *i < 2).for_each(|(e, i)| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `v1.iter().enumerate()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the order of the element and the index will be swapped = note: `-D clippy::range-zip-with-len` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::range_zip_with_len)]` +help: use + | +LL - v1.iter().zip(0..v1.len()).filter(|(_, i)| *i < 2).for_each(|(e, i)| { +LL + v1.iter().enumerate().filter(|(_, i)| *i < 2).for_each(|(e, i)| { + | error: aborting due to 1 previous error diff --git a/tests/ui/unit_arg_fixable.stderr b/tests/ui/unit_arg_fixable.stderr index ccd5aa8322f9..0e348c81c0d4 100644 --- a/tests/ui/unit_arg_fixable.stderr +++ b/tests/ui/unit_arg_fixable.stderr @@ -2,20 +2,27 @@ error: passing a unit value to a function --> tests/ui/unit_arg_fixable.rs:16:5 | LL | foo({}); - | ^^^^--^ - | | - | help: use a unit literal instead: `()` + | ^^^^^^^ | = note: `-D clippy::unit-arg` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unit_arg)]` +help: use a unit literal instead + | +LL - foo({}); +LL + foo(()); + | error: passing a unit value to a function --> tests/ui/unit_arg_fixable.rs:18:5 | LL | foo3({}, 2, 2); - | ^^^^^--^^^^^^^ - | | - | help: use a unit literal instead: `()` + | ^^^^^^^^^^^^^^ + | +help: use a unit literal instead + | +LL - foo3({}, 2, 2); +LL + foo3((), 2, 2); + | error: passing unit values to a function --> tests/ui/unit_arg_fixable.rs:20:5 @@ -46,9 +53,13 @@ error: passing a unit value to a function --> tests/ui/unit_arg_fixable.rs:35:5 | LL | fn_take_unit(Default::default()); - | ^^^^^^^^^^^^^------------------^ - | | - | help: use a unit literal instead: `()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use a unit literal instead + | +LL - fn_take_unit(Default::default()); +LL + fn_take_unit(()); + | error: passing a unit value to a function --> tests/ui/unit_arg_fixable.rs:49:5 @@ -78,9 +89,13 @@ error: passing a unit value to a function --> tests/ui/unit_arg_fixable.rs:60:5 | LL | fn_take_unit(mac!(nondef Default::default())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^------------------^^ - | | - | help: use a unit literal instead: `()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use a unit literal instead + | +LL - fn_take_unit(mac!(nondef Default::default())); +LL + fn_take_unit(mac!(nondef ())); + | error: passing a unit value to a function --> tests/ui/unit_arg_fixable.rs:62:5 diff --git a/tests/ui/unnecessary_fallible_conversions_unfixable.stderr b/tests/ui/unnecessary_fallible_conversions_unfixable.stderr index 43d0cde9399f..81d5b5397578 100644 --- a/tests/ui/unnecessary_fallible_conversions_unfixable.stderr +++ b/tests/ui/unnecessary_fallible_conversions_unfixable.stderr @@ -2,51 +2,81 @@ error: use of a fallible conversion when an infallible one could be used --> tests/ui/unnecessary_fallible_conversions_unfixable.rs:27:34 | LL | let _: Result = 0i64.try_into(); - | ^^^^^^^^ help: use: `into` + | ^^^^^^^^ | = note: converting `i64` to `Foo` cannot fail = note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]` +help: use + | +LL - let _: Result = 0i64.try_into(); +LL + let _: Result = 0i64.into(); + | error: use of a fallible conversion when an infallible one could be used --> tests/ui/unnecessary_fallible_conversions_unfixable.rs:29:29 | LL | let _: Result = i64::try_into(0i64); - | ^^^^^^^^^^^^^ help: use: `Into::into` + | ^^^^^^^^^^^^^ | = note: converting `i64` to `Foo` cannot fail +help: use + | +LL - let _: Result = i64::try_into(0i64); +LL + let _: Result = Into::into(0i64); + | error: use of a fallible conversion when an infallible one could be used --> tests/ui/unnecessary_fallible_conversions_unfixable.rs:31:29 | LL | let _: Result = Foo::try_from(0i64); - | ^^^^^^^^^^^^^ help: use: `From::from` + | ^^^^^^^^^^^^^ | = note: converting `i64` to `Foo` cannot fail +help: use + | +LL - let _: Result = Foo::try_from(0i64); +LL + let _: Result = From::from(0i64); + | error: use of a fallible conversion when an infallible one could be used --> tests/ui/unnecessary_fallible_conversions_unfixable.rs:34:34 | LL | let _: Result = 0i32.try_into(); - | ^^^^^^^^ help: use: `into` + | ^^^^^^^^ | = note: converting `i32` to `i64` cannot fail +help: use + | +LL - let _: Result = 0i32.try_into(); +LL + let _: Result = 0i32.into(); + | error: use of a fallible conversion when an infallible one could be used --> tests/ui/unnecessary_fallible_conversions_unfixable.rs:36:29 | LL | let _: Result = i32::try_into(0i32); - | ^^^^^^^^^^^^^ help: use: `Into::into` + | ^^^^^^^^^^^^^ | = note: converting `i32` to `i64` cannot fail +help: use + | +LL - let _: Result = i32::try_into(0i32); +LL + let _: Result = Into::into(0i32); + | error: use of a fallible conversion when an infallible one could be used --> tests/ui/unnecessary_fallible_conversions_unfixable.rs:38:29 | LL | let _: Result = <_>::try_from(0i32); - | ^^^^^^^^^^^^^ help: use: `From::from` + | ^^^^^^^^^^^^^ | = note: converting `i32` to `i64` cannot fail +help: use + | +LL - let _: Result = <_>::try_from(0i32); +LL + let _: Result = From::from(0i32); + | error: aborting due to 6 previous errors diff --git a/tests/ui/unnecessary_iter_cloned.stderr b/tests/ui/unnecessary_iter_cloned.stderr index 632c8f371106..d700446fce77 100644 --- a/tests/ui/unnecessary_iter_cloned.stderr +++ b/tests/ui/unnecessary_iter_cloned.stderr @@ -30,7 +30,13 @@ error: unnecessary use of `cloned` --> tests/ui/unnecessary_iter_cloned.rs:179:18 | LL | for c in v.iter().cloned() { - | ^^^^^^^^^^^^^^^^^ help: remove any references to the binding: `v.iter()` + | ^^^^^^^^^^^^^^^^^ + | +help: remove any references to the binding + | +LL - for c in v.iter().cloned() { +LL + for c in v.iter() { + | error: unnecessary use of `cloned` --> tests/ui/unnecessary_iter_cloned.rs:188:18 diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index cd90763263e9..9c93f5a09bb0 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -52,7 +52,13 @@ error: used `unwrap()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:24:16 | LL | let _val = None::<()>.unwrap(); - | ^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` + | ^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `unwrap()` + | +LL - let _val = None::<()>.unwrap(); +LL + let _val = panic!(); + | error: used `expect()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:26:16 @@ -70,7 +76,13 @@ error: used `unwrap_or_default()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:28:24 | LL | let _val: String = None.unwrap_or_default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap_or_default()`: `String::default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `unwrap_or_default()` + | +LL - let _val: String = None.unwrap_or_default(); +LL + let _val: String = String::default(); + | error: used `unwrap_or()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:30:21 @@ -124,7 +136,13 @@ error: used `unwrap()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:39:5 | LL | None::<()>.unwrap(); - | ^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` + | ^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `unwrap()` + | +LL - None::<()>.unwrap(); +LL + panic!(); + | error: used `expect()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:41:5 @@ -142,7 +160,13 @@ error: used `unwrap_or_default()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:43:5 | LL | None::.unwrap_or_default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap_or_default()`: `String::default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `unwrap_or_default()` + | +LL - None::.unwrap_or_default(); +LL + String::default(); + | error: used `unwrap_or()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:45:5 diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.stderr b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr index 4994eeded776..39418d0e3a96 100644 --- a/tests/ui/unnecessary_literal_unwrap_unfixable.stderr +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr @@ -100,13 +100,25 @@ error: used `unwrap_or_default()` on `None` value --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:37:21 | LL | let _val3: u8 = None.unwrap_or_default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap_or_default()`: `Default::default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `unwrap_or_default()` + | +LL - let _val3: u8 = None.unwrap_or_default(); +LL + let _val3: u8 = Default::default(); + | error: used `unwrap_or_default()` on `None` value --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:40:5 | LL | None::<()>.unwrap_or_default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap_or_default()`: `Default::default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `unwrap_or_default()` + | +LL - None::<()>.unwrap_or_default(); +LL + Default::default(); + | error: used `unwrap()` on `Ok` value --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:46:17 diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index d28b7a5cbfb6..24772af3818e 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -139,127 +139,154 @@ error: explicit call to `.into_iter()` in function argument accepting `IntoItera --> tests/ui/useless_conversion.rs:218:7 | LL | b(vec![1, 2].into_iter()); - | ^^^^^^^^^^------------ - | | - | help: consider removing the `.into_iter()` + | ^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> tests/ui/useless_conversion.rs:208:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider removing the `.into_iter()` + | +LL - b(vec![1, 2].into_iter()); +LL + b(vec![1, 2]); + | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` --> tests/ui/useless_conversion.rs:220:7 | LL | c(vec![1, 2].into_iter()); - | ^^^^^^^^^^------------ - | | - | help: consider removing the `.into_iter()` + | ^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> tests/ui/useless_conversion.rs:209:18 | LL | fn c(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider removing the `.into_iter()` + | +LL - c(vec![1, 2].into_iter()); +LL + c(vec![1, 2]); + | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` --> tests/ui/useless_conversion.rs:222:7 | LL | d(vec![1, 2].into_iter()); - | ^^^^^^^^^^------------ - | | - | help: consider removing the `.into_iter()` + | ^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> tests/ui/useless_conversion.rs:212:12 | LL | T: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider removing the `.into_iter()` + | +LL - d(vec![1, 2].into_iter()); +LL + d(vec![1, 2]); + | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` --> tests/ui/useless_conversion.rs:226:7 | LL | b(vec![1, 2].into_iter().into_iter()); - | ^^^^^^^^^^------------------------ - | | - | help: consider removing the `.into_iter()`s + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> tests/ui/useless_conversion.rs:208:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider removing the `.into_iter()`s + | +LL - b(vec![1, 2].into_iter().into_iter()); +LL + b(vec![1, 2]); + | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` --> tests/ui/useless_conversion.rs:228:7 | LL | b(vec![1, 2].into_iter().into_iter().into_iter()); - | ^^^^^^^^^^------------------------------------ - | | - | help: consider removing the `.into_iter()`s + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> tests/ui/useless_conversion.rs:208:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider removing the `.into_iter()`s + | +LL - b(vec![1, 2].into_iter().into_iter().into_iter()); +LL + b(vec![1, 2]); + | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` --> tests/ui/useless_conversion.rs:275:24 | LL | foo2::([1, 2, 3].into_iter()); - | ^^^^^^^^^------------ - | | - | help: consider removing the `.into_iter()` + | ^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> tests/ui/useless_conversion.rs:254:12 | LL | I: IntoIterator + Helper, | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider removing the `.into_iter()` + | +LL - foo2::([1, 2, 3].into_iter()); +LL + foo2::([1, 2, 3]); + | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` --> tests/ui/useless_conversion.rs:284:14 | LL | foo3([1, 2, 3].into_iter()); - | ^^^^^^^^^------------ - | | - | help: consider removing the `.into_iter()` + | ^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> tests/ui/useless_conversion.rs:263:12 | LL | I: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider removing the `.into_iter()` + | +LL - foo3([1, 2, 3].into_iter()); +LL + foo3([1, 2, 3]); + | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` --> tests/ui/useless_conversion.rs:294:16 | LL | S1.foo([1, 2].into_iter()); - | ^^^^^^------------ - | | - | help: consider removing the `.into_iter()` + | ^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> tests/ui/useless_conversion.rs:291:27 | LL | pub fn foo(&self, _: I) {} | ^^^^^^^^^^^^ +help: consider removing the `.into_iter()` + | +LL - S1.foo([1, 2].into_iter()); +LL + S1.foo([1, 2]); + | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` --> tests/ui/useless_conversion.rs:314:44 | LL | v0.into_iter().interleave_shortest(v1.into_iter()); - | ^^------------ - | | - | help: consider removing the `.into_iter()` + | ^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> tests/ui/useless_conversion.rs:301:20 | LL | J: IntoIterator, | ^^^^^^^^^^^^ +help: consider removing the `.into_iter()` + | +LL - v0.into_iter().interleave_shortest(v1.into_iter()); +LL + v0.into_iter().interleave_shortest(v1); + | error: useless conversion to the same type: `()` --> tests/ui/useless_conversion.rs:342:58 From 17a6d61dc9a6527277d5021f6cbb4bee4bca9596 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sat, 14 Feb 2026 11:06:57 -0600 Subject: [PATCH 04/38] Audit Symbols --- clippy_lints/src/await_holding_invalid.rs | 3 +- clippy_lints/src/box_default.rs | 4 +- clippy_lints/src/casts/as_ptr_cast_mut.rs | 3 +- clippy_lints/src/casts/unnecessary_cast.rs | 4 +- clippy_lints/src/collection_is_never_read.rs | 3 +- clippy_lints/src/create_dir.rs | 2 +- clippy_lints/src/dbg_macro.rs | 4 +- .../src/default_instead_of_iter_empty.rs | 4 +- clippy_lints/src/dereference.rs | 5 +- .../src/derive/unsafe_derive_deserialize.rs | 4 +- clippy_lints/src/entry.rs | 7 +- clippy_lints/src/error_impl_error.rs | 2 +- clippy_lints/src/exit.rs | 2 +- clippy_lints/src/format_args.rs | 4 +- clippy_lints/src/format_push_string.rs | 4 +- clippy_lints/src/iter_over_hash_type.rs | 2 +- clippy_lints/src/large_include_file.rs | 2 +- clippy_lints/src/large_stack_arrays.rs | 4 +- clippy_lints/src/legacy_numeric_constants.rs | 4 +- .../src/loops/manual_while_let_some.rs | 4 +- .../src/loops/unused_enumerate_index.rs | 4 +- clippy_lints/src/manual_abs_diff.rs | 3 +- clippy_lints/src/manual_bits.rs | 4 +- clippy_lints/src/manual_main_separator_str.rs | 3 +- clippy_lints/src/manual_retain.rs | 4 +- .../src/manual_slice_size_calculation.rs | 3 +- clippy_lints/src/manual_strip.rs | 4 +- clippy_lints/src/matches/single_match.rs | 4 +- clippy_lints/src/mem_replace.rs | 5 +- clippy_lints/src/methods/bytecount.rs | 3 +- clippy_lints/src/methods/clear_with_drain.rs | 3 +- clippy_lints/src/methods/drain_collect.rs | 4 +- clippy_lints/src/methods/expect_fun_call.rs | 3 +- clippy_lints/src/methods/filetype_is_file.rs | 4 +- .../src/methods/filter_map_bool_then.rs | 4 +- clippy_lints/src/methods/filter_next.rs | 3 +- .../methods/from_iter_instead_of_collect.rs | 3 +- clippy_lints/src/methods/get_first.rs | 2 +- clippy_lints/src/methods/get_last_with_len.rs | 3 +- clippy_lints/src/methods/get_unwrap.rs | 3 +- .../src/methods/inefficient_to_string.rs | 2 +- clippy_lints/src/methods/ip_constant.rs | 2 +- clippy_lints/src/methods/iter_count.rs | 3 +- .../src/methods/iter_out_of_bounds.rs | 3 +- clippy_lints/src/methods/iter_with_drain.rs | 3 +- .../src/methods/join_absolute_paths.rs | 3 +- clippy_lints/src/methods/manual_next_back.rs | 2 +- clippy_lints/src/methods/manual_repeat_n.rs | 3 +- clippy_lints/src/methods/manual_str_repeat.rs | 2 +- .../src/methods/option_as_ref_deref.rs | 4 +- .../src/methods/path_buf_push_overwrite.rs | 2 +- .../src/methods/path_ends_with_ext.rs | 2 +- .../src/methods/single_char_add_str.rs | 2 +- .../methods/suspicious_command_arg_space.rs | 3 +- .../src/methods/suspicious_to_owned.rs | 3 +- clippy_lints/src/methods/type_id_on_box.rs | 3 +- clippy_lints/src/methods/unbuffered_bytes.rs | 2 +- .../src/methods/unnecessary_get_then_check.rs | 3 +- .../src/methods/verbose_file_reads.rs | 2 +- clippy_lints/src/methods/waker_clone_wake.rs | 2 +- .../src/missing_const_for_thread_local.rs | 5 +- clippy_lints/src/mut_key.rs | 3 +- .../src/needless_borrows_for_generic_args.rs | 3 +- clippy_lints/src/non_copy_const.rs | 4 +- clippy_lints/src/operators/cmp_owned.rs | 2 +- .../operators/float_equality_without_abs.rs | 3 +- clippy_lints/src/panic_unimplemented.rs | 3 +- clippy_lints/src/ranges.rs | 4 +- clippy_lints/src/redundant_clone.rs | 4 +- clippy_lints/src/repeat_vec_with_capacity.rs | 4 +- clippy_lints/src/size_of_ref.rs | 2 +- clippy_lints/src/swap.rs | 4 +- clippy_lints/src/time_subtraction.rs | 2 +- clippy_lints/src/to_string_trait_impl.rs | 2 +- .../src/transmute/transmuting_null.rs | 3 +- .../transmute/unsound_collection_transmute.rs | 2 +- clippy_lints/src/types/borrowed_box.rs | 2 +- clippy_lints/src/types/box_collection.rs | 4 +- clippy_lints/src/types/linked_list.rs | 2 +- clippy_lints/src/types/owned_cow.rs | 3 +- clippy_lints/src/types/rc_buffer.rs | 3 +- clippy_lints/src/unconditional_recursion.rs | 4 +- .../src/unnecessary_owned_empty_strings.rs | 2 +- clippy_lints/src/zombie_processes.rs | 4 +- clippy_utils/src/hir_utils.rs | 4 +- clippy_utils/src/sym.rs | 231 ++++++++++++++++++ clippy_utils/src/ty/mod.rs | 3 +- clippy_utils/src/usage.rs | 3 +- 88 files changed, 357 insertions(+), 149 deletions(-) diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index 31cc004f6855..4ee955c035da 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -2,13 +2,14 @@ use clippy_config::types::{DisallowedPathWithoutReplacement, create_disallowed_map}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::paths::{self, PathNS}; +use clippy_utils::sym; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::CoroutineLayout; use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; -use rustc_span::{Span, sym}; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs index 6f51f2343ab5..b78aa1f1b63d 100644 --- a/clippy_lints/src/box_default.rs +++ b/clippy_lints/src/box_default.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_default_equivalent; +use clippy_utils::{is_default_equivalent, sym}; use clippy_utils::macros::macro_backtrace; use clippy_utils::res::{MaybeDef, MaybeResPath}; use clippy_utils::ty::expr_sig; @@ -9,7 +9,7 @@ use rustc_hir::{AmbigArg, Block, Expr, ExprKind, HirId, LangItem, LetStmt, Node, QPath, Ty, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; -use rustc_span::{Span, sym}; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/casts/as_ptr_cast_mut.rs b/clippy_lints/src/casts/as_ptr_cast_mut.rs index 15ecba20a0bc..10c97fac992e 100644 --- a/clippy_lints/src/casts/as_ptr_cast_mut.rs +++ b/clippy_lints/src/casts/as_ptr_cast_mut.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::SpanRangeExt; +use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -12,7 +13,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, if let ty::RawPtr(ptrty, Mutability::Mut) = cast_to.kind() && let ty::RawPtr(_, Mutability::Not) = cx.typeck_results().node_type(cast_expr.hir_id).kind() && let ExprKind::MethodCall(method_name, receiver, [], _) = cast_expr.peel_blocks().kind - && method_name.ident.name == rustc_span::sym::as_ptr + && method_name.ident.name == sym::as_ptr && let Some(as_ptr_did) = cx .typeck_results() .type_dependent_def_id(cast_expr.peel_blocks().hir_id) diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index 7bfe9201d812..8b0859722b13 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -3,7 +3,7 @@ use clippy_utils::res::MaybeResPath; use clippy_utils::source::{SpanRangeExt, snippet_opt}; use clippy_utils::visitors::{Visitable, for_each_expr_without_closures}; -use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias}; +use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, sym}; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::{self, FloatTy, InferTy, Ty}; -use rustc_span::{Symbol, sym}; +use rustc_span::Symbol; use std::ops::ControlFlow; use super::UNNECESSARY_CAST; diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs index fd84ce70bd71..5bf582f4da65 100644 --- a/clippy_lints/src/collection_is_never_read.rs +++ b/clippy_lints/src/collection_is_never_read.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::get_enclosing_block; +use clippy_utils::{get_enclosing_block, sym}; use clippy_utils::res::{MaybeDef, MaybeResPath}; use clippy_utils::visitors::{Visitable, for_each_expr}; use core::ops::ControlFlow; use rustc_hir::{Body, ExprKind, HirId, LangItem, LetStmt, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::symbol::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/create_dir.rs b/clippy_lints/src/create_dir.rs index f68c0b3a1ddc..b3be4e5a3f8e 100644 --- a/clippy_lints/src/create_dir.rs +++ b/clippy_lints/src/create_dir.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 45de4035d992..f47d0d4835a9 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::is_in_test; +use clippy_utils::{is_in_test, sym}; use clippy_utils::macros::{MacroCall, macro_backtrace}; use clippy_utils::source::snippet_with_applicability; use rustc_data_structures::fx::FxHashSet; @@ -8,7 +8,7 @@ use rustc_hir::{Arm, Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; -use rustc_span::{Span, SyntaxContext, sym}; +use rustc_span::{Span, SyntaxContext}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/default_instead_of_iter_empty.rs b/clippy_lints/src/default_instead_of_iter_empty.rs index 056e39c02af9..c7807f7b122a 100644 --- a/clippy_lints/src/default_instead_of_iter_empty.rs +++ b/clippy_lints/src/default_instead_of_iter_empty.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; -use clippy_utils::{last_path_segment, std_or_core}; +use clippy_utils::{last_path_segment, std_or_core, sym}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, GenericArg, QPath, TyKind, def}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::{SyntaxContext, sym}; +use rustc_span::SyntaxContext; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 32fd4afb122e..954f071b4068 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -3,9 +3,7 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::ty::{adjust_derefs_manually_drop, implements_trait, is_manually_drop, peel_and_count_ty_refs}; -use clippy_utils::{ - DefinedTy, ExprUseNode, expr_use_ctxt, get_parent_expr, is_block_like, is_from_proc_macro, is_lint_allowed, -}; +use clippy_utils::{DefinedTy, ExprUseNode, expr_use_ctxt, get_parent_expr, is_block_like, is_from_proc_macro, is_lint_allowed, sym}; use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; @@ -19,7 +17,6 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; use rustc_session::impl_lint_pass; -use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; use std::borrow::Cow; diff --git a/clippy_lints/src/derive/unsafe_derive_deserialize.rs b/clippy_lints/src/derive/unsafe_derive_deserialize.rs index 38f3251fd389..efcf2b70f0ca 100644 --- a/clippy_lints/src/derive/unsafe_derive_deserialize.rs +++ b/clippy_lints/src/derive/unsafe_derive_deserialize.rs @@ -1,14 +1,14 @@ use std::ops::ControlFlow; use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::{is_lint_allowed, paths}; +use clippy_utils::{is_lint_allowed, paths, sym}; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn, walk_item}; use rustc_hir::{self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Item, UnsafeSource}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty}; -use rustc_span::{Span, sym}; +use rustc_span::Span; use super::UNSAFE_DERIVE_DESERIALIZE; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 75ab890a8a7f..bb9c9ec3614b 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -2,10 +2,7 @@ use clippy_utils::source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context}; use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_expr; -use clippy_utils::{ - SpanlessEq, can_move_expr_to_closure_no_visit, desugar_await, higher, is_expr_final_block_expr, - is_expr_used_or_unified, paths, peel_hir_expr_while, span_contains_non_whitespace, -}; +use clippy_utils::{SpanlessEq, can_move_expr_to_closure_no_visit, desugar_await, higher, is_expr_final_block_expr, is_expr_used_or_unified, paths, peel_hir_expr_while, span_contains_non_whitespace, sym}; use core::fmt::{self, Write}; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; @@ -14,7 +11,7 @@ use rustc_hir::{Block, Expr, ExprKind, HirId, Pat, Stmt, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::{DUMMY_SP, Span, SyntaxContext, sym}; +use rustc_span::{DUMMY_SP, Span, SyntaxContext}; use std::ops::ControlFlow; declare_clippy_lint! { diff --git a/clippy_lints/src/error_impl_error.rs b/clippy_lints/src/error_impl_error.rs index 3d8650f05168..6604c9a4050b 100644 --- a/clippy_lints/src/error_impl_error.rs +++ b/clippy_lints/src/error_impl_error.rs @@ -1,12 +1,12 @@ use clippy_utils::diagnostics::{span_lint, span_lint_hir_and_then}; use clippy_utils::res::MaybeResPath; +use clippy_utils::sym; use clippy_utils::ty::implements_trait; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Visibility; use rustc_session::declare_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/exit.rs b/clippy_lints/src/exit.rs index 487db69027af..6030d53c3ad3 100644 --- a/clippy_lints/src/exit.rs +++ b/clippy_lints/src/exit.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint; +use clippy_utils::sym; use rustc_hir::{Expr, ExprKind, Item, ItemKind, OwnerNode}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 5fb1a0b80f1a..ca1b63c60c23 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -12,7 +12,7 @@ use clippy_utils::res::MaybeDef; use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::implements_trait; -use clippy_utils::{is_from_proc_macro, is_in_test, trait_ref_of_method}; +use clippy_utils::{is_from_proc_macro, is_in_test, sym, trait_ref_of_method}; use itertools::Itertools; use rustc_ast::{ FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions, @@ -28,7 +28,7 @@ use rustc_middle::ty::{self, GenericArg, List, TraitRef, Ty, TyCtxt, Upcast}; use rustc_session::impl_lint_pass; use rustc_span::edition::Edition::Edition2021; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, Symbol}; use rustc_trait_selection::infer::TyCtxtInferExt; use rustc_trait_selection::traits::{Obligation, ObligationCause, Selection, SelectionContext}; diff --git a/clippy_lints/src/format_push_string.rs b/clippy_lints/src/format_push_string.rs index fea55f91bce7..3e3cd0a77899 100644 --- a/clippy_lints/src/format_push_string.rs +++ b/clippy_lints/src/format_push_string.rs @@ -2,12 +2,12 @@ use clippy_utils::macros::{FormatArgsStorage, format_args_inputs_span, root_macro_call_first_node}; use clippy_utils::res::MaybeDef; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; -use clippy_utils::std_or_core; +use clippy_utils::{std_or_core, sym}; use rustc_errors::Applicability; use rustc_hir::{AssignOpKind, Expr, ExprKind, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; -use rustc_span::{Span, sym}; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/iter_over_hash_type.rs b/clippy_lints/src/iter_over_hash_type.rs index 6bb46ac3b554..aec863af4771 100644 --- a/clippy_lints/src/iter_over_hash_type.rs +++ b/clippy_lints/src/iter_over_hash_type.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::higher::ForLoop; use clippy_utils::res::MaybeDef; +use clippy_utils::sym; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs index 54599499515e..8ea756fa4b59 100644 --- a/clippy_lints/src/large_include_file.rs +++ b/clippy_lints/src/large_include_file.rs @@ -2,11 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::source::snippet_opt; +use clippy_utils::sym; use rustc_ast::{AttrArgs, AttrItemKind, AttrKind, Attribute, LitKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/large_stack_arrays.rs b/clippy_lints/src/large_stack_arrays.rs index 32c23a2d0362..fa85bef12a82 100644 --- a/clippy_lints/src/large_stack_arrays.rs +++ b/clippy_lints/src/large_stack_arrays.rs @@ -2,7 +2,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::is_from_proc_macro; +use clippy_utils::{is_from_proc_macro, sym}; use clippy_utils::macros::macro_backtrace; use clippy_utils::source::snippet; use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; @@ -10,7 +10,7 @@ use rustc_middle::ty; use rustc_middle::ty::layout::LayoutOf; use rustc_session::impl_lint_pass; -use rustc_span::{Span, sym}; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs index 8a5d97294d2b..d9920acb0f9f 100644 --- a/clippy_lints/src/legacy_numeric_constants.rs +++ b/clippy_lints/src/legacy_numeric_constants.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::is_from_proc_macro; +use clippy_utils::{is_from_proc_macro, sym}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use hir::def_id::DefId; @@ -10,7 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; -use rustc_span::{Symbol, sym}; +use rustc_span::Symbol; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/loops/manual_while_let_some.rs b/clippy_lints/src/loops/manual_while_let_some.rs index 9527e258db8a..caaf173bf90c 100644 --- a/clippy_lints/src/loops/manual_while_let_some.rs +++ b/clippy_lints/src/loops/manual_while_let_some.rs @@ -1,10 +1,10 @@ -use clippy_utils::SpanlessEq; +use clippy_utils::{sym, SpanlessEq}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp}; use rustc_lint::LateContext; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, Symbol}; use std::borrow::Cow; use super::MANUAL_WHILE_LET_SOME; diff --git a/clippy_lints/src/loops/unused_enumerate_index.rs b/clippy_lints/src/loops/unused_enumerate_index.rs index 816273c7ba8b..4ecfadbf9d49 100644 --- a/clippy_lints/src/loops/unused_enumerate_index.rs +++ b/clippy_lints/src/loops/unused_enumerate_index.rs @@ -2,11 +2,11 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::res::MaybeDef; use clippy_utils::source::{SpanRangeExt, walk_span_to_context}; -use clippy_utils::{expr_or_init, pat_is_wild}; +use clippy_utils::{expr_or_init, pat_is_wild, sym}; use rustc_errors::Applicability; use rustc_hir::{Closure, Expr, ExprKind, Pat, PatKind, TyKind}; use rustc_lint::LateContext; -use rustc_span::{Span, SyntaxContext, sym}; +use rustc_span::{Span, SyntaxContext}; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, diff --git a/clippy_lints/src/manual_abs_diff.rs b/clippy_lints/src/manual_abs_diff.rs index 22de5e8268bd..e3886517fdd3 100644 --- a/clippy_lints/src/manual_abs_diff.rs +++ b/clippy_lints/src/manual_abs_diff.rs @@ -6,13 +6,12 @@ use clippy_utils::source::HasSession as _; use clippy_utils::sugg::Sugg; use clippy_utils::ty::peel_and_count_ty_refs; -use clippy_utils::{eq_expr_value, peel_blocks, span_contains_comment}; +use clippy_utils::{eq_expr_value, peel_blocks, span_contains_comment, sym}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs index 40fe88532729..28790e5597fe 100644 --- a/clippy_lints/src/manual_bits.rs +++ b/clippy_lints/src/manual_bits.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::get_parent_expr; +use clippy_utils::{get_parent_expr, sym}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use rustc_ast::ast::LitKind; @@ -10,7 +10,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; -use rustc_span::{Span, sym}; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/manual_main_separator_str.rs b/clippy_lints/src/manual_main_separator_str.rs index e78f6affda2a..93a0ab5b60af 100644 --- a/clippy_lints/src/manual_main_separator_str.rs +++ b/clippy_lints/src/manual_main_separator_str.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::peel_hir_expr_refs; +use clippy_utils::{peel_hir_expr_refs, sym}; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -9,7 +9,6 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::impl_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs index 6870c9819fc0..5eeda32c7ceb 100644 --- a/clippy_lints/src/manual_retain.rs +++ b/clippy_lints/src/manual_retain.rs @@ -1,5 +1,5 @@ use clippy_config::Conf; -use clippy_utils::SpanlessEq; +use clippy_utils::{sym, SpanlessEq}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef; @@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::Span; -use rustc_span::symbol::{Symbol, sym}; +use rustc_span::symbol::Symbol; const ACCEPTABLE_METHODS: [Symbol; 5] = [ sym::binaryheap_iter, diff --git a/clippy_lints/src/manual_slice_size_calculation.rs b/clippy_lints/src/manual_slice_size_calculation.rs index de12fa29d02c..2c4998204f1f 100644 --- a/clippy_lints/src/manual_slice_size_calculation.rs +++ b/clippy_lints/src/manual_slice_size_calculation.rs @@ -3,13 +3,12 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::peel_and_count_ty_refs; -use clippy_utils::{expr_or_init, is_in_const_context, std_or_core}; +use clippy_utils::{expr_or_init, is_in_const_context, std_or_core, sym}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::impl_lint_pass; -use rustc_span::symbol::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index b668f391d67a..8be53dbe4712 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -4,7 +4,7 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::usage::mutated_variables; -use clippy_utils::{eq_expr_value, higher}; +use clippy_utils::{eq_expr_value, higher, sym}; use rustc_ast::BindingMode; use rustc_ast::ast::LitKind; use rustc_data_structures::fx::FxHashMap; @@ -16,7 +16,7 @@ use rustc_middle::ty; use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; -use rustc_span::{Symbol, SyntaxContext, sym}; +use rustc_span::{Symbol, SyntaxContext}; use std::iter; declare_clippy_lint! { diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index 8642c7e349b1..b96c869b5151 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -3,7 +3,7 @@ SpanRangeExt, expr_block, snippet, snippet_block_with_context, snippet_with_applicability, snippet_with_context, }; use clippy_utils::ty::{implements_trait, peel_and_count_ty_refs}; -use clippy_utils::{is_lint_allowed, is_unit_expr, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs}; +use clippy_utils::{is_lint_allowed, is_unit_expr, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs, sym}; use core::ops::ControlFlow; use rustc_arena::DroplessArena; use rustc_errors::{Applicability, Diag}; @@ -12,7 +12,7 @@ use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatExpr, PatExprKind, PatKind, QPath, StmtKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, AdtDef, TyCtxt, TypeckResults, VariantDef}; -use rustc_span::{Span, sym}; +use rustc_span::Span; use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE}; diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 0f32f89666a0..d8f4ee9b3189 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -5,15 +5,12 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_non_aggregate_primitive_type; -use clippy_utils::{ - as_some_expr, is_default_equivalent, is_expr_used_or_unified, is_none_expr, peel_ref_operators, std_or_core, -}; +use clippy_utils::{as_some_expr, is_default_equivalent, is_expr_used_or_unified, is_none_expr, peel_ref_operators, std_or_core, sym}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::Span; -use rustc_span::symbol::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/methods/bytecount.rs b/clippy_lints/src/methods/bytecount.rs index 77ac181ee633..2ad7facf64d8 100644 --- a/clippy_lints/src/methods/bytecount.rs +++ b/clippy_lints/src/methods/bytecount.rs @@ -2,12 +2,11 @@ use clippy_utils::res::{MaybeDef, MaybeResPath}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::visitors::is_local_used; -use clippy_utils::{peel_blocks, peel_ref_operators, strip_pat_refs}; +use clippy_utils::{peel_blocks, peel_ref_operators, strip_pat_refs, sym}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, UintTy}; -use rustc_span::sym; use super::NAIVE_BYTECOUNT; diff --git a/clippy_lints/src/methods/clear_with_drain.rs b/clippy_lints/src/methods/clear_with_drain.rs index 67def8767bb0..e6a8acb9c72e 100644 --- a/clippy_lints/src/methods/clear_with_drain.rs +++ b/clippy_lints/src/methods/clear_with_drain.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_range_full; +use clippy_utils::{is_range_full, sym}; use clippy_utils::res::MaybeDef; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem, QPath}; use rustc_lint::LateContext; use rustc_span::Span; -use rustc_span::symbol::sym; use super::CLEAR_WITH_DRAIN; diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs index 9b0c29057740..6c222640e260 100644 --- a/clippy_lints/src/methods/drain_collect.rs +++ b/clippy_lints/src/methods/drain_collect.rs @@ -2,13 +2,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef; use clippy_utils::source::snippet; -use clippy_utils::{is_range_full, std_or_core}; +use clippy_utils::{is_range_full, std_or_core, sym}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem, Path, QPath}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_middle::ty::Ty; -use rustc_span::{Symbol, sym}; +use rustc_span::Symbol; /// Checks if both types match the given diagnostic item, e.g.: /// diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs index e891b2ac6d64..081f958bc8b7 100644 --- a/clippy_lints/src/methods/expect_fun_call.rs +++ b/clippy_lints/src/methods/expect_fun_call.rs @@ -3,12 +3,11 @@ use clippy_utils::res::MaybeDef; use clippy_utils::source::snippet_with_applicability; use clippy_utils::visitors::for_each_expr; -use clippy_utils::{contains_return, is_inside_always_const_context, peel_blocks}; +use clippy_utils::{contains_return, is_inside_always_const_context, peel_blocks, sym}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::Span; -use rustc_span::symbol::sym; use std::borrow::Cow; use std::ops::ControlFlow; diff --git a/clippy_lints/src/methods/filetype_is_file.rs b/clippy_lints/src/methods/filetype_is_file.rs index a964cbf657b4..a2ed55796887 100644 --- a/clippy_lints/src/methods/filetype_is_file.rs +++ b/clippy_lints/src/methods/filetype_is_file.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::get_parent_expr; +use clippy_utils::{get_parent_expr, sym}; use clippy_utils::res::MaybeDef; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::{Span, sym}; +use rustc_span::Span; use super::FILETYPE_IS_FILE; diff --git a/clippy_lints/src/methods/filter_map_bool_then.rs b/clippy_lints/src/methods/filter_map_bool_then.rs index b803d1a3309d..8e5b271212e6 100644 --- a/clippy_lints/src/methods/filter_map_bool_then.rs +++ b/clippy_lints/src/methods/filter_map_bool_then.rs @@ -3,7 +3,7 @@ use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; use clippy_utils::source::{SpanRangeExt, snippet_with_context}; use clippy_utils::ty::is_copy; -use clippy_utils::{CaptureKind, can_move_expr_to_closure, contains_return, is_from_proc_macro, peel_blocks}; +use clippy_utils::{CaptureKind, can_move_expr_to_closure, contains_return, is_from_proc_macro, peel_blocks, sym}; use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::Binder; use rustc_middle::ty::adjustment::Adjust; -use rustc_span::{Span, sym}; +use rustc_span::Span; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &Expr<'_>, call_span: Span) { if !expr.span.in_external_macro(cx.sess().source_map()) diff --git a/clippy_lints/src/methods/filter_next.rs b/clippy_lints/src/methods/filter_next.rs index e1a9a79e20ee..66ab3075f715 100644 --- a/clippy_lints/src/methods/filter_next.rs +++ b/clippy_lints/src/methods/filter_next.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::path_to_local_with_projections; +use clippy_utils::{path_to_local_with_projections, sym}; use clippy_utils::source::snippet; use clippy_utils::ty::implements_trait; use rustc_ast::{BindingMode, Mutability}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::sym; use super::FILTER_NEXT; diff --git a/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/clippy_lints/src/methods/from_iter_instead_of_collect.rs index 11671f377e66..7b0ac90ced6c 100644 --- a/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef, MaybeQPath}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::sugg; +use clippy_utils::{sugg, sym}; use clippy_utils::ty::implements_trait; use rustc_ast::join_path_idents; use rustc_errors::Applicability; @@ -11,7 +11,6 @@ use rustc_hir::{self as hir, Expr, ExprKind, GenericArg, QPath, TyKind}; use rustc_lint::LateContext; use rustc_middle::ty::GenericParamDefKind; -use rustc_span::sym; use super::FROM_ITER_INSTEAD_OF_COLLECT; diff --git a/clippy_lints/src/methods/get_first.rs b/clippy_lints/src/methods/get_first.rs index 88e9f2fdaee3..414c4e0cd381 100644 --- a/clippy_lints/src/methods/get_first.rs +++ b/clippy_lints/src/methods/get_first.rs @@ -1,13 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef; use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sym; use rustc_ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::source_map::Spanned; -use rustc_span::sym; use super::GET_FIRST; diff --git a/clippy_lints/src/methods/get_last_with_len.rs b/clippy_lints/src/methods/get_last_with_len.rs index 5f6fb4c821d5..171079f52d9a 100644 --- a/clippy_lints/src/methods/get_last_with_len.rs +++ b/clippy_lints/src/methods/get_last_with_len.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{SpanlessEq, is_integer_literal}; +use clippy_utils::{SpanlessEq, is_integer_literal, sym}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::source_map::Spanned; -use rustc_span::sym; use super::GET_LAST_WITH_LEN; diff --git a/clippy_lints/src/methods/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs index d273558a7006..76499c5bd9e6 100644 --- a/clippy_lints/src/methods/get_unwrap.rs +++ b/clippy_lints/src/methods/get_unwrap.rs @@ -1,11 +1,10 @@ use super::utils::derefs_to_slice; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::get_parent_expr; +use clippy_utils::{get_parent_expr, sym}; use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::sym; use super::GET_UNWRAP; diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs index 7a49a5f31f03..374639985bee 100644 --- a/clippy_lints/src/methods/inefficient_to_string.rs +++ b/clippy_lints/src/methods/inefficient_to_string.rs @@ -2,12 +2,12 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef; use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sym; use clippy_utils::ty::peel_and_count_ty_refs; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_span::symbol::sym; use super::INEFFICIENT_TO_STRING; diff --git a/clippy_lints/src/methods/ip_constant.rs b/clippy_lints/src/methods/ip_constant.rs index 7c24cf03fd97..7a49553c6f59 100644 --- a/clippy_lints/src/methods/ip_constant.rs +++ b/clippy_lints/src/methods/ip_constant.rs @@ -1,10 +1,10 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sym; use rustc_data_structures::smallvec::SmallVec; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath, TyKind}; use rustc_lint::LateContext; -use rustc_span::sym; use super::IP_CONSTANT; diff --git a/clippy_lints/src/methods/iter_count.rs b/clippy_lints/src/methods/iter_count.rs index 8b303c0ca5b2..18278446bf61 100644 --- a/clippy_lints/src/methods/iter_count.rs +++ b/clippy_lints/src/methods/iter_count.rs @@ -2,10 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef; use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_span::{Symbol, sym}; +use rustc_span::Symbol; use super::ITER_COUNT; diff --git a/clippy_lints/src/methods/iter_out_of_bounds.rs b/clippy_lints/src/methods/iter_out_of_bounds.rs index 8cff3bd815a1..f7d7df267967 100644 --- a/clippy_lints/src/methods/iter_out_of_bounds.rs +++ b/clippy_lints/src/methods/iter_out_of_bounds.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_note; -use clippy_utils::expr_or_init; +use clippy_utils::{expr_or_init, sym}; use clippy_utils::higher::VecArgs; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self}; -use rustc_span::sym; use super::ITER_OUT_OF_BOUNDS; diff --git a/clippy_lints/src/methods/iter_with_drain.rs b/clippy_lints/src/methods/iter_with_drain.rs index aa45969c8982..8d1585baac45 100644 --- a/clippy_lints/src/methods/iter_with_drain.rs +++ b/clippy_lints/src/methods/iter_with_drain.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_range_full; +use clippy_utils::{is_range_full, sym}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::LateContext; use rustc_span::Span; -use rustc_span::symbol::sym; use super::ITER_WITH_DRAIN; diff --git a/clippy_lints/src/methods/join_absolute_paths.rs b/clippy_lints/src/methods/join_absolute_paths.rs index 905a58afa795..c731c2fc9434 100644 --- a/clippy_lints/src/methods/join_absolute_paths.rs +++ b/clippy_lints/src/methods/join_absolute_paths.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::expr_or_init; +use clippy_utils::{expr_or_init, sym}; use clippy_utils::res::MaybeDef; use clippy_utils::source::snippet; use rustc_ast::ast::LitKind; @@ -7,7 +7,6 @@ use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_span::Span; -use rustc_span::symbol::sym; use super::JOIN_ABSOLUTE_PATHS; diff --git a/clippy_lints/src/methods/manual_next_back.rs b/clippy_lints/src/methods/manual_next_back.rs index b064f978588c..221c7f08c923 100644 --- a/clippy_lints/src/methods/manual_next_back.rs +++ b/clippy_lints/src/methods/manual_next_back.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; +use clippy_utils::sym; use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_span::symbol::sym; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, diff --git a/clippy_lints/src/methods/manual_repeat_n.rs b/clippy_lints/src/methods/manual_repeat_n.rs index 1a7628ed43a4..1bb112732fa5 100644 --- a/clippy_lints/src/methods/manual_repeat_n.rs +++ b/clippy_lints/src/methods/manual_repeat_n.rs @@ -2,11 +2,10 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; use clippy_utils::source::{snippet, snippet_with_context}; -use clippy_utils::{expr_use_ctxt, fn_def_id, std_or_core}; +use clippy_utils::{expr_use_ctxt, fn_def_id, std_or_core, sym}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; -use rustc_span::sym; use super::MANUAL_REPEAT_N; diff --git a/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs index 4fe14f8053c9..457549d1091c 100644 --- a/clippy_lints/src/methods/manual_str_repeat.rs +++ b/clippy_lints/src/methods/manual_str_repeat.rs @@ -2,12 +2,12 @@ use clippy_utils::res::{MaybeDef, MaybeResPath}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; +use clippy_utils::sym; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_span::symbol::sym; use std::borrow::Cow; use super::MANUAL_STR_REPEAT; diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs index 7c95d65e6b95..d80feff11f34 100644 --- a/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/clippy_lints/src/methods/option_as_ref_deref.rs @@ -1,13 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::peel_blocks; +use clippy_utils::{peel_blocks, sym}; use clippy_utils::res::{MaybeDef, MaybeResPath}; use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::{Symbol, sym}; +use rustc_span::Symbol; use super::OPTION_AS_REF_DEREF; diff --git a/clippy_lints/src/methods/path_buf_push_overwrite.rs b/clippy_lints/src/methods/path_buf_push_overwrite.rs index 18046ff24f9d..fe4904804b5b 100644 --- a/clippy_lints/src/methods/path_buf_push_overwrite.rs +++ b/clippy_lints/src/methods/path_buf_push_overwrite.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef; +use clippy_utils::sym; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; -use rustc_span::symbol::sym; use std::path::{Component, Path}; use super::PATH_BUF_PUSH_OVERWRITE; diff --git a/clippy_lints/src/methods/path_ends_with_ext.rs b/clippy_lints/src/methods/path_ends_with_ext.rs index 87d1aa62b2c2..ffba244dcf61 100644 --- a/clippy_lints/src/methods/path_ends_with_ext.rs +++ b/clippy_lints/src/methods/path_ends_with_ext.rs @@ -3,12 +3,12 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef; use clippy_utils::source::snippet; +use clippy_utils::sym; use rustc_ast::{LitKind, StrStyle}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; -use rustc_span::sym; use std::fmt::Write; pub const DEFAULT_ALLOWED_DOTFILES: &[&str] = &[ diff --git a/clippy_lints/src/methods/single_char_add_str.rs b/clippy_lints/src/methods/single_char_add_str.rs index 1248d1658d77..581c400e25c5 100644 --- a/clippy_lints/src/methods/single_char_add_str.rs +++ b/clippy_lints/src/methods/single_char_add_str.rs @@ -1,12 +1,12 @@ use super::SINGLE_CHAR_ADD_STR; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{snippet_with_applicability, str_literal_to_char_literal}; +use clippy_utils::sym; use rustc_ast::BorrowKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::sym; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { diff --git a/clippy_lints/src/methods/suspicious_command_arg_space.rs b/clippy_lints/src/methods/suspicious_command_arg_space.rs index be733c5d3514..ca226dca8852 100644 --- a/clippy_lints/src/methods/suspicious_command_arg_space.rs +++ b/clippy_lints/src/methods/suspicious_command_arg_space.rs @@ -1,8 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeDef; +use clippy_utils::sym; use rustc_errors::{Applicability, Diag}; use rustc_lint::LateContext; -use rustc_span::{Span, sym}; +use rustc_span::Span; use {rustc_ast as ast, rustc_hir as hir}; use super::SUSPICIOUS_COMMAND_ARG_SPACE; diff --git a/clippy_lints/src/methods/suspicious_to_owned.rs b/clippy_lints/src/methods/suspicious_to_owned.rs index e9a5104eb3b4..5d0fd6ca4c80 100644 --- a/clippy_lints/src/methods/suspicious_to_owned.rs +++ b/clippy_lints/src/methods/suspicious_to_owned.rs @@ -1,10 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeDef; +use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::print::with_forced_trimmed_paths; -use rustc_span::{Span, sym}; +use rustc_span::Span; use super::SUSPICIOUS_TO_OWNED; diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs index 98f319be7a45..418eb4a6b2ac 100644 --- a/clippy_lints/src/methods/type_id_on_box.rs +++ b/clippy_lints/src/methods/type_id_on_box.rs @@ -1,13 +1,14 @@ use crate::methods::TYPE_ID_ON_BOX; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; +use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::{self, ExistentialPredicate, Ty}; -use rustc_span::{Span, sym}; +use rustc_span::Span; /// Checks if the given type is `dyn Any`, or a trait object that has `Any` as a supertrait. /// Only in those cases will its vtable have a `type_id` method that returns the implementor's diff --git a/clippy_lints/src/methods/unbuffered_bytes.rs b/clippy_lints/src/methods/unbuffered_bytes.rs index fdddd5e2771d..b86ba39d7b6c 100644 --- a/clippy_lints/src/methods/unbuffered_bytes.rs +++ b/clippy_lints/src/methods/unbuffered_bytes.rs @@ -1,10 +1,10 @@ use super::UNBUFFERED_BYTES; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; +use clippy_utils::sym; use clippy_utils::ty::implements_trait; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::sym; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { // Lint if the `.bytes()` call is from the `Read` trait and the implementor is not buffered. diff --git a/clippy_lints/src/methods/unnecessary_get_then_check.rs b/clippy_lints/src/methods/unnecessary_get_then_check.rs index 3207c4207fc0..b2413bb77aa7 100644 --- a/clippy_lints/src/methods/unnecessary_get_then_check.rs +++ b/clippy_lints/src/methods/unnecessary_get_then_check.rs @@ -1,12 +1,13 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::res::MaybeDef; use clippy_utils::source::SpanRangeExt; +use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::Ty; -use rustc_span::{Span, sym}; +use rustc_span::Span; use super::UNNECESSARY_GET_THEN_CHECK; diff --git a/clippy_lints/src/methods/verbose_file_reads.rs b/clippy_lints/src/methods/verbose_file_reads.rs index 5727843302d6..b67e084a3533 100644 --- a/clippy_lints/src/methods/verbose_file_reads.rs +++ b/clippy_lints/src/methods/verbose_file_reads.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; +use clippy_utils::sym; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::LateContext; -use rustc_span::sym; use super::VERBOSE_FILE_READS; diff --git a/clippy_lints/src/methods/waker_clone_wake.rs b/clippy_lints/src/methods/waker_clone_wake.rs index 3081d7f91f06..bb26c2d93578 100644 --- a/clippy_lints/src/methods/waker_clone_wake.rs +++ b/clippy_lints/src/methods/waker_clone_wake.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; -use rustc_span::sym; use super::WAKER_CLONE_WAKE; diff --git a/clippy_lints/src/missing_const_for_thread_local.rs b/clippy_lints/src/missing_const_for_thread_local.rs index ea74940828a1..4b4bc6a6e05d 100644 --- a/clippy_lints/src/missing_const_for_thread_local.rs +++ b/clippy_lints/src/missing_const_for_thread_local.rs @@ -4,12 +4,11 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::qualify_min_const_fn::is_min_const_fn; use clippy_utils::source::snippet; -use clippy_utils::{fn_has_unsatisfiable_preds, peel_blocks}; +use clippy_utils::{fn_has_unsatisfiable_preds, peel_blocks, sym}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, intravisit}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::sym::{self, thread_local_macro}; declare_clippy_lint! { /// ### What it does @@ -63,7 +62,7 @@ fn is_thread_local_initializer( ) -> Option { let macro_def_id = span.source_callee()?.macro_def_id?; Some( - cx.tcx.is_diagnostic_item(thread_local_macro, macro_def_id) + cx.tcx.is_diagnostic_item(sym::thread_local_macro, macro_def_id) && matches!(fn_kind, intravisit::FnKind::ItemFn(..)), ) } diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs index 98a9a98d281a..7669ad047c46 100644 --- a/clippy_lints/src/mut_key.rs +++ b/clippy_lints/src/mut_key.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::trait_ref_of_method; +use clippy_utils::{sym, trait_ref_of_method}; use clippy_utils::ty::InteriorMut; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -9,7 +9,6 @@ use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_span::def_id::LocalDefId; -use rustc_span::symbol::sym; use std::iter; declare_clippy_lint! { diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index 25fcc7ee568e..8da9a6dfcad4 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -4,7 +4,7 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{implements_trait, is_copy}; -use clippy_utils::{DefinedTy, ExprUseNode, expr_use_ctxt, peel_n_hir_expr_refs}; +use clippy_utils::{DefinedTy, ExprUseNode, expr_use_ctxt, peel_n_hir_expr_refs, sym}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -17,7 +17,6 @@ self, ClauseKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, ParamTy, ProjectionPredicate, Ty, }; use rustc_session::impl_lint_pass; -use rustc_span::symbol::sym; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{Obligation, ObligationCause}; use std::collections::VecDeque; diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index e09fc0a76366..79fcc5decfa1 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -20,7 +20,7 @@ use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant, const_item_rhs_to_expr}; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::is_in_const_context; +use clippy_utils::{is_in_const_context, sym}; use clippy_utils::macros::macro_backtrace; use clippy_utils::paths::{PathNS, lookup_path_str}; use clippy_utils::ty::{get_field_idx_by_name, implements_trait}; @@ -39,7 +39,7 @@ TypeckResults, TypingEnv, }; use rustc_session::impl_lint_pass; -use rustc_span::{DUMMY_SP, sym}; +use rustc_span::DUMMY_SP; use std::collections::hash_map::Entry; declare_clippy_lint! { diff --git a/clippy_lints/src/operators/cmp_owned.rs b/clippy_lints/src/operators/cmp_owned.rs index db55772f4e01..08ef5958b3bb 100644 --- a/clippy_lints/src/operators/cmp_owned.rs +++ b/clippy_lints/src/operators/cmp_owned.rs @@ -1,12 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeQPath; use clippy_utils::source::snippet_with_context; +use clippy_utils::sym; use clippy_utils::ty::{implements_trait, is_copy}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty::Ty; -use rustc_span::symbol::sym; use super::CMP_OWNED; diff --git a/clippy_lints/src/operators/float_equality_without_abs.rs b/clippy_lints/src/operators/float_equality_without_abs.rs index 17fa8017c978..c5eb7d24c30d 100644 --- a/clippy_lints/src/operators/float_equality_without_abs.rs +++ b/clippy_lints/src/operators/float_equality_without_abs.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::sugg; +use clippy_utils::{sugg, sym}; use rustc_ast::util::parser::AssocOp; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -7,7 +7,6 @@ use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::source_map::Spanned; -use rustc_span::sym; use super::FLOAT_EQUALITY_WITHOUT_ABS; diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 43db0085f2e3..cfe2513521eb 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,12 +1,11 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; -use clippy_utils::{is_in_test, is_inside_always_const_context}; +use clippy_utils::{is_in_test, is_inside_always_const_context, sym}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::sym; pub struct PanicUnimplemented { allow_panic_in_tests: bool, diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index ca0d41fca524..bed50918192e 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -6,7 +6,7 @@ use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::implements_trait; -use clippy_utils::{expr_use_ctxt, fn_def_id, get_parent_expr, higher, is_in_const_context, is_integer_const}; +use clippy_utils::{expr_use_ctxt, fn_def_id, get_parent_expr, higher, is_in_const_context, is_integer_const, sym}; use rustc_ast::Mutability; use rustc_ast::ast::RangeLimits; use rustc_errors::Applicability; @@ -15,7 +15,7 @@ use rustc_middle::ty::{self, ClauseKind, GenericArgKind, PredicatePolarity, Ty}; use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; -use rustc_span::{DesugaringKind, Span, sym}; +use rustc_span::{DesugaringKind, Span}; use std::cmp::Ordering; declare_clippy_lint! { diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 13c1b10bf2e8..7a2772f1d5e7 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; -use clippy_utils::fn_has_unsatisfiable_preds; +use clippy_utils::{fn_has_unsatisfiable_preds, sym}; use clippy_utils::mir::{LocalUsage, PossibleBorrowerMap, visit_local_usage}; use clippy_utils::res::MaybeDef; use clippy_utils::source::SpanRangeExt; @@ -12,7 +12,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; -use rustc_span::{BytePos, Span, sym}; +use rustc_span::{BytePos, Span}; macro_rules! unwrap_or_continue { ($x:expr) => { diff --git a/clippy_lints/src/repeat_vec_with_capacity.rs b/clippy_lints/src/repeat_vec_with_capacity.rs index 8805687efccf..fdb459364efe 100644 --- a/clippy_lints/src/repeat_vec_with_capacity.rs +++ b/clippy_lints/src/repeat_vec_with_capacity.rs @@ -5,12 +5,12 @@ use clippy_utils::macros::matching_root_macro_call; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; -use clippy_utils::{expr_or_init, fn_def_id, std_or_core}; +use clippy_utils::{expr_or_init, fn_def_id, std_or_core, sym}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::{Span, sym}; +use rustc_span::Span; pub struct RepeatVecWithCapacity { msrv: Msrv, diff --git a/clippy_lints/src/size_of_ref.rs b/clippy_lints/src/size_of_ref.rs index bf304ebcfdc0..3e48f0bc5037 100644 --- a/clippy_lints/src/size_of_ref.rs +++ b/clippy_lints/src/size_of_ref.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::res::{MaybeDef, MaybeResPath}; +use clippy_utils::sym; use clippy_utils::ty::peel_and_count_ty_refs; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index c3cb2c09752f..694be160e79a 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -3,7 +3,7 @@ use clippy_utils::source::{snippet_indent, snippet_with_context}; use clippy_utils::sugg::Sugg; -use clippy_utils::{can_mut_borrow_both, eq_expr_value, is_in_const_context, std_or_core}; +use clippy_utils::{can_mut_borrow_both, eq_expr_value, is_in_const_context, std_or_core, sym}; use itertools::Itertools; use rustc_data_structures::fx::FxIndexSet; @@ -16,7 +16,7 @@ use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; -use rustc_span::{Span, SyntaxContext, sym}; +use rustc_span::{Span, SyntaxContext}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/time_subtraction.rs b/clippy_lints/src/time_subtraction.rs index c241935d6c31..e7bf58078c3d 100644 --- a/clippy_lints/src/time_subtraction.rs +++ b/clippy_lints/src/time_subtraction.rs @@ -3,12 +3,12 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; use clippy_utils::sugg::Sugg; +use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::impl_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/to_string_trait_impl.rs b/clippy_lints/src/to_string_trait_impl.rs index 303f6028bd51..337b9b8b8220 100644 --- a/clippy_lints/src/to_string_trait_impl.rs +++ b/clippy_lints/src/to_string_trait_impl.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::sym; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/transmute/transmuting_null.rs b/clippy_lints/src/transmute/transmuting_null.rs index 4f06d98703f6..7d6a667eb8e5 100644 --- a/clippy_lints/src/transmute/transmuting_null.rs +++ b/clippy_lints/src/transmute/transmuting_null.rs @@ -1,11 +1,10 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint; -use clippy_utils::is_integer_const; +use clippy_utils::{is_integer_const, sym}; use clippy_utils::res::{MaybeDef, MaybeResPath}; use rustc_hir::{ConstBlock, Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::Ty; -use rustc_span::symbol::sym; use super::TRANSMUTING_NULL; diff --git a/clippy_lints/src/transmute/unsound_collection_transmute.rs b/clippy_lints/src/transmute/unsound_collection_transmute.rs index f46e95b0b832..65aebb5223b4 100644 --- a/clippy_lints/src/transmute/unsound_collection_transmute.rs +++ b/clippy_lints/src/transmute/unsound_collection_transmute.rs @@ -1,10 +1,10 @@ use super::UNSOUND_COLLECTION_TRANSMUTE; use super::utils::is_layout_incompatible; use clippy_utils::diagnostics::span_lint; +use clippy_utils::sym; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_span::symbol::sym; /// Checks for `unsound_collection_transmute` lint. /// Returns `true` if it's triggered, otherwise returns `false`. diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs index 4b23367645eb..c4e0d886c847 100644 --- a/clippy_lints/src/types/borrowed_box.rs +++ b/clippy_lints/src/types/borrowed_box.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; +use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::{ self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, MutTy, Mutability, Node, QPath, TyKind, }; use rustc_lint::LateContext; -use rustc_span::sym; use super::BORROWED_BOX; diff --git a/clippy_lints/src/types/box_collection.rs b/clippy_lints/src/types/box_collection.rs index 985057cd6734..cca04d39ca31 100644 --- a/clippy_lints/src/types/box_collection.rs +++ b/clippy_lints/src/types/box_collection.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::qpath_generic_tys; +use clippy_utils::{qpath_generic_tys, sym}; use clippy_utils::res::MaybeResPath; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, QPath}; use rustc_lint::LateContext; -use rustc_span::{Symbol, sym}; +use rustc_span::Symbol; use super::BOX_COLLECTION; diff --git a/clippy_lints/src/types/linked_list.rs b/clippy_lints/src/types/linked_list.rs index fba804bbe088..96126d3d4320 100644 --- a/clippy_lints/src/types/linked_list.rs +++ b/clippy_lints/src/types/linked_list.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::sym; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir}; use rustc_lint::LateContext; -use rustc_span::symbol::sym; use super::LINKEDLIST; diff --git a/clippy_lints/src/types/owned_cow.rs b/clippy_lints/src/types/owned_cow.rs index 0eef373be04e..e70348b481c8 100644 --- a/clippy_lints/src/types/owned_cow.rs +++ b/clippy_lints/src/types/owned_cow.rs @@ -1,11 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef, MaybeResPath}; use clippy_utils::source::snippet_opt; +use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir}; use rustc_lint::LateContext; -use rustc_span::{Span, sym}; +use rustc_span::Span; pub(super) fn check(cx: &LateContext<'_>, qpath: &hir::QPath<'_>, def_id: DefId) -> bool { if cx.tcx.is_diagnostic_item(sym::Cow, def_id) diff --git a/clippy_lints/src/types/rc_buffer.rs b/clippy_lints/src/types/rc_buffer.rs index 43b38bb662dc..8c864dab66d8 100644 --- a/clippy_lints/src/types/rc_buffer.rs +++ b/clippy_lints/src/types/rc_buffer.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::qpath_generic_tys; +use clippy_utils::{qpath_generic_tys, sym}; use clippy_utils::res::MaybeResPath; use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{QPath, Ty, TyKind}; use rustc_lint::LateContext; -use rustc_span::symbol::sym; use std::borrow::Cow; use super::RC_BUFFER; diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs index 48f1cda9ee7b..c1e03b7e8c70 100644 --- a/clippy_lints/src/unconditional_recursion.rs +++ b/clippy_lints/src/unconditional_recursion.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeQPath; -use clippy_utils::{expr_or_init, fn_def_id_with_node_args}; +use clippy_utils::{expr_or_init, fn_def_id_with_node_args, sym}; use rustc_ast::BinOpKind; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; @@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::impl_lint_pass; use rustc_span::symbol::{Ident, kw}; -use rustc_span::{Span, sym}; +use rustc_span::Span; use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor; use std::ops::ControlFlow; diff --git a/clippy_lints/src/unnecessary_owned_empty_strings.rs b/clippy_lints/src/unnecessary_owned_empty_strings.rs index 0388450c9f7e..229974b499ad 100644 --- a/clippy_lints/src/unnecessary_owned_empty_strings.rs +++ b/clippy_lints/src/unnecessary_owned_empty_strings.rs @@ -1,12 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef; +use clippy_utils::sym; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::declare_lint_pass; -use rustc_span::symbol::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/zombie_processes.rs b/clippy_lints/src/zombie_processes.rs index 0319f3e656e1..92a5752cc2df 100644 --- a/clippy_lints/src/zombie_processes.rs +++ b/clippy_lints/src/zombie_processes.rs @@ -1,7 +1,7 @@ use ControlFlow::{Break, Continue}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::{MaybeDef, MaybeResPath}; -use clippy_utils::{fn_def_id, get_enclosing_block}; +use clippy_utils::{fn_def_id, get_enclosing_block, sym}; use rustc_ast::Mutability; use rustc_ast::visit::visit_opt; use rustc_errors::Applicability; @@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_session::declare_lint_pass; -use rustc_span::{Span, sym}; +use rustc_span::Span; use std::ops::ControlFlow; declare_clippy_lint! { diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index abc6885bef2d..3ff40f2fb722 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -1,7 +1,7 @@ use crate::consts::ConstEvalCtxt; use crate::macros::macro_backtrace; use crate::source::{SpanRange, SpanRangeExt, walk_span_to_context}; -use crate::tokenize_with_text; +use crate::{sym, tokenize_with_text}; use rustc_ast::ast; use rustc_ast::ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::{FxHasher, FxIndexMap}; @@ -19,7 +19,7 @@ use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize}; use rustc_lint::LateContext; use rustc_middle::ty::TypeckResults; -use rustc_span::{BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext, sym}; +use rustc_span::{BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext}; use std::hash::{Hash, Hasher}; use std::ops::Range; use std::slice; diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index bd99525a86fb..6965225c12ab 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -34,25 +34,57 @@ macro_rules! generate { // // `cargo dev fmt` ensures that the content of the `generate!()` macro call stays sorted. generate! { + Any, Applicability, + ArrayIntoIter, AsyncReadExt, AsyncWriteExt, BACKSLASH_SINGLE_QUOTE: r"\'", + BTreeEntry, + BTreeSet, Binary, + BinaryHeap, CLIPPY_ARGS, CLIPPY_CONF_DIR, CRLF: "\r\n", Cargo_toml: "Cargo.toml", + Child, + Command, + Cow, Current, DOUBLE_QUOTE: "\"", + DebugStruct, Deserialize, + DirBuilder, + DoubleEndedIterator, + Duration, EarlyContext, EarlyLintPass, + Enumerate, + Error, + File, + FileType, + FsOpenOptions, + FsPermissions, + HashMapEntry, + Instant, IntoIter, + IoBufRead, + IoLines, + IoRead, + IoSeek, + IoWrite, + IpAddr, + Ipv4Addr, + Ipv6Addr, + IterEmpty, + IterOnce, + IterPeekable, Itertools, LF: "\n", LateContext, Lazy, + LinkedList, Lint, LowerExp, LowerHex, @@ -62,20 +94,37 @@ macro_rules! generate { MsrvStack, Octal, OpenOptions, + OsStr, + OsString, + Path, + PathBuf, PathLookup, + RangeBounds, + Receiver, + RefCellRef, + RefCellRefMut, Regex, RegexBuilder, RegexSet, + Saturating, + SeekFrom, + SliceIter, Start, + Stdin, Symbol, SyntaxContext, TBD, + ToOwned, + ToString, UpperExp, UpperHex, V4, V6, + VecDeque, Visitor, + Waker, Weak, + Wrapping, abs, ambiguous_glob_reexports, app, @@ -87,11 +136,18 @@ macro_rules! generate { as_deref_mut, as_mut, as_path, + as_ptr, + as_str, assert_failed, author, + binaryheap_iter, + bool_then, borrow, borrow_mut, box_assume_init_into_vec_unsafe, + btreemap_contains_key, + btreemap_insert, + btreeset_iter, build_hasher, by_ref, bytes, @@ -103,6 +159,8 @@ macro_rules! generate { ceil, ceil_char_boundary, chain, + char_is_ascii, + char_to_digit, chars, check_attributes, checked_abs, @@ -112,30 +170,40 @@ macro_rules! generate { checked_pow, checked_rem_euclid, checked_sub, + child_id, + child_kill, clamp, clippy_utils, clone_into, cloned, + cmp_max, + cmp_min, cognitive_complexity, collapsible_else_if, collapsible_if, collect, const_ptr, contains, + convert_identity, copied, copy_from, copy_from_nonoverlapping, copy_to, copy_to_nonoverlapping, core_arch, + core_panic_2021_macro, count_ones, create, create_new, + cstring_as_c_str, cx, cycle, cyclomatic_complexity, + dbg_macro, de, + debug_struct, deprecated_in_future, + deref_mut_method, diagnostics, disallowed_types, drain, @@ -144,12 +212,53 @@ macro_rules! generate { ends_with, enum_glob_use, enumerate, + enumerate_method, + eprint_macro, + eprintln_macro, err, exp, expect_err, expn_data, exported_private_dependencies, extend, + f128_consts_mod, + f128_epsilon, + f16_consts_mod, + f16_epsilon, + f32_consts_mod, + f32_epsilon, + f32_legacy_const_digits, + f32_legacy_const_epsilon, + f32_legacy_const_infinity, + f32_legacy_const_mantissa_dig, + f32_legacy_const_max, + f32_legacy_const_max_10_exp, + f32_legacy_const_max_exp, + f32_legacy_const_min, + f32_legacy_const_min_10_exp, + f32_legacy_const_min_exp, + f32_legacy_const_min_positive, + f32_legacy_const_nan, + f32_legacy_const_neg_infinity, + f32_legacy_const_radix, + f64_consts_mod, + f64_epsilon, + f64_legacy_const_digits, + f64_legacy_const_epsilon, + f64_legacy_const_infinity, + f64_legacy_const_mantissa_dig, + f64_legacy_const_max, + f64_legacy_const_max_10_exp, + f64_legacy_const_max_exp, + f64_legacy_const_min, + f64_legacy_const_min_10_exp, + f64_legacy_const_min_exp, + f64_legacy_const_min_positive, + f64_legacy_const_nan, + f64_legacy_const_neg_infinity, + f64_legacy_const_radix, + field, + file_options, filter, filter_map, find, @@ -163,11 +272,14 @@ macro_rules! generate { floor_char_boundary, fold, for_each, + format_args_macro, from_be_bytes, from_bytes_with_nul, from_bytes_with_nul_unchecked, from_days, + from_fn, from_hours, + from_iter_fn, from_le_bytes, from_micros, from_millis, @@ -178,9 +290,11 @@ macro_rules! generate { from_raw, from_raw_parts, from_secs, + from_str_method, from_str_radix, from_weeks, fs, + fs_create_dir, fuse, futures_util, get, @@ -190,19 +304,64 @@ macro_rules! generate { get_unchecked, get_unchecked_mut, has_significant_drop, + hashmap_contains_key, + hashmap_drain_ty, + hashmap_insert, + hashmap_iter_mut_ty, + hashmap_iter_ty, + hashmap_keys_ty, + hashmap_values_mut_ty, + hashmap_values_ty, + hashset_drain_ty, + hashset_iter, + hashset_iter_ty, help, hidden_glob_reexports, hygiene, + i128_legacy_const_max, + i128_legacy_const_min, + i128_legacy_fn_max_value, + i128_legacy_fn_min_value, + i128_legacy_mod, + i16_legacy_const_max, + i16_legacy_const_min, + i16_legacy_fn_max_value, + i16_legacy_fn_min_value, + i16_legacy_mod, + i32_legacy_const_max, + i32_legacy_const_min, + i32_legacy_fn_max_value, + i32_legacy_fn_min_value, + i32_legacy_mod, + i64_legacy_const_max, + i64_legacy_const_min, + i64_legacy_fn_max_value, + i64_legacy_fn_min_value, + i64_legacy_mod, + i8_legacy_const_max, + i8_legacy_const_min, + i8_legacy_fn_max_value, + i8_legacy_fn_min_value, + i8_legacy_mod, ilog, + include_bytes_macro, + include_str_macro, insert, insert_str, inspect, + instant_now, int_roundings, into, into_bytes, into_ok, into_owned, + intrinsics_unaligned_volatile_load, + intrinsics_unaligned_volatile_store, io, + io_error_new, + io_errorkind, + io_stderr, + io_stdout, is_ascii, is_char_boundary, is_diag_item, @@ -218,7 +377,16 @@ macro_rules! generate { is_some, is_some_and, is_sorted_by_key, + isize_legacy_const_max, + isize_legacy_const_min, + isize_legacy_fn_max_value, + isize_legacy_fn_min_value, + isize_legacy_mod, isqrt, + iter_cloned, + iter_copied, + iter_filter, + iter_repeat, itertools, join, kw, @@ -231,6 +399,7 @@ macro_rules! generate { log, log10, log2, + macro_concat, macro_use_imports, map_break, map_continue, @@ -239,11 +408,16 @@ macro_rules! generate { map_while, match_indices, matches, + matches_macro, max, max_by, max_by_key, max_value, maximum, + mem_align_of, + mem_replace, + mem_size_of, + mem_size_of_val, min, min_by, min_by_key, @@ -266,26 +440,48 @@ macro_rules! generate { ok_or, once_cell, open, + open_options_new, + option_expect, + option_unwrap, or_default, or_else, or_insert, or_insert_with, + os_str_to_os_string, + os_string_as_os_str, outer_expn, + panic_any, panic_str, parse, partition, + path_main_separator, + path_to_pathbuf, + pathbuf_as_path, paths, peek, peek_mut, peekable, + permissions_from_mode, + pin_macro, + position, pow, powf, powi, + print_macro, + println_macro, + process_abort, + process_exit, product, + ptr_read_volatile, + ptr_slice_from_raw_parts, + ptr_slice_from_raw_parts_mut, + ptr_without_provenance, + ptr_without_provenance_mut, push, push_back, push_front, push_str, + range_step, read, read_exact, read_line, @@ -305,6 +501,7 @@ macro_rules! generate { reserve, resize, restriction, + result_ok_method, rev, rfind, rmatch_indices, @@ -324,6 +521,7 @@ macro_rules! generate { rustfmt_skip, rwlock, saturating_abs, + saturating_div, saturating_pow, scan, seek, @@ -333,7 +531,11 @@ macro_rules! generate { set_readonly, signum, single_component_path_imports, + skip, skip_while, + slice_from_ref, + slice_into_vec, + slice_iter, slice_mut_unchecked, slice_unchecked, sort, @@ -358,6 +560,20 @@ macro_rules! generate { starts_with, std_detect, step_by, + str_chars, + str_ends_with, + str_len, + str_split_whitespace, + str_starts_with, + str_trim, + str_trim_end, + str_trim_start, + string_as_mut_str, + string_as_str, + string_from_utf8, + string_insert_str, + string_new, + string_push_str, strlen, style, subsec_micros, @@ -369,6 +585,7 @@ macro_rules! generate { tcx, then, then_some, + thread_local_macro, to_ascii_lowercase, to_ascii_uppercase, to_be_bytes, @@ -378,8 +595,11 @@ macro_rules! generate { to_ne_bytes, to_os_string, to_owned, + to_owned_method, to_path_buf, + to_string_method, to_uppercase, + todo_macro, tokio, trim, trim_end, @@ -389,6 +609,8 @@ macro_rules! generate { truncate, try_fold, try_for_each, + try_from_fn, + unimplemented_macro, unreachable_pub, unsafe_removed_from_name, unused, @@ -403,6 +625,15 @@ macro_rules! generate { unwrap_unchecked, unzip, utils, + vec_as_mut_slice, + vec_as_slice, + vec_from_elem, + vec_is_empty, + vec_macro, + vec_new, + vec_pop, + vec_with_capacity, + vecdeque_iter, visit_str, visit_string, wake, diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 639492b75747..a46b906f5024 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -25,7 +25,7 @@ TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; -use rustc_span::{DUMMY_SP, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::{Obligation, ObligationCause}; @@ -38,6 +38,7 @@ use crate::paths::{PathNS, lookup_path_str}; use crate::res::{MaybeDef, MaybeQPath}; +use crate::sym; mod type_certainty; pub use type_certainty::expr_type_is_certain; diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs index e27f1dabeefa..4a1d24024915 100644 --- a/clippy_utils/src/usage.rs +++ b/clippy_utils/src/usage.rs @@ -1,7 +1,7 @@ use crate::macros::root_macro_call_first_node; use crate::res::MaybeResPath; use crate::visitors::{Descend, Visitable, for_each_expr, for_each_expr_without_closures}; -use crate::{self as utils, get_enclosing_loop_or_multi_call_closure}; +use crate::{self as utils, get_enclosing_loop_or_multi_call_closure, sym}; use core::ops::ControlFlow; use hir::def::Res; use rustc_hir::intravisit::{self, Visitor}; @@ -11,7 +11,6 @@ use rustc_middle::hir::nested_filter; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty; -use rustc_span::sym; /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined. pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> Option { From a81565667cffff4e48b946abb5316d7e498262be Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 20 Feb 2026 03:56:31 -0500 Subject: [PATCH 05/38] fix: handle core panics in all format lints `core::panic` was missing in the formatting arg lints --- clippy_utils/src/macros.rs | 1 + tests/ui/uninlined_format_args.fixed | 21 ++++ tests/ui/uninlined_format_args.rs | 21 ++++ ...nlined_format_args_panic.edition2018.fixed | 34 +++++- ...lined_format_args_panic.edition2018.stderr | 2 +- ...nlined_format_args_panic.edition2021.fixed | 34 +++++- ...lined_format_args_panic.edition2021.stderr | 50 ++++++-- ...nlined_format_args_panic.edition2024.fixed | 70 +++++++++++ ...lined_format_args_panic.edition2024.stderr | 112 ++++++++++++++++++ tests/ui/uninlined_format_args_panic.rs | 34 +++++- 10 files changed, 368 insertions(+), 11 deletions(-) create mode 100644 tests/ui/uninlined_format_args_panic.edition2024.fixed create mode 100644 tests/ui/uninlined_format_args_panic.edition2024.stderr diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 4e06f010bd59..95fd42894684 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -19,6 +19,7 @@ sym::assert_eq_macro, sym::assert_macro, sym::assert_ne_macro, + sym::core_panic_macro, sym::debug_assert_eq_macro, sym::debug_assert_macro, sym::debug_assert_ne_macro, diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index 7b609d9163a9..ddb9b1d30338 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -363,3 +363,24 @@ fn user_format() { usr_println!(true, "{local_f64:.1}"); //~^ uninlined_format_args } + +// issue #16411: false negative when #[clippy::format_args] macro uses nested format_args +// without binding the inner args first +#[clippy::format_args] +macro_rules! nested_format_args { + ($($arg:tt)*) => {{ + // Wraps the user args in another format_args call + ::core::format_args!("{}\n", ::core::format_args!($($arg)*)) + }}; +} + +fn nested_format_args_user() { + let local_i32 = 1; + let local_f64 = 2.0; + + // false negative: should warn but currently doesn't because the inner format_args + // is not processed when it's used as an argument to another format_args + nested_format_args!("{}", local_i32); + nested_format_args!("val='{}'", local_i32); + nested_format_args!("{:.1}", local_f64); +} diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index 14e0b6caabc0..7dae77bbadc6 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -368,3 +368,24 @@ fn user_format() { usr_println!(true, "{:.1}", local_f64); //~^ uninlined_format_args } + +// issue #16411: false negative when #[clippy::format_args] macro uses nested format_args +// without binding the inner args first +#[clippy::format_args] +macro_rules! nested_format_args { + ($($arg:tt)*) => {{ + // Wraps the user args in another format_args call + ::core::format_args!("{}\n", ::core::format_args!($($arg)*)) + }}; +} + +fn nested_format_args_user() { + let local_i32 = 1; + let local_f64 = 2.0; + + // false negative: should warn but currently doesn't because the inner format_args + // is not processed when it's used as an argument to another format_args + nested_format_args!("{}", local_i32); + nested_format_args!("val='{}'", local_i32); + nested_format_args!("{:.1}", local_f64); +} diff --git a/tests/ui/uninlined_format_args_panic.edition2018.fixed b/tests/ui/uninlined_format_args_panic.edition2018.fixed index 3710036c0589..6d0f76eaf252 100644 --- a/tests/ui/uninlined_format_args_panic.edition2018.fixed +++ b/tests/ui/uninlined_format_args_panic.edition2018.fixed @@ -1,6 +1,7 @@ -//@revisions: edition2018 edition2021 +//@revisions: edition2018 edition2021 edition2024 //@[edition2018] edition:2018 //@[edition2021] edition:2021 +//@[edition2024] edition:2024 #![warn(clippy::uninlined_format_args)] #![allow(clippy::literal_string_with_formatting_args)] @@ -14,14 +15,17 @@ fn main() { if var > 0 { panic!("p1 {}", var); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args } if var > 0 { panic!("p2 {0}", var); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args } if var > 0 { panic!("p3 {var}", var = var); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args } #[allow(non_fmt_panics)] @@ -33,6 +37,34 @@ fn main() { assert!(var == 1, "p5 {}", var); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args debug_assert!(var == 1, "p6 {}", var); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + + // core::panic! with format string containing text: should warn on 2021+ (issue #16411) + if var > 0 { + core::panic!("p7 {}", var); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + if var > 0 { + core::panic!("p8 {0}", var); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + if var > 0 { + core::panic!("p9 {var}", var = var); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + + // std::panic! and core::panic! with only "{}" format string: false negative due to + // panic_display special case in panic_2021 macro - no format_args node is created + if var > 0 { + std::panic!("{}", var); + } + if var > 0 { + core::panic!("{}", var); + } } diff --git a/tests/ui/uninlined_format_args_panic.edition2018.stderr b/tests/ui/uninlined_format_args_panic.edition2018.stderr index 4b154abac5bc..24afb3d35abe 100644 --- a/tests/ui/uninlined_format_args_panic.edition2018.stderr +++ b/tests/ui/uninlined_format_args_panic.edition2018.stderr @@ -1,5 +1,5 @@ error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:11:5 + --> tests/ui/uninlined_format_args_panic.rs:12:5 | LL | println!("val='{}'", var); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/uninlined_format_args_panic.edition2021.fixed b/tests/ui/uninlined_format_args_panic.edition2021.fixed index 8a754d313806..ba741bfcd09d 100644 --- a/tests/ui/uninlined_format_args_panic.edition2021.fixed +++ b/tests/ui/uninlined_format_args_panic.edition2021.fixed @@ -1,6 +1,7 @@ -//@revisions: edition2018 edition2021 +//@revisions: edition2018 edition2021 edition2024 //@[edition2018] edition:2018 //@[edition2021] edition:2021 +//@[edition2024] edition:2024 #![warn(clippy::uninlined_format_args)] #![allow(clippy::literal_string_with_formatting_args)] @@ -14,14 +15,17 @@ fn main() { if var > 0 { panic!("p1 {var}"); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args } if var > 0 { panic!("p2 {var}"); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args } if var > 0 { panic!("p3 {var}"); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args } #[allow(non_fmt_panics)] @@ -33,6 +37,34 @@ fn main() { assert!(var == 1, "p5 {var}"); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args debug_assert!(var == 1, "p6 {var}"); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + + // core::panic! with format string containing text: should warn on 2021+ (issue #16411) + if var > 0 { + core::panic!("p7 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + if var > 0 { + core::panic!("p8 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + if var > 0 { + core::panic!("p9 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + + // std::panic! and core::panic! with only "{}" format string: false negative due to + // panic_display special case in panic_2021 macro - no format_args node is created + if var > 0 { + std::panic!("{}", var); + } + if var > 0 { + core::panic!("{}", var); + } } diff --git a/tests/ui/uninlined_format_args_panic.edition2021.stderr b/tests/ui/uninlined_format_args_panic.edition2021.stderr index 4db6e6a99312..dcf6747e2d64 100644 --- a/tests/ui/uninlined_format_args_panic.edition2021.stderr +++ b/tests/ui/uninlined_format_args_panic.edition2021.stderr @@ -1,5 +1,5 @@ error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:11:5 + --> tests/ui/uninlined_format_args_panic.rs:12:5 | LL | println!("val='{}'", var); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + println!("val='{var}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:15:9 + --> tests/ui/uninlined_format_args_panic.rs:16:9 | LL | panic!("p1 {}", var); | ^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + panic!("p1 {var}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:19:9 + --> tests/ui/uninlined_format_args_panic.rs:21:9 | LL | panic!("p2 {0}", var); | ^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + panic!("p2 {var}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:23:9 + --> tests/ui/uninlined_format_args_panic.rs:26:9 | LL | panic!("p3 {var}", var = var); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + panic!("p3 {var}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:34:5 + --> tests/ui/uninlined_format_args_panic.rs:38:5 | LL | assert!(var == 1, "p5 {}", var); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + assert!(var == 1, "p5 {var}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:36:5 + --> tests/ui/uninlined_format_args_panic.rs:41:5 | LL | debug_assert!(var == 1, "p6 {}", var); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,5 +72,41 @@ LL - debug_assert!(var == 1, "p6 {}", var); LL + debug_assert!(var == 1, "p6 {var}"); | -error: aborting due to 6 previous errors +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:47:9 + | +LL | core::panic!("p7 {}", var); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - core::panic!("p7 {}", var); +LL + core::panic!("p7 {var}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:52:9 + | +LL | core::panic!("p8 {0}", var); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - core::panic!("p8 {0}", var); +LL + core::panic!("p8 {var}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:57:9 + | +LL | core::panic!("p9 {var}", var = var); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - core::panic!("p9 {var}", var = var); +LL + core::panic!("p9 {var}"); + | + +error: aborting due to 9 previous errors diff --git a/tests/ui/uninlined_format_args_panic.edition2024.fixed b/tests/ui/uninlined_format_args_panic.edition2024.fixed new file mode 100644 index 000000000000..ba741bfcd09d --- /dev/null +++ b/tests/ui/uninlined_format_args_panic.edition2024.fixed @@ -0,0 +1,70 @@ +//@revisions: edition2018 edition2021 edition2024 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 + +#![warn(clippy::uninlined_format_args)] +#![allow(clippy::literal_string_with_formatting_args)] + +fn main() { + let var = 1; + + println!("val='{var}'"); + //~^ uninlined_format_args + + if var > 0 { + panic!("p1 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + if var > 0 { + panic!("p2 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + if var > 0 { + panic!("p3 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + + #[allow(non_fmt_panics)] + { + if var > 0 { + panic!("p4 {var}"); + } + } + + assert!(var == 1, "p5 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + debug_assert!(var == 1, "p6 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + + // core::panic! with format string containing text: should warn on 2021+ (issue #16411) + if var > 0 { + core::panic!("p7 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + if var > 0 { + core::panic!("p8 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + if var > 0 { + core::panic!("p9 {var}"); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + + // std::panic! and core::panic! with only "{}" format string: false negative due to + // panic_display special case in panic_2021 macro - no format_args node is created + if var > 0 { + std::panic!("{}", var); + } + if var > 0 { + core::panic!("{}", var); + } +} diff --git a/tests/ui/uninlined_format_args_panic.edition2024.stderr b/tests/ui/uninlined_format_args_panic.edition2024.stderr new file mode 100644 index 000000000000..dcf6747e2d64 --- /dev/null +++ b/tests/ui/uninlined_format_args_panic.edition2024.stderr @@ -0,0 +1,112 @@ +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:12:5 + | +LL | println!("val='{}'", var); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::uninlined-format-args` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::uninlined_format_args)]` +help: change this to + | +LL - println!("val='{}'", var); +LL + println!("val='{var}'"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:16:9 + | +LL | panic!("p1 {}", var); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - panic!("p1 {}", var); +LL + panic!("p1 {var}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:21:9 + | +LL | panic!("p2 {0}", var); + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - panic!("p2 {0}", var); +LL + panic!("p2 {var}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:26:9 + | +LL | panic!("p3 {var}", var = var); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - panic!("p3 {var}", var = var); +LL + panic!("p3 {var}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:38:5 + | +LL | assert!(var == 1, "p5 {}", var); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - assert!(var == 1, "p5 {}", var); +LL + assert!(var == 1, "p5 {var}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:41:5 + | +LL | debug_assert!(var == 1, "p6 {}", var); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - debug_assert!(var == 1, "p6 {}", var); +LL + debug_assert!(var == 1, "p6 {var}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:47:9 + | +LL | core::panic!("p7 {}", var); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - core::panic!("p7 {}", var); +LL + core::panic!("p7 {var}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:52:9 + | +LL | core::panic!("p8 {0}", var); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - core::panic!("p8 {0}", var); +LL + core::panic!("p8 {var}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args_panic.rs:57:9 + | +LL | core::panic!("p9 {var}", var = var); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - core::panic!("p9 {var}", var = var); +LL + core::panic!("p9 {var}"); + | + +error: aborting due to 9 previous errors + diff --git a/tests/ui/uninlined_format_args_panic.rs b/tests/ui/uninlined_format_args_panic.rs index 94de4f057e99..7ee17d8fb16e 100644 --- a/tests/ui/uninlined_format_args_panic.rs +++ b/tests/ui/uninlined_format_args_panic.rs @@ -1,6 +1,7 @@ -//@revisions: edition2018 edition2021 +//@revisions: edition2018 edition2021 edition2024 //@[edition2018] edition:2018 //@[edition2021] edition:2021 +//@[edition2024] edition:2024 #![warn(clippy::uninlined_format_args)] #![allow(clippy::literal_string_with_formatting_args)] @@ -14,14 +15,17 @@ fn main() { if var > 0 { panic!("p1 {}", var); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args } if var > 0 { panic!("p2 {0}", var); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args } if var > 0 { panic!("p3 {var}", var = var); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args } #[allow(non_fmt_panics)] @@ -33,6 +37,34 @@ fn main() { assert!(var == 1, "p5 {}", var); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args debug_assert!(var == 1, "p6 {}", var); //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + + // core::panic! with format string containing text: should warn on 2021+ (issue #16411) + if var > 0 { + core::panic!("p7 {}", var); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + if var > 0 { + core::panic!("p8 {0}", var); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + if var > 0 { + core::panic!("p9 {var}", var = var); + //~[edition2021]^ uninlined_format_args + //~[edition2024]^^ uninlined_format_args + } + + // std::panic! and core::panic! with only "{}" format string: false negative due to + // panic_display special case in panic_2021 macro - no format_args node is created + if var > 0 { + std::panic!("{}", var); + } + if var > 0 { + core::panic!("{}", var); + } } From 87b3f55b16011d5f85895373c6bead55b5810f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Wed, 18 Feb 2026 14:28:07 +0100 Subject: [PATCH 06/38] fix src/tools --- clippy_lints/src/attrs/inline_always.rs | 4 ++-- clippy_lints/src/attrs/repr_attributes.rs | 4 ++-- clippy_lints/src/cognitive_complexity.rs | 1 + .../src/default_union_representation.rs | 4 ++-- clippy_lints/src/eta_reduction.rs | 5 ++--- clippy_lints/src/exhaustive_items.rs | 3 +-- clippy_lints/src/format_args.rs | 6 +----- clippy_lints/src/functions/must_use.rs | 14 +++++-------- clippy_lints/src/incompatible_msrv.rs | 10 +++------ clippy_lints/src/inline_fn_without_body.rs | 3 +-- clippy_lints/src/loops/empty_loop.rs | 3 +-- clippy_lints/src/macro_metavars_in_unsafe.rs | 4 +--- clippy_lints/src/macro_use.rs | 5 ++--- clippy_lints/src/manual_non_exhaustive.rs | 5 ++--- clippy_lints/src/matches/match_wild_enum.rs | 2 +- .../matches/significant_drop_in_scrutinee.rs | 1 + clippy_lints/src/methods/is_empty.rs | 3 +-- clippy_lints/src/missing_inline.rs | 3 +-- clippy_lints/src/pass_by_ref_or_value.rs | 4 ++-- clippy_lints/src/return_self_not_must_use.rs | 3 +-- .../src/significant_drop_tightening.rs | 1 + clippy_utils/src/attrs.rs | 8 +++---- clippy_utils/src/lib.rs | 21 ++++++++++--------- clippy_utils/src/macros.rs | 8 ++++++- clippy_utils/src/ty/mod.rs | 12 ++++------- 25 files changed, 59 insertions(+), 78 deletions(-) diff --git a/clippy_lints/src/attrs/inline_always.rs b/clippy_lints/src/attrs/inline_always.rs index fb86ae8da9d6..c0b14c2a4b66 100644 --- a/clippy_lints/src/attrs/inline_always.rs +++ b/clippy_lints/src/attrs/inline_always.rs @@ -1,6 +1,6 @@ use super::INLINE_ALWAYS; use clippy_utils::diagnostics::span_lint; -use rustc_hir::attrs::{AttributeKind, InlineAttr}; +use rustc_hir::attrs::InlineAttr; use rustc_hir::{Attribute, find_attr}; use rustc_lint::LateContext; use rustc_span::Span; @@ -11,7 +11,7 @@ pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Att return; } - if let Some(span) = find_attr!(attrs, AttributeKind::Inline(InlineAttr::Always, span) => *span) { + if let Some(span) = find_attr!(attrs, Inline(InlineAttr::Always, span) => *span) { span_lint( cx, INLINE_ALWAYS, diff --git a/clippy_lints/src/attrs/repr_attributes.rs b/clippy_lints/src/attrs/repr_attributes.rs index 8a530e8cff2e..2a3e4b96b1cd 100644 --- a/clippy_lints/src/attrs/repr_attributes.rs +++ b/clippy_lints/src/attrs/repr_attributes.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::{AttributeKind, ReprAttr}; +use rustc_hir::attrs::ReprAttr; use rustc_hir::{Attribute, find_attr}; use rustc_lint::LateContext; use rustc_span::Span; @@ -9,7 +9,7 @@ use super::REPR_PACKED_WITHOUT_ABI; pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute], msrv: Msrv) { - if let Some(reprs) = find_attr!(attrs, AttributeKind::Repr { reprs, .. } => reprs) { + if let Some(reprs) = find_attr!(attrs, Repr { reprs, .. } => reprs) { let packed_span = reprs .iter() .find(|(r, _)| matches!(r, ReprAttr::ReprPacked(..))) diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index 595625c08bef..dfc1ca107feb 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -146,6 +146,7 @@ fn check_fn( span: Span, def_id: LocalDefId, ) { + #[allow(deprecated)] if !cx.tcx.has_attr(def_id, sym::test) { let expr = if kind.asyncness().is_async() { match get_async_fn_body(cx.tcx, body) { diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs index df6525ce040e..c1005688a921 100644 --- a/clippy_lints/src/default_union_representation.rs +++ b/clippy_lints/src/default_union_representation.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use rustc_hir::attrs::{AttributeKind, ReprAttr}; +use rustc_hir::attrs::ReprAttr; use rustc_hir::{HirId, Item, ItemKind, find_attr}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; @@ -99,5 +99,5 @@ fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: ty::GenericArgsR fn has_c_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { let attrs = cx.tcx.hir_attrs(hir_id); - find_attr!(attrs, AttributeKind::Repr { reprs, .. } if reprs.iter().any(|(x, _)| *x == ReprAttr::ReprC)) + find_attr!(attrs, Repr { reprs, .. } if reprs.iter().any(|(x, _)| *x == ReprAttr::ReprC)) } diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 3e46c370fb70..bb94a111f7a1 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -6,7 +6,6 @@ use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate}; use rustc_abi::ExternAbi; use rustc_errors::Applicability; -use rustc_hir::attrs::AttributeKind; use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind, find_attr}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; @@ -154,7 +153,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx let sig = match callee_ty_adjusted.kind() { ty::FnDef(def, _) => { // Rewriting `x(|| f())` to `x(f)` where f is marked `#[track_caller]` moves the `Location` - if find_attr!(cx.tcx.get_all_attrs(*def), AttributeKind::TrackCaller(..)) { + if find_attr!(cx.tcx, *def, TrackCaller(..)) { return; } @@ -262,7 +261,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx }, ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => { if let Some(method_def_id) = typeck.type_dependent_def_id(body.value.hir_id) - && !find_attr!(cx.tcx.get_all_attrs(method_def_id), AttributeKind::TrackCaller(..)) + && !find_attr!(cx.tcx, method_def_id, TrackCaller(..)) && check_sig(closure_sig, cx.tcx.fn_sig(method_def_id).skip_binder().skip_binder()) { let mut app = Applicability::MachineApplicable; diff --git a/clippy_lints/src/exhaustive_items.rs b/clippy_lints/src/exhaustive_items.rs index ac61ce705eb7..13c8f2d2059a 100644 --- a/clippy_lints/src/exhaustive_items.rs +++ b/clippy_lints/src/exhaustive_items.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::indent_of; use rustc_errors::Applicability; -use rustc_hir::attrs::AttributeKind; use rustc_hir::{Item, ItemKind, find_attr}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -85,7 +84,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { }; if cx.effective_visibilities.is_exported(item.owner_id.def_id) && let attrs = cx.tcx.hir_attrs(item.hir_id()) - && !find_attr!(attrs, AttributeKind::NonExhaustive(..)) + && !find_attr!(attrs, NonExhaustive(..)) && fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public()) { span_lint_and_then(cx, lint, item.span, msg, |diag| { diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 5fb1a0b80f1a..774c88233af6 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -21,7 +21,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::{Expr, ExprKind, LangItem, RustcVersion, find_attr}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; @@ -662,10 +661,7 @@ fn has_pointer_debug(&mut self, ty: Ty<'tcx>, depth: usize) -> bool { }; let selection = SelectionContext::new(&infcx).select(&obligation); let derived = if let Ok(Some(Selection::UserDefined(data))) = selection { - find_attr!( - tcx.get_all_attrs(data.impl_def_id), - AttributeKind::AutomaticallyDerived(..) - ) + find_attr!(tcx, data.impl_def_id, AutomaticallyDerived(..)) } else { false }; diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index 9ad36f778904..b9f16f2a371a 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -2,7 +2,7 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefIdSet; -use rustc_hir::{self as hir, Attribute, QPath}; +use rustc_hir::{self as hir, Attribute, QPath, find_attr}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::{self, Ty}; @@ -14,8 +14,6 @@ use clippy_utils::ty::is_must_use_ty; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{is_entrypoint_fn, return_ty, trait_ref_of_method}; -use rustc_hir::attrs::AttributeKind; -use rustc_hir::find_attr; use rustc_span::Symbol; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -25,7 +23,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { let attrs = cx.tcx.hir_attrs(item.hir_id()); - let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason)); + let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), MustUse { span, reason } => (span, reason)); if let hir::ItemKind::Fn { ref sig, body: ref body_id, @@ -47,7 +45,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> attrs, sig, ); - } else if is_public && !is_proc_macro(attrs) && !find_attr!(attrs, AttributeKind::NoMangle(..)) { + } else if is_public && !is_proc_macro(attrs) && !find_attr!(attrs, NoMangle(..)) { check_must_use_candidate( cx, sig.decl, @@ -66,8 +64,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir_attrs(item.hir_id()); - let attr = - find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason)); + let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), MustUse { span, reason } => (span, reason)); if let Some((attr_span, reason)) = attr { check_needless_must_use( cx, @@ -100,8 +97,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir_attrs(item.hir_id()); - let attr = - find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason)); + let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), MustUse { span, reason } => (span, reason)); if let Some((attr_span, reason)) = attr { check_needless_must_use( cx, diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index 8d538ff1acba..6ef3459f222c 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -3,7 +3,6 @@ use clippy_utils::msrvs::Msrv; use clippy_utils::{is_in_const_context, is_in_test, sym}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::attrs::AttributeKind; use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, RustcVersion, StabilityLevel, StableSince, find_attr}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, TyCtxt}; @@ -268,10 +267,7 @@ fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &'tcx hir::Ty<'tcx, Ambig /// Heuristic checking if the node `hir_id` is under a `#[cfg()]` or `#[cfg_attr()]` /// attribute. fn is_under_cfg_attribute(cx: &LateContext<'_>, hir_id: HirId) -> bool { - cx.tcx.hir_parent_id_iter(hir_id).any(|id| { - find_attr!( - cx.tcx.hir_attrs(id), - AttributeKind::CfgTrace(..) | AttributeKind::CfgAttrTrace - ) - }) + cx.tcx + .hir_parent_id_iter(hir_id) + .any(|id| find_attr!(cx.tcx.hir_attrs(id), CfgTrace(..) | CfgAttrTrace)) } diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index e416ac079d6f..2da13b57aec4 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg::DiagExt; use rustc_errors::Applicability; -use rustc_hir::attrs::AttributeKind; use rustc_hir::{TraitFn, TraitItem, TraitItemKind, find_attr}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -35,7 +34,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_> && let Some(attr_span) = find_attr!(cx .tcx .hir_attrs(item.hir_id()), - AttributeKind::Inline(_, span) => *span + Inline(_, span) => *span ) { span_lint_and_then( diff --git a/clippy_lints/src/loops/empty_loop.rs b/clippy_lints/src/loops/empty_loop.rs index 0a5b26bfa689..f2b2b77c3496 100644 --- a/clippy_lints/src/loops/empty_loop.rs +++ b/clippy_lints/src/loops/empty_loop.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::{is_in_panic_handler, is_no_std_crate}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::{Block, Expr, ItemKind, Node, find_attr}; use rustc_lint::LateContext; @@ -11,7 +10,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, loop_block: &Block<'_ if let Node::Item(parent_node) = cx.tcx.hir_node(parent_hir_id) && matches!(parent_node.kind, ItemKind::Fn { .. }) && let attrs = cx.tcx.hir_attrs(parent_hir_id) - && find_attr!(attrs, AttributeKind::RustcIntrinsic) + && find_attr!(attrs, RustcIntrinsic) { // Intrinsic functions are expanded into an empty loop when lowering the AST // to simplify the job of later passes which might expect any function to have a body. diff --git a/clippy_lints/src/macro_metavars_in_unsafe.rs b/clippy_lints/src/macro_metavars_in_unsafe.rs index a323c7cf8307..db1ed269bb0e 100644 --- a/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::is_lint_allowed; use itertools::Itertools; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt}; use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource, find_attr}; @@ -147,8 +146,7 @@ struct BodyVisitor<'a, 'tcx> { } fn is_public_macro(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { - (cx.effective_visibilities.is_exported(def_id) - || find_attr!(cx.tcx.get_all_attrs(def_id), AttributeKind::MacroExport { .. })) + (cx.effective_visibilities.is_exported(def_id) || find_attr!(cx.tcx, def_id, MacroExport { .. })) && !cx.tcx.is_doc_hidden(def_id) } diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 8989793625aa..005a04002cf3 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; -use hir::def::{DefKind, Res}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::attrs::AttributeKind; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::{self as hir, AmbigArg, find_attr}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; @@ -100,7 +99,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { && let hir::ItemKind::Use(path, _kind) = &item.kind && let hir_id = item.hir_id() && let attrs = cx.tcx.hir_attrs(hir_id) - && let Some(mac_attr_span) = find_attr!(attrs, AttributeKind::MacroUse {span, ..} => *span) + && let Some(mac_attr_span) = find_attr!(attrs, MacroUse {span, ..} => *span) && let Some(Res::Def(DefKind::Mod, id)) = path.res.type_ns && !id.is_local() { diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index 0d783fde3313..8e09d88232f6 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -6,7 +6,6 @@ use itertools::Itertools; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData, find_attr}; use rustc_lint::{LateContext, LateLintPass}; @@ -93,7 +92,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { .then_some((v.def_id, v.span)) }); if let Ok((id, span)) = iter.exactly_one() - && !find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::NonExhaustive(..)) + && !find_attr!(cx.tcx.hir_attrs(item.hir_id()), NonExhaustive(..)) { self.potential_enums.push((item.owner_id.def_id, id, item.span, span)); } @@ -114,7 +113,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { "this seems like a manual implementation of the non-exhaustive pattern", |diag| { if let Some(non_exhaustive_span) = - find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::NonExhaustive(span) => *span) + find_attr!(cx.tcx.hir_attrs(item.hir_id()), NonExhaustive(span) => *span) { diag.span_note(non_exhaustive_span, "the struct is already non-exhaustive"); } else { diff --git a/clippy_lints/src/matches/match_wild_enum.rs b/clippy_lints/src/matches/match_wild_enum.rs index 00bd1c2ca698..768d0e8e268c 100644 --- a/clippy_lints/src/matches/match_wild_enum.rs +++ b/clippy_lints/src/matches/match_wild_enum.rs @@ -208,5 +208,5 @@ fn with_prefix(&mut self, path: &'a [PathSegment<'a>]) { } fn is_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool { - cx.tcx.is_doc_hidden(variant_def.def_id) || cx.tcx.has_attr(variant_def.def_id, sym::unstable) + cx.tcx.is_doc_hidden(variant_def.def_id) } diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 14d265bfdad8..4267cd118552 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -185,6 +185,7 @@ fn has_sig_drop_attr_impl(&mut self, ty: Ty<'tcx>) -> bool { if let Some(adt) = ty.ty_adt_def() && get_builtin_attr( self.cx.sess(), + #[allow(deprecated)] self.cx.tcx.get_all_attrs(adt.did()), sym::has_significant_drop, ) diff --git a/clippy_lints/src/methods/is_empty.rs b/clippy_lints/src/methods/is_empty.rs index 8135c67d0d78..4577be34d4a7 100644 --- a/clippy_lints/src/methods/is_empty.rs +++ b/clippy_lints/src/methods/is_empty.rs @@ -3,7 +3,6 @@ use clippy_utils::macros::{is_assert_macro, root_macro_call}; use clippy_utils::res::MaybeResPath; use clippy_utils::{find_binding_init, get_parent_expr, is_inside_always_const_context}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::{Expr, HirId, find_attr}; use rustc_lint::{LateContext, LintContext}; @@ -40,7 +39,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_ fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool { cx.tcx .hir_parent_id_iter(id) - .any(|id| find_attr!(cx.tcx.hir_attrs(id), AttributeKind::CfgTrace(..))) + .any(|id| find_attr!(cx.tcx.hir_attrs(id), CfgTrace(..))) } /// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index c308f2a34585..0dd531d36742 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -1,5 +1,4 @@ use clippy_utils::diagnostics::{span_lint, span_lint_hir}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, Attribute, find_attr}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -72,7 +71,7 @@ fn check_missing_inline_attrs( desc: &'static str, hir_id: Option, ) { - if !find_attr!(attrs, AttributeKind::Inline(..)) { + if !find_attr!(attrs, Inline(..)) { let msg = format!("missing `#[inline]` for {desc}"); if let Some(hir_id) = hir_id { span_lint_hir(cx, MISSING_INLINE_IN_PUBLIC_ITEMS, hir_id, sp, msg); diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 6e9142b22e0e..666476cb4bac 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::{AttributeKind, InlineAttr}; +use rustc_hir::attrs::InlineAttr; use rustc_hir::intravisit::FnKind; use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind, find_attr}; use rustc_lint::{LateContext, LateLintPass}; @@ -270,7 +270,7 @@ fn check_fn( return; } let attrs = cx.tcx.hir_attrs(hir_id); - if find_attr!(attrs, AttributeKind::Inline(InlineAttr::Always, _)) { + if find_attr!(attrs, Inline(InlineAttr::Always, _)) { return; } diff --git a/clippy_lints/src/return_self_not_must_use.rs b/clippy_lints/src/return_self_not_must_use.rs index 83a226b29e75..78f5167fa543 100644 --- a/clippy_lints/src/return_self_not_must_use.rs +++ b/clippy_lints/src/return_self_not_must_use.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::is_must_use_ty; use clippy_utils::{nth_arg, return_ty}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind, find_attr}; @@ -77,7 +76,7 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa // We don't want to emit this lint if the `#[must_use]` attribute is already there. && !find_attr!( cx.tcx.hir_attrs(owner_id.into()), - AttributeKind::MustUse { .. } + MustUse { .. } ) && cx.tcx.visibility(fn_def.to_def_id()).is_public() && let ret_ty = return_ty(cx, owner_id) diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index c2c1778882d3..3e77c98b8845 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -171,6 +171,7 @@ fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>, depth: usize) -> bool { if let Some(adt) = ty.ty_adt_def() { let mut iter = get_builtin_attr( self.cx.sess(), + #[allow(deprecated)] self.cx.tcx.get_all_attrs(adt.did()), sym::has_significant_drop, ); diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index 56490cfc8b65..6e7434771369 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -4,7 +4,6 @@ use crate::{sym, tokenize_with_text}; use rustc_ast::attr::AttributeExt; use rustc_errors::Applicability; -use rustc_hir::attrs::AttributeKind; use rustc_hir::find_attr; use rustc_lexer::TokenKind; use rustc_lint::LateContext; @@ -95,14 +94,13 @@ pub fn is_doc_hidden(attrs: &[impl AttributeExt]) -> bool { /// Checks whether the given ADT, or any of its fields/variants, are marked as `#[non_exhaustive]` pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool { adt.is_variant_list_non_exhaustive() - || find_attr!(tcx.get_all_attrs(adt.did()), AttributeKind::NonExhaustive(..)) + || find_attr!(tcx, adt.did(), NonExhaustive(..)) || adt.variants().iter().any(|variant_def| { - variant_def.is_field_list_non_exhaustive() - || find_attr!(tcx.get_all_attrs(variant_def.def_id), AttributeKind::NonExhaustive(..)) + variant_def.is_field_list_non_exhaustive() || find_attr!(tcx, variant_def.def_id, NonExhaustive(..)) }) || adt .all_fields() - .any(|field_def| find_attr!(tcx.get_all_attrs(field_def.did), AttributeKind::NonExhaustive(..))) + .any(|field_def| find_attr!(tcx, field_def.did, NonExhaustive(..))) } /// Checks whether the given span contains a `#[cfg(..)]` attribute diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index d8b2b22dd09d..9a49845d9d46 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -89,7 +89,7 @@ use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnindexMap; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; -use rustc_hir::attrs::{AttributeKind, CfgEntry}; +use rustc_hir::attrs::CfgEntry; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::definitions::{DefPath, DefPathData}; @@ -1691,7 +1691,7 @@ pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool { } pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { - find_attr!(cx.tcx.hir_attrs(hir_id), AttributeKind::Repr { .. }) + find_attr!(cx.tcx.hir_attrs(hir_id), Repr { .. }) } pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool { @@ -1716,7 +1716,7 @@ pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool { .any(|(id, _)| { find_attr!( tcx.hir_attrs(tcx.local_def_id_to_hir_id(id.def_id)), - AttributeKind::AutomaticallyDerived(..) + AutomaticallyDerived(..) ) }) } @@ -1807,7 +1807,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { _ => None, }; - did.is_some_and(|did| find_attr!(cx.tcx.get_all_attrs(did), AttributeKind::MustUse { .. })) + did.is_some_and(|did| find_attr!(cx.tcx, did, MustUse { .. })) } /// Checks if a function's body represents the identity function. Looks for bodies of the form: @@ -2034,11 +2034,11 @@ pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { } pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool { - find_attr!(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), AttributeKind::NoStd(..)) + find_attr!(cx.tcx, crate, NoStd(..)) } pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool { - find_attr!(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), AttributeKind::NoCore(..)) + find_attr!(cx.tcx, crate, NoCore(..)) } /// Check if parent of a hir node is a trait implementation block. @@ -2318,6 +2318,7 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind && let Res::Def(_, def_id) = path.res { + #[allow(deprecated)] return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr); } false @@ -2343,7 +2344,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl FnOnce(& // We could also check for the type name `test::TestDescAndFn` && let Res::Def(DefKind::Struct, _) = path.res { - if find_attr!(tcx.hir_attrs(item.hir_id()), AttributeKind::RustcTestMarker(..)) { + if find_attr!(tcx.hir_attrs(item.hir_id()), RustcTestMarker(..)) { names.push(ident.name); } } @@ -2401,7 +2402,7 @@ pub fn is_test_function(tcx: TyCtxt<'_>, fn_def_id: LocalDefId) -> bool { /// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent /// use [`is_in_cfg_test`] pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { - if let Some(cfgs) = find_attr!(tcx.hir_attrs(id), AttributeKind::CfgTrace(cfgs) => cfgs) + if let Some(cfgs) = find_attr!(tcx.hir_attrs(id), CfgTrace(cfgs) => cfgs) && cfgs .iter() .any(|(cfg, _)| matches!(cfg, CfgEntry::NameValue { name: sym::test, .. })) @@ -2424,11 +2425,11 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool { /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied. pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - find_attr!(tcx.get_all_attrs(def_id), AttributeKind::CfgTrace(..)) + find_attr!(tcx, def_id, CfgTrace(..)) || find_attr!( tcx.hir_parent_iter(tcx.local_def_id_to_hir_id(def_id)) .flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id)), - AttributeKind::CfgTrace(..) + CfgTrace(..) ) } diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 4e06f010bd59..3cfe648fdf32 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -42,7 +42,13 @@ pub fn is_format_macro(cx: &LateContext<'_>, macro_def_id: DefId) -> bool { } else { // Allow users to tag any macro as being format!-like // TODO: consider deleting FORMAT_MACRO_DIAG_ITEMS and using just this method - get_unique_builtin_attr(cx.sess(), cx.tcx.get_all_attrs(macro_def_id), sym::format_args).is_some() + get_unique_builtin_attr( + cx.sess(), + #[allow(deprecated)] + cx.tcx.get_all_attrs(macro_def_id), + sym::format_args, + ) + .is_some() } } diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 639492b75747..66b044e485f5 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -7,7 +7,6 @@ use rustc_ast::ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, FnDecl, LangItem, find_attr}; @@ -311,8 +310,8 @@ pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { // Returns whether the type has #[must_use] attribute pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { - ty::Adt(adt, _) => find_attr!(cx.tcx.get_all_attrs(adt.did()), AttributeKind::MustUse { .. }), - ty::Foreign(did) => find_attr!(cx.tcx.get_all_attrs(*did), AttributeKind::MustUse { .. }), + ty::Adt(adt, _) => find_attr!(cx.tcx, adt.did(), MustUse { .. }), + ty::Foreign(did) => find_attr!(cx.tcx, *did, MustUse { .. }), ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => { // for the Array case we don't need to care for the len == 0 case // because we don't want to lint functions returning empty arrays @@ -322,10 +321,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => { for (predicate, _) in cx.tcx.explicit_item_self_bounds(def_id).skip_binder() { if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() - && find_attr!( - cx.tcx.get_all_attrs(trait_predicate.trait_ref.def_id), - AttributeKind::MustUse { .. } - ) + && find_attr!(cx.tcx, trait_predicate.trait_ref.def_id, MustUse { .. }) { return true; } @@ -335,7 +331,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { ty::Dynamic(binder, _) => { for predicate in *binder { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() - && find_attr!(cx.tcx.get_all_attrs(trait_ref.def_id), AttributeKind::MustUse { .. }) + && find_attr!(cx.tcx, trait_ref.def_id, MustUse { .. }) { return true; } From 180e4a7155c019e50a5c375ba9c33e71b1dd644d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Feb 2026 10:59:44 +1100 Subject: [PATCH 07/38] Remove `impl IntoQueryParam

for &'a P`. `IntoQueryParam` is a trait that lets query callers be a bit sloppy with the passed-in key. - Types similar to `DefId` will be auto-converted to `DefId`. Likewise for `LocalDefId`. - Reference types will be auto-derefed. The auto-conversion is genuinely useful; the auto-derefing much less so. In practice it's only used for passing `&DefId` to queries that accept `DefId`, which is an anti-pattern because `DefId` is marked with `#[rustc_pass_by_value]`. This commit removes the auto-deref impl and makes the necessary sigil adjustments. (I generally avoid using `*` to deref manually at call sites, preferring to deref via `&` in patterns or via `*` in match expressions. Mostly because that way a single deref often covers multiple call sites.) --- clippy_lints/src/eta_reduction.rs | 6 +++--- clippy_lints/src/methods/or_fun_call.rs | 4 ++-- clippy_lints/src/operators/identity_op.rs | 2 +- clippy_lints/src/unconditional_recursion.rs | 4 ++-- clippy_utils/src/lib.rs | 4 ++-- clippy_utils/src/paths.rs | 2 +- clippy_utils/src/ty/mod.rs | 8 ++++---- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index bb94a111f7a1..20cf3796c8be 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -150,16 +150,16 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx let callee_ty_adjustments = typeck.expr_adjustments(callee); let callee_ty_adjusted = callee_ty_adjustments.last().map_or(callee_ty, |a| a.target); - let sig = match callee_ty_adjusted.kind() { + let sig = match *callee_ty_adjusted.kind() { ty::FnDef(def, _) => { // Rewriting `x(|| f())` to `x(f)` where f is marked `#[track_caller]` moves the `Location` - if find_attr!(cx.tcx, *def, TrackCaller(..)) { + if find_attr!(cx.tcx, def, TrackCaller(..)) { return; } cx.tcx.fn_sig(def).skip_binder().skip_binder() }, - ty::FnPtr(sig_tys, hdr) => sig_tys.with(*hdr).skip_binder(), + ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr).skip_binder(), ty::Closure(_, subs) => cx .tcx .signature_unclosure(subs.as_closure().sig(), Safety::Safe) diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs index aed4a0075c2f..832197d36cc6 100644 --- a/clippy_lints/src/methods/or_fun_call.rs +++ b/clippy_lints/src/methods/or_fun_call.rs @@ -133,7 +133,7 @@ fn check_unwrap_or_default( let output_type_implements_default = |fun| { let fun_ty = cx.typeck_results().expr_ty(fun); - if let ty::FnDef(def_id, args) = fun_ty.kind() { + if let ty::FnDef(def_id, args) = *fun_ty.kind() { let output_ty = cx.tcx.fn_sig(def_id).instantiate(cx.tcx, args).skip_binder().output(); cx.tcx .get_diagnostic_item(sym::Default) @@ -153,7 +153,7 @@ fn check_unwrap_or_default( cx.tcx .inherent_impls(adt_def.did()) .iter() - .flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg)) + .flat_map(|&impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg)) .find_map(|assoc| { if assoc.is_method() && cx.tcx.fn_sig(assoc.def_id).skip_binder().inputs().skip_binder().len() == 1 { Some(assoc.def_id) diff --git a/clippy_lints/src/operators/identity_op.rs b/clippy_lints/src/operators/identity_op.rs index 43c62e1e131a..92515bd3fb80 100644 --- a/clippy_lints/src/operators/identity_op.rs +++ b/clippy_lints/src/operators/identity_op.rs @@ -287,7 +287,7 @@ fn is_assoc_fn_without_type_instance<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<' .. }, )) = func.kind - && let output_ty = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder().output() + && let output_ty = cx.tcx.fn_sig(*def_id).instantiate_identity().skip_binder().output() && let ty::Param(ty::ParamTy { name: kw::SelfUpper, .. }) = output_ty.kind() diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs index c1e03b7e8c70..1b7d7fd6c68c 100644 --- a/clippy_lints/src/unconditional_recursion.rs +++ b/clippy_lints/src/unconditional_recursion.rs @@ -335,8 +335,8 @@ fn init_default_impl_for_type_if_needed(&mut self, cx: &LateContext<'_>) { let impls = cx.tcx.trait_impls_of(default_trait_id); for (ty, impl_def_ids) in impls.non_blanket_impls() { let Some(self_def_id) = ty.def() else { continue }; - for impl_def_id in impl_def_ids { - if !cx.tcx.is_automatically_derived(*impl_def_id) && + for &impl_def_id in impl_def_ids { + if !cx.tcx.is_automatically_derived(impl_def_id) && let Some(assoc_item) = cx .tcx .associated_items(impl_def_id) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 9a49845d9d46..fdd270c2774a 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -601,9 +601,9 @@ pub fn is_default_equivalent_call( && let StatementKind::Assign(assign) = &block_data.statements[0].kind && assign.0.local == RETURN_PLACE && let Rvalue::Aggregate(kind, _places) = &assign.1 - && let AggregateKind::Adt(did, variant_index, _, _, _) = &**kind + && let AggregateKind::Adt(did, variant_index, _, _, _) = **kind && let def = cx.tcx.adt_def(did) - && let variant = &def.variant(*variant_index) + && let variant = &def.variant(variant_index) && variant.fields.is_empty() && let Some((_, did)) = variant.ctor && did == repl_def_id diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 8aa663163caf..e6593aa8b554 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -335,7 +335,7 @@ fn non_local_item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, ns: PathNS, name .associated_item_def_ids(def_id) .iter() .copied() - .find(|assoc_def_id| tcx.item_name(*assoc_def_id) == name && ns.matches(tcx.def_kind(assoc_def_id).ns())), + .find(|&assoc_def_id| tcx.item_name(assoc_def_id) == name && ns.matches(tcx.def_kind(assoc_def_id).ns())), _ => None, } } diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 3e1ad6c0ef51..36410a81fbf6 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -310,13 +310,13 @@ pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { // Returns whether the type has #[must_use] attribute pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.kind() { + match *ty.kind() { ty::Adt(adt, _) => find_attr!(cx.tcx, adt.did(), MustUse { .. }), - ty::Foreign(did) => find_attr!(cx.tcx, *did, MustUse { .. }), + ty::Foreign(did) => find_attr!(cx.tcx, did, MustUse { .. }), ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => { // for the Array case we don't need to care for the len == 0 case // because we don't want to lint functions returning empty arrays - is_must_use_ty(cx, *ty) + is_must_use_ty(cx, ty) }, ty::Tuple(args) => args.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => { @@ -330,7 +330,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { false }, ty::Dynamic(binder, _) => { - for predicate in *binder { + for predicate in binder { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() && find_attr!(cx.tcx, trait_ref.def_id, MustUse { .. }) { From 9d8302c50c34ae83bfd02e287279be8571eaf027 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 22 Feb 2026 21:44:01 +0100 Subject: [PATCH 08/38] Add automatic creation of FCP Zulip topics with triagebot --- triagebot.toml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index eb8442ab21e2..21784ee88c02 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -60,6 +60,26 @@ labels = ["S-waiting-on-concerns"] [view-all-comments-link] threshold = 20 +[notify-zulip."lint-nominated"] +zulip_stream = 257328 # #clippy +topic = "FCP rust-clippy#{number}: {title}" +# Zulip polls may not be preceded by any other text and pings & short links inside +# the title of a poll don't get recognized. Therefore we need to send two messages. +message_on_add = [ + """\ +PR rust-clippy#{number} "{title}" has been nominated for lint inclusion. +""", + """\ +/poll Approve lint inclusion of rust-clippy#{number}? +approve +decline +don't know +""", +] +message_on_remove = "PR rust-clippy#{number} lint nomination has been removed." +message_on_close = "PR rust-clippy#{number} has been closed. Thanks for participating!" +message_on_reopen = "PR rust-clippy#{number} has been reopened." + [assign] contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md" users_on_vacation = [ From feadf6021b48dcd256fe394fecfa68d618e09abb Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 23 Feb 2026 12:08:27 +0900 Subject: [PATCH 09/38] Set default PR messages to fail the changelog CI --- .github/workflows/clippy_changelog.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/clippy_changelog.yml b/.github/workflows/clippy_changelog.yml index 4d84d6b6dae4..121e1b84543f 100644 --- a/.github/workflows/clippy_changelog.yml +++ b/.github/workflows/clippy_changelog.yml @@ -20,7 +20,8 @@ jobs: - name: Check Changelog if: ${{ github.event_name == 'pull_request' }} run: | - if [[ -z $(grep -oP 'changelog: *\K\S+' <<< "$PR_BODY") ]]; then + # Checks that the PR body contains a changelog entry, ignoring the placeholder from the PR template. + if [[ -z $(grep -oP 'changelog: *\K(?!\[`lint_name`\])\S+' <<< "$PR_BODY") ]]; then echo "::error::Pull request message must contain 'changelog: ...' with your changelog. Please add it." exit 1 fi From faf9506169ecb8cb0b358f531278e359adfd84e8 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Mon, 23 Feb 2026 21:33:59 +0000 Subject: [PATCH 10/38] fix: `suboptimal_flops` FN on add and sub assign --- .../src/floating_point_arithmetic/mul_add.rs | 159 +++++++++++------- tests/ui/floating_point_mul_add.fixed | 12 ++ tests/ui/floating_point_mul_add.rs | 12 ++ tests/ui/floating_point_mul_add.stderr | 14 +- 4 files changed, 132 insertions(+), 65 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic/mul_add.rs b/clippy_lints/src/floating_point_arithmetic/mul_add.rs index 03a9d3b05f88..e0a6498f62fd 100644 --- a/clippy_lints/src/floating_point_arithmetic/mul_add.rs +++ b/clippy_lints/src/floating_point_arithmetic/mul_add.rs @@ -1,6 +1,7 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg::Sugg; use clippy_utils::{get_parent_expr, has_ambiguous_literal_in_expr, sym}; +use rustc_ast::AssignOpKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; use rustc_lint::LateContext; @@ -26,69 +27,99 @@ fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&' } pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::Binary( - Spanned { - node: op @ (BinOpKind::Add | BinOpKind::Sub), - .. - }, - lhs, - rhs, - ) = &expr.kind + let (is_assign, op, lhs, rhs) = match &expr.kind { + ExprKind::AssignOp( + Spanned { + node: AssignOpKind::AddAssign, + .. + }, + lhs, + rhs, + ) => (true, BinOpKind::Add, lhs, rhs), + ExprKind::AssignOp( + Spanned { + node: AssignOpKind::SubAssign, + .. + }, + lhs, + rhs, + ) => (true, BinOpKind::Sub, lhs, rhs), + ExprKind::Binary( + Spanned { + node: op @ (BinOpKind::Add | BinOpKind::Sub), + .. + }, + lhs, + rhs, + ) => (false, *op, lhs, rhs), + _ => return, + }; + + if !is_assign + && let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::MethodCall(PathSegment { ident: method, .. }, receiver, ..) = parent.kind + && method.name == sym::sqrt + // we don't care about the applicability as this is an early-return condition + && super::hypot::detect(cx, receiver, &mut Applicability::Unspecified).is_some() { - if let Some(parent) = get_parent_expr(cx, expr) - && let ExprKind::MethodCall(PathSegment { ident: method, .. }, receiver, ..) = parent.kind - && method.name == sym::sqrt - // we don't care about the applicability as this is an early-return condition - && super::hypot::detect(cx, receiver, &mut Applicability::Unspecified).is_some() - { - return; - } - - let maybe_neg_sugg = |expr, app: &mut _| { - let sugg = Sugg::hir_with_applicability(cx, expr, "_", app); - if let BinOpKind::Sub = op { -sugg } else { sugg } - }; - - let mut app = Applicability::MachineApplicable; - let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) - && cx.typeck_results().expr_ty(rhs).is_floating_point() - { - ( - inner_lhs, - Sugg::hir_with_applicability(cx, inner_rhs, "_", &mut app), - maybe_neg_sugg(rhs, &mut app), - ) - } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) - && cx.typeck_results().expr_ty(lhs).is_floating_point() - { - ( - inner_lhs, - maybe_neg_sugg(inner_rhs, &mut app), - Sugg::hir_with_applicability(cx, lhs, "_", &mut app), - ) - } else { - return; - }; - - // Check if any variable in the expression has an ambiguous type (could be f32 or f64) - // see: https://github.com/rust-lang/rust-clippy/issues/14897 - if (matches!(recv.kind, ExprKind::Path(_)) || matches!(recv.kind, ExprKind::Call(_, _))) - && has_ambiguous_literal_in_expr(cx, recv) - { - return; - } - - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "multiply and add expressions can be calculated more efficiently and accurately", - "consider using", - format!( - "{}.mul_add({arg1}, {arg2})", - super::lib::prepare_receiver_sugg(cx, recv, &mut app) - ), - app, - ); + return; } + + // Check if any variable in the expression has an ambiguous type (could be f32 or f64) + // see: https://github.com/rust-lang/rust-clippy/issues/14897 + let has_ambiguous_type = |expr: &Expr<'_>| { + (matches!(expr.kind, ExprKind::Path(_)) || matches!(expr.kind, ExprKind::Call(_, _))) + && has_ambiguous_literal_in_expr(cx, expr) + }; + + let (recv, arg1, arg2, is_from_rhs) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) + && cx.typeck_results().expr_ty(lhs).is_floating_point() + && !has_ambiguous_type(inner_lhs) + { + (inner_lhs, inner_rhs, lhs, true) + } else if !is_assign + && let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) + && cx.typeck_results().expr_ty(rhs).is_floating_point() + && !has_ambiguous_type(inner_lhs) + { + (inner_lhs, inner_rhs, rhs, false) + } else { + return; + }; + + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "multiply and add expressions can be calculated more efficiently and accurately", + |diag| { + let maybe_neg_sugg = |expr, app: &mut _| { + let sugg = Sugg::hir_with_applicability(cx, expr, "_", app); + if let BinOpKind::Sub = op { -sugg } else { sugg } + }; + let mut app = Applicability::MachineApplicable; + let recv_sugg = super::lib::prepare_receiver_sugg(cx, recv, &mut app); + let (arg1, arg2) = if is_from_rhs { + ( + maybe_neg_sugg(arg1, &mut app), + Sugg::hir_with_applicability(cx, arg2, "_", &mut app), + ) + } else { + ( + Sugg::hir_with_applicability(cx, arg1, "_", &mut app), + maybe_neg_sugg(arg2, &mut app), + ) + }; + diag.span_suggestion( + expr.span, + "consider using", + if is_assign { + format!("{arg2} = {recv_sugg}.mul_add({arg1}, {arg2})") + } else { + format!("{recv_sugg}.mul_add({arg1}, {arg2})") + }, + app, + ); + }, + ); } diff --git a/tests/ui/floating_point_mul_add.fixed b/tests/ui/floating_point_mul_add.fixed index 884bae004320..a4841d309d56 100644 --- a/tests/ui/floating_point_mul_add.fixed +++ b/tests/ui/floating_point_mul_add.fixed @@ -113,3 +113,15 @@ fn _issue14897() { let _ = 1.0f64.mul_add(2.0, 0.5); //~^ suboptimal_flops } + +fn issue16573() { + let mut a = 3.0_f32; + let b = 4.0_f32; + let c = 7.0_f32; + + a = b.mul_add(c, a); + //~^ suboptimal_flops + + a = b.mul_add(-c, a); + //~^ suboptimal_flops +} diff --git a/tests/ui/floating_point_mul_add.rs b/tests/ui/floating_point_mul_add.rs index 9ceb2ec96062..c048653a4123 100644 --- a/tests/ui/floating_point_mul_add.rs +++ b/tests/ui/floating_point_mul_add.rs @@ -113,3 +113,15 @@ fn _issue14897() { let _ = 1.0 * 2.0 + 0.5; //~^ suboptimal_flops } + +fn issue16573() { + let mut a = 3.0_f32; + let b = 4.0_f32; + let c = 7.0_f32; + + a += b * c; + //~^ suboptimal_flops + + a -= b * c; + //~^ suboptimal_flops +} diff --git a/tests/ui/floating_point_mul_add.stderr b/tests/ui/floating_point_mul_add.stderr index dad65ddf2ec3..3f2ca76826f4 100644 --- a/tests/ui/floating_point_mul_add.stderr +++ b/tests/ui/floating_point_mul_add.stderr @@ -109,5 +109,17 @@ error: multiply and add expressions can be calculated more efficiently and accur LL | let _ = 1.0 * 2.0 + 0.5; | ^^^^^^^^^^^^^^^ help: consider using: `1.0f64.mul_add(2.0, 0.5)` -error: aborting due to 18 previous errors +error: multiply and add expressions can be calculated more efficiently and accurately + --> tests/ui/floating_point_mul_add.rs:122:5 + | +LL | a += b * c; + | ^^^^^^^^^^ help: consider using: `a = b.mul_add(c, a)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> tests/ui/floating_point_mul_add.rs:125:5 + | +LL | a -= b * c; + | ^^^^^^^^^^ help: consider using: `a = b.mul_add(-c, a)` + +error: aborting due to 20 previous errors From 94554413c09f0cd761fc974c85313af0c4b3e8c2 Mon Sep 17 00:00:00 2001 From: Jacob Adam Date: Tue, 24 Feb 2026 01:15:40 +0100 Subject: [PATCH 11/38] Fix the compile-test tests when setting Cargo's `build.build-dir` setting to a path that's distinct from `target-dir` In this approach, we're using the `CARGO_BIN_EXE_clippy-driver` env var, which is set to the appropriate absolute path, invariant across the various possible `target-dir` and `build.build-dir` configurations. Do the same for `CARGO_CLIPPY_PATH` in tests/test_utils/mod.rs. --- tests/compile-test.rs | 9 +-------- tests/test_utils/mod.rs | 7 +------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index a92bb8f5ca73..c5af6d2d27c4 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -197,9 +197,6 @@ fn base_config(&self, test_dir: &str, mandatory_annotations: bool) -> Config { defaults.set_custom("diagnostic-collector", collector); } config.with_args(&self.args); - let current_exe_path = env::current_exe().unwrap(); - let deps_path = current_exe_path.parent().unwrap(); - let profile_path = deps_path.parent().unwrap(); config.program.args.extend( [ @@ -224,11 +221,7 @@ fn base_config(&self, test_dir: &str, mandatory_annotations: bool) -> Config { config.program.args.push(format!("--sysroot={sysroot}").into()); } - config.program.program = profile_path.join(if cfg!(windows) { - "clippy-driver.exe" - } else { - "clippy-driver" - }); + config.program.program = PathBuf::from(env!("CARGO_BIN_EXE_clippy-driver")); config } diff --git a/tests/test_utils/mod.rs b/tests/test_utils/mod.rs index ea8c54e08b33..9099f91693a7 100644 --- a/tests/test_utils/mod.rs +++ b/tests/test_utils/mod.rs @@ -3,11 +3,6 @@ use std::path::PathBuf; use std::sync::LazyLock; -pub static CARGO_CLIPPY_PATH: LazyLock = LazyLock::new(|| { - let mut path = std::env::current_exe().unwrap(); - assert!(path.pop()); // deps - path.set_file_name("cargo-clippy"); - path -}); +pub static CARGO_CLIPPY_PATH: LazyLock = LazyLock::new(|| PathBuf::from(env!("CARGO_BIN_EXE_cargo-clippy"))); pub const IS_RUSTC_TEST_SUITE: bool = option_env!("RUSTC_TEST_SUITE").is_some(); From 088022c7d49ab6b7df64e7c6fdc4e85cd5e8ecae Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Tue, 24 Feb 2026 12:00:51 +0100 Subject: [PATCH 12/38] Merge commit 'df995ede1b3e61f0e87081d9548e6cd2a3ec9095' into clippy-subtree-update --- CHANGELOG.md | 9 + book/src/configuration.md | 6 +- .../infrastructure/changelog_update.md | 6 +- book/src/lint_configuration.md | 34 ++ clippy_config/src/conf.rs | 20 + clippy_dev/src/edit_lints.rs | 216 +++++------ clippy_dev/src/lib.rs | 1 + clippy_dev/src/new_lint.rs | 18 +- clippy_dev/src/parse.rs | 159 ++++++-- clippy_dev/src/update_lints.rs | 137 +++---- .../src/assertions_on_result_states.rs | 4 +- clippy_lints/src/attrs/deprecated_semver.rs | 3 +- clippy_lints/src/borrow_deref_ref.rs | 15 +- clippy_lints/src/cargo/common_metadata.rs | 2 +- clippy_lints/src/casts/unnecessary_cast.rs | 47 +-- clippy_lints/src/cognitive_complexity.rs | 6 +- clippy_lints/src/collapsible_if.rs | 4 +- clippy_lints/src/declared_lints.rs | 32 +- clippy_lints/src/disallowed_fields.rs | 160 ++++++++ clippy_lints/src/doc/mod.rs | 16 +- clippy_lints/src/double_parens.rs | 74 ++-- clippy_lints/src/format_args.rs | 56 ++- clippy_lints/src/functions/must_use.rs | 8 + clippy_lints/src/infinite_iter.rs | 6 +- clippy_lints/src/lib.rs | 2 + .../src/loops/explicit_counter_loop.rs | 85 +++-- clippy_lints/src/loops/utils.rs | 24 +- clippy_lints/src/macro_metavars_in_unsafe.rs | 4 +- clippy_lints/src/manual_let_else.rs | 9 +- clippy_lints/src/manual_option_as_slice.rs | 39 +- clippy_lints/src/manual_strip.rs | 21 +- clippy_lints/src/map_unit_fn.rs | 16 +- clippy_lints/src/matches/collapsible_match.rs | 76 +++- .../src/matches/match_single_binding.rs | 6 +- clippy_lints/src/methods/clone_on_ref_ptr.rs | 20 +- clippy_lints/src/methods/iter_kv_map.rs | 3 +- .../src/methods/iter_overeager_cloned.rs | 39 +- .../src/methods/join_absolute_paths.rs | 8 +- .../src/methods/manual_is_variant_and.rs | 40 ++ clippy_lints/src/methods/mod.rs | 40 +- clippy_lints/src/methods/or_fun_call.rs | 8 +- .../src/methods/unnecessary_filter_map.rs | 14 +- clippy_lints/src/methods/unnecessary_fold.rs | 33 +- .../src/methods/unnecessary_min_or_max.rs | 12 +- .../src/methods/unnecessary_to_owned.rs | 15 +- .../src/methods/unwrap_expect_used.rs | 55 +++ clippy_lints/src/missing_assert_message.rs | 4 +- .../src/mixed_read_write_in_expression.rs | 18 +- .../src/multiple_unsafe_ops_per_block.rs | 6 +- clippy_lints/src/mutable_debug_assertion.rs | 54 +-- clippy_lints/src/needless_maybe_sized.rs | 3 + .../src/non_send_fields_in_send_ty.rs | 24 +- clippy_lints/src/operators/bit_mask.rs | 16 +- clippy_lints/src/operators/identity_op.rs | 16 +- clippy_lints/src/operators/manual_div_ceil.rs | 11 +- clippy_lints/src/operators/mod.rs | 4 +- clippy_lints/src/question_mark.rs | 3 +- .../src/redundant_static_lifetimes.rs | 30 +- clippy_lints/src/std_instead_of_core.rs | 9 +- clippy_lints/src/strings.rs | 46 ++- clippy_lints/src/time_subtraction.rs | 70 +++- clippy_lints/src/useless_conversion.rs | 6 +- clippy_utils/README.md | 2 +- clippy_utils/src/ast_utils/mod.rs | 4 +- clippy_utils/src/check_proc_macro.rs | 47 ++- clippy_utils/src/diagnostics.rs | 41 +-- clippy_utils/src/lib.rs | 32 +- clippy_utils/src/macros.rs | 67 ++-- clippy_utils/src/msrvs.rs | 10 +- clippy_utils/src/paths.rs | 40 ++ clippy_utils/src/sugg.rs | 30 ++ clippy_utils/src/sym.rs | 3 + clippy_utils/src/ty/mod.rs | 40 +- rust-toolchain.toml | 2 +- src/driver.rs | 1 + tests/compile-test.rs | 2 +- tests/missing-test-files.rs | 6 +- .../await_holding_invalid_type.rs | 7 +- tests/ui-toml/expect_used/expect_used.rs | 4 - tests/ui-toml/expect_used/expect_used.stderr | 8 +- .../lint_decimal_readability/test.fixed | 2 - .../ui-toml/lint_decimal_readability/test.rs | 2 - .../lint_decimal_readability/test.stderr | 4 +- .../index_refutable_slice.fixed | 5 +- .../index_refutable_slice.rs | 5 +- .../min_rust_version/min_rust_version.fixed | 10 +- .../min_rust_version/min_rust_version.rs | 10 +- tests/ui-toml/mut_key/mut_key.rs | 5 +- .../toml_disallowed_fields/clippy.toml | 14 + .../conf_disallowed_fields.rs | 50 +++ .../conf_disallowed_fields.stderr | 61 ++++ .../toml_unknown_key/conf_unknown_key.stderr | 6 + tests/ui-toml/unwrap_used_allowed/clippy.toml | 1 + .../unwrap_used_allowed.rs | 20 + .../unwrap_used_allowed.stderr | 22 ++ tests/ui/attrs.rs | 13 +- tests/ui/borrow_deref_ref.fixed | 24 ++ tests/ui/borrow_deref_ref.rs | 24 ++ tests/ui/clone_on_ref_ptr.fixed | 29 +- tests/ui/clone_on_ref_ptr.rs | 27 +- tests/ui/clone_on_ref_ptr.stderr | 42 ++- tests/ui/cmp_owned/with_suggestion.fixed | 10 +- tests/ui/cmp_owned/with_suggestion.rs | 10 +- tests/ui/cmp_owned/with_suggestion.stderr | 4 +- tests/ui/collapsible_match_fixable.fixed | 30 ++ tests/ui/collapsible_match_fixable.rs | 31 ++ tests/ui/collapsible_match_fixable.stderr | 50 +++ tests/ui/crashes/ice-10912.rs | 2 +- tests/ui/crashes/ice-6250.fixed | 19 + tests/ui/crashes/ice-6250.rs | 3 +- tests/ui/crashes/ice-6250.stderr | 4 +- tests/ui/crashes/ice-9041.fixed | 12 + tests/ui/crashes/ice-9041.rs | 4 +- tests/ui/crashes/ice-9041.stderr | 2 +- tests/ui/crashes/returns.rs | 5 +- tests/ui/debug_assert_with_mut_call.rs | 10 +- tests/ui/doc/doc-fixable.fixed | 4 - tests/ui/doc/doc-fixable.rs | 4 - tests/ui/doc/doc-fixable.stderr | 40 +- tests/ui/doc_link_with_quotes.rs | 4 +- tests/ui/doc_link_with_quotes.stderr | 4 +- tests/ui/double_must_use.rs | 32 +- tests/ui/double_must_use.stderr | 26 +- tests/ui/drop_non_drop.rs | 9 + tests/ui/drop_non_drop.stderr | 22 +- tests/ui/duplicate_underscore_argument.rs | 5 +- tests/ui/duration_suboptimal_units.fixed | 11 + tests/ui/duration_suboptimal_units.rs | 11 + tests/ui/duration_suboptimal_units.stderr | 14 +- tests/ui/erasing_op.rs | 4 +- tests/ui/eta.fixed | 9 + tests/ui/eta.rs | 9 + tests/ui/eta.stderr | 8 +- tests/ui/expect.rs | 6 +- tests/ui/explicit_counter_loop.rs | 20 +- tests/ui/explicit_counter_loop.stderr | 20 +- tests/ui/floating_point_abs.fixed | 16 +- tests/ui/floating_point_abs.rs | 16 +- tests/ui/four_forward_slashes_bare_cr.rs | 1 - tests/ui/four_forward_slashes_bare_cr.stderr | 2 +- tests/ui/infinite_iter.rs | 5 +- tests/ui/infinite_iter.stderr | 2 +- tests/ui/ip_constant_from_external.rs | 4 +- tests/ui/iter_kv_map.fixed | 38 +- tests/ui/iter_kv_map.rs | 38 +- tests/ui/iter_kv_map.stderr | 300 ++++++++------- tests/ui/iter_on_empty_collections.fixed | 6 +- tests/ui/iter_on_empty_collections.rs | 6 +- tests/ui/iter_on_single_items.fixed | 6 +- tests/ui/iter_on_single_items.rs | 6 +- tests/ui/iter_overeager_cloned.fixed | 60 +++ tests/ui/iter_overeager_cloned.rs | 61 ++++ tests/ui/iter_overeager_cloned.stderr | 44 ++- tests/ui/iter_with_drain.fixed | 7 +- tests/ui/iter_with_drain.rs | 7 +- tests/ui/join_absolute_paths.1.fixed | 36 ++ tests/ui/join_absolute_paths.2.fixed | 36 ++ tests/ui/join_absolute_paths.rs | 18 +- tests/ui/join_absolute_paths.stderr | 80 ++-- tests/ui/len_without_is_empty_expect.rs | 1 - tests/ui/len_without_is_empty_expect.stderr | 2 +- tests/ui/let_if_seq.rs | 5 - tests/ui/let_if_seq.stderr | 12 +- tests/ui/let_underscore_future.rs | 2 +- tests/ui/let_underscore_must_use.rs | 10 + tests/ui/let_underscore_must_use.stderr | 10 +- tests/ui/manual_is_variant_and.fixed | 22 +- tests/ui/manual_is_variant_and.rs | 22 +- tests/ui/manual_is_variant_and.stderr | 80 ++-- tests/ui/manual_let_else.rs | 18 + tests/ui/manual_let_else.stderr | 38 +- .../ui/manual_memcpy/with_loop_counters.fixed | 55 +++ tests/ui/manual_memcpy/with_loop_counters.rs | 3 +- .../manual_memcpy/with_loop_counters.stderr | 22 +- .../manual_memcpy/without_loop_counters.fixed | 175 +++++++++ .../ui/manual_memcpy/without_loop_counters.rs | 4 +- tests/ui/manual_option_as_slice.fixed | 5 +- tests/ui/manual_option_as_slice.rs | 5 +- tests/ui/manual_retain.fixed | 17 +- tests/ui/manual_retain.rs | 17 +- tests/ui/manual_retain.stderr | 76 ++-- tests/ui/manual_take.fixed | 2 - tests/ui/manual_take.rs | 2 - tests/ui/manual_take.stderr | 4 +- tests/ui/map_flatten.fixed | 67 ++++ tests/ui/map_flatten.rs | 8 +- tests/ui/map_unwrap_or.rs | 5 +- tests/ui/map_unwrap_or.stderr | 8 +- tests/ui/map_unwrap_or_fixable.fixed | 5 +- tests/ui/map_unwrap_or_fixable.rs | 5 +- tests/ui/map_unwrap_or_fixable.stderr | 18 +- tests/ui/mem_replace.fixed | 6 +- tests/ui/mem_replace.rs | 6 +- tests/ui/mem_replace.stderr | 18 +- tests/ui/mem_replace_no_std.fixed | 6 +- tests/ui/mem_replace_no_std.rs | 6 +- tests/ui/mem_replace_no_std.stderr | 6 +- tests/ui/methods.rs | 7 +- tests/ui/methods_unfixable.rs | 4 +- tests/ui/methods_unfixable.stderr | 4 +- ...missing_assert_message.edition2015.stderr} | 32 +- .../missing_assert_message.edition2021.stderr | 132 +++++++ tests/ui/missing_assert_message.rs | 5 +- .../mixed_attributes_style/mod_declaration.rs | 2 +- tests/ui/must_use_candidates.fixed | 12 + tests/ui/must_use_candidates.rs | 10 + tests/ui/must_use_candidates.stderr | 28 +- tests/ui/must_use_unit.fixed | 16 +- tests/ui/must_use_unit.rs | 16 +- tests/ui/needless_collect_indirect.fixed | 344 ++++++++++++++++++ tests/ui/needless_collect_indirect.rs | 10 +- tests/ui/needless_collect_indirect.stderr | 32 +- tests/ui/needless_doc_main.rs | 5 +- tests/ui/needless_maybe_sized.fixed | 9 + tests/ui/needless_maybe_sized.rs | 9 + tests/ui/never_loop.rs | 17 +- tests/ui/never_loop.stderr | 22 +- tests/ui/panicking_macros.rs | 13 +- tests/ui/panicking_overflow_checks.rs | 4 +- tests/ui/println_empty_string.fixed | 2 +- tests/ui/println_empty_string.rs | 2 +- tests/ui/regex.rs | 6 +- tests/ui/result_map_unit_fn_fixable.stderr | 36 +- tests/ui/result_map_unit_fn_unfixable.stderr | 12 +- tests/ui/set_contains_or_insert.rs | 8 +- tests/ui/set_contains_or_insert.stderr | 2 +- tests/ui/should_impl_trait/method_list_2.rs | 2 +- tests/ui/skip_while_next.rs | 4 +- tests/ui/slow_vector_initialization.fixed | 8 +- tests/ui/slow_vector_initialization.rs | 8 +- tests/ui/slow_vector_initialization.stderr | 26 +- tests/ui/std_instead_of_core_unfixable.rs | 2 - tests/ui/std_instead_of_core_unfixable.stderr | 6 +- tests/ui/str_to_string.fixed | 25 +- tests/ui/str_to_string.rs | 25 +- tests/ui/str_to_string.stderr | 44 +-- tests/ui/string_add.rs | 2 +- tests/ui/track-diagnostics-clippy.fixed | 22 ++ tests/ui/track-diagnostics-clippy.rs | 1 - tests/ui/transmute_null_to_fn.rs | 5 +- tests/ui/transmute_ref_to_ref.fixed | 38 ++ tests/ui/transmute_ref_to_ref.rs | 4 +- tests/ui/transmute_ref_to_ref.stderr | 12 +- tests/ui/transmute_ref_to_ref_no_std.fixed | 30 ++ tests/ui/transmute_ref_to_ref_no_std.rs | 4 +- tests/ui/transmute_ref_to_ref_no_std.stderr | 8 +- tests/ui/transmuting_null.rs | 8 +- tests/ui/try_err.fixed | 23 +- tests/ui/try_err.rs | 23 +- tests/ui/try_err.stderr | 10 +- tests/ui/unchecked_time_subtraction.fixed | 16 +- tests/ui/unchecked_time_subtraction.rs | 14 +- tests/ui/unchecked_time_subtraction.stderr | 24 +- .../unchecked_time_subtraction_unfixable.rs | 9 + ...nchecked_time_subtraction_unfixable.stderr | 26 +- tests/ui/unconditional_recursion.rs | 2 - tests/ui/unconditional_recursion.stderr | 90 ++--- tests/ui/unicode.fixed | 5 +- tests/ui/unicode.rs | 5 +- tests/ui/uninlined_format_args.fixed | 4 +- tests/ui/uninlined_format_args.rs | 4 +- tests/ui/uninlined_format_args.stderr | 10 +- tests/ui/unit_arg.rs | 5 +- tests/ui/unit_arg.stderr | 6 +- tests/ui/unit_arg_fixable.fixed | 4 +- tests/ui/unit_arg_fixable.rs | 4 +- tests/ui/unit_arg_fixable.stderr | 12 +- tests/ui/unnecessary_cast.fixed | 9 +- tests/ui/unnecessary_cast.rs | 7 +- tests/ui/unnecessary_cast.stderr | 72 ++-- tests/ui/unnecessary_fold.fixed | 30 +- tests/ui/unnecessary_fold.rs | 30 +- tests/ui/unnecessary_fold.stderr | 100 +++-- tests/ui/unnecessary_literal_unwrap.fixed | 10 +- tests/ui/unnecessary_literal_unwrap.rs | 10 +- .../unnecessary_literal_unwrap_unfixable.rs | 14 +- tests/ui/unnecessary_min_or_max.fixed | 26 ++ tests/ui/unnecessary_min_or_max.rs | 26 ++ tests/ui/unnecessary_min_or_max.stderr | 50 ++- tests/ui/unnecessary_sort_by.fixed | 6 +- tests/ui/unnecessary_sort_by.rs | 6 +- tests/ui/unnecessary_sort_by.stderr | 20 +- tests/ui/unnecessary_trailing_comma.fixed | 86 +++++ tests/ui/unnecessary_trailing_comma.rs | 86 +++++ tests/ui/unnecessary_trailing_comma.stderr | 119 ++++++ tests/ui/unused_async.rs | 5 +- tests/ui/unused_peekable.rs | 5 +- tests/ui/unused_peekable.stderr | 16 +- tests/ui/useless_asref.fixed | 5 +- tests/ui/useless_asref.rs | 5 +- tests/ui/useless_attribute.fixed | 4 +- tests/ui/useless_attribute.rs | 4 +- tests/ui/useless_conversion.fixed | 46 ++- tests/ui/useless_conversion.rs | 46 ++- tests/ui/useless_conversion.stderr | 157 +++++--- tests/ui/while_immutable_condition.rs | 14 +- 296 files changed, 5060 insertions(+), 2011 deletions(-) create mode 100644 clippy_lints/src/disallowed_fields.rs create mode 100644 tests/ui-toml/toml_disallowed_fields/clippy.toml create mode 100644 tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs create mode 100644 tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.stderr create mode 100644 tests/ui-toml/unwrap_used_allowed/clippy.toml create mode 100644 tests/ui-toml/unwrap_used_allowed/unwrap_used_allowed.rs create mode 100644 tests/ui-toml/unwrap_used_allowed/unwrap_used_allowed.stderr create mode 100644 tests/ui/collapsible_match_fixable.fixed create mode 100644 tests/ui/collapsible_match_fixable.rs create mode 100644 tests/ui/collapsible_match_fixable.stderr create mode 100644 tests/ui/crashes/ice-6250.fixed create mode 100644 tests/ui/crashes/ice-9041.fixed create mode 100644 tests/ui/join_absolute_paths.1.fixed create mode 100644 tests/ui/join_absolute_paths.2.fixed create mode 100644 tests/ui/manual_memcpy/with_loop_counters.fixed create mode 100644 tests/ui/manual_memcpy/without_loop_counters.fixed create mode 100644 tests/ui/map_flatten.fixed rename tests/ui/{missing_assert_message.stderr => missing_assert_message.edition2015.stderr} (81%) create mode 100644 tests/ui/missing_assert_message.edition2021.stderr create mode 100644 tests/ui/needless_collect_indirect.fixed create mode 100644 tests/ui/track-diagnostics-clippy.fixed create mode 100644 tests/ui/transmute_ref_to_ref.fixed create mode 100644 tests/ui/transmute_ref_to_ref_no_std.fixed create mode 100644 tests/ui/unnecessary_trailing_comma.fixed create mode 100644 tests/ui/unnecessary_trailing_comma.rs create mode 100644 tests/ui/unnecessary_trailing_comma.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 795eba1dfeaf..7c798a3c2e5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ document. [92b4b68...master](https://github.com/rust-lang/rust-clippy/compare/92b4b68...master) +### New Lints + +* Added [`unnecessary_trailing_comma`] to `style` (single-line format-like macros only) + [#13965](https://github.com/rust-lang/rust-clippy/issues/13965) + ## Rust 1.93 Current stable, released 2026-01-22 @@ -6433,6 +6438,7 @@ Released 2018-09-13 [`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord [`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq [`derived_hash_with_manual_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derived_hash_with_manual_eq +[`disallowed_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_fields [`disallowed_macros`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros [`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method [`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods @@ -7136,6 +7142,7 @@ Released 2018-09-13 [`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by [`unnecessary_struct_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_struct_initialization [`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned +[`unnecessary_trailing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_trailing_comma [`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap [`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps [`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern @@ -7233,6 +7240,7 @@ Released 2018-09-13 [`allow-renamed-params-for`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-renamed-params-for [`allow-unwrap-in-consts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-consts [`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests +[`allow-unwrap-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-types [`allow-useless-vec-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-useless-vec-in-tests [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles [`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates @@ -7252,6 +7260,7 @@ Released 2018-09-13 [`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items [`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold [`const-literal-digits-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#const-literal-digits-threshold +[`disallowed-fields`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-fields [`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros [`disallowed-methods`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods [`disallowed-names`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-names diff --git a/book/src/configuration.md b/book/src/configuration.md index b13054431898..b270c11ab397 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -2,13 +2,17 @@ > **Note:** The configuration file is unstable and may be deprecated in the future. -Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`, which is searched for in: +Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`, which is searched for starting in the +first defined directory according to the following priority order: 1. The directory specified by the `CLIPPY_CONF_DIR` environment variable, or 2. The directory specified by the [CARGO_MANIFEST_DIR](https://doc.rust-lang.org/cargo/reference/environment-variables.html) environment variable, or 3. The current directory. +If the chosen directory does not contain a configuration file, Clippy will walk up the directory tree, searching each +parent directory until it finds one or reaches the filesystem root. + It contains a basic `variable = value` mapping e.g. ```toml diff --git a/book/src/development/infrastructure/changelog_update.md b/book/src/development/infrastructure/changelog_update.md index 9eb7e7cc9c9e..4652d71a9ea3 100644 --- a/book/src/development/infrastructure/changelog_update.md +++ b/book/src/development/infrastructure/changelog_update.md @@ -28,8 +28,8 @@ bullet points might be helpful: check out the Clippy commit of the current Rust `beta` branch. [Link][rust_beta_tools] * When writing the release notes for the **upcoming beta release**, you need to - check out the Clippy commit of the current Rust `master`. - [Link][rust_master_tools] + check out the Clippy commit of the current Rust `main`. + [Link][rust_main_tools] * When writing the (forgotten) release notes for a **past stable release**, you need to check out the Rust release tag of the stable release. [Link][rust_stable_tools] @@ -112,7 +112,7 @@ written for. If not, update the version to the changelog version. [changelog]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md [forge]: https://forge.rust-lang.org/ -[rust_master_tools]: https://github.com/rust-lang/rust/tree/HEAD/src/tools/clippy +[rust_main_tools]: https://github.com/rust-lang/rust/tree/HEAD/src/tools/clippy [rust_beta_tools]: https://github.com/rust-lang/rust/tree/beta/src/tools/clippy [rust_stable_tools]: https://github.com/rust-lang/rust/releases [`beta-accepted`]: https://github.com/rust-lang/rust-clippy/issues?q=label%3Abeta-accepted+ diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 57ac01828e59..c87f8e9a68de 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -214,6 +214,23 @@ Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` * [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) +## `allow-unwrap-types` +List of types to allow `unwrap()` and `expect()` on. + +#### Example + +```toml +allow-unwrap-types = [ "std::sync::LockResult" ] +``` + +**Default Value:** `[]` + +--- +**Affected lints:** +* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) +* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) + + ## `allow-useless-vec-in-tests` Whether `useless_vec` should ignore test functions or `#[cfg(test)]` @@ -505,6 +522,23 @@ The minimum digits a const float literal must have to supress the `excessive_pre * [`excessive_precision`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision) +## `disallowed-fields` +The list of disallowed fields, written as fully qualified paths. + +**Fields:** +- `path` (required): the fully qualified path to the field that should be disallowed +- `reason` (optional): explanation why this field is disallowed +- `replacement` (optional): suggested alternative method +- `allow-invalid` (optional, `false` by default): when set to `true`, it will ignore this entry + if the path doesn't exist, instead of emitting an error + +**Default Value:** `[]` + +--- +**Affected lints:** +* [`disallowed_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_fields) + + ## `disallowed-macros` The list of disallowed macros, written as fully qualified paths. diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 3f4997a395a8..41099f94b044 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -413,6 +413,15 @@ fn span_from_toml_range(file: &SourceFile, span: Range) -> Span { /// Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` #[lints(unwrap_used)] allow_unwrap_in_tests: bool = false, + /// List of types to allow `unwrap()` and `expect()` on. + /// + /// #### Example + /// + /// ```toml + /// allow-unwrap-types = [ "std::sync::LockResult" ] + /// ``` + #[lints(expect_used, unwrap_used)] + allow_unwrap_types: Vec = Vec::new(), /// Whether `useless_vec` should ignore test functions or `#[cfg(test)]` #[lints(useless_vec)] allow_useless_vec_in_tests: bool = false, @@ -581,6 +590,17 @@ fn span_from_toml_range(file: &SourceFile, span: Range) -> Span { /// Use the Cognitive Complexity lint instead. #[conf_deprecated("Please use `cognitive-complexity-threshold` instead", cognitive_complexity_threshold)] cyclomatic_complexity_threshold: u64 = 25, + /// The list of disallowed fields, written as fully qualified paths. + /// + /// **Fields:** + /// - `path` (required): the fully qualified path to the field that should be disallowed + /// - `reason` (optional): explanation why this field is disallowed + /// - `replacement` (optional): suggested alternative method + /// - `allow-invalid` (optional, `false` by default): when set to `true`, it will ignore this entry + /// if the path doesn't exist, instead of emitting an error + #[disallowed_paths_allow_replacements = true] + #[lints(disallowed_fields)] + disallowed_fields: Vec = Vec::new(), /// The list of disallowed macros, written as fully qualified paths. /// /// **Fields:** diff --git a/clippy_dev/src/edit_lints.rs b/clippy_dev/src/edit_lints.rs index fb1c1458c50c..411bf530b22b 100644 --- a/clippy_dev/src/edit_lints.rs +++ b/clippy_dev/src/edit_lints.rs @@ -1,11 +1,13 @@ use crate::parse::cursor::{self, Capture, Cursor}; -use crate::parse::{DeprecatedLint, Lint, ParseCx, RenamedLint}; +use crate::parse::{ActiveLint, DeprecatedLint, Lint, LintData, LintName, ParseCx, RenamedLint}; use crate::update_lints::generate_lint_files; use crate::utils::{ ErrAction, FileUpdater, UpdateMode, UpdateStatus, Version, delete_dir_if_exists, delete_file_if_exists, expect_action, try_rename_dir, try_rename_file, walk_dir_no_dot_or_target, }; +use core::mem; use rustc_lexer::TokenKind; +use std::collections::hash_map::Entry; use std::ffi::OsString; use std::fs; use std::path::Path; @@ -20,74 +22,51 @@ /// /// If a file path could not read from or written to pub fn deprecate<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, name: &'env str, reason: &'env str) { - let mut lints = cx.find_lint_decls(); - let (mut deprecated_lints, renamed_lints) = cx.read_deprecated_lints(); + let mut data = cx.parse_lint_decls(); - let Some(lint_idx) = lints.iter().position(|l| l.name == name) else { + let Entry::Occupied(mut lint) = data.lints.entry(name) else { eprintln!("error: failed to find lint `{name}`"); return; }; + let Lint::Active(prev_lint) = mem::replace( + lint.get_mut(), + Lint::Deprecated(DeprecatedLint { + reason, + version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), + }), + ) else { + eprintln!("error: `{name}` is already deprecated"); + return; + }; - let prefixed_name = cx.str_buf.with(|buf| { - buf.extend(["clippy::", name]); - cx.arena.alloc_str(buf) - }); - match deprecated_lints.binary_search_by(|x| x.name.cmp(prefixed_name)) { - Ok(_) => { - println!("`{name}` is already deprecated"); - return; - }, - Err(idx) => deprecated_lints.insert( - idx, - DeprecatedLint { - name: prefixed_name, - reason, - version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), - }, - ), - } - - remove_lint_declaration(lint_idx, &mut lints, &mut FileUpdater::default()); - generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); + remove_lint_declaration(name, &prev_lint, &data, &mut FileUpdater::default()); + generate_lint_files(UpdateMode::Change, &data); println!("info: `{name}` has successfully been deprecated"); println!("note: you must run `cargo uitest` to update the test results"); } pub fn uplift<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'env str, new_name: &'env str) { - let mut lints = cx.find_lint_decls(); - let (deprecated_lints, mut renamed_lints) = cx.read_deprecated_lints(); + let mut data = cx.parse_lint_decls(); - let Some(lint_idx) = lints.iter().position(|l| l.name == old_name) else { + update_rename_targets(&mut data, old_name, LintName::new_rustc(new_name)); + + let Entry::Occupied(mut lint) = data.lints.entry(old_name) else { eprintln!("error: failed to find lint `{old_name}`"); return; }; - - let old_name_prefixed = cx.str_buf.with(|buf| { - buf.extend(["clippy::", old_name]); - cx.arena.alloc_str(buf) - }); - for lint in &mut renamed_lints { - if lint.new_name == old_name_prefixed { - lint.new_name = new_name; - } - } - match renamed_lints.binary_search_by(|x| x.old_name.cmp(old_name_prefixed)) { - Ok(_) => { - println!("`{old_name}` is already deprecated"); - return; - }, - Err(idx) => renamed_lints.insert( - idx, - RenamedLint { - old_name: old_name_prefixed, - new_name, - version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), - }, - ), - } + let Lint::Active(prev_lint) = mem::replace( + lint.get_mut(), + Lint::Renamed(RenamedLint { + new_name: LintName::new_rustc(new_name), + version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), + }), + ) else { + eprintln!("error: `{old_name}` is already deprecated"); + return; + }; let mut updater = FileUpdater::default(); - let remove_mod = remove_lint_declaration(lint_idx, &mut lints, &mut updater); + let remove_mod = remove_lint_declaration(old_name, &prev_lint, &data, &mut updater); let mut update_fn = uplift_update_fn(old_name, new_name, remove_mod); for e in walk_dir_no_dot_or_target(".") { let e = expect_action(e, ErrAction::Read, "."); @@ -95,7 +74,7 @@ pub fn uplift<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_nam updater.update_file(e.path(), &mut update_fn); } } - generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); + generate_lint_files(UpdateMode::Change, &data); println!("info: `{old_name}` has successfully been uplifted as `{new_name}`"); println!("note: you must run `cargo uitest` to update the test results"); } @@ -117,79 +96,50 @@ pub fn uplift<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_nam /// * If `old_name` names a deprecated or renamed lint. pub fn rename<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'env str, new_name: &'env str) { let mut updater = FileUpdater::default(); - let mut lints = cx.find_lint_decls(); - let (deprecated_lints, mut renamed_lints) = cx.read_deprecated_lints(); + let mut data = cx.parse_lint_decls(); - let Ok(lint_idx) = lints.binary_search_by(|x| x.name.cmp(old_name)) else { - panic!("could not find lint `{old_name}`"); + update_rename_targets(&mut data, old_name, LintName::new_clippy(new_name)); + + let Entry::Occupied(mut lint) = data.lints.entry(old_name) else { + eprintln!("error: failed to find lint `{old_name}`"); + return; + }; + let Lint::Active(mut prev_lint) = mem::replace( + lint.get_mut(), + Lint::Renamed(RenamedLint { + new_name: LintName::new_clippy(new_name), + version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), + }), + ) else { + eprintln!("error: `{old_name}` is already deprecated"); + return; }; - let old_name_prefixed = cx.str_buf.with(|buf| { - buf.extend(["clippy::", old_name]); - cx.arena.alloc_str(buf) - }); - let new_name_prefixed = cx.str_buf.with(|buf| { - buf.extend(["clippy::", new_name]); - cx.arena.alloc_str(buf) - }); - - for lint in &mut renamed_lints { - if lint.new_name == old_name_prefixed { - lint.new_name = new_name_prefixed; - } - } - match renamed_lints.binary_search_by(|x| x.old_name.cmp(old_name_prefixed)) { - Ok(_) => { - println!("`{old_name}` already has a rename registered"); - return; - }, - Err(idx) => { - renamed_lints.insert( - idx, - RenamedLint { - old_name: old_name_prefixed, - new_name: new_name_prefixed, - version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), - }, - ); - }, - } - let mut rename_mod = false; - if lints.binary_search_by(|x| x.name.cmp(new_name)).is_err() { - let lint = &mut lints[lint_idx]; - if lint.module.ends_with(old_name) - && lint + if let Entry::Vacant(e) = data.lints.entry(new_name) { + if prev_lint.module.ends_with(old_name) + && prev_lint .path .file_stem() .is_some_and(|x| x.as_encoded_bytes() == old_name.as_bytes()) { - let mut new_path = lint.path.with_file_name(new_name).into_os_string(); + let mut new_path = prev_lint.path.with_file_name(new_name).into_os_string(); new_path.push(".rs"); - if try_rename_file(lint.path.as_ref(), new_path.as_ref()) { + if try_rename_file(prev_lint.path.as_ref(), new_path.as_ref()) { rename_mod = true; } - lint.module = cx.str_buf.with(|buf| { - buf.push_str(&lint.module[..lint.module.len() - old_name.len()]); + prev_lint.module = cx.str_buf.with(|buf| { + buf.push_str(&prev_lint.module[..prev_lint.module.len() - old_name.len()]); buf.push_str(new_name); cx.arena.alloc_str(buf) }); } + e.insert(Lint::Active(prev_lint)); - rename_test_files( - old_name, - new_name, - &lints[lint_idx + 1..] - .iter() - .map(|l| l.name) - .take_while(|&n| n.starts_with(old_name)) - .collect::>(), - ); - lints[lint_idx].name = new_name; - lints.sort_by(|lhs, rhs| lhs.name.cmp(rhs.name)); + rename_test_files(old_name, new_name, &create_ignored_prefixes(old_name, &data)); } else { - println!("Renamed `clippy::{old_name}` to `clippy::{new_name}`"); + println!("Renamed `{old_name}` to `{new_name}`"); println!("Since `{new_name}` already exists the existing code has not been changed"); return; } @@ -201,9 +151,9 @@ pub fn rename<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_nam updater.update_file(e.path(), &mut update_fn); } } - generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); + generate_lint_files(UpdateMode::Change, &data); - println!("Renamed `clippy::{old_name}` to `clippy::{new_name}`"); + println!("Renamed `{old_name}` to `{new_name}`"); println!("All code referencing the old name has been updated"); println!("Make sure to inspect the results as some things may have been missed"); println!("note: `cargo uibless` still needs to be run to update the test results"); @@ -211,9 +161,14 @@ pub fn rename<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_nam /// Removes a lint's declaration and test files. Returns whether the module containing the /// lint was deleted. -fn remove_lint_declaration(lint_idx: usize, lints: &mut Vec>, updater: &mut FileUpdater) -> bool { - let lint = lints.remove(lint_idx); - let delete_mod = if lints.iter().all(|l| l.module != lint.module) { +fn remove_lint_declaration(name: &str, lint: &ActiveLint<'_>, data: &LintData<'_>, updater: &mut FileUpdater) -> bool { + let delete_mod = if data.lints.iter().all(|(_, l)| { + if let Lint::Active(l) = l { + l.module != lint.module + } else { + true + } + }) { delete_file_if_exists(lint.path.as_ref()) } else { updater.update_file(&lint.path, &mut |_, src, dst| -> UpdateStatus { @@ -231,18 +186,35 @@ fn remove_lint_declaration(lint_idx: usize, lints: &mut Vec>, updater: }); false }; - delete_test_files( - lint.name, - &lints[lint_idx..] - .iter() - .map(|l| l.name) - .take_while(|&n| n.starts_with(lint.name)) - .collect::>(), - ); + delete_test_files(name, &create_ignored_prefixes(name, data)); delete_mod } +/// Updates all renames to the old name to be renames to the new name. +/// +/// This is needed because rustc doesn't allow a lint to be renamed to a lint that has +/// also been renamed. +fn update_rename_targets<'cx>(data: &mut LintData<'cx>, old_name: &str, new_name: LintName<'cx>) { + let old_name = LintName::new_clippy(old_name); + for lint in data.lints.values_mut() { + if let Lint::Renamed(lint) = lint + && lint.new_name == old_name + { + lint.new_name = new_name; + } + } +} + +/// Creates a list of prefixes to ignore when +fn create_ignored_prefixes<'cx>(name: &str, data: &LintData<'cx>) -> Vec<&'cx str> { + data.lints + .keys() + .copied() + .filter(|&x| x.len() > name.len() && x.starts_with(name)) + .collect() +} + fn collect_ui_test_names(lint: &str, ignored_prefixes: &[&str], dst: &mut Vec<(OsString, bool)>) { for e in fs::read_dir("tests/ui").expect("error reading `tests/ui`") { let e = e.expect("error reading `tests/ui`"); diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 69309403c8d0..cff51d34c30e 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -19,6 +19,7 @@ #![allow(clippy::missing_panics_doc)] extern crate rustc_arena; +extern crate rustc_data_structures; #[expect(unused_extern_crates, reason = "required to link to rustc crates")] extern crate rustc_driver; extern crate rustc_lexer; diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 72f281ca4d9d..2abe471bed2b 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -526,18 +526,14 @@ fn parse_mod_file(path: &Path, contents: &str) -> (&'static str, usize) { let mut captures = [Capture::EMPTY]; while let Some(name) = cursor.find_any_ident() { match cursor.get_text(name) { - "declare_clippy_lint" => { - if cursor.match_all(&[Bang, OpenBrace], &mut []) && cursor.find_pat(CloseBrace) { - decl_end = Some(cursor.pos()); - } + "declare_clippy_lint" if cursor.match_all(&[Bang, OpenBrace], &mut []) && cursor.find_pat(CloseBrace) => { + decl_end = Some(cursor.pos()); }, - "impl" => { - if cursor.match_all(&[Lt, Lifetime, Gt, CaptureIdent], &mut captures) { - match cursor.get_text(captures[0]) { - "LateLintPass" => context = Some("LateContext"), - "EarlyLintPass" => context = Some("EarlyContext"), - _ => {}, - } + "impl" if cursor.match_all(&[Lt, Lifetime, Gt, CaptureIdent], &mut captures) => { + match cursor.get_text(captures[0]) { + "LateLintPass" => context = Some("LateContext"), + "EarlyLintPass" => context = Some("EarlyContext"), + _ => {}, } }, _ => {}, diff --git a/clippy_dev/src/parse.rs b/clippy_dev/src/parse.rs index de5caf4e1ef6..ffb50784a9a7 100644 --- a/clippy_dev/src/parse.rs +++ b/clippy_dev/src/parse.rs @@ -2,9 +2,10 @@ use self::cursor::{Capture, Cursor}; use crate::utils::{ErrAction, File, Scoped, expect_action, walk_dir_no_dot_or_target}; -use core::fmt::{Display, Write as _}; +use core::fmt::{self, Display, Write as _}; use core::range::Range; use rustc_arena::DroplessArena; +use rustc_data_structures::fx::FxHashMap; use std::fs; use std::path::{self, Path, PathBuf}; use std::str::pattern::Pattern; @@ -81,8 +82,49 @@ pub fn with(&mut self, f: impl FnOnce(&mut String) -> T) -> T { } } -pub struct Lint<'cx> { +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub enum LintTool { + Rustc, + Clippy, +} +impl LintTool { + /// Gets the namespace prefix to use when naming a lint including the `::`. + pub fn prefix(self) -> &'static str { + match self { + Self::Rustc => "", + Self::Clippy => "clippy::", + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct LintName<'cx> { pub name: &'cx str, + pub tool: LintTool, +} +impl<'cx> LintName<'cx> { + pub fn new_rustc(name: &'cx str) -> Self { + Self { + name, + tool: LintTool::Rustc, + } + } + + pub fn new_clippy(name: &'cx str) -> Self { + Self { + name, + tool: LintTool::Clippy, + } + } +} +impl Display for LintName<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.tool.prefix())?; + f.write_str(self.name) + } +} + +pub struct ActiveLint<'cx> { pub group: &'cx str, pub module: &'cx str, pub path: PathBuf, @@ -90,22 +132,34 @@ pub struct Lint<'cx> { } pub struct DeprecatedLint<'cx> { - pub name: &'cx str, pub reason: &'cx str, pub version: &'cx str, } pub struct RenamedLint<'cx> { - pub old_name: &'cx str, - pub new_name: &'cx str, + pub new_name: LintName<'cx>, pub version: &'cx str, } +pub enum Lint<'cx> { + Active(ActiveLint<'cx>), + Deprecated(DeprecatedLint<'cx>), + Renamed(RenamedLint<'cx>), +} + +pub struct LintData<'cx> { + pub lints: FxHashMap<&'cx str, Lint<'cx>>, +} + impl<'cx> ParseCxImpl<'cx> { - /// Finds all lint declarations (`declare_clippy_lint!`) + /// Finds and parses all lint declarations. #[must_use] - pub fn find_lint_decls(&mut self) -> Vec> { - let mut lints = Vec::with_capacity(1000); + pub fn parse_lint_decls(&mut self) -> LintData<'cx> { + let mut data = LintData { + #[expect(clippy::default_trait_access)] + lints: FxHashMap::with_capacity_and_hasher(1000, Default::default()), + }; + let mut contents = String::new(); for e in expect_action(fs::read_dir("."), ErrAction::Read, ".") { let e = expect_action(e, ErrAction::Read, "."); @@ -143,17 +197,18 @@ pub fn find_lint_decls(&mut self) -> Vec> { e.path(), File::open_read_to_cleared_string(e.path(), &mut contents), module, - &mut lints, + &mut data, ); } } } - lints.sort_by(|lhs, rhs| lhs.name.cmp(rhs.name)); - lints + + self.read_deprecated_lints(&mut data); + data } /// Parse a source file looking for `declare_clippy_lint` macro invocations. - fn parse_clippy_lint_decls(&mut self, path: &Path, contents: &str, module: &'cx str, lints: &mut Vec>) { + fn parse_clippy_lint_decls(&mut self, path: &Path, contents: &str, module: &'cx str, data: &mut LintData<'cx>) { #[allow(clippy::enum_glob_use)] use cursor::Pat::*; #[rustfmt::skip] @@ -170,19 +225,24 @@ fn parse_clippy_lint_decls(&mut self, path: &Path, contents: &str, module: &'cx let mut captures = [Capture::EMPTY; 2]; while let Some(start) = cursor.find_ident("declare_clippy_lint") { if cursor.match_all(DECL_TOKENS, &mut captures) && cursor.find_pat(CloseBrace) { - lints.push(Lint { - name: self.str_buf.alloc_ascii_lower(self.arena, cursor.get_text(captures[0])), - group: self.arena.alloc_str(cursor.get_text(captures[1])), - module, - path: path.into(), - declaration_range: start as usize..cursor.pos() as usize, - }); + assert!( + data.lints + .insert( + self.str_buf.alloc_ascii_lower(self.arena, cursor.get_text(captures[0])), + Lint::Active(ActiveLint { + group: self.arena.alloc_str(cursor.get_text(captures[1])), + module, + path: path.into(), + declaration_range: start as usize..cursor.pos() as usize, + }), + ) + .is_none() + ); } } } - #[must_use] - pub fn read_deprecated_lints(&mut self) -> (Vec>, Vec>) { + fn read_deprecated_lints(&mut self, data: &mut LintData<'cx>) { #[allow(clippy::enum_glob_use)] use cursor::Pat::*; #[rustfmt::skip] @@ -204,8 +264,6 @@ pub fn read_deprecated_lints(&mut self) -> (Vec>, Vec (Vec>, Vec (Vec>, Vec &'cx str { ); value } + + fn parse_clippy_lint_name(&mut self, path: &Path, s: &str) -> &'cx str { + match self.parse_str_single_line(path, s).strip_prefix("clippy::") { + Some(x) => x, + None => panic!( + "error parsing `{}`: `{s}` should be a string starting with `clippy::`", + path.display() + ), + } + } + + fn parse_lint_name(&mut self, path: &Path, s: &str) -> LintName<'cx> { + let s = self.parse_str_single_line(path, s); + let (name, tool) = match s.strip_prefix("clippy::") { + Some(s) => (s, LintTool::Clippy), + None => (s, LintTool::Rustc), + }; + LintName { name, tool } + } } diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 3d0da6846114..a4cf15058986 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -1,5 +1,5 @@ use crate::parse::cursor::Cursor; -use crate::parse::{DeprecatedLint, Lint, ParseCx, RenamedLint}; +use crate::parse::{Lint, LintData, ParseCx}; use crate::utils::{FileUpdater, UpdateMode, UpdateStatus, update_text_region_fn}; use itertools::Itertools; use std::collections::HashSet; @@ -22,35 +22,16 @@ /// /// Panics if a file path could not read from or then written to pub fn update(cx: ParseCx<'_>, update_mode: UpdateMode) { - let lints = cx.find_lint_decls(); - let (deprecated, renamed) = cx.read_deprecated_lints(); - generate_lint_files(update_mode, &lints, &deprecated, &renamed); + let data = cx.parse_lint_decls(); + generate_lint_files(update_mode, &data); } #[expect(clippy::too_many_lines)] -pub fn generate_lint_files( - update_mode: UpdateMode, - lints: &[Lint<'_>], - deprecated: &[DeprecatedLint<'_>], - renamed: &[RenamedLint<'_>], -) { +pub fn generate_lint_files(update_mode: UpdateMode, data: &LintData<'_>) { let mut updater = FileUpdater::default(); - updater.update_file_checked( - "cargo dev update_lints", - update_mode, - "README.md", - &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| { - write!(dst, "{}", round_to_fifty(lints.len())).unwrap(); - }), - ); - updater.update_file_checked( - "cargo dev update_lints", - update_mode, - "book/src/README.md", - &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| { - write!(dst, "{}", round_to_fifty(lints.len())).unwrap(); - }), - ); + + let mut lints: Vec<_> = data.lints.iter().map(|(&x, y)| (x, y)).collect(); + lints.sort_by_key(|&(x, _)| x); updater.update_file_checked( "cargo dev update_lints", update_mode, @@ -59,18 +40,44 @@ pub fn generate_lint_files( "\n", "", |dst| { - for lint in lints - .iter() - .map(|l| l.name) - .chain(deprecated.iter().filter_map(|l| l.name.strip_prefix("clippy::"))) - .chain(renamed.iter().filter_map(|l| l.old_name.strip_prefix("clippy::"))) - .sorted() - { + for &(lint, _) in &lints { writeln!(dst, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap(); } }, ), ); + + let mut active = Vec::with_capacity(lints.len()); + let mut deprecated = Vec::with_capacity(lints.len() / 8); + let mut renamed = Vec::with_capacity(lints.len() / 8); + for &(name, lint) in &lints { + match lint { + Lint::Active(lint) => active.push((name, lint)), + Lint::Deprecated(lint) => deprecated.push((name, lint)), + Lint::Renamed(lint) => renamed.push((name, lint)), + } + } + active.sort_by_key(|&(_, lint)| lint.module); + + // Round to avoid updating the readme every time a lint is added/deprecated. + let lint_count = active.len() / 50 * 50; + updater.update_file_checked( + "cargo dev update_lints", + update_mode, + "README.md", + &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| { + write!(dst, "{lint_count}").unwrap(); + }), + ); + updater.update_file_checked( + "cargo dev update_lints", + update_mode, + "book/src/README.md", + &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| { + write!(dst, "{lint_count}").unwrap(); + }), + ); + updater.update_file_checked( "cargo dev update_lints", update_mode, @@ -84,11 +91,11 @@ pub fn generate_lint_files( ); dst.push_str(&src[..cursor.pos() as usize]); dst.push_str("! { DEPRECATED(DEPRECATED_VERSION) = [\n"); - for lint in deprecated { + for &(name, data) in &deprecated { write!( dst, - " #[clippy::version = \"{}\"]\n (\"{}\", \"{}\"),\n", - lint.version, lint.name, lint.reason, + " #[clippy::version = \"{}\"]\n (\"clippy::{name}\", \"{}\"),\n", + data.version, data.reason, ) .unwrap(); } @@ -98,11 +105,11 @@ pub fn generate_lint_files( declare_with_version! { RENAMED(RENAMED_VERSION) = [\n\ ", ); - for lint in renamed { + for &(name, data) in &renamed { write!( dst, - " #[clippy::version = \"{}\"]\n (\"{}\", \"{}\"),\n", - lint.version, lint.old_name, lint.new_name, + " #[clippy::version = \"{}\"]\n (\"clippy::{name}\", \"{}\"),\n", + data.version, data.new_name, ) .unwrap(); } @@ -116,8 +123,8 @@ pub fn generate_lint_files( "tests/ui/deprecated.rs", &mut |_, src, dst| { dst.push_str(GENERATED_FILE_COMMENT); - for lint in deprecated { - writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.name, lint.name).unwrap(); + for &(lint, _) in &deprecated { + writeln!(dst, "#![warn(clippy::{lint})] //~ ERROR: lint `clippy::{lint}`").unwrap(); } dst.push_str("\nfn main() {}\n"); UpdateStatus::from_changed(src != dst) @@ -131,25 +138,25 @@ pub fn generate_lint_files( let mut seen_lints = HashSet::new(); dst.push_str(GENERATED_FILE_COMMENT); dst.push_str("#![allow(clippy::duplicated_attributes)]\n"); - for lint in renamed { + for &(_, lint) in &renamed { if seen_lints.insert(lint.new_name) { writeln!(dst, "#![allow({})]", lint.new_name).unwrap(); } } - seen_lints.clear(); - for lint in renamed { - if seen_lints.insert(lint.old_name) { - writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.old_name, lint.old_name).unwrap(); - } + for &(lint, _) in &renamed { + writeln!(dst, "#![warn(clippy::{lint})] //~ ERROR: lint `clippy::{lint}`").unwrap(); } dst.push_str("\nfn main() {}\n"); UpdateStatus::from_changed(src != dst) }, ); - for (crate_name, lints) in lints.iter().into_group_map_by(|&l| { - let Some(path::Component::Normal(name)) = l.path.components().next() else { + for (crate_name, lints) in active.iter().copied().into_group_map_by(|&(_, lint)| { + let Some(path::Component::Normal(name)) = lint.path.components().next() else { // All paths should start with `{crate_name}/src` when parsed from `find_lint_decls` - panic!("internal error: can't read crate name from path `{}`", l.path.display()); + panic!( + "internal error: can't read crate name from path `{}`", + lint.path.display() + ); }; name }) { @@ -161,14 +168,12 @@ pub fn generate_lint_files( "// begin lints modules, do not remove this comment, it's used in `update_lints`\n", "// end lints modules, do not remove this comment, it's used in `update_lints`", |dst| { - for lint_mod in lints - .iter() - .filter(|l| !l.module.is_empty()) - .map(|l| l.module.split_once("::").map_or(l.module, |x| x.0)) - .sorted() - .dedup() - { - writeln!(dst, "mod {lint_mod};").unwrap(); + let mut prev = ""; + for &(_, lint) in &lints { + if lint.module != prev { + writeln!(dst, "mod {};", lint.module).unwrap(); + prev = lint.module; + } } }, ), @@ -180,11 +185,15 @@ pub fn generate_lint_files( &mut |_, src, dst| { dst.push_str(GENERATED_FILE_COMMENT); dst.push_str("pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[\n"); - for (module_path, lint_name) in lints.iter().map(|l| (&l.module, l.name.to_uppercase())).sorted() { - if module_path.is_empty() { - writeln!(dst, " crate::{lint_name}_INFO,").unwrap(); + let mut buf = String::new(); + for &(name, lint) in &lints { + buf.clear(); + buf.push_str(name); + buf.make_ascii_uppercase(); + if lint.module.is_empty() { + writeln!(dst, " crate::{buf}_INFO,").unwrap(); } else { - writeln!(dst, " crate::{module_path}::{lint_name}_INFO,").unwrap(); + writeln!(dst, " crate::{}::{buf}_INFO,", lint.module).unwrap(); } } dst.push_str("];\n"); @@ -193,7 +202,3 @@ pub fn generate_lint_files( ); } } - -fn round_to_fifty(count: usize) -> usize { - count / 50 * 50 -} diff --git a/clippy_lints/src/assertions_on_result_states.rs b/clippy_lints/src/assertions_on_result_states.rs index cc62306b33b5..d48ef10c8cd2 100644 --- a/clippy_lints/src/assertions_on_result_states.rs +++ b/clippy_lints/src/assertions_on_result_states.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::macros::{PanicExpn, find_assert_args, root_macro_call_first_node}; +use clippy_utils::macros::{find_assert_args, root_macro_call_first_node}; use clippy_utils::res::{MaybeDef, MaybeResPath}; use clippy_utils::source::snippet_with_context; use clippy_utils::sym; @@ -52,7 +52,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let Some(macro_call) = root_macro_call_first_node(cx, e) && matches!(cx.tcx.get_diagnostic_name(macro_call.def_id), Some(sym::assert_macro)) && let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) - && matches!(panic_expn, PanicExpn::Empty) + && panic_expn.is_default_message() && let ExprKind::MethodCall(method_segment, recv, [], _) = condition.kind && let result_type_with_refs = cx.typeck_results().expr_ty(recv) && let result_type = result_type_with_refs.peel_refs() diff --git a/clippy_lints/src/attrs/deprecated_semver.rs b/clippy_lints/src/attrs/deprecated_semver.rs index bd6459d6f9db..e3b1a05bda7d 100644 --- a/clippy_lints/src/attrs/deprecated_semver.rs +++ b/clippy_lints/src/attrs/deprecated_semver.rs @@ -2,13 +2,14 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::sym; use rustc_ast::{LitKind, MetaItemLit}; +use rustc_hir::VERSION_PLACEHOLDER; use rustc_lint::EarlyContext; use rustc_span::Span; use semver::Version; pub(super) fn check(cx: &EarlyContext<'_>, span: Span, lit: &MetaItemLit) { if let LitKind::Str(is, _) = lit.kind - && (is == sym::TBD || Version::parse(is.as_str()).is_ok()) + && (is == sym::TBD || is.as_str() == VERSION_PLACEHOLDER || Version::parse(is.as_str()).is_ok()) { return; } diff --git a/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs index 70c9c45a60c8..947b99696bb1 100644 --- a/clippy_lints/src/borrow_deref_ref.rs +++ b/clippy_lints/src/borrow_deref_ref.rs @@ -2,7 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; -use clippy_utils::{get_parent_expr, is_expr_temporary_value, is_from_proc_macro, is_lint_allowed, is_mutable}; +use clippy_utils::{ + get_enclosing_closure, get_parent_expr, is_expr_temporary_value, is_from_proc_macro, is_lint_allowed, is_mutable, + is_upvar_in_closure, path_to_local_with_projections, +}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Node, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -81,6 +84,16 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) { && (is_expr_temporary_value(cx, deref_target) || !potentially_bound_to_mutable_ref(cx, e)) && let Some(deref_text) = deref_target.span.get_source_text(cx) { + // `&*x` can be needed to shorten the borrow of `x`. Replacing it with `x` can be + // incorrect when `x` is a closure-captured upvar (e.g. a closure returning another + // closure that captures `x`). + if let Some(closure) = get_enclosing_closure(cx, e.hir_id) + && let Some(local_id) = path_to_local_with_projections(deref_target) + && is_upvar_in_closure(cx, closure, local_id) + { + return; + } + span_lint_and_then( cx, BORROW_DEREF_REF, diff --git a/clippy_lints/src/cargo/common_metadata.rs b/clippy_lints/src/cargo/common_metadata.rs index 80514cb52e6e..e92e3d115b17 100644 --- a/clippy_lints/src/cargo/common_metadata.rs +++ b/clippy_lints/src/cargo/common_metadata.rs @@ -9,7 +9,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, ignore_publish: b for package in &metadata.packages { // only run the lint if publish is `None` (`publish = true` or skipped entirely) // or if the vector isn't empty (`publish = ["something"]`) - if package.publish.as_ref().filter(|publish| publish.is_empty()).is_none() || ignore_publish { + if package.publish.as_ref().is_none_or(|publish| !publish.is_empty()) || ignore_publish { if is_empty_str(package.description.as_ref()) { missing_warning(cx, package, "package.description"); } diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index 8b0859722b13..5cc41c121965 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -1,13 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::numeric_literal::NumericLiteral; -use clippy_utils::res::MaybeResPath; +use clippy_utils::res::MaybeResPath as _; use clippy_utils::source::{SpanRangeExt, snippet_opt}; use clippy_utils::visitors::{Visitable, for_each_expr_without_closures}; use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, sym}; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Expr, ExprKind, Lit, Node, Path, QPath, TyKind, UnOp}; +use rustc_hir::{Expr, ExprKind, FnRetTy, Lit, Node, Path, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::{self, FloatTy, InferTy, Ty}; @@ -39,10 +39,8 @@ pub(super) fn check<'tcx>( // Ignore casts to pointers that are aliases or cfg dependant, e.g. // - p as *const std::ffi::c_char (alias) // - p as *const std::os::raw::c_char (cfg dependant) - TyKind::Path(qpath) => { - if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) { - return false; - } + TyKind::Path(qpath) if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) => { + return false; }, // Ignore `p as *const _` TyKind::Infer(()) => return false, @@ -97,7 +95,7 @@ pub(super) fn check<'tcx>( // skip cast of fn call that returns type alias if let ExprKind::Cast(inner, ..) = expr.kind - && is_cast_from_ty_alias(cx, inner, cast_from) + && is_cast_from_ty_alias(cx, inner) { return false; } @@ -270,34 +268,25 @@ fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 { /// Finds whether an `Expr` returns a type alias. /// -/// TODO: Maybe we should move this to `clippy_utils` so others won't need to go down this dark, -/// dark path reimplementing this (or something similar). -fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx>, cast_from: Ty<'tcx>) -> bool { +/// When in doubt, for example because it calls a non-local function that we don't have the +/// declaration for, assume if might be a type alias. +fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx>) -> bool { for_each_expr_without_closures(expr, |expr| { // Calls are a `Path`, and usage of locals are a `Path`. So, this checks // - call() as i32 // - local as i32 if let ExprKind::Path(qpath) = expr.kind { let res = cx.qpath_res(&qpath, expr.hir_id); - // Function call if let Res::Def(DefKind::Fn, def_id) = res { - let Some(snippet) = cx.tcx.def_span(def_id).get_source_text(cx) else { - return ControlFlow::Continue(()); + let Some(def_id) = def_id.as_local() else { + // External function, we can't know, better be safe + return ControlFlow::Break(()); }; - // This is the worst part of this entire function. This is the only way I know of to - // check whether a function returns a type alias. Sure, you can get the return type - // from a function in the current crate as an hir ty, but how do you get it for - // external functions?? Simple: It's impossible. So, we check whether a part of the - // function's declaration snippet is exactly equal to the `Ty`. That way, we can - // see whether it's a type alias. - // - // FIXME: This won't work if the type is given an alias through `use`, should we - // consider this a type alias as well? - if !snippet - .split("->") - .skip(1) - .any(|s| snippet_eq_ty(s, cast_from) || s.split("where").any(|ty| snippet_eq_ty(ty, cast_from))) + if let Some(FnRetTy::Return(ty)) = cx.tcx.hir_get_fn_output(def_id) + && let TyKind::Path(qpath) = ty.kind + && is_ty_alias(&qpath) { + // Function call to a local function returning a type alias return ControlFlow::Break(()); } // Local usage @@ -305,7 +294,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx && let Node::LetStmt(l) = cx.tcx.parent_hir_node(hir_id) { if let Some(e) = l.init - && is_cast_from_ty_alias(cx, e, cast_from) + && is_cast_from_ty_alias(cx, e) { return ControlFlow::Break::<()>(()); } @@ -323,7 +312,3 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx }) .is_some() } - -fn snippet_eq_ty(snippet: &str, ty: Ty<'_>) -> bool { - snippet.trim() == ty.to_string() || snippet.trim().contains(&format!("::{ty}")) -} diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index dfc1ca107feb..c256ad9b06a4 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -81,10 +81,8 @@ fn check<'tcx>( } cc += arms.iter().filter(|arm| arm.guard.is_some()).count() as u64; }, - ExprKind::Ret(_) => { - if !matches!(prev_expr, Some(ExprKind::Ret(_))) { - returns += 1; - } + ExprKind::Ret(_) if !matches!(prev_expr, Some(ExprKind::Ret(_))) => { + returns += 1; }, _ => {}, } diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index be07ce1272bd..17e11b8b281d 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -307,7 +307,7 @@ fn expr_block<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> { } /// If the expression is a `||`, suggest parentheses around it. -fn parens_around(expr: &Expr<'_>) -> Vec<(Span, String)> { +pub(super) fn parens_around(expr: &Expr<'_>) -> Vec<(Span, String)> { if let ExprKind::Binary(op, _, _) = expr.peel_drop_temps().kind && op.node == BinOpKind::Or { @@ -334,7 +334,7 @@ fn span_extract_keyword(sm: &SourceMap, span: Span, keyword: &str) -> Option (Span, Span, Span) { +pub(super) fn peel_parens(sm: &SourceMap, mut span: Span) -> (Span, Span, Span) { use crate::rustc_span::Pos; let start = span.shrink_to_lo(); diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index a04d133b0d72..e16b194c0cad 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -100,11 +100,12 @@ crate::dereference::NEEDLESS_BORROW_INFO, crate::dereference::REF_BINDING_TO_REFERENCE_INFO, crate::derivable_impls::DERIVABLE_IMPLS_INFO, - crate::derive::DERIVED_HASH_WITH_MANUAL_EQ_INFO, crate::derive::DERIVE_ORD_XOR_PARTIAL_ORD_INFO, crate::derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ_INFO, + crate::derive::DERIVED_HASH_WITH_MANUAL_EQ_INFO, crate::derive::EXPL_IMPL_CLONE_ON_COPY_INFO, crate::derive::UNSAFE_DERIVE_DESERIALIZE_INFO, + crate::disallowed_fields::DISALLOWED_FIELDS_INFO, crate::disallowed_macros::DISALLOWED_MACROS_INFO, crate::disallowed_methods::DISALLOWED_METHODS_INFO, crate::disallowed_names::DISALLOWED_NAMES_INFO, @@ -173,6 +174,7 @@ crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO, crate::format_args::UNINLINED_FORMAT_ARGS_INFO, crate::format_args::UNNECESSARY_DEBUG_FORMATTING_INFO, + crate::format_args::UNNECESSARY_TRAILING_COMMA_INFO, crate::format_args::UNUSED_FORMAT_SPECS_INFO, crate::format_impl::PRINT_IN_FORMAT_IMPL_INFO, crate::format_impl::RECURSIVE_FORMAT_IMPL_INFO, @@ -204,8 +206,8 @@ crate::if_not_else::IF_NOT_ELSE_INFO, crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO, crate::ifs::BRANCHES_SHARING_CODE_INFO, - crate::ifs::IFS_SAME_COND_INFO, crate::ifs::IF_SAME_THEN_ELSE_INFO, + crate::ifs::IFS_SAME_COND_INFO, crate::ifs::SAME_FUNCTIONS_IN_IF_CONDITION_INFO, crate::ignored_unit_patterns::IGNORED_UNIT_PATTERNS_INFO, crate::impl_hash_with_borrow_str_and_bytes::IMPL_HASH_BORROW_WITH_STR_AND_BYTES_INFO, @@ -336,8 +338,8 @@ crate::matches::MATCH_SAME_ARMS_INFO, crate::matches::MATCH_SINGLE_BINDING_INFO, crate::matches::MATCH_STR_CASE_MISMATCH_INFO, - crate::matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS_INFO, crate::matches::MATCH_WILD_ERR_ARM_INFO, + crate::matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS_INFO, crate::matches::NEEDLESS_MATCH_INFO, crate::matches::REDUNDANT_GUARDS_INFO, crate::matches::REDUNDANT_PATTERN_MATCHING_INFO, @@ -359,9 +361,9 @@ crate::methods::CHARS_LAST_CMP_INFO, crate::methods::CHARS_NEXT_CMP_INFO, crate::methods::CLEAR_WITH_DRAIN_INFO, - crate::methods::CLONED_INSTEAD_OF_COPIED_INFO, crate::methods::CLONE_ON_COPY_INFO, crate::methods::CLONE_ON_REF_PTR_INFO, + crate::methods::CLONED_INSTEAD_OF_COPIED_INFO, crate::methods::COLLAPSIBLE_STR_REPLACE_INFO, crate::methods::CONST_IS_EMPTY_INFO, crate::methods::DOUBLE_ENDED_ITERATOR_LAST_INFO, @@ -389,7 +391,6 @@ crate::methods::IO_OTHER_ERROR_INFO, crate::methods::IP_CONSTANT_INFO, crate::methods::IS_DIGIT_ASCII_RADIX_INFO, - crate::methods::ITERATOR_STEP_BY_ZERO_INFO, crate::methods::ITER_CLONED_COLLECT_INFO, crate::methods::ITER_COUNT_INFO, crate::methods::ITER_FILTER_IS_OK_INFO, @@ -405,10 +406,11 @@ crate::methods::ITER_SKIP_NEXT_INFO, crate::methods::ITER_SKIP_ZERO_INFO, crate::methods::ITER_WITH_DRAIN_INFO, + crate::methods::ITERATOR_STEP_BY_ZERO_INFO, crate::methods::JOIN_ABSOLUTE_PATHS_INFO, crate::methods::LINES_FILTER_MAP_OK_INFO, - crate::methods::MANUAL_CONTAINS_INFO, crate::methods::MANUAL_C_STR_LITERALS_INFO, + crate::methods::MANUAL_CONTAINS_INFO, crate::methods::MANUAL_FILTER_MAP_INFO, crate::methods::MANUAL_FIND_MAP_INFO, crate::methods::MANUAL_INSPECT_INFO, @@ -437,8 +439,8 @@ crate::methods::NEEDLESS_OPTION_TAKE_INFO, crate::methods::NEEDLESS_SPLITN_INFO, crate::methods::NEW_RET_NO_SELF_INFO, - crate::methods::NONSENSICAL_OPEN_OPTIONS_INFO, crate::methods::NO_EFFECT_REPLACE_INFO, + crate::methods::NONSENSICAL_OPEN_OPTIONS_INFO, crate::methods::OBFUSCATED_IF_ELSE_INFO, crate::methods::OK_EXPECT_INFO, crate::methods::OPTION_AS_REF_CLONED_INFO, @@ -452,8 +454,8 @@ crate::methods::PTR_OFFSET_BY_LITERAL_INFO, crate::methods::PTR_OFFSET_WITH_CAST_INFO, crate::methods::RANGE_ZIP_WITH_LEN_INFO, - crate::methods::READONLY_WRITE_LOCK_INFO, crate::methods::READ_LINE_WITHOUT_TRIM_INFO, + crate::methods::READONLY_WRITE_LOCK_INFO, crate::methods::REDUNDANT_AS_STR_INFO, crate::methods::REDUNDANT_ITER_CLONED_INFO, crate::methods::REPEAT_ONCE_INFO, @@ -468,9 +470,9 @@ crate::methods::SKIP_WHILE_NEXT_INFO, crate::methods::SLICED_STRING_AS_BYTES_INFO, crate::methods::STABLE_SORT_PRIMITIVE_INFO, + crate::methods::STR_SPLIT_AT_NEWLINE_INFO, crate::methods::STRING_EXTEND_CHARS_INFO, crate::methods::STRING_LIT_CHARS_ANY_INFO, - crate::methods::STR_SPLIT_AT_NEWLINE_INFO, crate::methods::SUSPICIOUS_COMMAND_ARG_SPACE_INFO, crate::methods::SUSPICIOUS_MAP_INFO, crate::methods::SUSPICIOUS_OPEN_OPTIONS_INFO, @@ -641,8 +643,8 @@ crate::ranges::RANGE_MINUS_ONE_INFO, crate::ranges::RANGE_PLUS_ONE_INFO, crate::ranges::REVERSED_EMPTY_RANGES_INFO, - crate::raw_strings::NEEDLESS_RAW_STRINGS_INFO, crate::raw_strings::NEEDLESS_RAW_STRING_HASHES_INFO, + crate::raw_strings::NEEDLESS_RAW_STRINGS_INFO, crate::rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT_INFO, crate::read_zero_byte_vec::READ_ZERO_BYTE_VEC_INFO, crate::redundant_async_block::REDUNDANT_ASYNC_BLOCK_INFO, @@ -695,12 +697,12 @@ crate::std_instead_of_core::STD_INSTEAD_OF_CORE_INFO, crate::string_patterns::MANUAL_PATTERN_CHAR_COMPARISON_INFO, crate::string_patterns::SINGLE_CHAR_PATTERN_INFO, + crate::strings::STR_TO_STRING_INFO, crate::strings::STRING_ADD_INFO, crate::strings::STRING_ADD_ASSIGN_INFO, crate::strings::STRING_FROM_UTF8_AS_BYTES_INFO, crate::strings::STRING_LIT_AS_BYTES_INFO, crate::strings::STRING_SLICE_INFO, - crate::strings::STR_TO_STRING_INFO, crate::strings::TRIM_SPLIT_WHITESPACE_INFO, crate::strlen_on_c_strings::STRLEN_ON_C_STRINGS_INFO, crate::suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS_INFO, @@ -724,7 +726,6 @@ crate::transmute::CROSSPOINTER_TRANSMUTE_INFO, crate::transmute::EAGER_TRANSMUTE_INFO, crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS_INFO, - crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO, crate::transmute::TRANSMUTE_BYTES_TO_STR_INFO, crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO, crate::transmute::TRANSMUTE_INT_TO_NON_ZERO_INFO, @@ -732,6 +733,7 @@ crate::transmute::TRANSMUTE_PTR_TO_PTR_INFO, crate::transmute::TRANSMUTE_PTR_TO_REF_INFO, crate::transmute::TRANSMUTE_UNDEFINED_REPR_INFO, + crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO, crate::transmute::TRANSMUTING_NULL_INFO, crate::transmute::UNSOUND_COLLECTION_TRANSMUTE_INFO, crate::transmute::USELESS_TRANSMUTE_INFO, @@ -789,20 +791,20 @@ crate::useless_vec::USELESS_VEC_INFO, crate::vec_init_then_push::VEC_INIT_THEN_PUSH_INFO, crate::visibility::NEEDLESS_PUB_SELF_INFO, - crate::visibility::PUB_WITHOUT_SHORTHAND_INFO, crate::visibility::PUB_WITH_SHORTHAND_INFO, + crate::visibility::PUB_WITHOUT_SHORTHAND_INFO, crate::volatile_composites::VOLATILE_COMPOSITES_INFO, crate::wildcard_imports::ENUM_GLOB_USE_INFO, crate::wildcard_imports::WILDCARD_IMPORTS_INFO, - crate::write::PRINTLN_EMPTY_STRING_INFO, crate::write::PRINT_LITERAL_INFO, crate::write::PRINT_STDERR_INFO, crate::write::PRINT_STDOUT_INFO, crate::write::PRINT_WITH_NEWLINE_INFO, + crate::write::PRINTLN_EMPTY_STRING_INFO, crate::write::USE_DEBUG_INFO, - crate::write::WRITELN_EMPTY_STRING_INFO, crate::write::WRITE_LITERAL_INFO, crate::write::WRITE_WITH_NEWLINE_INFO, + crate::write::WRITELN_EMPTY_STRING_INFO, crate::zero_div_zero::ZERO_DIVIDED_BY_ZERO_INFO, crate::zero_repeat_side_effects::ZERO_REPEAT_SIDE_EFFECTS_INFO, crate::zero_sized_map_values::ZERO_SIZED_MAP_VALUES_INFO, diff --git a/clippy_lints/src/disallowed_fields.rs b/clippy_lints/src/disallowed_fields.rs new file mode 100644 index 000000000000..f1136556e2ed --- /dev/null +++ b/clippy_lints/src/disallowed_fields.rs @@ -0,0 +1,160 @@ +use clippy_config::Conf; +use clippy_config::types::{DisallowedPath, create_disallowed_map}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::paths::PathNS; +use clippy_utils::ty::get_field_def_id_by_name; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def_id::DefIdMap; +use rustc_hir::{Expr, ExprKind, Pat, PatKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::TyCtxt; +use rustc_session::impl_lint_pass; + +declare_clippy_lint! { + /// ### What it does + /// Denies the configured fields in clippy.toml + /// + /// Note: Even though this lint is warn-by-default, it will only trigger if + /// fields are defined in the clippy.toml file. + /// + /// ### Why is this bad? + /// Some fields are undesirable in certain contexts, and it's beneficial to + /// lint for them as needed. + /// + /// ### Example + /// An example clippy.toml configuration: + /// ```toml + /// # clippy.toml + /// disallowed-fields = [ + /// # Can use a string as the path of the disallowed field. + /// "std::ops::Range::start", + /// # Can also use an inline table with a `path` key. + /// { path = "std::ops::Range::start" }, + /// # When using an inline table, can add a `reason` for why the field + /// # is disallowed. + /// { path = "std::ops::Range::start", reason = "The start of the range is not used" }, + /// ] + /// ``` + /// + /// ```rust + /// use std::ops::Range; + /// + /// let range = Range { start: 0, end: 1 }; + /// println!("{}", range.start); // `start` is disallowed in the config. + /// ``` + /// + /// Use instead: + /// ```rust + /// use std::ops::Range; + /// + /// let range = Range { start: 0, end: 1 }; + /// println!("{}", range.end); // `end` is _not_ disallowed in the config. + /// ``` + #[clippy::version = "1.93.0"] + pub DISALLOWED_FIELDS, + style, + "declaration of a disallowed field use" +} + +pub struct DisallowedFields { + disallowed: DefIdMap<(&'static str, &'static DisallowedPath)>, +} + +impl DisallowedFields { + pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { + let (disallowed, _) = create_disallowed_map( + tcx, + &conf.disallowed_fields, + PathNS::Field, + |def_kind| matches!(def_kind, DefKind::Field), + "field", + false, + ); + Self { disallowed } + } +} + +impl_lint_pass!(DisallowedFields => [DISALLOWED_FIELDS]); + +impl<'tcx> LateLintPass<'tcx> for DisallowedFields { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + let (id, span) = match &expr.kind { + ExprKind::Path(path) if let Res::Def(_, id) = cx.qpath_res(path, expr.hir_id) => (id, expr.span), + ExprKind::Field(e, ident) => { + // Very round-about way to get the field `DefId` from the expr: first we get its + // parent `Ty`. Then we go through all its fields to find the one with the expected + // name and get the `DefId` from it. + if let Some(parent_ty) = cx.typeck_results().expr_ty_adjusted_opt(e) + && let Some(field_def_id) = get_field_def_id_by_name(parent_ty, ident.name) + { + (field_def_id, ident.span) + } else { + return; + } + }, + _ => return, + }; + if let Some(&(path, disallowed_path)) = self.disallowed.get(&id) { + span_lint_and_then( + cx, + DISALLOWED_FIELDS, + span, + format!("use of a disallowed field `{path}`"), + disallowed_path.diag_amendment(span), + ); + } + } + + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { + let PatKind::Struct(struct_path, pat_fields, _) = pat.kind else { + return; + }; + match cx.typeck_results().qpath_res(&struct_path, pat.hir_id) { + Res::Def(DefKind::Struct, struct_def_id) => { + let adt_def = cx.tcx.adt_def(struct_def_id); + for field in pat_fields { + if let Some(def_id) = adt_def.all_fields().find_map(|adt_field| { + if field.ident.name == adt_field.name { + Some(adt_field.did) + } else { + None + } + }) && let Some(&(path, disallowed_path)) = self.disallowed.get(&def_id) + { + span_lint_and_then( + cx, + DISALLOWED_FIELDS, + field.span, + format!("use of a disallowed field `{path}`"), + disallowed_path.diag_amendment(field.span), + ); + } + } + }, + Res::Def(DefKind::Variant, variant_def_id) => { + let enum_def_id = cx.tcx.parent(variant_def_id); + let variant = cx.tcx.adt_def(enum_def_id).variant_with_id(variant_def_id); + + for field in pat_fields { + if let Some(def_id) = variant.fields.iter().find_map(|adt_field| { + if field.ident.name == adt_field.name { + Some(adt_field.did) + } else { + None + } + }) && let Some(&(path, disallowed_path)) = self.disallowed.get(&def_id) + { + span_lint_and_then( + cx, + DISALLOWED_FIELDS, + field.span, + format!("use of a disallowed field `{path}`"), + disallowed_path.diag_amendment(field.span), + ); + } + } + }, + _ => {}, + } + } +} diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index e7a984694831..0a2871f23964 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -763,19 +763,11 @@ fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) self.check_private_items, ); match item.kind { - ItemKind::Fn { sig, body, .. } => { + ItemKind::Fn { sig, body, .. } if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) - || item.span.in_external_macro(cx.tcx.sess.source_map())) - { - missing_headers::check( - cx, - item.owner_id, - sig, - headers, - Some(body), - self.check_private_items, - ); - } + || item.span.in_external_macro(cx.tcx.sess.source_map())) => + { + missing_headers::check(cx, item.owner_id, sig, headers, Some(body), self.check_private_items); }, ItemKind::Trait(_, _, unsafety, ..) => match (headers.safety, unsafety) { (false, Safety::Unsafe) => span_lint( diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 351d29d87432..acc3e4936e44 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -46,28 +46,28 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { // ((..)) // ^^^^^^ expr // ^^^^ inner - ExprKind::Paren(inner) if matches!(inner.kind, ExprKind::Paren(_) | ExprKind::Tup(_)) => { - if expr.span.eq_ctxt(inner.span) + ExprKind::Paren(inner) + if matches!(inner.kind, ExprKind::Paren(_) | ExprKind::Tup(_)) + && expr.span.eq_ctxt(inner.span) && !expr.span.in_external_macro(cx.sess().source_map()) - && check_source(cx, inner) - { - // suggest removing the outer parens + && check_source(cx, inner) => + { + // suggest removing the outer parens - let mut applicability = Applicability::MachineApplicable; - // We don't need to use `snippet_with_context` here, because: - // - if `inner`'s `ctxt` is from macro, we don't lint in the first place (see the check above) - // - otherwise, calling `snippet_with_applicability` on a not-from-macro span is fine - let sugg = snippet_with_applicability(cx.sess(), inner.span, "_", &mut applicability); - span_lint_and_sugg( - cx, - DOUBLE_PARENS, - expr.span, - "unnecessary parentheses", - "remove them", - sugg.to_string(), - applicability, - ); - } + let mut applicability = Applicability::MachineApplicable; + // We don't need to use `snippet_with_context` here, because: + // - if `inner`'s `ctxt` is from macro, we don't lint in the first place (see the check above) + // - otherwise, calling `snippet_with_applicability` on a not-from-macro span is fine + let sugg = snippet_with_applicability(cx.sess(), inner.span, "_", &mut applicability); + span_lint_and_sugg( + cx, + DOUBLE_PARENS, + expr.span, + "unnecessary parentheses", + "remove them", + sugg.to_string(), + applicability, + ); }, // func((n)) @@ -76,26 +76,24 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { // ^ inner ExprKind::Call(_, args) | ExprKind::MethodCall(box MethodCall { args, .. }) if let [arg] = &**args - && let ExprKind::Paren(inner) = &arg.kind => - { - if expr.span.eq_ctxt(arg.span) + && let ExprKind::Paren(inner) = &arg.kind + && expr.span.eq_ctxt(arg.span) && !arg.span.in_external_macro(cx.sess().source_map()) - && check_source(cx, arg) - { - // suggest removing the inner parens + && check_source(cx, arg) => + { + // suggest removing the inner parens - let mut applicability = Applicability::MachineApplicable; - let sugg = snippet_with_context(cx.sess(), inner.span, arg.span.ctxt(), "_", &mut applicability).0; - span_lint_and_sugg( - cx, - DOUBLE_PARENS, - arg.span, - "unnecessary parentheses", - "remove them", - sugg.to_string(), - applicability, - ); - } + let mut applicability = Applicability::MachineApplicable; + let sugg = snippet_with_context(cx.sess(), inner.span, arg.span.ctxt(), "_", &mut applicability).0; + span_lint_and_sugg( + cx, + DOUBLE_PARENS, + arg.span, + "unnecessary parentheses", + "remove them", + sugg.to_string(), + applicability, + ); }, _ => {}, } diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index b4d2d99fd9ff..d987a76f5394 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -27,7 +27,7 @@ use rustc_middle::ty::{self, GenericArg, List, TraitRef, Ty, TyCtxt, Upcast}; use rustc_session::impl_lint_pass; use rustc_span::edition::Edition::Edition2021; -use rustc_span::{Span, Symbol}; +use rustc_span::{BytePos, Pos, Span, Symbol}; use rustc_trait_selection::infer::TyCtxtInferExt; use rustc_trait_selection::traits::{Obligation, ObligationCause, Selection, SelectionContext}; @@ -228,6 +228,35 @@ "formatting a pointer" } +declare_clippy_lint! { + /// ### What it does + /// Suggests removing an unnecessary trailing comma before the closing parenthesis in + /// single-line macro invocations. + /// + /// ### Why is this bad? + /// The trailing comma is redundant and removing it is more consistent with how + /// `rustfmt` formats regular function calls. + /// + /// ### Known limitations + /// This lint currently only runs on format-like macros (e.g. `format!`, `println!`, + /// `write!`) because it relies on format-argument parsing; applying it to arbitrary + /// user macros could cause incorrect suggestions. It may be extended to other + /// macros in the future. Only single-line macro invocations are linted. + /// + /// ### Example + /// ```no_run + /// println!("Foo={}", 1,); + /// ``` + /// Use instead: + /// ```no_run + /// println!("Foo={}", 1); + /// ``` + #[clippy::version = "1.95.0"] + pub UNNECESSARY_TRAILING_COMMA, + pedantic, + "unnecessary trailing comma before closing parenthesis" +} + impl_lint_pass!(FormatArgs<'_> => [ FORMAT_IN_FORMAT_ARGS, TO_STRING_IN_FORMAT_ARGS, @@ -235,6 +264,7 @@ UNNECESSARY_DEBUG_FORMATTING, UNUSED_FORMAT_SPECS, POINTER_FORMAT, + UNNECESSARY_TRAILING_COMMA, ]); #[expect(clippy::struct_field_names)] @@ -279,6 +309,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { has_pointer_format: &mut self.has_pointer_format, }; + linter.check_trailing_comma(); linter.check_templates(); if self.msrv.meets(cx, msrvs::FORMAT_ARGS_CAPTURE) { @@ -301,6 +332,29 @@ struct FormatArgsExpr<'a, 'tcx> { } impl<'tcx> FormatArgsExpr<'_, 'tcx> { + /// Check if there is a comma after the last format macro arg. + fn check_trailing_comma(&self) { + let span = self.macro_call.span; + if let Some(src) = span.get_source_text(self.cx) + && let Some(src) = src.strip_suffix([')', ']', '}']) + && let src = src.trim_end_matches(|c: char| c.is_whitespace() && c != '\n') + && let Some(src) = src.strip_suffix(',') + && let src = src.trim_end_matches(|c: char| c.is_whitespace() && c != '\n') + && !src.ends_with('\n') + { + span_lint_and_sugg( + self.cx, + UNNECESSARY_TRAILING_COMMA, + span.with_lo(span.lo() + BytePos::from_usize(src.len())) + .with_hi(span.hi() - BytePos(1)), + "unnecessary trailing comma", + "remove the trailing comma", + String::new(), + Applicability::MachineApplicable, + ); + } + } + fn check_templates(&mut self) { for piece in &self.format_args.template { if let FormatArgsPiece::Placeholder(placeholder) = piece diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index b9f16f2a371a..15f34169b0d8 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -1,3 +1,4 @@ +use clippy_utils::res::MaybeDef as _; use hir::FnSig; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -219,6 +220,13 @@ fn check_must_use_candidate<'tcx>( format!("#[must_use] \n{indent}"), Applicability::MachineApplicable, ); + if let Some(msg) = match return_ty(cx, item_id).opt_diag_name(cx) { + Some(sym::ControlFlow) => Some("`ControlFlow` as `C` when `B` is uninhabited"), + Some(sym::Result) => Some("`Result` as `T` when `E` is uninhabited"), + _ => None, + } { + diag.note(format!("a future version of Rust will treat {msg} wrt `#[must_use]`")); + } }); } diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 8f6de9fc60bd..8b0a4b4d78d9 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -252,10 +252,8 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { } } }, - ExprKind::Binary(op, l, r) => { - if op.node.is_comparison() { - return is_infinite(cx, l).and(is_infinite(cx, r)).and(MaybeInfinite); - } + ExprKind::Binary(op, l, r) if op.node.is_comparison() => { + return is_infinite(cx, l).and(is_infinite(cx, r)).and(MaybeInfinite); }, // TODO: ExprKind::Loop + Match _ => (), } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 653c1cc7280f..4dca8dfe94d0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -103,6 +103,7 @@ mod dereference; mod derivable_impls; mod derive; +mod disallowed_fields; mod disallowed_macros; mod disallowed_methods; mod disallowed_names; @@ -857,6 +858,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co Box::new(|_| Box::new(toplevel_ref_arg::ToplevelRefArg)), Box::new(|_| Box::new(volatile_composites::VolatileComposites)), Box::new(|_| Box::::default()), + Box::new(move |tcx| Box::new(disallowed_fields::DisallowedFields::new(tcx, conf))), Box::new(move |_| Box::new(manual_ilog2::ManualIlog2::new(conf))), Box::new(|_| Box::new(same_length_and_capacity::SameLengthAndCapacity)), Box::new(move |tcx| Box::new(duration_suboptimal_units::DurationSuboptimalUnits::new(tcx, conf))), diff --git a/clippy_lints/src/loops/explicit_counter_loop.rs b/clippy_lints/src/loops/explicit_counter_loop.rs index 9aa4d2f0adc2..bfd4d4bcd564 100644 --- a/clippy_lints/src/loops/explicit_counter_loop.rs +++ b/clippy_lints/src/loops/explicit_counter_loop.rs @@ -1,17 +1,19 @@ +use std::borrow::Cow; + use super::{EXPLICIT_COUNTER_LOOP, IncrementVisitor, InitializeVisitor, make_iterator_snippet}; -use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{get_enclosing_block, is_integer_const}; -use rustc_ast::Label; +use clippy_utils::sugg::{EMPTY, Sugg}; +use clippy_utils::{get_enclosing_block, is_integer_const, is_integer_literal_untyped}; +use rustc_ast::{Label, RangeLimits}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_block, walk_expr}; use rustc_hir::{Expr, Pat}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty, UintTy}; -// To trigger the EXPLICIT_COUNTER_LOOP lint, a variable must be -// incremented exactly once in the loop body, and initialized to zero -// at the start of the loop. +// To trigger the EXPLICIT_COUNTER_LOOP lint, a variable must be incremented exactly once in the +// loop body. pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, @@ -31,34 +33,11 @@ pub(super) fn check<'tcx>( let mut initialize_visitor = InitializeVisitor::new(cx, expr, id); walk_block(&mut initialize_visitor, block); - if let Some((name, ty, initializer)) = initialize_visitor.get_result() - && is_integer_const(cx, initializer, 0) - { + if let Some((name, ty, initializer)) = initialize_visitor.get_result() { + let is_zero = is_integer_const(cx, initializer, 0); let mut applicability = Applicability::MaybeIncorrect; let span = expr.span.with_hi(arg.span.hi()); let loop_label = label.map_or(String::new(), |l| format!("{}: ", l.ident.name)); - let int_name = match ty.map(Ty::kind) { - // usize or inferred - Some(ty::Uint(UintTy::Usize)) | None => { - span_lint_and_sugg( - cx, - EXPLICIT_COUNTER_LOOP, - span, - format!("the variable `{name}` is used as a loop counter"), - "consider using", - format!( - "{loop_label}for ({name}, {}) in {}.enumerate()", - snippet_with_applicability(cx, pat.span, "item", &mut applicability), - make_iterator_snippet(cx, arg, &mut applicability), - ), - applicability, - ); - return; - }, - Some(ty::Int(int_ty)) => int_ty.name_str(), - Some(ty::Uint(uint_ty)) => uint_ty.name_str(), - _ => return, - }; span_lint_and_then( cx, @@ -66,20 +45,52 @@ pub(super) fn check<'tcx>( span, format!("the variable `{name}` is used as a loop counter"), |diag| { + let pat_snippet = snippet_with_applicability(cx, pat.span, "item", &mut applicability); + let iter_snippet = make_iterator_snippet(cx, arg, &mut applicability); + let int_name = match ty.map(Ty::kind) { + Some(ty::Uint(UintTy::Usize)) | None => { + if is_zero { + diag.span_suggestion( + span, + "consider using", + format!( + "{loop_label}for ({name}, {pat_snippet}) in {iter_snippet}.enumerate()", + ), + applicability, + ); + return; + } + None + }, + Some(ty::Int(int_ty)) => Some(int_ty.name_str()), + Some(ty::Uint(uint_ty)) => Some(uint_ty.name_str()), + _ => None, + } + .filter(|_| is_integer_literal_untyped(initializer)); + + let initializer = Sugg::hir_from_snippet(cx, initializer, |span| { + let snippet = snippet_with_applicability(cx, span, "..", &mut applicability); + if let Some(int_name) = int_name { + return Cow::Owned(format!("{snippet}_{int_name}")); + } + snippet + }); + diag.span_suggestion( span, "consider using", format!( - "{loop_label}for ({name}, {}) in (0_{int_name}..).zip({})", - snippet_with_applicability(cx, pat.span, "item", &mut applicability), - make_iterator_snippet(cx, arg, &mut applicability), + "{loop_label}for ({name}, {pat_snippet}) in ({}).zip({iter_snippet})", + initializer.range(&EMPTY, RangeLimits::HalfOpen) ), applicability, ); - diag.note(format!( - "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`" - )); + if is_zero && let Some(int_name) = int_name { + diag.note(format!( + "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`" + )); + } }, ); } diff --git a/clippy_lints/src/loops/utils.rs b/clippy_lints/src/loops/utils.rs index 56d535c4f262..2c37e2679d97 100644 --- a/clippy_lints/src/loops/utils.rs +++ b/clippy_lints/src/loops/utils.rs @@ -57,19 +57,17 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { } match parent.kind { - ExprKind::AssignOp(op, lhs, rhs) => { - if lhs.hir_id == expr.hir_id { - *state = if op.node == AssignOpKind::AddAssign - && is_integer_const(self.cx, rhs, 1) - && *state == IncrementVisitorVarState::Initial - && self.depth == 0 - { - IncrementVisitorVarState::IncrOnce - } else { - // Assigned some other value or assigned multiple times - IncrementVisitorVarState::DontWarn - }; - } + ExprKind::AssignOp(op, lhs, rhs) if lhs.hir_id == expr.hir_id => { + *state = if op.node == AssignOpKind::AddAssign + && is_integer_const(self.cx, rhs, 1) + && *state == IncrementVisitorVarState::Initial + && self.depth == 0 + { + IncrementVisitorVarState::IncrOnce + } else { + // Assigned some other value or assigned multiple times + IncrementVisitorVarState::DontWarn + }; }, ExprKind::Assign(lhs, _, _) if lhs.hir_id == expr.hir_id => { *state = IncrementVisitorVarState::DontWarn; diff --git a/clippy_lints/src/macro_metavars_in_unsafe.rs b/clippy_lints/src/macro_metavars_in_unsafe.rs index db1ed269bb0e..4d8f10506b59 100644 --- a/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -243,8 +243,8 @@ fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { // We want to lint unsafe blocks #0 and #1 let bad_unsafe_blocks = self .metavar_expns - .iter() - .filter_map(|(_, state)| match state { + .values() + .filter_map(|state| match state { MetavarState::ReferencedInUnsafe { unsafe_blocks } => Some(unsafe_blocks.as_slice()), MetavarState::ReferencedInSafe => None, }) diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index cb3cc999c936..8b92c3b8cbeb 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -9,7 +9,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::def::{CtorOf, DefKind, Res}; -use rustc_hir::{Arm, Expr, ExprKind, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath, Stmt, StmtKind}; +use rustc_hir::{ + Arm, BlockCheckMode, Expr, ExprKind, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath, Stmt, StmtKind, +}; use rustc_lint::{LateContext, LintContext}; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; @@ -177,7 +179,10 @@ fn emit_manual_let_else( let (sn_expr, _) = snippet_with_context(cx, expr.span, span.ctxt(), "", &mut app); let (sn_else, else_is_mac_call) = snippet_with_context(cx, else_body.span, span.ctxt(), "", &mut app); - let else_bl = if matches!(else_body.kind, ExprKind::Block(..)) && !else_is_mac_call { + let else_bl = if let ExprKind::Block(block, None) = else_body.kind + && matches!(block.rules, BlockCheckMode::DefaultBlock) + && !else_is_mac_call + { sn_else.into_owned() } else { format!("{{ {sn_else} }}") diff --git a/clippy_lints/src/manual_option_as_slice.rs b/clippy_lints/src/manual_option_as_slice.rs index 5cf90eecaa97..cb451d8c0da3 100644 --- a/clippy_lints/src/manual_option_as_slice.rs +++ b/clippy_lints/src/manual_option_as_slice.rs @@ -59,12 +59,11 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { return; } match expr.kind { - ExprKind::Match(scrutinee, [arm1, arm2], _) => { + ExprKind::Match(scrutinee, [arm1, arm2], _) if is_none_pattern(cx, arm2.pat) && check_arms(cx, arm2, arm1) - || is_none_pattern(cx, arm1.pat) && check_arms(cx, arm1, arm2) - { - check_as_ref(cx, scrutinee, span, self.msrv); - } + || is_none_pattern(cx, arm1.pat) && check_arms(cx, arm1, arm2) => + { + check_as_ref(cx, scrutinee, span, self.msrv); }, ExprKind::If(cond, then, Some(other)) => { if let ExprKind::Let(let_expr) = cond.kind @@ -75,34 +74,24 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { check_as_ref(cx, let_expr.init, span, self.msrv); } }, - ExprKind::MethodCall(seg, callee, [], _) => { - if seg.ident.name == sym::unwrap_or_default { - check_map(cx, callee, span, self.msrv); - } + ExprKind::MethodCall(seg, callee, [], _) if seg.ident.name == sym::unwrap_or_default => { + check_map(cx, callee, span, self.msrv); }, ExprKind::MethodCall(seg, callee, [or], _) => match seg.ident.name { - sym::unwrap_or => { - if is_empty_slice(cx, or) { - check_map(cx, callee, span, self.msrv); - } + sym::unwrap_or if is_empty_slice(cx, or) => { + check_map(cx, callee, span, self.msrv); }, - sym::unwrap_or_else => { - if returns_empty_slice(cx, or) { - check_map(cx, callee, span, self.msrv); - } + sym::unwrap_or_else if returns_empty_slice(cx, or) => { + check_map(cx, callee, span, self.msrv); }, _ => {}, }, ExprKind::MethodCall(seg, callee, [or_else, map], _) => match seg.ident.name { - sym::map_or => { - if is_empty_slice(cx, or_else) && is_slice_from_ref(cx, map) { - check_as_ref(cx, callee, span, self.msrv); - } + sym::map_or if is_empty_slice(cx, or_else) && is_slice_from_ref(cx, map) => { + check_as_ref(cx, callee, span, self.msrv); }, - sym::map_or_else => { - if returns_empty_slice(cx, or_else) && is_slice_from_ref(cx, map) { - check_as_ref(cx, callee, span, self.msrv); - } + sym::map_or_else if returns_empty_slice(cx, or_else) && is_slice_from_ref(cx, map) => { + check_as_ref(cx, callee, span, self.msrv); }, _ => {}, }, diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index 8be53dbe4712..a3f6ea2d8886 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -242,13 +242,13 @@ fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { && self.cx.qpath_res(path, ex.hir_id) == self.target { match (self.strip_kind, start, end) { - (StripKind::Prefix, Some(start), None) => { - if eq_pattern_length(self.cx, self.pattern, start, self.ctxt) { - self.results.push(ex); - return; - } + (StripKind::Prefix, Some(start), None) + if eq_pattern_length(self.cx, self.pattern, start, self.ctxt) => + { + self.results.push(ex); + return; }, - (StripKind::Suffix, None, Some(end)) => { + (StripKind::Suffix, None, Some(end)) if let ExprKind::Binary( Spanned { node: BinOpKind::Sub, .. @@ -259,11 +259,10 @@ fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { && let Some(left_arg) = len_arg(self.cx, left) && let ExprKind::Path(left_path) = &left_arg.kind && self.cx.qpath_res(left_path, left_arg.hir_id) == self.target - && eq_pattern_length(self.cx, self.pattern, right, self.ctxt) - { - self.results.push(ex); - return; - } + && eq_pattern_length(self.cx, self.pattern, right, self.ctxt) => + { + self.results.push(ex); + return; }, _ => {}, } diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index b07d4fe81f8a..6a02bb38d17b 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -193,8 +193,10 @@ fn let_binding_name(cx: &LateContext<'_>, var_arg: &hir::Expr<'_>) -> String { } #[must_use] -fn suggestion_msg(function_type: &str, map_type: &str) -> String { - format!("called `map(f)` on an `{map_type}` value where `f` is a {function_type} that returns the unit type `()`") +fn suggestion_msg(function_type: &str, article: &str, map_type: &str) -> String { + format!( + "called `map(f)` on {article} `{map_type}` value where `f` is a {function_type} that returns the unit type `()`" + ) } fn lint_map_unit_fn( @@ -205,10 +207,10 @@ fn lint_map_unit_fn( ) { let var_arg = &map_args.0; - let (map_type, variant, lint) = if cx.typeck_results().expr_ty(var_arg).is_diag_item(cx, sym::Option) { - ("Option", "Some", OPTION_MAP_UNIT_FN) + let (article, map_type, variant, lint) = if cx.typeck_results().expr_ty(var_arg).is_diag_item(cx, sym::Option) { + ("an", "Option", "Some", OPTION_MAP_UNIT_FN) } else if cx.typeck_results().expr_ty(var_arg).is_diag_item(cx, sym::Result) { - ("Result", "Ok", RESULT_MAP_UNIT_FN) + ("a", "Result", "Ok", RESULT_MAP_UNIT_FN) } else { return; }; @@ -219,7 +221,7 @@ fn lint_map_unit_fn( if is_unit_function(cx, fn_arg) { let mut applicability = Applicability::MachineApplicable; - let msg = suggestion_msg("function", map_type); + let msg = suggestion_msg("function", article, map_type); let suggestion = format!( "if let {0}({binding}) = {1} {{ {2}({binding}) }}", variant, @@ -232,7 +234,7 @@ fn lint_map_unit_fn( diag.span_suggestion_verbose(stmt.span, SUGG_MSG, suggestion, applicability); }); } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { - let msg = suggestion_msg("closure", map_type); + let msg = suggestion_msg("closure", article, map_type); span_lint_and_then(cx, lint, expr.span, msg, |diag| { if let Some((reduced_expr_span, is_unsafe)) = reduce_unit_expression(cx, closure_expr) { diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs index 79f737f07eb1..c95a72da6e29 100644 --- a/clippy_lints/src/matches/collapsible_match.rs +++ b/clippy_lints/src/matches/collapsible_match.rs @@ -1,17 +1,19 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::higher::IfLetOrMatch; +use clippy_utils::higher::{If, IfLetOrMatch}; use clippy_utils::msrvs::Msrv; use clippy_utils::res::{MaybeDef, MaybeResPath}; -use clippy_utils::source::snippet; +use clippy_utils::source::{IntoSpan, SpanRangeExt, snippet}; use clippy_utils::visitors::is_local_used; use clippy_utils::{SpanlessEq, get_ref_operators, is_unit_expr, peel_blocks_with_stmt, peel_ref_operators}; use rustc_ast::BorrowKind; -use rustc_errors::MultiSpan; +use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::LangItem::OptionNone; use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatExpr, PatExprKind, PatKind}; use rustc_lint::LateContext; -use rustc_span::Span; use rustc_span::symbol::Ident; +use rustc_span::{BytePos, Span}; + +use crate::collapsible_if::{parens_around, peel_parens}; use super::{COLLAPSIBLE_MATCH, pat_contains_disallowed_or}; @@ -34,7 +36,7 @@ pub(super) fn check_if_let<'tcx>( check_arm(cx, false, pat, let_expr, body, None, else_expr, msrv); } -#[expect(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments, clippy::too_many_lines)] fn check_arm<'tcx>( cx: &LateContext<'tcx>, outer_is_match: bool, @@ -119,6 +121,70 @@ fn check_arm<'tcx>( "the outer pattern can be modified to include the inner pattern", ); }); + } else if outer_is_match // Leave if-let to the `collapsible_if` lint + && let Some(inner) = If::hir(inner_expr) + && outer_pat.span.eq_ctxt(inner.cond.span) + && match (outer_else_body, inner.r#else) { + (None, None) => true, + (None, Some(e)) | (Some(e), None) => is_unit_expr(e), + (Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b), + } + { + span_lint_hir_and_then( + cx, + COLLAPSIBLE_MATCH, + inner_expr.hir_id, + inner_expr.span, + "this `if` can be collapsed into the outer `match`", + |diag| { + let outer_then_open_bracket = outer_then_body + .span + .split_at(1) + .0 + .with_leading_whitespace(cx) + .into_span(); + let outer_then_closing_bracket = { + let end = outer_then_body.span.shrink_to_hi(); + end.with_lo(end.lo() - BytePos(1)) + .with_leading_whitespace(cx) + .into_span() + }; + let outer_arrow_end = if let Some(outer_guard) = outer_guard { + outer_guard.span.shrink_to_hi() + } else { + outer_pat.span.shrink_to_hi() + }; + let (paren_start, inner_if_span, paren_end) = peel_parens(cx.tcx.sess.source_map(), inner_expr.span); + let inner_if = inner_if_span.split_at(2).0; + let mut sugg = vec![ + (inner.then.span.shrink_to_lo(), "=> ".to_string()), + (outer_arrow_end.to(outer_then_open_bracket), String::new()), + (outer_then_closing_bracket, String::new()), + ]; + + if let Some(outer_guard) = outer_guard { + sugg.extend(parens_around(outer_guard)); + sugg.push((inner_if, "&&".to_string())); + } + + if !paren_start.is_empty() { + sugg.push((paren_start, String::new())); + } + + if !paren_end.is_empty() { + sugg.push((paren_end, String::new())); + } + + sugg.extend(parens_around(inner.cond)); + + if let Some(else_inner) = inner.r#else { + let else_inner_span = inner.then.span.shrink_to_hi().to(else_inner.span); + sugg.push((else_inner_span, String::new())); + } + + diag.multipart_suggestion("collapse nested if block", sugg, Applicability::MachineApplicable); + }, + ); } } diff --git a/clippy_lints/src/matches/match_single_binding.rs b/clippy_lints/src/matches/match_single_binding.rs index e40e21c490f3..3c0fad01835f 100644 --- a/clippy_lints/src/matches/match_single_binding.rs +++ b/clippy_lints/src/matches/match_single_binding.rs @@ -386,10 +386,8 @@ fn sugg_with_curlies<'a>( | Node::Expr(Expr { kind: ExprKind::Block(..) | ExprKind::ConstBlock(..), .. - }) => { - if needs_var_binding && is_var_binding_used_later { - add_curlies(); - } + }) if needs_var_binding && is_var_binding_used_later => { + add_curlies(); }, Node::Expr(..) | Node::AnonConst(..) diff --git a/clippy_lints/src/methods/clone_on_ref_ptr.rs b/clippy_lints/src/methods/clone_on_ref_ptr.rs index 238e1fe988b3..de32b0476d20 100644 --- a/clippy_lints/src/methods/clone_on_ref_ptr.rs +++ b/clippy_lints/src/methods/clone_on_ref_ptr.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_with_context; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::peel_and_count_ty_refs; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -9,9 +10,10 @@ use super::CLONE_ON_REF_PTR; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>) { - let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); + let receiver_ty = cx.typeck_results().expr_ty(receiver); + let (receiver_ty_peeled, n_refs, _) = peel_and_count_ty_refs(receiver_ty); - if let ty::Adt(adt, subst) = obj_ty.kind() + if let ty::Adt(adt, subst) = receiver_ty_peeled.kind() && let Some(name) = cx.tcx.get_diagnostic_name(adt.did()) { let caller_type = match name { @@ -29,20 +31,26 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir:: |diag| { // Sometimes unnecessary ::<_> after Rc/Arc/Weak let mut app = Applicability::Unspecified; - let snippet = snippet_with_context(cx, receiver.span, expr.span.ctxt(), "..", &mut app).0; + let mut sugg = Sugg::hir_with_context(cx, receiver, expr.span.ctxt(), "..", &mut app); + if n_refs == 0 { + sugg = sugg.addr(); + } + // References on argument position don't need to preserve parentheses + // even if they were present in the original expression. + sugg = sugg.strip_paren(); let generic = subst.type_at(0); if generic.is_suggestable(cx.tcx, true) { diag.span_suggestion( expr.span, "try", - format!("{caller_type}::<{generic}>::clone(&{snippet})"), + format!("{caller_type}::<{generic}>::clone({sugg})"), app, ); } else { diag.span_suggestion( expr.span, "try", - format!("{caller_type}::::clone(&{snippet})"), + format!("{caller_type}::::clone({sugg})"), Applicability::HasPlaceholders, ); } diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs index 366bfaed73d4..79034fa23300 100644 --- a/clippy_lints/src/methods/iter_kv_map.rs +++ b/clippy_lints/src/methods/iter_kv_map.rs @@ -21,6 +21,7 @@ pub(super) fn check<'tcx>( recv: &'tcx Expr<'tcx>, // hashmap m_arg: &'tcx Expr<'tcx>, // |(_, v)| v msrv: Msrv, + method_name: Symbol, ) { if map_type == sym::into_iter && !msrv.meets(cx, msrvs::INTO_KEYS) { return; @@ -67,7 +68,7 @@ pub(super) fn check<'tcx>( format!("iterating on a map's {replacement_kind}s"), "try", format!( - "{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{}{bound_ident}| {body_snippet})", + "{recv_snippet}.{into_prefix}{replacement_kind}s().{method_name}(|{}{bound_ident}| {body_snippet})", annotation.prefix_str(), ), applicability, diff --git a/clippy_lints/src/methods/iter_overeager_cloned.rs b/clippy_lints/src/methods/iter_overeager_cloned.rs index e3bcca64e923..241791e57c8e 100644 --- a/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -1,13 +1,15 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{implements_trait, is_copy}; +use clippy_utils::visitors::for_each_expr_without_closures; +use core::ops::ControlFlow; use rustc_ast::BindingMode; use rustc_errors::Applicability; -use rustc_hir::{Body, Expr, ExprKind, HirId, HirIdSet, PatKind}; +use rustc_hir::{Body, CaptureBy, Closure, Expr, ExprKind, HirId, HirIdSet, Param, PatKind}; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_lint::LateContext; use rustc_middle::mir::{FakeReadCause, Mutability}; -use rustc_middle::ty::{self, BorrowKind}; +use rustc_middle::ty::{self, BorrowKind, UpvarCapture}; use rustc_span::{Symbol, sym}; use super::{ITER_OVEREAGER_CLONED, REDUNDANT_ITER_CLONED}; @@ -64,6 +66,11 @@ pub(super) fn check<'tcx>( let body @ Body { params: [p], .. } = cx.tcx.hir_body(closure.body) else { return; }; + + if param_captured_by_move_block(cx, body.value, p) { + return; + } + let mut delegate = MoveDelegate { used_move: HirIdSet::default(), }; @@ -140,6 +147,34 @@ struct MoveDelegate { used_move: HirIdSet, } +/// Checks if the expression contains a closure or coroutine with `move` capture semantics that +/// captures the given parameter. +fn param_captured_by_move_block(cx: &LateContext<'_>, expr: &Expr<'_>, param: &Param<'_>) -> bool { + let mut param_hir_ids = HirIdSet::default(); + param.pat.walk(|pat| { + param_hir_ids.insert(pat.hir_id); + true + }); + + for_each_expr_without_closures(expr, |e| { + if let ExprKind::Closure(Closure { + capture_clause: CaptureBy::Value { .. }, + def_id, + .. + }) = e.kind + && cx.tcx.closure_captures(*def_id).iter().any(|capture| { + matches!(capture.info.capture_kind, UpvarCapture::ByValue) + && matches!(capture.place.base, PlaceBase::Upvar(upvar) if param_hir_ids.contains(&upvar.var_path.hir_id)) + }) + { + return ControlFlow::Break(()); + } + + ControlFlow::Continue(()) + }) + .is_some() +} + impl<'tcx> Delegate<'tcx> for MoveDelegate { fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, _: HirId) { if let PlaceBase::Local(l) = place_with_id.place.base { diff --git a/clippy_lints/src/methods/join_absolute_paths.rs b/clippy_lints/src/methods/join_absolute_paths.rs index c731c2fc9434..248c76181250 100644 --- a/clippy_lints/src/methods/join_absolute_paths.rs +++ b/clippy_lints/src/methods/join_absolute_paths.rs @@ -2,7 +2,7 @@ use clippy_utils::{expr_or_init, sym}; use clippy_utils::res::MaybeDef; use clippy_utils::source::snippet; -use rustc_ast::ast::LitKind; +use rustc_ast::ast::{LitKind, StrStyle}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a let ty = cx.typeck_results().expr_ty(recv).peel_refs(); if matches!(ty.opt_diag_name(cx), Some(sym::Path | sym::PathBuf)) && let ExprKind::Lit(spanned) = expr_or_init(cx, join_arg).kind - && let LitKind::Str(symbol, _) = spanned.node + && let LitKind::Str(symbol, style) = spanned.node && let sym_str = symbol.as_str() && sym_str.starts_with(['/', '\\']) { @@ -28,8 +28,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a let no_separator = if sym_str.starts_with('/') { arg_str.replacen('/', "", 1) - } else { + } else if let StrStyle::Raw(_) = style { arg_str.replacen('\\', "", 1) + } else { + arg_str.replacen("\\\\", "", 1) }; diag.note("joining a path starting with separator will replace the path instead") diff --git a/clippy_lints/src/methods/manual_is_variant_and.rs b/clippy_lints/src/methods/manual_is_variant_and.rs index d877b0a62291..472d21977c7a 100644 --- a/clippy_lints/src/methods/manual_is_variant_and.rs +++ b/clippy_lints/src/methods/manual_is_variant_and.rs @@ -290,3 +290,43 @@ pub(super) fn check_or<'tcx>( }, ); } + +pub(super) fn check_is_some_is_none<'tcx>( + cx: &LateContext<'tcx>, + call_span: Span, + recv: &'tcx Expr<'tcx>, + arg: &'tcx Expr<'tcx>, + is_some: bool, + msrv: Msrv, +) { + if cx + .typeck_results() + .expr_ty_adjusted(recv) + .peel_refs() + .is_diag_item(cx, sym::Option) + && (is_some || msrv.meets(cx, msrvs::IS_NONE_OR)) + && let Ok(map_func) = MapFunc::try_from(arg) + { + let method = if is_some { "is_some_and" } else { "is_none_or" }; + let lint_span = recv.span.to(call_span); + span_lint_and_then( + cx, + MANUAL_IS_VARIANT_AND, + lint_span, + format!("manual implementation of `Option::{method}`"), + |diag| { + let mut app = Applicability::MachineApplicable; + let (recv_snip, _) = snippet_with_context(cx, recv.span, lint_span.ctxt(), "_", &mut app); + let map_func_snip = map_func.sugg(cx, !is_some, &mut app); + + // We need to use `as_ref()` because `filter` takes a reference + diag.span_suggestion( + lint_span, + "use", + format!("{recv_snip}.as_ref().{method}({map_func_snip})"), + app, + ); + }, + ); + } +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 264405e6c3fb..74db7ae03ba0 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4760,6 +4760,7 @@ pub struct Methods { allow_unwrap_in_consts: bool, allowed_dotfiles: FxHashSet<&'static str>, format_args: FormatArgsStorage, + allow_unwrap_types: Vec, } impl Methods { @@ -4776,6 +4777,7 @@ pub fn new(conf: &'static Conf, format_args: FormatArgsStorage) -> Self { allow_unwrap_in_consts: conf.allow_unwrap_in_consts, allowed_dotfiles, format_args, + allow_unwrap_types: conf.allow_unwrap_types.clone(), } } } @@ -4974,6 +4976,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { self.allow_expect_in_tests, self.allow_unwrap_in_consts, self.allow_expect_in_consts, + &self.allow_unwrap_types, ); }, ExprKind::MethodCall(..) => { @@ -5165,6 +5168,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { format_collect::check(cx, expr, m_arg, m_ident_span); }, Some((sym::take, take_self_arg, [take_arg], _, _)) => { + #[expect(clippy::collapsible_match)] if self.msrv.meets(cx, msrvs::STR_REPEAT) { manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg); } @@ -5275,6 +5279,9 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { call_span, self.msrv, ); + if let Some((map_name @ (sym::iter | sym::into_iter), recv2, _, _, _)) = method_call(recv) { + iter_kv_map::check(cx, map_name, expr, recv2, arg, self.msrv, sym::filter_map); + } }, (sym::find_map, [arg]) => { unnecessary_filter_map::check(cx, expr, arg, call_span, unnecessary_filter_map::Kind::FindMap); @@ -5285,6 +5292,9 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { lines_filter_map_ok::check_filter_or_flat_map( cx, expr, recv, "flat_map", arg, call_span, self.msrv, ); + if let Some((map_name @ (sym::iter | sym::into_iter), recv2, _, _, _)) = method_call(recv) { + iter_kv_map::check(cx, map_name, expr, recv2, arg, self.msrv, sym::flat_map); + } }, (sym::flatten, []) => { match method_call(recv) { @@ -5343,8 +5353,8 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { }, (sym::is_file, []) => filetype_is_file::check(cx, expr, recv), (sym::is_digit, [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, self.msrv), - (sym::is_none, []) => check_is_some_is_none(cx, expr, recv, call_span, false), - (sym::is_some, []) => check_is_some_is_none(cx, expr, recv, call_span, true), + (sym::is_none, []) => check_is_some_is_none(cx, expr, recv, call_span, false, self.msrv), + (sym::is_some, []) => check_is_some_is_none(cx, expr, recv, call_span, true, self.msrv), (sym::iter | sym::iter_mut | sym::into_iter, []) => { iter_on_single_or_empty_collections::check(cx, expr, name, recv); }, @@ -5383,7 +5393,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { manual_is_variant_and::check_map(cx, expr); match method_call(recv) { Some((map_name @ (sym::iter | sym::into_iter), recv2, _, _, _)) => { - iter_kv_map::check(cx, map_name, expr, recv2, m_arg, self.msrv); + iter_kv_map::check(cx, map_name, expr, recv2, m_arg, self.msrv, sym::map); }, Some((sym::cloned, recv2, [], _, _)) => iter_overeager_cloned::check( cx, @@ -5484,7 +5494,9 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { (sym::open, [_]) => { open_options::check(cx, expr, recv); }, - (sym::or_else, [arg]) => { + (sym::or_else, [arg]) => + { + #[expect(clippy::collapsible_match)] if !bind_instead_of_map::check_or_else_err(cx, expr, recv, arg) { unnecessary_lazy_eval::check(cx, expr, recv, arg, "or"); } @@ -5589,7 +5601,9 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { (sym::try_into, []) if cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::TryInto) => { unnecessary_fallible_conversions::check_method(cx, expr); }, - (sym::to_owned, []) => { + (sym::to_owned, []) => + { + #[expect(clippy::collapsible_match)] if !suspicious_to_owned::check(cx, expr, span) { implicit_clone::check(cx, name, expr, recv); } @@ -5716,6 +5730,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { false, self.allow_expect_in_consts, self.allow_expect_in_tests, + &self.allow_unwrap_types, unwrap_expect_used::Variant::Expect, ); expect_fun_call::check(cx, &self.format_args, expr, method_span, recv, arg); @@ -5728,6 +5743,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { true, self.allow_expect_in_consts, self.allow_expect_in_tests, + &self.allow_unwrap_types, unwrap_expect_used::Variant::Expect, ); }, @@ -5748,6 +5764,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { false, self.allow_unwrap_in_consts, self.allow_unwrap_in_tests, + &self.allow_unwrap_types, unwrap_expect_used::Variant::Unwrap, ); }, @@ -5759,6 +5776,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { true, self.allow_unwrap_in_consts, self.allow_unwrap_in_tests, + &self.allow_unwrap_types, unwrap_expect_used::Variant::Unwrap, ); }, @@ -5768,7 +5786,14 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { } } -fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, call_span: Span, is_some: bool) { +fn check_is_some_is_none<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + recv: &'tcx Expr<'tcx>, + call_span: Span, + is_some: bool, + msrv: Msrv, +) { match method_call(recv) { Some((name @ (sym::find | sym::position | sym::rposition), f_recv, [arg], span, _)) => { search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span); @@ -5779,6 +5804,9 @@ fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, Some((sym::first, f_recv, [], _, _)) => { unnecessary_first_then_check::check(cx, call_span, recv, f_recv, is_some); }, + Some((sym::filter, f_recv, [arg], _, _)) => { + manual_is_variant_and::check_is_some_is_none(cx, call_span, f_recv, arg, is_some, msrv); + }, _ => {}, } } diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs index 832197d36cc6..94c61a74dac6 100644 --- a/clippy_lints/src/methods/or_fun_call.rs +++ b/clippy_lints/src/methods/or_fun_call.rs @@ -84,10 +84,10 @@ pub(super) fn check<'tcx>( return ControlFlow::Break(()); } }, - hir::ExprKind::MethodCall(..) => { - if check_or_fn_call(cx, name, method_span, receiver, arg, Some(lambda), expr.span, None) { - return ControlFlow::Break(()); - } + hir::ExprKind::MethodCall(..) + if check_or_fn_call(cx, name, method_span, receiver, arg, Some(lambda), expr.span, None) => + { + return ControlFlow::Break(()); }, _ => {}, } diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index 72f1c42da2ee..54f3fe410519 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -131,17 +131,13 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc } (true, true) }, - hir::ExprKind::MethodCall(segment, recv, [arg], _) => { + hir::ExprKind::MethodCall(segment, recv, [arg], _) if segment.ident.name == sym::then_some && cx.typeck_results().expr_ty(recv).is_bool() - && arg.res_local_id() == Some(arg_id) - { - // bool.then_some(arg_id) - (false, true) - } else { - // bool.then_some(not arg_id) - (true, true) - } + && arg.res_local_id() == Some(arg_id) => + { + // bool.then_some(arg_id) + (false, true) }, hir::ExprKind::Block(block, _) => block .expr diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index c3f031edff2e..367d98ece195 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -89,6 +89,28 @@ fn maybe_turbofish(&self, ty: Ty<'_>) -> String { } } +fn get_triggered_expr_span( + left_expr: &hir::Expr<'_>, + right_expr: &hir::Expr<'_>, + first_arg_id: hir::HirId, + second_arg_id: hir::HirId, + replacement: Replacement, +) -> Option { + if left_expr.res_local_id() == Some(first_arg_id) + && (replacement.has_args || right_expr.res_local_id() == Some(second_arg_id)) + { + right_expr.span.into() + } + // https://github.com/rust-lang/rust-clippy/issues/16581 + else if right_expr.res_local_id() == Some(first_arg_id) + && (replacement.has_args || left_expr.res_local_id() == Some(second_arg_id)) + { + left_expr.span.into() + } else { + None + } +} + fn check_fold_with_op( cx: &LateContext<'_>, expr: &hir::Expr<'_>, @@ -111,8 +133,13 @@ fn check_fold_with_op( && let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind && let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind - && left_expr.res_local_id() == Some(first_arg_id) - && (replacement.has_args || right_expr.res_local_id() == Some(second_arg_id)) + && let Some(triggered_expr_span) = get_triggered_expr_span( + left_expr, + right_expr, + first_arg_id, + second_arg_id, + replacement + ) { let span = fold_span.with_hi(expr.span.hi()); span_lint_and_then( @@ -125,7 +152,7 @@ fn check_fold_with_op( let turbofish = replacement.maybe_turbofish(cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs()); let (r_snippet, _) = - snippet_with_context(cx, right_expr.span, expr.span.ctxt(), "EXPR", &mut applicability); + snippet_with_context(cx, triggered_expr_span, expr.span.ctxt(), "EXPR", &mut applicability); let sugg = if replacement.has_args { format!( "{method}{turbofish}(|{second_arg_ident}| {r_snippet})", diff --git a/clippy_lints/src/methods/unnecessary_min_or_max.rs b/clippy_lints/src/methods/unnecessary_min_or_max.rs index bf91a469e7f0..ea1dff636940 100644 --- a/clippy_lints/src/methods/unnecessary_min_or_max.rs +++ b/clippy_lints/src/methods/unnecessary_min_or_max.rs @@ -88,7 +88,17 @@ fn detect_extrema<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option< match (cv.int_value(cx.tcx, ty)?, ty.kind()) { (FullInt::S(i), &ty::Int(ity)) if i == i128::MIN >> (128 - ity.bit_width()?) => Some(Extrema::Minimum), (FullInt::S(i), &ty::Int(ity)) if i == i128::MAX >> (128 - ity.bit_width()?) => Some(Extrema::Maximum), - (FullInt::U(i), &ty::Uint(uty)) if i == u128::MAX >> (128 - uty.bit_width()?) => Some(Extrema::Maximum), + (FullInt::U(i), &ty::Uint(uty)) + if { + let bits = match uty { + ty::UintTy::Usize => u32::try_from(cx.tcx.data_layout.pointer_size().bits()).ok()?, + _ => u32::try_from(uty.bit_width()?).ok()?, + }; + i == u128::MAX >> (128 - bits) + } => + { + Some(Extrema::Maximum) + }, (FullInt::U(0), &ty::Uint(_)) => Some(Extrema::Minimum), _ => None, } diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 607aaef9627b..af5498c353d4 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -482,15 +482,11 @@ fn get_input_traits_and_projections<'tcx>( let mut projection_predicates = Vec::new(); for predicate in cx.tcx.param_env(callee_def_id).caller_bounds() { match predicate.kind().skip_binder() { - ClauseKind::Trait(trait_predicate) => { - if trait_predicate.trait_ref.self_ty() == input { - trait_predicates.push(trait_predicate); - } + ClauseKind::Trait(trait_predicate) if trait_predicate.trait_ref.self_ty() == input => { + trait_predicates.push(trait_predicate); }, - ClauseKind::Projection(projection_predicate) => { - if projection_predicate.projection_term.self_ty() == input { - projection_predicates.push(projection_predicate); - } + ClauseKind::Projection(projection_predicate) if projection_predicate.projection_term.self_ty() == input => { + projection_predicates.push(projection_predicate); }, _ => {}, } @@ -702,8 +698,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx sym::to_vec => cx .tcx .impl_of_assoc(method_def_id) - .filter(|&impl_did| cx.tcx.type_of(impl_did).instantiate_identity().is_slice()) - .is_some(), + .is_some_and(|impl_did| cx.tcx.type_of(impl_did).instantiate_identity().is_slice()), _ => false, } && let original_arg_ty = cx.typeck_results().node_type(caller.hir_id).peel_refs() diff --git a/clippy_lints/src/methods/unwrap_expect_used.rs b/clippy_lints/src/methods/unwrap_expect_used.rs index 4effab3a5e63..6d8777cbc23f 100644 --- a/clippy_lints/src/methods/unwrap_expect_used.rs +++ b/clippy_lints/src/methods/unwrap_expect_used.rs @@ -36,6 +36,7 @@ fn lint(self) -> &'static Lint { /// Lint usage of `unwrap` or `unwrap_err` for `Result` and `unwrap()` for `Option` (and their /// `expect` counterparts). +#[allow(clippy::too_many_arguments)] pub(super) fn check( cx: &LateContext<'_>, expr: &Expr<'_>, @@ -43,6 +44,7 @@ pub(super) fn check( is_err: bool, allow_unwrap_in_consts: bool, allow_unwrap_in_tests: bool, + allow_unwrap_types: &[String], variant: Variant, ) { let ty = cx.typeck_results().expr_ty(recv).peel_refs(); @@ -64,6 +66,54 @@ pub(super) fn check( let method_suffix = if is_err { "_err" } else { "" }; + let ty_name = ty.to_string(); + if allow_unwrap_types + .iter() + .any(|allowed_type| ty_name.starts_with(allowed_type) || ty_name == *allowed_type) + { + return; + } + + for s in allow_unwrap_types { + let def_ids = clippy_utils::paths::lookup_path_str(cx.tcx, clippy_utils::paths::PathNS::Type, s); + for def_id in def_ids { + if let ty::Adt(adt, _) = ty.kind() + && adt.did() == def_id + { + return; + } + if cx.tcx.def_kind(def_id) == DefKind::TyAlias { + let alias_ty = cx.tcx.type_of(def_id).instantiate_identity(); + if let (ty::Adt(adt, substs), ty::Adt(alias_adt, alias_substs)) = (ty.kind(), alias_ty.kind()) + && adt.did() == alias_adt.did() + { + let mut all_match = true; + for (arg, alias_arg) in substs.iter().zip(alias_substs.iter()) { + if let (Some(arg_ty), Some(alias_arg_ty)) = (arg.as_type(), alias_arg.as_type()) { + if matches!(alias_arg_ty.kind(), ty::Param(_)) { + continue; + } + if let (ty::Adt(arg_adt, _), ty::Adt(alias_arg_adt, _)) = + (arg_ty.peel_refs().kind(), alias_arg_ty.peel_refs().kind()) + { + if arg_adt.did() != alias_arg_adt.did() { + all_match = false; + break; + } + } else if arg_ty != alias_arg_ty { + all_match = false; + break; + } + } + } + if all_match { + return; + } + } + } + } + } + if allow_unwrap_in_tests && is_in_test(cx.tcx, expr.hir_id) { return; } @@ -99,6 +149,7 @@ pub(super) fn check_call( allow_unwrap_in_tests: bool, allow_expect_in_consts: bool, allow_expect_in_tests: bool, + allow_unwrap_types: &[String], ) { let Some(recv) = args.first() else { return; @@ -116,6 +167,7 @@ pub(super) fn check_call( false, allow_unwrap_in_consts, allow_unwrap_in_tests, + allow_unwrap_types, Variant::Unwrap, ); }, @@ -127,6 +179,7 @@ pub(super) fn check_call( false, allow_expect_in_consts, allow_expect_in_tests, + allow_unwrap_types, Variant::Expect, ); }, @@ -138,6 +191,7 @@ pub(super) fn check_call( true, allow_unwrap_in_consts, allow_unwrap_in_tests, + allow_unwrap_types, Variant::Unwrap, ); }, @@ -149,6 +203,7 @@ pub(super) fn check_call( true, allow_expect_in_consts, allow_expect_in_tests, + allow_unwrap_types, Variant::Expect, ); }, diff --git a/clippy_lints/src/missing_assert_message.rs b/clippy_lints/src/missing_assert_message.rs index 86348f04600b..dcb185b51a09 100644 --- a/clippy_lints/src/missing_assert_message.rs +++ b/clippy_lints/src/missing_assert_message.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_in_test; -use clippy_utils::macros::{PanicExpn, find_assert_args, find_assert_eq_args, root_macro_call_first_node}; +use clippy_utils::macros::{find_assert_args, find_assert_eq_args, root_macro_call_first_node}; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -78,7 +78,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { panic_expn }; - if let PanicExpn::Empty = panic_expn { + if panic_expn.is_default_message() { #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] span_lint_and_then( cx, diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index ddd4271960e1..53f97abe0b44 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -154,18 +154,14 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) { match e.kind { // fix #10776 ExprKind::Block(block, ..) => match (block.stmts, block.expr) { - (stmts, Some(e)) => { - if stmts.iter().all(|stmt| !stmt_might_diverge(stmt)) { - self.visit_expr(e); - } + (stmts, Some(e)) if stmts.iter().all(|stmt| !stmt_might_diverge(stmt)) => { + self.visit_expr(e); }, - ([first @ .., stmt], None) => { - if first.iter().all(|stmt| !stmt_might_diverge(stmt)) { - match stmt.kind { - StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), - _ => {}, - } - } + ([first @ .., stmt], None) + if first.iter().all(|stmt| !stmt_might_diverge(stmt)) + && let StmtKind::Expr(e) | StmtKind::Semi(e) = stmt.kind => + { + self.visit_expr(e); }, _ => {}, }, diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 42dc9f2f1fa8..ebf7ccfd5ba7 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -165,10 +165,8 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { return self.visit_expr(inner); }, - ExprKind::Field(e, _) => { - if self.typeck_results.expr_ty(e).is_union() { - self.insert_span(expr.span, "union field access occurs here"); - } + ExprKind::Field(e, _) if self.typeck_results.expr_ty(e).is_union() => { + self.insert_span(expr.span, "union field access occurs here"); }, ExprKind::Path(QPath::Resolved( diff --git a/clippy_lints/src/mutable_debug_assertion.rs b/clippy_lints/src/mutable_debug_assertion.rs index 3b271ca0dc14..a18817ac716b 100644 --- a/clippy_lints/src/mutable_debug_assertion.rs +++ b/clippy_lints/src/mutable_debug_assertion.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::macros::{find_assert_eq_args, root_macro_call_first_node}; +use clippy_utils::macros::{MacroCall, find_assert_args, find_assert_eq_args, root_macro_call_first_node}; use clippy_utils::sym; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{BorrowKind, Expr, ExprKind, MatchSource, Mutability}; @@ -43,33 +43,39 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { let Some(macro_call) = root_macro_call_first_node(cx, e) else { return; }; - if !matches!( - cx.tcx.get_diagnostic_name(macro_call.def_id), - Some(sym::debug_assert_macro | sym::debug_assert_eq_macro | sym::debug_assert_ne_macro) - ) { - return; - } - let Some((lhs, rhs, _)) = find_assert_eq_args(cx, e, macro_call.expn) else { - return; - }; - for arg in [lhs, rhs] { - let mut visitor = MutArgVisitor::new(cx); - visitor.visit_expr(arg); - if let Some(span) = visitor.expr_span() { - span_lint( - cx, - DEBUG_ASSERT_WITH_MUT_CALL, - span, - format!( - "do not call a function with mutable arguments inside of `{}!`", - cx.tcx.item_name(macro_call.def_id) - ), - ); - } + match cx.tcx.get_diagnostic_name(macro_call.def_id) { + Some(sym::debug_assert_macro) => { + if let Some((arg, _)) = find_assert_args(cx, e, macro_call.expn) { + check_arg(cx, arg, ¯o_call); + } + }, + Some(sym::debug_assert_ne_macro | sym::debug_assert_eq_macro) => { + if let Some((lhs, rhs, _)) = find_assert_eq_args(cx, e, macro_call.expn) { + check_arg(cx, lhs, ¯o_call); + check_arg(cx, rhs, ¯o_call); + } + }, + _ => {}, } } } +fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>, macro_call: &MacroCall) { + let mut visitor = MutArgVisitor::new(cx); + visitor.visit_expr(arg); + if let Some(span) = visitor.expr_span() { + span_lint( + cx, + DEBUG_ASSERT_WITH_MUT_CALL, + span, + format!( + "do not call a function with mutable arguments inside of `{}!`", + cx.tcx.item_name(macro_call.def_id) + ), + ); + } +} + struct MutArgVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, expr_span: Option, diff --git a/clippy_lints/src/needless_maybe_sized.rs b/clippy_lints/src/needless_maybe_sized.rs index 4bcd26c74f57..e7ae54e0d0e1 100644 --- a/clippy_lints/src/needless_maybe_sized.rs +++ b/clippy_lints/src/needless_maybe_sized.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_from_proc_macro; use rustc_errors::Applicability; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_hir::{BoundPolarity, GenericBound, Generics, PolyTraitRef, TraitBoundModifiers, WherePredicateKind}; @@ -34,6 +35,7 @@ declare_lint_pass!(NeedlessMaybeSized => [NEEDLESS_MAYBE_SIZED]); #[expect(clippy::struct_field_names)] +#[derive(Debug)] struct Bound<'tcx> { /// The [`DefId`] of the type parameter the bound refers to param: DefId, @@ -127,6 +129,7 @@ fn check_generics(&mut self, cx: &LateContext<'_>, generics: &Generics<'_>) { if bound.trait_bound.modifiers == TraitBoundModifiers::NONE && let Some(sized_bound) = maybe_sized_params.get(&bound.param) && let Some(path) = path_to_sized_bound(cx, bound.trait_bound) + && !is_from_proc_macro(cx, bound.trait_bound) { span_lint_and_then( cx, diff --git a/clippy_lints/src/non_send_fields_in_send_ty.rs b/clippy_lints/src/non_send_fields_in_send_ty.rs index fd5562f310e4..3c4dfade3439 100644 --- a/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -205,17 +205,13 @@ fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t .iter() .all(|ty| ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait)), ty::Array(ty, _) | ty::Slice(ty) => ty_allowed_with_raw_pointer_heuristic(cx, *ty, send_trait), - ty::Adt(_, args) => { - if contains_pointer_like(cx, ty) { - // descends only if ADT contains any raw pointers - args.iter().all(|generic_arg| match generic_arg.kind() { - GenericArgKind::Type(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait), - // Lifetimes and const generics are not solid part of ADT and ignored - GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => true, - }) - } else { - false - } + ty::Adt(_, args) if contains_pointer_like(cx, ty) => { + // descends only if ADT contains any raw pointers + args.iter().all(|generic_arg| match generic_arg.kind() { + GenericArgKind::Type(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait), + // Lifetimes and const generics are not solid part of ADT and ignored + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => true, + }) }, // Raw pointers are `!Send` but allowed by the heuristic ty::RawPtr(_, _) => true, @@ -231,10 +227,8 @@ fn contains_pointer_like<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> b ty::RawPtr(_, _) => { return true; }, - ty::Adt(adt_def, _) => { - if cx.tcx.is_diagnostic_item(sym::NonNull, adt_def.did()) { - return true; - } + ty::Adt(adt_def, _) if cx.tcx.is_diagnostic_item(sym::NonNull, adt_def.did()) => { + return true; }, _ => (), } diff --git a/clippy_lints/src/operators/bit_mask.rs b/clippy_lints/src/operators/bit_mask.rs index d6af0234f010..7f6dea573de8 100644 --- a/clippy_lints/src/operators/bit_mask.rs +++ b/clippy_lints/src/operators/bit_mask.rs @@ -71,15 +71,13 @@ fn check_bit_mask( span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); } }, - BinOpKind::BitOr => { - if mask_value | cmp_value != cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - span, - format!("incompatible bit mask: `_ | {mask_value}` can never be equal to `{cmp_value}`"), - ); - } + BinOpKind::BitOr if mask_value | cmp_value != cmp_value => { + span_lint( + cx, + BAD_BIT_MASK, + span, + format!("incompatible bit mask: `_ | {mask_value}` can never be equal to `{cmp_value}`"), + ); }, _ => (), }, diff --git a/clippy_lints/src/operators/identity_op.rs b/clippy_lints/src/operators/identity_op.rs index 92515bd3fb80..ce50e6e35dcc 100644 --- a/clippy_lints/src/operators/identity_op.rs +++ b/clippy_lints/src/operators/identity_op.rs @@ -52,11 +52,9 @@ pub(crate) fn check<'tcx>( span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); } }, - BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => { - if is_redundant_op(cx, right, 0, ctxt) { - let paren = needs_parenthesis(cx, expr, left); - span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); - } + BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub if is_redundant_op(cx, right, 0, ctxt) => { + let paren = needs_parenthesis(cx, expr, left); + span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); }, BinOpKind::Mul => { if is_redundant_op(cx, left, 1, ctxt) { @@ -67,11 +65,9 @@ pub(crate) fn check<'tcx>( span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); } }, - BinOpKind::Div => { - if is_redundant_op(cx, right, 1, ctxt) { - let paren = needs_parenthesis(cx, expr, left); - span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); - } + BinOpKind::Div if is_redundant_op(cx, right, 1, ctxt) => { + let paren = needs_parenthesis(cx, expr, left); + span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); }, BinOpKind::BitAnd => { if is_redundant_op(cx, left, -1, ctxt) { diff --git a/clippy_lints/src/operators/manual_div_ceil.rs b/clippy_lints/src/operators/manual_div_ceil.rs index 5ed923d719bc..6751532ecbc7 100644 --- a/clippy_lints/src/operators/manual_div_ceil.rs +++ b/clippy_lints/src/operators/manual_div_ceil.rs @@ -73,14 +73,13 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, op: BinOpKind, lhs: & build_suggestion(cx, expr, inner_lhs, rhs, &mut applicability); } }, - ExprKind::MethodCall(method, receiver, [next_multiple_of_arg], _) => { - // x.next_multiple_of(Y) / Y + ExprKind::MethodCall(method, receiver, [next_multiple_of_arg], _) if method.ident.name == sym::next_multiple_of && check_int_ty(cx.typeck_results().expr_ty(receiver)) - && check_eq_expr(cx, next_multiple_of_arg, rhs) - { - build_suggestion(cx, expr, receiver, rhs, &mut applicability); - } + && check_eq_expr(cx, next_multiple_of_arg, rhs) => + { + // x.next_multiple_of(Y) / Y + build_suggestion(cx, expr, receiver, rhs, &mut applicability); }, ExprKind::Call(callee, [receiver, next_multiple_of_arg]) => { // int_type::next_multiple_of(x, Y) / Y diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index 383b135dfa50..5b00f1b0bd13 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -1064,7 +1064,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { assign_op_pattern::check(cx, e, lhs, rhs, self.msrv); self_assignment::check(cx, e, lhs, rhs); }, - ExprKind::Unary(op, arg) => { + ExprKind::Unary(op, arg) => + { + #[expect(clippy::collapsible_match)] if op == UnOp::Neg { self.arithmetic_context.check_negate(cx, e, arg); } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 5517b7f260ea..719f364357d3 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -490,8 +490,7 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: || is_early_return(sym::Result, cx, &if_block)) && if_else .map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))) - .filter(|e| *e) - .is_none() + .is_none_or(|e| !e) { if !is_copy(cx, caller_ty) && let Some(hir_id) = let_expr.res_local_id() diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index b4e1f70d1535..da85125730a8 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -66,25 +66,19 @@ fn visit_type(ty: &Ty, cx: &EarlyContext<'_>, reason: &'static str) { // Match the 'static lifetime if let Some(lifetime) = *optional_lifetime { match borrow_type.ty.kind { - TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => { - if lifetime.ident.name == kw::StaticLifetime { - let snip = snippet(cx, borrow_type.ty.span, ""); - let sugg = format!("&{}{snip}", borrow_type.mutbl.prefix_str()); - span_lint_and_then( - cx, - REDUNDANT_STATIC_LIFETIMES, - lifetime.ident.span, - reason, - |diag| { - diag.span_suggestion( - ty.span, - "consider removing `'static`", - sugg, - Applicability::MachineApplicable, //snippet - ); - }, + TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) + if lifetime.ident.name == kw::StaticLifetime => + { + let snip = snippet(cx, borrow_type.ty.span, ""); + let sugg = format!("&{}{snip}", borrow_type.mutbl.prefix_str()); + span_lint_and_then(cx, REDUNDANT_STATIC_LIFETIMES, lifetime.ident.span, reason, |diag| { + diag.span_suggestion( + ty.span, + "consider removing `'static`", + sugg, + Applicability::MachineApplicable, //snippet ); - } + }); }, _ => {}, } diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index 8c4a50041e67..143be5137038 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -138,14 +138,7 @@ fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) { return; }, }, - sym::alloc => { - if cx.tcx.crate_name(def_id.krate) == sym::core { - (ALLOC_INSTEAD_OF_CORE, "alloc", "core") - } else { - self.lint_if_finish(cx, first_segment.ident.span, LintPoint::Conflict); - return; - } - }, + sym::alloc if cx.tcx.crate_name(def_id.krate) == sym::core => (ALLOC_INSTEAD_OF_CORE, "alloc", "core"), _ => { self.lint_if_finish(cx, first_segment.ident.span, LintPoint::Conflict); return; diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 509ad4e4fcb3..9d3e4a6b1d92 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -155,36 +155,32 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { }, left, _, - ) => { - if is_string(cx, left) { - if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) { - let parent = get_parent_expr(cx, e); - if let Some(p) = parent + ) if is_string(cx, left) => { + if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) { + let parent = get_parent_expr(cx, e); + if let Some(p) = parent && let ExprKind::Assign(target, _, _) = p.kind // avoid duplicate matches && SpanlessEq::new(cx).eq_expr(target, left) - { - return; - } + { + return; } - span_lint( - cx, - STRING_ADD, - e.span, - "you added something to a string. Consider using `String::push_str()` instead", - ); } + span_lint( + cx, + STRING_ADD, + e.span, + "you added something to a string. Consider using `String::push_str()` instead", + ); }, - ExprKind::Assign(target, src, _) => { - if is_string(cx, target) && is_add(cx, src, target) { - span_lint( - cx, - STRING_ADD_ASSIGN, - e.span, - "you assigned the result of adding something to this string. Consider using \ + ExprKind::Assign(target, src, _) if is_string(cx, target) && is_add(cx, src, target) => { + span_lint( + cx, + STRING_ADD_ASSIGN, + e.span, + "you assigned the result of adding something to this string. Consider using \ `String::push_str()` instead", - ); - } + ); }, ExprKind::Index(target, _idx, _) => { let e_ty = cx.typeck_results().expr_ty_adjusted(target).peel_refs(); @@ -417,6 +413,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { && args.iter().any(|a| a.hir_id == expr.hir_id) && let Res::Def(DefKind::AssocFn, def_id) = expr.res(cx) && cx.tcx.is_diagnostic_item(sym::to_string_method, def_id) + && let Some(args) = cx.typeck_results().node_args_opt(expr.hir_id) + && args.type_at(0).is_str() { // Detected `ToString::to_string` passed as an argument (generic: any call or method call) span_lint_and_sugg( @@ -425,7 +423,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { expr.span, "`ToString::to_string` used as `&str` to `String` converter", "try", - "ToOwned::to_owned".to_string(), + "str::to_owned".to_string(), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/time_subtraction.rs b/clippy_lints/src/time_subtraction.rs index e7bf58078c3d..457a8f48f7e2 100644 --- a/clippy_lints/src/time_subtraction.rs +++ b/clippy_lints/src/time_subtraction.rs @@ -1,14 +1,18 @@ +use std::time::Duration; + use clippy_config::Conf; -use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; +use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; use clippy_utils::sugg::Sugg; use clippy_utils::sym; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::impl_lint_pass; +use rustc_span::SyntaxContext; declare_clippy_lint! { /// ### What it does @@ -111,6 +115,27 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { && !expr.span.from_expansion() && self.msrv.meets(cx, msrvs::TRY_FROM) { + let const_eval = ConstEvalCtxt::new(cx); + let ctxt = expr.span.ctxt(); + if let Some(lhs) = const_eval_duration(&const_eval, lhs, ctxt) + && let Some(rhs) = const_eval_duration(&const_eval, rhs, ctxt) + { + if lhs >= rhs { + // If the duration subtraction can be proven to not underflow, then we don't lint + return; + } + + span_lint_and_note( + cx, + UNCHECKED_TIME_SUBTRACTION, + expr.span, + "unchecked subtraction of two `Duration` that will underflow", + None, + "if this is intentional, consider allowing the lint", + ); + return; + } + print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr); } } @@ -189,3 +214,44 @@ fn print_unchecked_duration_subtraction_sugg( }, ); } + +fn const_eval_duration(const_eval: &ConstEvalCtxt<'_>, expr: &Expr<'_>, ctxt: SyntaxContext) -> Option { + if let ExprKind::Call(func, args) = expr.kind + && let ExprKind::Path(QPath::TypeRelative(_, func_name)) = func.kind + { + macro_rules! try_parse_duration { + (($( $name:ident : $var:ident ( $ty:ty ) ),+ $(,)?) -> $ctor:ident ( $($args:tt)* )) => {{ + let [$( $name ),+] = args else { return None }; + $( + let Some(Constant::$var(v)) = const_eval.eval_local($name, ctxt) else { return None }; + let $name = <$ty>::try_from(v).ok()?; + )+ + Some(Duration::$ctor($($args)*)) + }}; + } + + return match func_name.ident.name { + sym::new => try_parse_duration! { (secs: Int(u64), nanos: Int(u32)) -> new(secs, nanos) }, + sym::from_nanos => try_parse_duration! { (nanos: Int(u64)) -> from_nanos(nanos) }, + sym::from_nanos_u128 => try_parse_duration! { (nanos: Int(u128)) -> from_nanos_u128(nanos) }, + sym::from_micros => try_parse_duration! { (micros: Int(u64)) -> from_micros(micros) }, + sym::from_millis => try_parse_duration! { (millis: Int(u64)) -> from_millis(millis) }, + sym::from_secs => try_parse_duration! { (secs: Int(u64)) -> from_secs(secs) }, + sym::from_secs_f32 => try_parse_duration! { (secs: F32(f32)) -> from_secs_f32(secs) }, + sym::from_secs_f64 => try_parse_duration! { (secs: F64(f64)) -> from_secs_f64(secs) }, + sym::from_mins => try_parse_duration! { (mins: Int(u64)) -> from_mins(mins) }, + sym::from_hours => { + try_parse_duration! { (hours: Int(u64)) -> from_hours(hours) } + }, + sym::from_days => { + try_parse_duration! { (days: Int(u64)) -> from_hours(days * 24) } + }, + sym::from_weeks => { + try_parse_duration! { (weeks: Int(u64)) -> from_hours(weeks * 24 * 7) } + }, + _ => None, + }; + } + + None +} diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 4ce132e9e3ab..e287a3de86bd 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -157,7 +157,9 @@ fn into_iter_deep_call<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) - impl<'tcx> LateLintPass<'tcx> for UselessConversion { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if e.span.from_expansion() { - self.expn_depth += 1; + if e.span.desugaring_kind().is_none() { + self.expn_depth += 1; + } return; } @@ -437,7 +439,7 @@ fn check_expr_post(&mut self, _: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if Some(&e.hir_id) == self.try_desugar_arm.last() { self.try_desugar_arm.pop(); } - if e.span.from_expansion() { + if e.span.from_expansion() && e.span.desugaring_kind().is_none() { self.expn_depth -= 1; } } diff --git a/clippy_utils/README.md b/clippy_utils/README.md index 1b85dcfd848d..87048ceff891 100644 --- a/clippy_utils/README.md +++ b/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: ``` -nightly-2026-02-11 +nightly-2026-02-19 ``` diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index 239f721ae05b..67ae1dcef81b 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -820,8 +820,8 @@ pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool { matches!( (l, r), (Defaultness::Implicit, Defaultness::Implicit) - | (Defaultness::Default(_), Defaultness::Default(_)) - | (Defaultness::Final(_), Defaultness::Final(_)) + | (Defaultness::Default(_), Defaultness::Default(_)) + | (Defaultness::Final(_), Defaultness::Final(_)) ) } diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index def5d968b063..1b2ba0fe182a 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -21,10 +21,10 @@ use rustc_ast::token::CommentKind; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl, - ImplItem, ImplItemImplKind, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, - QPath, Safety, TraitImplHeader, TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, - YieldSource, + Block, BlockCheckMode, Body, BoundConstness, BoundPolarity, Closure, Destination, Expr, ExprKind, FieldDef, + FnHeader, FnRetTy, HirId, Impl, ImplItem, ImplItemImplKind, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, + MatchSource, MutTy, Node, Path, PolyTraitRef, QPath, Safety, TraitBoundModifiers, TraitImplHeader, TraitItem, + TraitItemKind, TraitRef, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource, }; use rustc_lint::{EarlyContext, LateContext, LintContext}; use rustc_middle::ty::TyCtxt; @@ -541,6 +541,44 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { } } +// NOTE: can't `impl WithSearchPat for TraitRef`, because `TraitRef` doesn't have a `span` field +// (nor a method) +fn trait_ref_search_pat(trait_ref: &TraitRef<'_>) -> (Pat, Pat) { + path_search_pat(trait_ref.path) +} + +fn poly_trait_ref_search_pat(poly_trait_ref: &PolyTraitRef<'_>) -> (Pat, Pat) { + // NOTE: unfortunately we can't use `bound_generic_params` to see whether the pattern starts with + // `for<..>`, because if it's empty, we could have either `for<>` (nothing bound), or + // no `for` at all + let PolyTraitRef { + modifiers: TraitBoundModifiers { constness, polarity }, + trait_ref, + .. + } = poly_trait_ref; + + let trait_ref_search_pat = trait_ref_search_pat(trait_ref); + + #[expect( + clippy::unnecessary_lazy_evaluations, + reason = "the closure in `or_else` has `match polarity`, which isn't free" + )] + let start = match constness { + BoundConstness::Never => None, + BoundConstness::Maybe(_) => Some(Pat::Str("[const]")), + BoundConstness::Always(_) => Some(Pat::Str("const")), + } + .or_else(|| match polarity { + BoundPolarity::Negative(_) => Some(Pat::Str("!")), + BoundPolarity::Maybe(_) => Some(Pat::Str("?")), + BoundPolarity::Positive => None, + }) + .unwrap_or(trait_ref_search_pat.0); + let end = trait_ref_search_pat.1; + + (start, end) +} + fn ident_search_pat(ident: Ident) -> (Pat, Pat) { (Pat::Sym(ident.name), Pat::Sym(ident.name)) } @@ -573,6 +611,7 @@ fn span(&self) -> Span { impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ident) => ident_search_pat(*self)); impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&self.node)); impl_with_search_pat!((_cx: LateContext<'tcx>, self: Path<'_>) => path_search_pat(self)); +impl_with_search_pat!((_cx: LateContext<'tcx>, self: PolyTraitRef<'_>) => poly_trait_ref_search_pat(self)); impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self)); impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: ast::Ty) => ast_ty_search_pat(self)); diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs index 4ba9af58f90a..81b06ea0c539 100644 --- a/clippy_utils/src/diagnostics.rs +++ b/clippy_utils/src/diagnostics.rs @@ -104,14 +104,7 @@ fn validate_diag(diag: &Diag<'_, impl EmissionGuarantee>) { /// ``` #[track_caller] pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into, msg: impl Into) { - #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, sp, |diag| { - diag.primary_message(msg); - docs_link(diag, lint); - - #[cfg(debug_assertions)] - validate_diag(diag); - }); + span_lint_and_then(cx, lint, sp, msg, |_| {}); } /// Same as [`span_lint`] but with an extra `help` message. @@ -157,18 +150,12 @@ pub fn span_lint_and_help( help_span: Option, help: impl Into, ) { - #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, span, |diag| { - diag.primary_message(msg); + span_lint_and_then(cx, lint, span, msg, |diag| { if let Some(help_span) = help_span { diag.span_help(help_span, help.into()); } else { diag.help(help.into()); } - docs_link(diag, lint); - - #[cfg(debug_assertions)] - validate_diag(diag); }); } @@ -218,18 +205,12 @@ pub fn span_lint_and_note( note_span: Option, note: impl Into, ) { - #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, span, |diag| { - diag.primary_message(msg); + span_lint_and_then(cx, lint, span, msg, |diag| { if let Some(note_span) = note_span { diag.span_note(note_span, note.into()); } else { diag.note(note.into()); } - docs_link(diag, lint); - - #[cfg(debug_assertions)] - validate_diag(diag); }); } @@ -296,14 +277,7 @@ pub fn span_lint_and_then(cx: &C, lint: &'static Lint, sp: S, msg: M /// the `#[allow]` will work. #[track_caller] pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: impl Into) { - #[expect(clippy::disallowed_methods)] - cx.tcx.node_span_lint(lint, hir_id, sp, |diag| { - diag.primary_message(msg); - docs_link(diag, lint); - - #[cfg(debug_assertions)] - validate_diag(diag); - }); + span_lint_hir_and_then(cx, lint, hir_id, sp, msg, |_| {}); } /// Like [`span_lint_and_then`], but emits the lint at the node identified by the given `HirId`. @@ -383,7 +357,6 @@ pub fn span_lint_hir_and_then( /// | /// = note: `-D fold-any` implied by `-D warnings` /// ``` -#[cfg_attr(not(debug_assertions), expect(clippy::collapsible_span_lint_calls))] #[track_caller] pub fn span_lint_and_sugg( cx: &T, @@ -397,7 +370,9 @@ pub fn span_lint_and_sugg( span_lint_and_then(cx, lint, sp, msg.into(), |diag| { diag.span_suggestion(sp, help.into(), sugg, applicability); - #[cfg(debug_assertions)] - validate_diag(diag); + // This dummy construct is here to prevent the internal `clippy::collapsible_span_lint_calls` + // lint from triggering. We don't want to allow/expect it as internal lints might or might + // not be activated when linting, and we don't want an unknown lint warning either. + std::hint::black_box(()); }); } diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index fdd270c2774a..f2f8cd583f31 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1144,6 +1144,27 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio }) } +/// Returns the [`Closure`] enclosing `hir_id`, if any. +pub fn get_enclosing_closure<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Closure<'tcx>> { + cx.tcx.hir_parent_iter(hir_id).find_map(|(_, node)| { + if let Node::Expr(expr) = node + && let ExprKind::Closure(closure) = expr.kind + { + Some(closure) + } else { + None + } + }) +} + +/// Checks whether a local identified by `local_id` is captured as an upvar by the given `closure`. +pub fn is_upvar_in_closure(cx: &LateContext<'_>, closure: &Closure<'_>, local_id: HirId) -> bool { + cx.typeck_results() + .closure_min_captures + .get(&closure.def_id) + .is_some_and(|x| x.contains_key(&local_id)) +} + /// Gets the loop or closure enclosing the given expression, if any. pub fn get_enclosing_loop_or_multi_call_closure<'tcx>( cx: &LateContext<'tcx>, @@ -2341,12 +2362,11 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl FnOnce(& && let item = tcx.hir_item(id) && let ItemKind::Const(ident, _generics, ty, _body) = item.kind && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind - // We could also check for the type name `test::TestDescAndFn` - && let Res::Def(DefKind::Struct, _) = path.res + // We could also check for the type name `test::TestDescAndFn` + && let Res::Def(DefKind::Struct, _) = path.res + && find_attr!(tcx.hir_attrs(item.hir_id()), RustcTestMarker(..)) { - if find_attr!(tcx.hir_attrs(item.hir_id()), RustcTestMarker(..)) { - names.push(ident.name); - } + names.push(ident.name); } } names.sort_unstable(); @@ -3245,6 +3265,8 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St None } }))) + } else if go_up_by == 0 && path.is_empty() { + String::from("Self") } else { join_path_syms(repeat_n(kw::Super, go_up_by).chain(path)) } diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 3cfe648fdf32..ed5db32d1117 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -234,19 +234,30 @@ pub fn is_assert_macro(cx: &LateContext<'_>, def_id: DefId) -> bool { matches!(name, sym::assert_macro | sym::debug_assert_macro) } +/// A call to a function in [`std::rt`] or [`core::panicking`] that results in a panic, typically +/// part of a `panic!()` expansion (often wrapped in a block) but may be called directly by other +/// macros such as `assert`. #[derive(Debug)] -pub enum PanicExpn<'a> { - /// No arguments - `panic!()` - Empty, - /// A string literal or any `&str` - `panic!("message")` or `panic!(message)` - Str(&'a Expr<'a>), - /// A single argument that implements `Display` - `panic!("{}", object)` +pub enum PanicCall<'a> { + // The default message - `panic!()`, `assert!(true)`, etc. + DefaultMessage, + /// A string literal or any `&str` in edition 2015/2018 - `panic!("message")` or + /// `panic!(message)`. + /// + /// In edition 2021+ `panic!("message")` will be a [`PanicCall::Format`] and `panic!(message)` a + /// compile error. + Str2015(&'a Expr<'a>), + /// A single argument that implements `Display` - `panic!("{}", object)`. + /// + /// `panic!("{object}")` will still be a [`PanicCall::Format`]. Display(&'a Expr<'a>), - /// Anything else - `panic!("error {}: {}", a, b)` + /// Anything else - `panic!("error {}: {}", a, b)`, `panic!("on edition 2021+")`. + /// + /// See [`FormatArgsStorage::get`] to examine the contents of the formatting. Format(&'a Expr<'a>), } -impl<'a> PanicExpn<'a> { +impl<'a> PanicCall<'a> { pub fn parse(expr: &'a Expr<'a>) -> Option { let ExprKind::Call(callee, args) = &expr.kind else { return None; @@ -260,8 +271,13 @@ pub fn parse(expr: &'a Expr<'a>) -> Option { return None; }; let result = match name { - sym::panic if arg.span.eq_ctxt(expr.span) => Self::Empty, - sym::panic | sym::panic_str => Self::Str(arg), + sym::panic | sym::begin_panic | sym::panic_str_2015 => { + if arg.span.eq_ctxt(expr.span) || arg.span.is_dummy() { + Self::DefaultMessage + } else { + Self::Str2015(arg) + } + }, sym::panic_display => { let ExprKind::AddrOf(_, _, e) = &arg.kind else { return None; @@ -281,13 +297,17 @@ pub fn parse(expr: &'a Expr<'a>) -> Option { let msg_arg = &rest[2]; match msg_arg.kind { ExprKind::Call(_, [fmt_arg]) => Self::Format(fmt_arg), - _ => Self::Empty, + _ => Self::DefaultMessage, } }, _ => return None, }; Some(result) } + + pub fn is_default_message(&self) -> bool { + matches!(self, Self::DefaultMessage) + } } /// Finds the arguments of an `assert!` or `debug_assert!` macro call within the macro expansion @@ -295,18 +315,8 @@ pub fn find_assert_args<'a>( cx: &LateContext<'_>, expr: &'a Expr<'a>, expn: ExpnId, -) -> Option<(&'a Expr<'a>, PanicExpn<'a>)> { - find_assert_args_inner(cx, expr, expn).map(|([e], mut p)| { - // `assert!(..)` expands to `core::panicking::panic("assertion failed: ...")` (which we map to - // `PanicExpn::Str(..)`) and `assert!(.., "..")` expands to - // `core::panicking::panic_fmt(format_args!(".."))` (which we map to `PanicExpn::Format(..)`). - // So even we got `PanicExpn::Str(..)` that means there is no custom message provided - if let PanicExpn::Str(_) = p { - p = PanicExpn::Empty; - } - - (e, p) - }) +) -> Option<(&'a Expr<'a>, PanicCall<'a>)> { + find_assert_args_inner(cx, expr, expn).map(|([e], p)| (e, p)) } /// Finds the arguments of an `assert_eq!` or `debug_assert_eq!` macro call within the macro @@ -315,7 +325,7 @@ pub fn find_assert_eq_args<'a>( cx: &LateContext<'_>, expr: &'a Expr<'a>, expn: ExpnId, -) -> Option<(&'a Expr<'a>, &'a Expr<'a>, PanicExpn<'a>)> { +) -> Option<(&'a Expr<'a>, &'a Expr<'a>, PanicCall<'a>)> { find_assert_args_inner(cx, expr, expn).map(|([a, b], p)| (a, b, p)) } @@ -323,7 +333,7 @@ fn find_assert_args_inner<'a, const N: usize>( cx: &LateContext<'_>, expr: &'a Expr<'a>, expn: ExpnId, -) -> Option<([&'a Expr<'a>; N], PanicExpn<'a>)> { +) -> Option<([&'a Expr<'a>; N], PanicCall<'a>)> { let macro_id = expn.expn_data().macro_def_id?; let (expr, expn) = match cx.tcx.item_name(macro_id).as_str().strip_prefix("debug_") { None => (expr, expn), @@ -332,7 +342,7 @@ fn find_assert_args_inner<'a, const N: usize>( let mut args = ArrayVec::new(); let panic_expn = for_each_expr_without_closures(expr, |e| { if args.is_full() { - match PanicExpn::parse(e) { + match PanicCall::parse(e) { Some(expn) => ControlFlow::Break(expn), None => ControlFlow::Continue(Descend::Yes), } @@ -344,10 +354,7 @@ fn find_assert_args_inner<'a, const N: usize>( } }); let args = args.into_inner().ok()?; - // if no `panic!(..)` is found, use `PanicExpn::Empty` - // to indicate that the default assertion message is used - let panic_expn = panic_expn.unwrap_or(PanicExpn::Empty); - Some((args, panic_expn)) + Some((args, panic_expn?)) } fn find_assert_within_debug_assert<'a>( diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 18fab6035f28..5aa457b9d19c 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -142,12 +142,10 @@ pub fn read_cargo(&mut self, sess: &Session) { match (self.0, cargo_msrv) { (None, Some(cargo_msrv)) => self.0 = Some(cargo_msrv), - (Some(clippy_msrv), Some(cargo_msrv)) => { - if clippy_msrv != cargo_msrv { - sess.dcx().warn(format!( - "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`" - )); - } + (Some(clippy_msrv), Some(cargo_msrv)) if clippy_msrv != cargo_msrv => { + sess.dcx().warn(format!( + "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`" + )); }, _ => {}, } diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index e6593aa8b554..3bd98ef24038 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -26,6 +26,7 @@ pub enum PathNS { Type, Value, Macro, + Field, /// Resolves to the name in the first available namespace, e.g. for `std::vec` this would return /// either the macro or the module but **not** both @@ -41,6 +42,7 @@ fn matches(self, ns: Option) -> bool { PathNS::Type => TypeNS, PathNS::Value => ValueNS, PathNS::Macro => MacroNS, + PathNS::Field => return false, PathNS::Arbitrary => return true, }; @@ -286,6 +288,20 @@ fn local_item_child_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, ns: PathNS, n &root_mod }, Node::Item(item) => &item.kind, + Node::Variant(variant) if ns == PathNS::Field => { + return if let rustc_hir::VariantData::Struct { fields, .. } = variant.data + && let Some(field_def_id) = fields.iter().find_map(|field| { + if field.ident.name == name { + Some(field.def_id.to_def_id()) + } else { + None + } + }) { + Some(field_def_id) + } else { + None + }; + }, _ => return None, }; @@ -299,6 +315,7 @@ fn local_item_child_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, ns: PathNS, n PathNS::Type => opt_def_id(path.res.type_ns), PathNS::Value => opt_def_id(path.res.value_ns), PathNS::Macro => opt_def_id(path.res.macro_ns), + PathNS::Field => None, PathNS::Arbitrary => unreachable!(), } } else { @@ -318,6 +335,24 @@ fn local_item_child_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, ns: PathNS, n .filter_by_name_unhygienic(name) .find(|assoc_item| ns.matches(Some(assoc_item.namespace()))) .map(|assoc_item| assoc_item.def_id), + ItemKind::Struct(_, _, rustc_hir::VariantData::Struct { fields, .. }) if ns == PathNS::Field => { + fields.iter().find_map(|field| { + if field.ident.name == name { + Some(field.def_id.to_def_id()) + } else { + None + } + }) + }, + ItemKind::Enum(_, _, rustc_hir::EnumDef { variants }) if ns == PathNS::Type => { + variants.iter().find_map(|variant| { + if variant.ident.name == name { + Some(variant.def_id.to_def_id()) + } else { + None + } + }) + }, _ => None, } } @@ -336,6 +371,11 @@ fn non_local_item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, ns: PathNS, name .iter() .copied() .find(|&assoc_def_id| tcx.item_name(assoc_def_id) == name && ns.matches(tcx.def_kind(assoc_def_id).ns())), + DefKind::Struct => tcx + .associated_item_def_ids(def_id) + .iter() + .copied() + .find(|&assoc_def_id| tcx.item_name(assoc_def_id) == name), _ => None, } } diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 3ade38bea8ed..641c6684a0bd 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -370,6 +370,20 @@ pub fn maybe_paren(self) -> Self { } } + /// Strip enclosing parentheses if present. This method must be called when + /// it is known that removing those will not change the meaning. For example, + /// if `self` is known to represent a reference and the suggestion will be + /// used as the argument of a function call, it is safe to remove the enclosing + /// parentheses. It would not be safe to do so for an expression that might + /// represent a tuple. + #[must_use] + pub fn strip_paren(self) -> Self { + match self { + Sugg::NonParen(s) | Sugg::MaybeParen(s) => Sugg::NonParen(strip_enclosing_paren(s)), + sugg => sugg, + } + } + pub fn into_string(self) -> String { match self { Sugg::NonParen(p) | Sugg::MaybeParen(p) => p.into_owned(), @@ -430,6 +444,22 @@ pub fn has_enclosing_paren(sugg: impl AsRef) -> bool { } } +/// Strip enclosing parentheses from a snippet if present. +fn strip_enclosing_paren(snippet: Cow<'_, str>) -> Cow<'_, str> { + if has_enclosing_paren(&snippet) { + match snippet { + Cow::Borrowed(s) => Cow::Borrowed(&s[1..s.len() - 1]), + Cow::Owned(mut s) => { + s.pop(); + s.remove(0); + Cow::Owned(s) + }, + } + } else { + snippet + } +} + /// Copied from the rust standard library, and then edited macro_rules! forward_binop_impls_to_ref { (impl $imp:ident, $method:ident for $t:ty, type Output = $o:ty) => { diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index 6965225c12ab..250e73afd4f0 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -285,11 +285,14 @@ macro_rules! generate { from_millis, from_mins, from_nanos, + from_nanos_u128, from_ne_bytes, from_ptr, from_raw, from_raw_parts, from_secs, + from_secs_f32, + from_secs_f64, from_str_method, from_str_radix, from_weeks, diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 36410a81fbf6..a9e29987bc32 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -114,16 +114,15 @@ fn contains_ty_adt_constructor_opaque_inner<'tcx>( match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substitutions to find `U`. - ty::ClauseKind::Trait(trait_predicate) => { + ty::ClauseKind::Trait(trait_predicate) if trait_predicate .trait_ref .args .types() .skip(1) // Skip the implicit `Self` generic parameter - .any(|ty| contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen)) - { - return true; - } + .any(|ty| contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen)) => + { + return true; }, // For `impl Trait`, it will register a predicate of `::Assoc = U`, // so we check the term for `U`. @@ -308,19 +307,29 @@ pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { } } -// Returns whether the type has #[must_use] attribute +// Returns whether the `ty` has `#[must_use]` attribute. If `ty` is a `Result`/`ControlFlow` +// whose `Err`/`Break` payload is an uninhabited type, the `Ok`/`Continue` payload type +// will be used instead. See . pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - match *ty.kind() { - ty::Adt(adt, _) => find_attr!(cx.tcx, adt.did(), MustUse { .. }), - ty::Foreign(did) => find_attr!(cx.tcx, did, MustUse { .. }), + match ty.kind() { + ty::Adt(adt, args) => match cx.tcx.get_diagnostic_name(adt.did()) { + Some(sym::Result) if args.type_at(1).is_privately_uninhabited(cx.tcx, cx.typing_env()) => { + is_must_use_ty(cx, args.type_at(0)) + }, + Some(sym::ControlFlow) if args.type_at(0).is_privately_uninhabited(cx.tcx, cx.typing_env()) => { + is_must_use_ty(cx, args.type_at(1)) + }, + _ => find_attr!(cx.tcx, adt.did(), MustUse { .. }), + }, + ty::Foreign(did) => find_attr!(cx.tcx, *did, MustUse { .. }), ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => { // for the Array case we don't need to care for the len == 0 case // because we don't want to lint functions returning empty arrays - is_must_use_ty(cx, ty) + is_must_use_ty(cx, *ty) }, ty::Tuple(args) => args.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => { - for (predicate, _) in cx.tcx.explicit_item_self_bounds(def_id).skip_binder() { + for (predicate, _) in cx.tcx.explicit_item_self_bounds(*def_id).skip_binder() { if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && find_attr!(cx.tcx, trait_predicate.trait_ref.def_id, MustUse { .. }) { @@ -330,7 +339,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { false }, ty::Dynamic(binder, _) => { - for predicate in binder { + for predicate in *binder { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() && find_attr!(cx.tcx, trait_ref.def_id, MustUse { .. }) { @@ -1262,6 +1271,13 @@ pub fn get_field_by_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> } } +pub fn get_field_def_id_by_name(ty: Ty<'_>, name: Symbol) -> Option { + let ty::Adt(adt_def, ..) = ty.kind() else { return None }; + adt_def + .all_fields() + .find_map(|field| if field.name == name { Some(field.did) } else { None }) +} + /// Check if `ty` is an `Option` and return its argument type if it is. pub fn option_arg_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { match *ty.kind() { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 558f808a7a3e..e9b06bcbdaef 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2026-02-11" +channel = "nightly-2026-02-19" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/src/driver.rs b/src/driver.rs index 409eb182fe33..f27cb6708709 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -126,6 +126,7 @@ fn config(&mut self, config: &mut interface::Config) { config.psess_created = Some(Box::new(move |psess| { track_clippy_args(psess, clippy_args_var.as_deref()); })); + config.extra_symbols = sym::EXTRA_SYMBOLS.into(); } } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index fa2b6cf26806..a92bb8f5ca73 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -469,7 +469,7 @@ enum DiagnosticOrMessage { } /// Collects applicabilities from the diagnostics produced for each UI test, producing the -/// `util/gh-pages/lints.json` file used by +/// `util/gh-pages/index.html` file used by #[derive(Debug, Clone)] struct DiagnosticCollector { sender: Sender>, diff --git a/tests/missing-test-files.rs b/tests/missing-test-files.rs index 9fff3132498d..dbb25ac545fc 100644 --- a/tests/missing-test-files.rs +++ b/tests/missing-test-files.rs @@ -53,10 +53,8 @@ fn explore_directory(dir: &Path) -> Vec { if let Some(ext) = path.extension() { match ext.to_str().unwrap() { "rs" | "toml" => current_file.clone_from(&file_prefix), - "stderr" | "stdout" => { - if file_prefix != current_file { - missing_files.push(path.to_str().unwrap().to_string()); - } + "stderr" | "stdout" if file_prefix != current_file => { + missing_files.push(path.to_str().unwrap().to_string()); }, _ => {}, } diff --git a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs index 4a179cd929f0..673a2d167652 100644 --- a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs +++ b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs @@ -39,9 +39,4 @@ fn block_bad() -> impl std::future::Future { } } -fn main() { - good(); - bad(); - bad_reason(); - block_bad(); -} +fn main() {} diff --git a/tests/ui-toml/expect_used/expect_used.rs b/tests/ui-toml/expect_used/expect_used.rs index 9955c9b6baa1..143b2cd28035 100644 --- a/tests/ui-toml/expect_used/expect_used.rs +++ b/tests/ui-toml/expect_used/expect_used.rs @@ -1,5 +1,4 @@ //@compile-flags: --test -//@no-rustfix #![warn(clippy::expect_used)] #![allow(clippy::unnecessary_literal_unwrap)] @@ -16,9 +15,6 @@ fn expect_result() { } fn main() { - expect_option(); - expect_result(); - const SOME: Option = Some(3); const UNWRAPPED: i32 = SOME.expect("Not three?"); //~^ expect_used diff --git a/tests/ui-toml/expect_used/expect_used.stderr b/tests/ui-toml/expect_used/expect_used.stderr index 3bb471e6dfcc..b794c2fc42fc 100644 --- a/tests/ui-toml/expect_used/expect_used.stderr +++ b/tests/ui-toml/expect_used/expect_used.stderr @@ -1,5 +1,5 @@ error: used `expect()` on an `Option` value - --> tests/ui-toml/expect_used/expect_used.rs:8:13 + --> tests/ui-toml/expect_used/expect_used.rs:7:13 | LL | let _ = opt.expect(""); | ^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | let _ = opt.expect(""); = help: to override `-D warnings` add `#[allow(clippy::expect_used)]` error: used `expect()` on a `Result` value - --> tests/ui-toml/expect_used/expect_used.rs:14:13 + --> tests/ui-toml/expect_used/expect_used.rs:13:13 | LL | let _ = res.expect(""); | ^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let _ = res.expect(""); = note: if this value is an `Err`, it will panic error: used `expect()` on an `Option` value - --> tests/ui-toml/expect_used/expect_used.rs:23:28 + --> tests/ui-toml/expect_used/expect_used.rs:19:28 | LL | const UNWRAPPED: i32 = SOME.expect("Not three?"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | const UNWRAPPED: i32 = SOME.expect("Not three?"); = note: if this value is `None`, it will panic error: used `expect()` on an `Option` value - --> tests/ui-toml/expect_used/expect_used.rs:26:9 + --> tests/ui-toml/expect_used/expect_used.rs:22:9 | LL | SOME.expect("Still not three?"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/lint_decimal_readability/test.fixed b/tests/ui-toml/lint_decimal_readability/test.fixed index 2d76824128bf..47a61122c9bc 100644 --- a/tests/ui-toml/lint_decimal_readability/test.fixed +++ b/tests/ui-toml/lint_decimal_readability/test.fixed @@ -7,8 +7,6 @@ fn allow_inconsistent_digit_grouping() { } fn main() { - allow_inconsistent_digit_grouping(); - let _pass1 = 100_200_300.100_200_300; let _pass2 = 1.123456789; let _pass3 = 1.0; diff --git a/tests/ui-toml/lint_decimal_readability/test.rs b/tests/ui-toml/lint_decimal_readability/test.rs index b42e31085217..eca273274d0d 100644 --- a/tests/ui-toml/lint_decimal_readability/test.rs +++ b/tests/ui-toml/lint_decimal_readability/test.rs @@ -7,8 +7,6 @@ fn allow_inconsistent_digit_grouping() { } fn main() { - allow_inconsistent_digit_grouping(); - let _pass1 = 100_200_300.100_200_300; let _pass2 = 1.123456789; let _pass3 = 1.0; diff --git a/tests/ui-toml/lint_decimal_readability/test.stderr b/tests/ui-toml/lint_decimal_readability/test.stderr index c4e164c67ed8..e010e1e4d2fd 100644 --- a/tests/ui-toml/lint_decimal_readability/test.stderr +++ b/tests/ui-toml/lint_decimal_readability/test.stderr @@ -1,5 +1,5 @@ error: digits grouped inconsistently by underscores - --> tests/ui-toml/lint_decimal_readability/test.rs:19:18 + --> tests/ui-toml/lint_decimal_readability/test.rs:17:18 | LL | let _fail1 = 100_200_300.123456789; | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.123_456_789` @@ -8,7 +8,7 @@ LL | let _fail1 = 100_200_300.123456789; = help: to override `-D warnings` add `#[allow(clippy::inconsistent_digit_grouping)]` error: long literal lacking separators - --> tests/ui-toml/lint_decimal_readability/test.rs:23:18 + --> tests/ui-toml/lint_decimal_readability/test.rs:21:18 | LL | let _fail2 = 100200300.300200100; | ^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.300_200_100` diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed index 36540bf1dcf7..92c356b9b277 100644 --- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed +++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed @@ -18,7 +18,4 @@ fn above_limit() { } } -fn main() { - below_limit(); - above_limit(); -} +fn main() {} diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs index da76bb20fd96..3bf743c25664 100644 --- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs +++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs @@ -18,7 +18,4 @@ fn above_limit() { } } -fn main() { - below_limit(); - above_limit(); -} +fn main() {} diff --git a/tests/ui-toml/min_rust_version/min_rust_version.fixed b/tests/ui-toml/min_rust_version/min_rust_version.fixed index 685f77b7efe8..d73da96543d7 100644 --- a/tests/ui-toml/min_rust_version/min_rust_version.fixed +++ b/tests/ui-toml/min_rust_version/min_rust_version.fixed @@ -88,12 +88,4 @@ fn manual_bits() { size_of_val(&0u32) * 8; } -fn main() { - option_as_ref_deref(); - match_like_matches(); - match_same_arms(); - match_same_arms2(); - manual_strip_msrv(); - check_index_refutable_slice(); - borrow_as_ptr(); -} +fn main() {} diff --git a/tests/ui-toml/min_rust_version/min_rust_version.rs b/tests/ui-toml/min_rust_version/min_rust_version.rs index 0bf073af8903..78cfba1189fb 100644 --- a/tests/ui-toml/min_rust_version/min_rust_version.rs +++ b/tests/ui-toml/min_rust_version/min_rust_version.rs @@ -88,12 +88,4 @@ fn manual_bits() { size_of_val(&0u32) * 8; } -fn main() { - option_as_ref_deref(); - match_like_matches(); - match_same_arms(); - match_same_arms2(); - manual_strip_msrv(); - check_index_refutable_slice(); - borrow_as_ptr(); -} +fn main() {} diff --git a/tests/ui-toml/mut_key/mut_key.rs b/tests/ui-toml/mut_key/mut_key.rs index b23c2340b7d6..aca6c6f84113 100644 --- a/tests/ui-toml/mut_key/mut_key.rs +++ b/tests/ui-toml/mut_key/mut_key.rs @@ -56,7 +56,4 @@ fn should_not_take_this_arg(_v: HashSet>) {} fn indirect(_: HashMap) {} -fn main() { - should_not_take_this_arg(HashSet::new()); - indirect(HashMap::new()); -} +fn main() {} diff --git a/tests/ui-toml/toml_disallowed_fields/clippy.toml b/tests/ui-toml/toml_disallowed_fields/clippy.toml new file mode 100644 index 000000000000..615d405a87a4 --- /dev/null +++ b/tests/ui-toml/toml_disallowed_fields/clippy.toml @@ -0,0 +1,14 @@ +disallowed-fields = [ + # just a string is shorthand for path only + "std::ops::Range::start", + # can give path and reason with an inline table + { path = "std::ops::Range::end", reason = "no end allowed" }, + # can use an inline table but omit reason + { path = "std::ops::RangeTo::end" }, + # local paths + "conf_disallowed_fields::X::y", + # re-exports + "conf_disallowed_fields::Y::y", + # field of a variant + "conf_disallowed_fields::Z::B::x", +] diff --git a/tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs b/tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs new file mode 100644 index 000000000000..7804b605a67a --- /dev/null +++ b/tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs @@ -0,0 +1,50 @@ +#![warn(clippy::disallowed_fields)] +#![allow(clippy::match_single_binding)] + +use std::ops::{Range, RangeTo}; + +struct X { + y: u32, +} + +enum Z { + A { x: u32 }, + B { x: u32 }, +} + +use crate::X as Y; + +fn b(X { y }: X) {} +//~^ disallowed_fields + +fn main() { + let x = X { y: 0 }; + let _ = x.y; + //~^ disallowed_fields + + let x = Y { y: 0 }; + let _ = x.y; + //~^ disallowed_fields + + let x = Range { start: 0, end: 0 }; + let _ = x.start; + //~^ disallowed_fields + let _ = x.end; + //~^ disallowed_fields + let Range { start, .. } = x; + //~^ disallowed_fields + + let x = RangeTo { end: 0 }; + let _ = x.end; + //~^ disallowed_fields + + match x { + RangeTo { end } => {}, //~ disallowed_fields + } + + let x = Z::B { x: 0 }; + match x { + Z::A { x } => {}, + Z::B { x } => {}, //~ disallowed_fields + } +} diff --git a/tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.stderr b/tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.stderr new file mode 100644 index 000000000000..ac43c702bbdc --- /dev/null +++ b/tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.stderr @@ -0,0 +1,61 @@ +error: use of a disallowed field `conf_disallowed_fields::Y::y` + --> tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs:17:10 + | +LL | fn b(X { y }: X) {} + | ^ + | + = note: `-D clippy::disallowed-fields` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::disallowed_fields)]` + +error: use of a disallowed field `conf_disallowed_fields::Y::y` + --> tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs:22:15 + | +LL | let _ = x.y; + | ^ + +error: use of a disallowed field `conf_disallowed_fields::Y::y` + --> tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs:26:15 + | +LL | let _ = x.y; + | ^ + +error: use of a disallowed field `std::ops::Range::start` + --> tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs:30:15 + | +LL | let _ = x.start; + | ^^^^^ + +error: use of a disallowed field `std::ops::Range::end` + --> tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs:32:15 + | +LL | let _ = x.end; + | ^^^ + | + = note: no end allowed + +error: use of a disallowed field `std::ops::Range::start` + --> tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs:34:17 + | +LL | let Range { start, .. } = x; + | ^^^^^ + +error: use of a disallowed field `std::ops::RangeTo::end` + --> tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs:38:15 + | +LL | let _ = x.end; + | ^^^ + +error: use of a disallowed field `std::ops::RangeTo::end` + --> tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs:42:19 + | +LL | RangeTo { end } => {}, + | ^^^ + +error: use of a disallowed field `conf_disallowed_fields::Z::B::x` + --> tests/ui-toml/toml_disallowed_fields/conf_disallowed_fields.rs:48:16 + | +LL | Z::B { x } => {}, + | ^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index e208bd510657..6bb3db8db67f 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -18,6 +18,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-renamed-params-for allow-unwrap-in-consts allow-unwrap-in-tests + allow-unwrap-types allow-useless-vec-in-tests allowed-dotfiles allowed-duplicate-crates @@ -37,6 +38,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect check-private-items cognitive-complexity-threshold const-literal-digits-threshold + disallowed-fields disallowed-macros disallowed-methods disallowed-names @@ -117,6 +119,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-renamed-params-for allow-unwrap-in-consts allow-unwrap-in-tests + allow-unwrap-types allow-useless-vec-in-tests allowed-dotfiles allowed-duplicate-crates @@ -136,6 +139,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect check-private-items cognitive-complexity-threshold const-literal-digits-threshold + disallowed-fields disallowed-macros disallowed-methods disallowed-names @@ -216,6 +220,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni allow-renamed-params-for allow-unwrap-in-consts allow-unwrap-in-tests + allow-unwrap-types allow-useless-vec-in-tests allowed-dotfiles allowed-duplicate-crates @@ -235,6 +240,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni check-private-items cognitive-complexity-threshold const-literal-digits-threshold + disallowed-fields disallowed-macros disallowed-methods disallowed-names diff --git a/tests/ui-toml/unwrap_used_allowed/clippy.toml b/tests/ui-toml/unwrap_used_allowed/clippy.toml new file mode 100644 index 000000000000..cceb303c126f --- /dev/null +++ b/tests/ui-toml/unwrap_used_allowed/clippy.toml @@ -0,0 +1 @@ +allow-unwrap-types = ["std::sync::LockResult"] \ No newline at end of file diff --git a/tests/ui-toml/unwrap_used_allowed/unwrap_used_allowed.rs b/tests/ui-toml/unwrap_used_allowed/unwrap_used_allowed.rs new file mode 100644 index 000000000000..7905674e21e7 --- /dev/null +++ b/tests/ui-toml/unwrap_used_allowed/unwrap_used_allowed.rs @@ -0,0 +1,20 @@ +#![warn(clippy::unwrap_used)] +#![allow(clippy::unnecessary_literal_unwrap)] +#![allow(unused_variables)] +use std::sync::Mutex; + +fn main() { + let m = Mutex::new(0); + // This is allowed because `LockResult` is configured! + let _guard = m.lock().unwrap(); + + let optional: Option = Some(1); + // This is not allowed! + let _opt = optional.unwrap(); + //~^ ERROR: used `unwrap()` on an `Option` value + + let result: Result = Ok(1); + // This is not allowed! + let _res = result.unwrap(); + //~^ ERROR: used `unwrap()` on a `Result` value +} diff --git a/tests/ui-toml/unwrap_used_allowed/unwrap_used_allowed.stderr b/tests/ui-toml/unwrap_used_allowed/unwrap_used_allowed.stderr new file mode 100644 index 000000000000..1df89bf2eb92 --- /dev/null +++ b/tests/ui-toml/unwrap_used_allowed/unwrap_used_allowed.stderr @@ -0,0 +1,22 @@ +error: used `unwrap()` on an `Option` value + --> tests/ui-toml/unwrap_used_allowed/unwrap_used_allowed.rs:13:16 + | +LL | let _opt = optional.unwrap(); + | ^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + = help: consider using `expect()` to provide a better panic message + = note: `-D clippy::unwrap-used` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]` + +error: used `unwrap()` on a `Result` value + --> tests/ui-toml/unwrap_used_allowed/unwrap_used_allowed.rs:18:16 + | +LL | let _res = result.unwrap(); + | ^^^^^^^^^^^^^^^ + | + = note: if this value is an `Err`, it will panic + = help: consider using `expect()` to provide a better panic message + +error: aborting due to 2 previous errors + diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index f60c71837d5e..128fb6f5e38d 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -37,15 +37,4 @@ fn empty_and_false_positive_stmt() { #[deprecated(since = "TBD")] pub const GONNA_DEPRECATE_THIS_LATER: u8 = 0; -fn main() { - test_attr_lint(); - if false { - false_positive_expr() - } - if false { - false_positive_stmt() - } - if false { - empty_and_false_positive_stmt() - } -} +fn main() {} diff --git a/tests/ui/borrow_deref_ref.fixed b/tests/ui/borrow_deref_ref.fixed index 6d06fcc3037a..60334922a08a 100644 --- a/tests/ui/borrow_deref_ref.fixed +++ b/tests/ui/borrow_deref_ref.fixed @@ -171,3 +171,27 @@ fn issue_14934() { //~^ borrow_deref_ref } } + +mod issue16556 { + use std::pin::Pin; + + async fn async_main() { + for_each_city(|city| { + Box::pin(async { + // Do not lint, as it would not compile without reborrowing + let city = &*city; + println!("{city}") + }) + }) + .await; + } + + async fn for_each_city(mut f: F) + where + F: for<'c> FnMut(&'c str) -> Pin + Send + 'c>>, + { + for x in ["New York", "London", "Tokyo"] { + f(x).await; + } + } +} diff --git a/tests/ui/borrow_deref_ref.rs b/tests/ui/borrow_deref_ref.rs index b43f4c93bf2b..99fd1ae0acbc 100644 --- a/tests/ui/borrow_deref_ref.rs +++ b/tests/ui/borrow_deref_ref.rs @@ -171,3 +171,27 @@ fn issue_14934() { //~^ borrow_deref_ref } } + +mod issue16556 { + use std::pin::Pin; + + async fn async_main() { + for_each_city(|city| { + Box::pin(async { + // Do not lint, as it would not compile without reborrowing + let city = &*city; + println!("{city}") + }) + }) + .await; + } + + async fn for_each_city(mut f: F) + where + F: for<'c> FnMut(&'c str) -> Pin + Send + 'c>>, + { + for x in ["New York", "London", "Tokyo"] { + f(x).await; + } + } +} diff --git a/tests/ui/clone_on_ref_ptr.fixed b/tests/ui/clone_on_ref_ptr.fixed index ede9d171517e..86ae237f09af 100644 --- a/tests/ui/clone_on_ref_ptr.fixed +++ b/tests/ui/clone_on_ref_ptr.fixed @@ -50,10 +50,6 @@ mod issue2076 { } } -#[allow( - clippy::needless_borrow, - reason = "the suggestion creates `Weak::clone(&rec)`, but `rec` is already a reference" -)] mod issue15009 { use std::rc::{Rc, Weak}; use std::sync::atomic::{AtomicU32, Ordering}; @@ -62,7 +58,7 @@ mod issue15009 { let counter = AtomicU32::new(0); let counter_ref = &counter; let factorial = Rc::new_cyclic(move |rec| { - let rec = std::rc::Weak::::clone(&rec) as Weak u32>; + let rec = std::rc::Weak::::clone(rec) as Weak u32>; //~^ clone_on_ref_ptr move |x| { // can capture env @@ -79,3 +75,26 @@ mod issue15009 { println!("{}", counter.load(Ordering::Relaxed)); // 14 } } + +fn issue15741(mut rc: Rc, ref_rc: &Rc, refmut_rc: &mut Rc) { + std::rc::Rc::::clone(&rc); + //~^ clone_on_ref_ptr + std::rc::Rc::::clone(ref_rc); + //~^ clone_on_ref_ptr + std::rc::Rc::::clone(refmut_rc); + //~^ clone_on_ref_ptr + + // The following cases already cause warn-by-default lints to fire, and the suggestion just makes + // another set of warn-by-default lints to fire, so this is probably fine + + #[allow(clippy::needless_borrow, clippy::unnecessary_mut_passed)] // before the suggestion + #[allow(clippy::double_parens)] // after the suggestion + { + std::rc::Rc::::clone(&(rc)); + //~^ clone_on_ref_ptr + std::rc::Rc::::clone(&rc); + //~^ clone_on_ref_ptr + std::rc::Rc::::clone(&mut rc); + //~^ clone_on_ref_ptr + }; +} diff --git a/tests/ui/clone_on_ref_ptr.rs b/tests/ui/clone_on_ref_ptr.rs index 5999b4069d0f..cc6d2b611575 100644 --- a/tests/ui/clone_on_ref_ptr.rs +++ b/tests/ui/clone_on_ref_ptr.rs @@ -50,10 +50,6 @@ fn func() -> Option> { } } -#[allow( - clippy::needless_borrow, - reason = "the suggestion creates `Weak::clone(&rec)`, but `rec` is already a reference" -)] mod issue15009 { use std::rc::{Rc, Weak}; use std::sync::atomic::{AtomicU32, Ordering}; @@ -79,3 +75,26 @@ fn main() { println!("{}", counter.load(Ordering::Relaxed)); // 14 } } + +fn issue15741(mut rc: Rc, ref_rc: &Rc, refmut_rc: &mut Rc) { + rc.clone(); + //~^ clone_on_ref_ptr + ref_rc.clone(); + //~^ clone_on_ref_ptr + refmut_rc.clone(); + //~^ clone_on_ref_ptr + + // The following cases already cause warn-by-default lints to fire, and the suggestion just makes + // another set of warn-by-default lints to fire, so this is probably fine + + #[allow(clippy::needless_borrow, clippy::unnecessary_mut_passed)] // before the suggestion + #[allow(clippy::double_parens)] // after the suggestion + { + (rc).clone(); + //~^ clone_on_ref_ptr + (&rc).clone(); + //~^ clone_on_ref_ptr + (&mut rc).clone(); + //~^ clone_on_ref_ptr + }; +} diff --git a/tests/ui/clone_on_ref_ptr.stderr b/tests/ui/clone_on_ref_ptr.stderr index b8ddc3058c01..6a151e9ee101 100644 --- a/tests/ui/clone_on_ref_ptr.stderr +++ b/tests/ui/clone_on_ref_ptr.stderr @@ -38,10 +38,46 @@ LL | Some(try_opt!(Some(rc)).clone()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::rc::Rc::::clone(&try_opt!(Some(rc)))` error: using `.clone()` on a ref-counted pointer - --> tests/ui/clone_on_ref_ptr.rs:65:23 + --> tests/ui/clone_on_ref_ptr.rs:61:23 | LL | let rec = rec.clone() as Weak u32>; - | ^^^^^^^^^^^ help: try: `std::rc::Weak::::clone(&rec)` + | ^^^^^^^^^^^ help: try: `std::rc::Weak::::clone(rec)` -error: aborting due to 7 previous errors +error: using `.clone()` on a ref-counted pointer + --> tests/ui/clone_on_ref_ptr.rs:80:5 + | +LL | rc.clone(); + | ^^^^^^^^^^ help: try: `std::rc::Rc::::clone(&rc)` + +error: using `.clone()` on a ref-counted pointer + --> tests/ui/clone_on_ref_ptr.rs:82:5 + | +LL | ref_rc.clone(); + | ^^^^^^^^^^^^^^ help: try: `std::rc::Rc::::clone(ref_rc)` + +error: using `.clone()` on a ref-counted pointer + --> tests/ui/clone_on_ref_ptr.rs:84:5 + | +LL | refmut_rc.clone(); + | ^^^^^^^^^^^^^^^^^ help: try: `std::rc::Rc::::clone(refmut_rc)` + +error: using `.clone()` on a ref-counted pointer + --> tests/ui/clone_on_ref_ptr.rs:93:9 + | +LL | (rc).clone(); + | ^^^^^^^^^^^^ help: try: `std::rc::Rc::::clone(&(rc))` + +error: using `.clone()` on a ref-counted pointer + --> tests/ui/clone_on_ref_ptr.rs:95:9 + | +LL | (&rc).clone(); + | ^^^^^^^^^^^^^ help: try: `std::rc::Rc::::clone(&rc)` + +error: using `.clone()` on a ref-counted pointer + --> tests/ui/clone_on_ref_ptr.rs:97:9 + | +LL | (&mut rc).clone(); + | ^^^^^^^^^^^^^^^^^ help: try: `std::rc::Rc::::clone(&mut rc)` + +error: aborting due to 13 previous errors diff --git a/tests/ui/cmp_owned/with_suggestion.fixed b/tests/ui/cmp_owned/with_suggestion.fixed index f65339605e75..471905b47df7 100644 --- a/tests/ui/cmp_owned/with_suggestion.fixed +++ b/tests/ui/cmp_owned/with_suggestion.fixed @@ -114,6 +114,12 @@ fn issue16322(item: String) { } fn issue16458() { + macro_rules! m { + () => { + "" + }; + } + macro_rules! partly_comes_from_macro { ($i:ident: $ty:ty, $def:expr) => { let _ = { @@ -125,7 +131,7 @@ fn issue16458() { } partly_comes_from_macro! { - required_version: String, env!("HOME").to_string() + required_version: String, m!().to_string() } macro_rules! all_comes_from_macro { @@ -141,6 +147,6 @@ fn issue16458() { }; } all_comes_from_macro! { - required_version: String, env!("HOME").to_string(); + required_version: String, m!().to_string(); } } diff --git a/tests/ui/cmp_owned/with_suggestion.rs b/tests/ui/cmp_owned/with_suggestion.rs index ed2300c80eaa..3323176d34e3 100644 --- a/tests/ui/cmp_owned/with_suggestion.rs +++ b/tests/ui/cmp_owned/with_suggestion.rs @@ -114,6 +114,12 @@ fn issue16322(item: String) { } fn issue16458() { + macro_rules! m { + () => { + "" + }; + } + macro_rules! partly_comes_from_macro { ($i:ident: $ty:ty, $def:expr) => { let _ = { @@ -125,7 +131,7 @@ macro_rules! partly_comes_from_macro { } partly_comes_from_macro! { - required_version: String, env!("HOME").to_string() + required_version: String, m!().to_string() } macro_rules! all_comes_from_macro { @@ -141,6 +147,6 @@ macro_rules! all_comes_from_macro { }; } all_comes_from_macro! { - required_version: String, env!("HOME").to_string(); + required_version: String, m!().to_string(); } } diff --git a/tests/ui/cmp_owned/with_suggestion.stderr b/tests/ui/cmp_owned/with_suggestion.stderr index 38d124baa4b5..3797810e3b98 100644 --- a/tests/ui/cmp_owned/with_suggestion.stderr +++ b/tests/ui/cmp_owned/with_suggestion.stderr @@ -56,13 +56,13 @@ LL | if item == t!(frohes_neu_Jahr).to_string() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t!(frohes_neu_Jahr)` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/with_suggestion.rs:135:51 + --> tests/ui/cmp_owned/with_suggestion.rs:141:51 | LL | let res = <$ty>::default() == "$def".to_string(); | ^^^^^^^^^^^^^^^^^^ help: try: `"$def"` ... LL | / all_comes_from_macro! { -LL | | required_version: String, env!("HOME").to_string(); +LL | | required_version: String, m!().to_string(); LL | | } | |_____- in this macro invocation | diff --git a/tests/ui/collapsible_match_fixable.fixed b/tests/ui/collapsible_match_fixable.fixed new file mode 100644 index 000000000000..db76530aee14 --- /dev/null +++ b/tests/ui/collapsible_match_fixable.fixed @@ -0,0 +1,30 @@ +#![warn(clippy::collapsible_match)] +#![allow(clippy::single_match, clippy::redundant_guards)] + +fn issue16558() { + let opt = Some(1); + let _ = match opt { + Some(s) + if s == 1 => { s } + //~^ collapsible_match + , + _ => 1, + }; + + match opt { + Some(s) + if s == 1 => { + //~^ collapsible_match + todo!() + }, + _ => {}, + }; + + let _ = match opt { + Some(s) if s > 2 + && s == 1 => { s } + //~^ collapsible_match + , + _ => 1, + }; +} diff --git a/tests/ui/collapsible_match_fixable.rs b/tests/ui/collapsible_match_fixable.rs new file mode 100644 index 000000000000..94bf1d6bfdfa --- /dev/null +++ b/tests/ui/collapsible_match_fixable.rs @@ -0,0 +1,31 @@ +#![warn(clippy::collapsible_match)] +#![allow(clippy::single_match, clippy::redundant_guards)] + +fn issue16558() { + let opt = Some(1); + let _ = match opt { + Some(s) => { + if s == 1 { s } else { 1 } + //~^ collapsible_match + }, + _ => 1, + }; + + match opt { + Some(s) => { + (if s == 1 { + //~^ collapsible_match + todo!() + }) + }, + _ => {}, + }; + + let _ = match opt { + Some(s) if s > 2 => { + if s == 1 { s } else { 1 } + //~^ collapsible_match + }, + _ => 1, + }; +} diff --git a/tests/ui/collapsible_match_fixable.stderr b/tests/ui/collapsible_match_fixable.stderr new file mode 100644 index 000000000000..4d501cbd0993 --- /dev/null +++ b/tests/ui/collapsible_match_fixable.stderr @@ -0,0 +1,50 @@ +error: this `if` can be collapsed into the outer `match` + --> tests/ui/collapsible_match_fixable.rs:8:13 + | +LL | if s == 1 { s } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::collapsible-match` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::collapsible_match)]` +help: collapse nested if block + | +LL ~ Some(s) +LL ~ if s == 1 => { s } +LL | +LL ~ , + | + +error: this `if` can be collapsed into the outer `match` + --> tests/ui/collapsible_match_fixable.rs:16:13 + | +LL | / (if s == 1 { +LL | | +LL | | todo!() +LL | | }) + | |______________^ + | +help: collapse nested if block + | +LL ~ Some(s) +LL ~ if s == 1 => { +LL | +LL | todo!() +LL ~ }, + | + +error: this `if` can be collapsed into the outer `match` + --> tests/ui/collapsible_match_fixable.rs:26:13 + | +LL | if s == 1 { s } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: collapse nested if block + | +LL ~ Some(s) if s > 2 +LL ~ && s == 1 => { s } +LL | +LL ~ , + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/crashes/ice-10912.rs b/tests/ui/crashes/ice-10912.rs index 1d689e1d0082..57403d98e5d0 100644 --- a/tests/ui/crashes/ice-10912.rs +++ b/tests/ui/crashes/ice-10912.rs @@ -1,5 +1,5 @@ #![warn(clippy::unreadable_literal)] -//@no-rustfix + fn f2() -> impl Sized { && 3.14159265358979323846E } //~^ ERROR: expected at least one digit in exponent diff --git a/tests/ui/crashes/ice-6250.fixed b/tests/ui/crashes/ice-6250.fixed new file mode 100644 index 000000000000..71b3c90d56b0 --- /dev/null +++ b/tests/ui/crashes/ice-6250.fixed @@ -0,0 +1,19 @@ +// originally from glacier/fixed/77218.rs +// ice while adjusting... +#![expect(clippy::useless_vec)] + +pub struct Cache { + data: Vec, +} + +pub fn list_data(cache: &Cache, key: usize) { + for reference in vec![1, 2, 3] { + if + /* let */ + let Some(reference) = cache.data.get(key) { + //~^ ERROR: mismatched types + //~| ERROR: mismatched types + unimplemented!() + } + } +} diff --git a/tests/ui/crashes/ice-6250.rs b/tests/ui/crashes/ice-6250.rs index 65cdce793142..8c6100e2054d 100644 --- a/tests/ui/crashes/ice-6250.rs +++ b/tests/ui/crashes/ice-6250.rs @@ -1,6 +1,7 @@ // originally from glacier/fixed/77218.rs // ice while adjusting... -//@no-rustfix +#![expect(clippy::useless_vec)] + pub struct Cache { data: Vec, } diff --git a/tests/ui/crashes/ice-6250.stderr b/tests/ui/crashes/ice-6250.stderr index c126547611f3..83a7ef9fd2cf 100644 --- a/tests/ui/crashes/ice-6250.stderr +++ b/tests/ui/crashes/ice-6250.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> tests/ui/crashes/ice-6250.rs:12:14 + --> tests/ui/crashes/ice-6250.rs:13:14 | LL | for reference in vec![1, 2, 3] { | --------- expected due to the type of this binding @@ -8,7 +8,7 @@ LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^ expected integer, found `&i32` error[E0308]: mismatched types - --> tests/ui/crashes/ice-6250.rs:12:9 + --> tests/ui/crashes/ice-6250.rs:13:9 | LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` diff --git a/tests/ui/crashes/ice-9041.fixed b/tests/ui/crashes/ice-9041.fixed new file mode 100644 index 000000000000..32399e4255d1 --- /dev/null +++ b/tests/ui/crashes/ice-9041.fixed @@ -0,0 +1,12 @@ +#![warn(clippy::search_is_some)] +#![allow(clippy::needless_borrow)] + +pub struct Thing; + +pub fn has_thing(things: &[Thing]) -> bool { + let is_thing_ready = |_peer: &Thing| -> bool { todo!() }; + things.iter().any(|p| is_thing_ready(&p)) + //~^ search_is_some +} + +fn main() {} diff --git a/tests/ui/crashes/ice-9041.rs b/tests/ui/crashes/ice-9041.rs index fae3233ba2f5..55e88fa6da5a 100644 --- a/tests/ui/crashes/ice-9041.rs +++ b/tests/ui/crashes/ice-9041.rs @@ -1,6 +1,8 @@ #![warn(clippy::search_is_some)] +#![allow(clippy::needless_borrow)] + pub struct Thing; -//@no-rustfix + pub fn has_thing(things: &[Thing]) -> bool { let is_thing_ready = |_peer: &Thing| -> bool { todo!() }; things.iter().find(|p| is_thing_ready(p)).is_some() diff --git a/tests/ui/crashes/ice-9041.stderr b/tests/ui/crashes/ice-9041.stderr index 256c8b833034..98bdff9bbfac 100644 --- a/tests/ui/crashes/ice-9041.stderr +++ b/tests/ui/crashes/ice-9041.stderr @@ -1,5 +1,5 @@ error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/crashes/ice-9041.rs:6:19 + --> tests/ui/crashes/ice-9041.rs:8:19 | LL | things.iter().find(|p| is_thing_ready(p)).is_some() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|p| is_thing_ready(&p))` diff --git a/tests/ui/crashes/returns.rs b/tests/ui/crashes/returns.rs index ccab9522753e..a28266a2d2f1 100644 --- a/tests/ui/crashes/returns.rs +++ b/tests/ui/crashes/returns.rs @@ -18,7 +18,4 @@ fn cfg_let_and_return() -> i32 { x } -fn main() { - cfg_return(); - cfg_let_and_return(); -} +fn main() {} diff --git a/tests/ui/debug_assert_with_mut_call.rs b/tests/ui/debug_assert_with_mut_call.rs index 74d59b7593fa..199f217a02b9 100644 --- a/tests/ui/debug_assert_with_mut_call.rs +++ b/tests/ui/debug_assert_with_mut_call.rs @@ -179,12 +179,4 @@ async fn debug_await() { }.await); } -fn main() { - func_non_mutable(); - func_mutable(); - method_non_mutable(); - method_mutable(); - - misc(); - debug_await(); -} +fn main() {} diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index 58d8b8b33ade..570d8090f8e3 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -109,10 +109,6 @@ fn test_allowed() { /// `be_sure_we_got_to_the_end_of_it` //~^ doc_markdown fn main() { - foo_bar(); - multiline_codeblock(); - test_emphasis(); - test_units(); } /// ## `CamelCaseThing` diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index 0b1237f716fa..dd80bc4b25ee 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -109,10 +109,6 @@ fn test_allowed() { /// be_sure_we_got_to_the_end_of_it //~^ doc_markdown fn main() { - foo_bar(); - multiline_codeblock(); - test_emphasis(); - test_units(); } /// ## CamelCaseThing diff --git a/tests/ui/doc/doc-fixable.stderr b/tests/ui/doc/doc-fixable.stderr index 2a94a8f31658..a04d06f6db1a 100644 --- a/tests/ui/doc/doc-fixable.stderr +++ b/tests/ui/doc/doc-fixable.stderr @@ -169,7 +169,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:118:8 + --> tests/ui/doc/doc-fixable.rs:114:8 | LL | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + /// ## `CamelCaseThing` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:122:7 + --> tests/ui/doc/doc-fixable.rs:118:7 | LL | /// # CamelCaseThing | ^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + /// # `CamelCaseThing` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:125:22 + --> tests/ui/doc/doc-fixable.rs:121:22 | LL | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + /// Not a title #897 `CamelCaseThing` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:127:5 + --> tests/ui/doc/doc-fixable.rs:123:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:135:5 + --> tests/ui/doc/doc-fixable.rs:131:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:149:5 + --> tests/ui/doc/doc-fixable.rs:145:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:161:43 + --> tests/ui/doc/doc-fixable.rs:157:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ @@ -253,7 +253,7 @@ LL + /** E.g., serialization of an empty list: `FooBar` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:166:5 + --> tests/ui/doc/doc-fixable.rs:162:5 | LL | And BarQuz too. | ^^^^^^ @@ -265,7 +265,7 @@ LL + And `BarQuz` too. | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:167:1 + --> tests/ui/doc/doc-fixable.rs:163:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL + `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:175:43 + --> tests/ui/doc/doc-fixable.rs:171:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ @@ -289,7 +289,7 @@ LL + /** E.g., serialization of an empty list: `FooBar` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:180:5 + --> tests/ui/doc/doc-fixable.rs:176:5 | LL | And BarQuz too. | ^^^^^^ @@ -301,7 +301,7 @@ LL + And `BarQuz` too. | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:181:1 + --> tests/ui/doc/doc-fixable.rs:177:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL + `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:195:5 + --> tests/ui/doc/doc-fixable.rs:191:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +325,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:215:22 + --> tests/ui/doc/doc-fixable.rs:211:22 | LL | /// An iterator over mycrate::Collection's values. | ^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL + /// An iterator over `mycrate::Collection`'s values. | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:240:34 + --> tests/ui/doc/doc-fixable.rs:236:34 | LL | /// Foo \[bar\] \[baz\] \[qux\]. DocMarkdownLint | ^^^^^^^^^^^^^^^ @@ -349,7 +349,7 @@ LL + /// Foo \[bar\] \[baz\] \[qux\]. `DocMarkdownLint` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:264:22 + --> tests/ui/doc/doc-fixable.rs:260:22 | LL | /// There is no try (do() or do_not()). | ^^^^ @@ -361,7 +361,7 @@ LL + /// There is no try (`do()` or do_not()). | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:264:30 + --> tests/ui/doc/doc-fixable.rs:260:30 | LL | /// There is no try (do() or do_not()). | ^^^^^^^^ @@ -373,7 +373,7 @@ LL + /// There is no try (do() or `do_not()`). | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:269:5 + --> tests/ui/doc/doc-fixable.rs:265:5 | LL | /// ABes | ^^^^ @@ -385,7 +385,7 @@ LL + /// `ABes` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:276:9 + --> tests/ui/doc/doc-fixable.rs:272:9 | LL | /// foo() | ^^^^^ @@ -397,7 +397,7 @@ LL + /// `foo()` | error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> tests/ui/doc/doc-fixable.rs:281:5 + --> tests/ui/doc/doc-fixable.rs:277:5 | LL | /// https://github.com/rust-lang/rust-clippy/pull/12836 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `` diff --git a/tests/ui/doc_link_with_quotes.rs b/tests/ui/doc_link_with_quotes.rs index 0c0e273da6db..82ec8fc2e081 100644 --- a/tests/ui/doc_link_with_quotes.rs +++ b/tests/ui/doc_link_with_quotes.rs @@ -1,8 +1,6 @@ #![warn(clippy::doc_link_with_quotes)] -fn main() { - foo() -} +fn main() {} /// Calls ['bar'] uselessly //~^ doc_link_with_quotes diff --git a/tests/ui/doc_link_with_quotes.stderr b/tests/ui/doc_link_with_quotes.stderr index 47c60390310c..729fc483f562 100644 --- a/tests/ui/doc_link_with_quotes.stderr +++ b/tests/ui/doc_link_with_quotes.stderr @@ -1,5 +1,5 @@ error: possible intra-doc link using quotes instead of backticks - --> tests/ui/doc_link_with_quotes.rs:7:12 + --> tests/ui/doc_link_with_quotes.rs:5:12 | LL | /// Calls ['bar'] uselessly | ^^^^^ @@ -8,7 +8,7 @@ LL | /// Calls ['bar'] uselessly = help: to override `-D warnings` add `#[allow(clippy::doc_link_with_quotes)]` error: possible intra-doc link using quotes instead of backticks - --> tests/ui/doc_link_with_quotes.rs:13:12 + --> tests/ui/doc_link_with_quotes.rs:11:12 | LL | /// Calls ["bar"] uselessly | ^^^^^ diff --git a/tests/ui/double_must_use.rs b/tests/ui/double_must_use.rs index 3d4aaa9baa49..c8b5828889fc 100644 --- a/tests/ui/double_must_use.rs +++ b/tests/ui/double_must_use.rs @@ -1,5 +1,8 @@ #![warn(clippy::double_must_use)] #![allow(clippy::result_unit_err)] +#![feature(never_type)] + +use std::ops::ControlFlow; #[must_use] pub fn must_use_result() -> Result<(), ()> { @@ -40,8 +43,29 @@ async fn async_must_use_result() -> Result<(), ()> { Ok(()) } -fn main() { - must_use_result(); - must_use_tuple(); - must_use_with_note(); +#[must_use] +pub fn must_use_result_with_uninhabited() -> Result<(), !> { + unimplemented!(); } + +#[must_use] +pub struct T; + +#[must_use] +pub fn must_use_result_with_uninhabited_2() -> Result { + //~^ double_must_use + unimplemented!(); +} + +#[must_use] +pub fn must_use_controlflow_with_uninhabited() -> ControlFlow { + unimplemented!(); +} + +#[must_use] +pub fn must_use_controlflow_with_uninhabited_2() -> ControlFlow { + //~^ double_must_use + unimplemented!(); +} + +fn main() {} diff --git a/tests/ui/double_must_use.stderr b/tests/ui/double_must_use.stderr index 555dd8902cac..50b1640c47f5 100644 --- a/tests/ui/double_must_use.stderr +++ b/tests/ui/double_must_use.stderr @@ -1,5 +1,5 @@ error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` - --> tests/ui/double_must_use.rs:5:1 + --> tests/ui/double_must_use.rs:8:1 | LL | pub fn must_use_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | pub fn must_use_result() -> Result<(), ()> { = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]` error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` - --> tests/ui/double_must_use.rs:12:1 + --> tests/ui/double_must_use.rs:15:1 | LL | pub fn must_use_tuple() -> (Result<(), ()>, u8) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | pub fn must_use_tuple() -> (Result<(), ()>, u8) { = help: either add some descriptive message or remove the attribute error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` - --> tests/ui/double_must_use.rs:19:1 + --> tests/ui/double_must_use.rs:22:1 | LL | pub fn must_use_array() -> [Result<(), ()>; 1] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,12 +25,28 @@ LL | pub fn must_use_array() -> [Result<(), ()>; 1] { = help: either add some descriptive message or remove the attribute error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` - --> tests/ui/double_must_use.rs:37:1 + --> tests/ui/double_must_use.rs:40:1 | LL | async fn async_must_use_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: either add some descriptive message or remove the attribute -error: aborting due to 4 previous errors +error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` + --> tests/ui/double_must_use.rs:55:1 + | +LL | pub fn must_use_result_with_uninhabited_2() -> Result { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: either add some descriptive message or remove the attribute + +error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` + --> tests/ui/double_must_use.rs:66:1 + | +LL | pub fn must_use_controlflow_with_uninhabited_2() -> ControlFlow { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: either add some descriptive message or remove the attribute + +error: aborting due to 6 previous errors diff --git a/tests/ui/drop_non_drop.rs b/tests/ui/drop_non_drop.rs index 0345e8670ab8..e6433de5163d 100644 --- a/tests/ui/drop_non_drop.rs +++ b/tests/ui/drop_non_drop.rs @@ -6,6 +6,11 @@ fn make_result(t: T) -> Result { Ok(t) } +// The return type should behave as `T` as the `Err` variant is uninhabited +fn make_result_uninhabited_err(t: T) -> Result { + Ok(t) +} + #[must_use] fn must_use(t: T) -> T { t @@ -41,4 +46,8 @@ fn drop(&mut self) {} // Don't lint drop(Baz(Bar)); + + // Lint + drop(make_result_uninhabited_err(Foo)); + //~^ drop_non_drop } diff --git a/tests/ui/drop_non_drop.stderr b/tests/ui/drop_non_drop.stderr index b431c62c92c5..567a820990c6 100644 --- a/tests/ui/drop_non_drop.stderr +++ b/tests/ui/drop_non_drop.stderr @@ -1,11 +1,11 @@ error: call to `std::mem::drop` with a value that does not implement `Drop`. Dropping such a type only extends its contained lifetimes - --> tests/ui/drop_non_drop.rs:22:5 + --> tests/ui/drop_non_drop.rs:27:5 | LL | drop(Foo); | ^^^^^^^^^ | note: argument has type `main::Foo` - --> tests/ui/drop_non_drop.rs:22:10 + --> tests/ui/drop_non_drop.rs:27:10 | LL | drop(Foo); | ^^^ @@ -13,16 +13,28 @@ LL | drop(Foo); = help: to override `-D warnings` add `#[allow(clippy::drop_non_drop)]` error: call to `std::mem::drop` with a value that does not implement `Drop`. Dropping such a type only extends its contained lifetimes - --> tests/ui/drop_non_drop.rs:39:5 + --> tests/ui/drop_non_drop.rs:44:5 | LL | drop(Baz(Foo)); | ^^^^^^^^^^^^^^ | note: argument has type `main::Baz` - --> tests/ui/drop_non_drop.rs:39:10 + --> tests/ui/drop_non_drop.rs:44:10 | LL | drop(Baz(Foo)); | ^^^^^^^^ -error: aborting due to 2 previous errors +error: call to `std::mem::drop` with a value that does not implement `Drop`. Dropping such a type only extends its contained lifetimes + --> tests/ui/drop_non_drop.rs:51:5 + | +LL | drop(make_result_uninhabited_err(Foo)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: argument has type `std::result::Result` + --> tests/ui/drop_non_drop.rs:51:10 + | +LL | drop(make_result_uninhabited_err(Foo)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors diff --git a/tests/ui/duplicate_underscore_argument.rs b/tests/ui/duplicate_underscore_argument.rs index b71f5a20a843..820930bc6c12 100644 --- a/tests/ui/duplicate_underscore_argument.rs +++ b/tests/ui/duplicate_underscore_argument.rs @@ -5,7 +5,4 @@ fn join_the_dark_side(darth: i32, _darth: i32) {} fn join_the_light_side(knight: i32, _master: i32) {} // the Force is strong with this one -fn main() { - join_the_dark_side(0, 0); - join_the_light_side(0, 0); -} +fn main() {} diff --git a/tests/ui/duration_suboptimal_units.fixed b/tests/ui/duration_suboptimal_units.fixed index 515ec10e572b..a4eb981ebfa2 100644 --- a/tests/ui/duration_suboptimal_units.fixed +++ b/tests/ui/duration_suboptimal_units.fixed @@ -94,3 +94,14 @@ fn issue16457() { // Methods taking something else than `u64` are not covered _ = Duration::from_nanos_u128(1 << 90); } + +#[clippy::msrv = "1.90"] +fn insufficient_msrv() { + _ = Duration::from_secs(67_768_040_922_076_800); +} + +#[clippy::msrv = "1.91"] +fn sufficient_msrv() { + _ = Duration::from_hours(18824455811688); + //~^ duration_suboptimal_units +} diff --git a/tests/ui/duration_suboptimal_units.rs b/tests/ui/duration_suboptimal_units.rs index 357c52cffb35..e31ca679b5a1 100644 --- a/tests/ui/duration_suboptimal_units.rs +++ b/tests/ui/duration_suboptimal_units.rs @@ -94,3 +94,14 @@ fn issue16457() { // Methods taking something else than `u64` are not covered _ = Duration::from_nanos_u128(1 << 90); } + +#[clippy::msrv = "1.90"] +fn insufficient_msrv() { + _ = Duration::from_secs(67_768_040_922_076_800); +} + +#[clippy::msrv = "1.91"] +fn sufficient_msrv() { + _ = Duration::from_secs(67_768_040_922_076_800); + //~^ duration_suboptimal_units +} diff --git a/tests/ui/duration_suboptimal_units.stderr b/tests/ui/duration_suboptimal_units.stderr index f129dbade8dc..97b26f6667eb 100644 --- a/tests/ui/duration_suboptimal_units.stderr +++ b/tests/ui/duration_suboptimal_units.stderr @@ -148,5 +148,17 @@ LL - Duration::from_secs(300) LL + Duration::from_mins(5) | -error: aborting due to 12 previous errors +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:105:9 + | +LL | _ = Duration::from_secs(67_768_040_922_076_800); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - _ = Duration::from_secs(67_768_040_922_076_800); +LL + _ = Duration::from_hours(18824455811688); + | + +error: aborting due to 13 previous errors diff --git a/tests/ui/erasing_op.rs b/tests/ui/erasing_op.rs index 9237b9eb11f0..8867f445edcb 100644 --- a/tests/ui/erasing_op.rs +++ b/tests/ui/erasing_op.rs @@ -49,6 +49,4 @@ fn test(x: u8) { //~^ erasing_op } -fn main() { - test(0) -} +fn main() {} diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index 107318e5323d..fdaf1c37b201 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -643,3 +643,12 @@ where { maybe.map(|x| visitor(x)); } + +trait Issue16360: Sized { + fn method(&self); + + fn ice_machine(array: [Self; 1]) { + array.iter().for_each(Self::method); + //~^ redundant_closure_for_method_calls + } +} diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index b85e8e75153a..1054060db449 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -643,3 +643,12 @@ async fn issue13892<'a, T, F>(maybe: Option<&'a T>, visitor: F) { maybe.map(|x| visitor(x)); } + +trait Issue16360: Sized { + fn method(&self); + + fn ice_machine(array: [Self; 1]) { + array.iter().for_each(|item| item.method()); + //~^ redundant_closure_for_method_calls + } +} diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 0b401cdea987..2e0ccc557915 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -256,5 +256,11 @@ error: redundant closure LL | .map(|n| f(n)) | ^^^^^^^^ help: replace the closure with the function itself: `f` -error: aborting due to 42 previous errors +error: redundant closure + --> tests/ui/eta.rs:651:31 + | +LL | array.iter().for_each(|item| item.method()); + | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `Self::method` + +error: aborting due to 43 previous errors diff --git a/tests/ui/expect.rs b/tests/ui/expect.rs index 1ab01ecfcfe3..75b7916ecc5b 100644 --- a/tests/ui/expect.rs +++ b/tests/ui/expect.rs @@ -34,8 +34,4 @@ fn issue_15247() { //~^ expect_used } -fn main() { - expect_option(); - expect_result(); - issue_15247(); -} +fn main() {} diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs index ec4cecf37766..ebb261a0d97a 100644 --- a/tests/ui/explicit_counter_loop.rs +++ b/tests/ui/explicit_counter_loop.rs @@ -33,10 +33,10 @@ fn main() { } let vec = [1, 2, 3, 4]; - // Potential false positives let mut _index = 0; _index = 1; for _v in &vec { + //~^ explicit_counter_loop _index += 1 } @@ -299,3 +299,21 @@ pub fn test() { } } } + +fn issue16612(v: Vec, s: i64) { + use std::hint::black_box; + + let mut i = 1; + for item in &v { + //~^ explicit_counter_loop + black_box((i, *item)); + i += 1; + } + + let mut j = s + 1; + for item in &v { + //~^ explicit_counter_loop + black_box((j, *item)); + j += 1; + } +} diff --git a/tests/ui/explicit_counter_loop.stderr b/tests/ui/explicit_counter_loop.stderr index a73516558c20..7a83df05ec0a 100644 --- a/tests/ui/explicit_counter_loop.stderr +++ b/tests/ui/explicit_counter_loop.stderr @@ -25,6 +25,12 @@ error: the variable `_index` is used as a loop counter LL | for _v in vec { | ^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.into_iter().enumerate()` +error: the variable `_index` is used as a loop counter + --> tests/ui/explicit_counter_loop.rs:38:5 + | +LL | for _v in &vec { + | ^^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in (1..).zip(vec.iter())` + error: the variable `count` is used as a loop counter --> tests/ui/explicit_counter_loop.rs:118:9 | @@ -63,5 +69,17 @@ error: the variable `_index` is used as a loop counter LL | 'label: for v in vec { | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `'label: for (_index, v) in vec.into_iter().enumerate()` -error: aborting due to 10 previous errors +error: the variable `i` is used as a loop counter + --> tests/ui/explicit_counter_loop.rs:307:5 + | +LL | for item in &v { + | ^^^^^^^^^^^^^^ help: consider using: `for (i, item) in (1..).zip(v.iter())` + +error: the variable `j` is used as a loop counter + --> tests/ui/explicit_counter_loop.rs:314:5 + | +LL | for item in &v { + | ^^^^^^^^^^^^^^ help: consider using: `for (j, item) in (s + 1..).zip(v.iter())` + +error: aborting due to 13 previous errors diff --git a/tests/ui/floating_point_abs.fixed b/tests/ui/floating_point_abs.fixed index e8d64a3d7c29..53e9014e284f 100644 --- a/tests/ui/floating_point_abs.fixed +++ b/tests/ui/floating_point_abs.fixed @@ -73,18 +73,4 @@ fn not_fake_abs5(a: A) -> f64 { if a.a > 0.0 { a.a } else { -a.b } } -fn main() { - fake_abs1(5.0); - fake_abs2(5.0); - fake_abs3(A { a: 5.0, b: 5.0 }); - fake_abs4(5.0); - fake_abs5(A { a: 5.0, b: 5.0 }); - fake_nabs1(5.0); - fake_nabs2(5.0); - fake_nabs3(A { a: 5.0, b: 5.0 }); - not_fake_abs1(5.0); - not_fake_abs2(5.0); - not_fake_abs3(5.0, 5.0); - not_fake_abs4(A { a: 5.0, b: 5.0 }); - not_fake_abs5(A { a: 5.0, b: 5.0 }); -} +fn main() {} diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs index a27279b0662f..d5c792f6eb9c 100644 --- a/tests/ui/floating_point_abs.rs +++ b/tests/ui/floating_point_abs.rs @@ -73,18 +73,4 @@ fn not_fake_abs5(a: A) -> f64 { if a.a > 0.0 { a.a } else { -a.b } } -fn main() { - fake_abs1(5.0); - fake_abs2(5.0); - fake_abs3(A { a: 5.0, b: 5.0 }); - fake_abs4(5.0); - fake_abs5(A { a: 5.0, b: 5.0 }); - fake_nabs1(5.0); - fake_nabs2(5.0); - fake_nabs3(A { a: 5.0, b: 5.0 }); - not_fake_abs1(5.0); - not_fake_abs2(5.0); - not_fake_abs3(5.0, 5.0); - not_fake_abs4(A { a: 5.0, b: 5.0 }); - not_fake_abs5(A { a: 5.0, b: 5.0 }); -} +fn main() {} diff --git a/tests/ui/four_forward_slashes_bare_cr.rs b/tests/ui/four_forward_slashes_bare_cr.rs index 19123cd206e3..9f3388512a05 100644 --- a/tests/ui/four_forward_slashes_bare_cr.rs +++ b/tests/ui/four_forward_slashes_bare_cr.rs @@ -1,4 +1,3 @@ -//@no-rustfix #![warn(clippy::four_forward_slashes)] //~v four_forward_slashes diff --git a/tests/ui/four_forward_slashes_bare_cr.stderr b/tests/ui/four_forward_slashes_bare_cr.stderr index 64e70b97db9a..266a5fa72c54 100644 --- a/tests/ui/four_forward_slashes_bare_cr.stderr +++ b/tests/ui/four_forward_slashes_bare_cr.stderr @@ -1,5 +1,5 @@ error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't - --> tests/ui/four_forward_slashes_bare_cr.rs:5:1 + --> tests/ui/four_forward_slashes_bare_cr.rs:4:1 | LL | / //// nondoc comment with bare CR: '␍' LL | | fn main() {} diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index 4e1668ed04fb..f09b2a4b7591 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -87,10 +87,7 @@ fn potential_infinite_iters() { repeat(42).take_while(|x| *x == 42).next(); } -fn main() { - infinite_iters(); - potential_infinite_iters(); -} +fn main() {} mod finite_collect { use std::collections::HashSet; diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index 3db97313b621..3017940c82cb 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -100,7 +100,7 @@ LL | (0..).all(|x| x == 24); | ^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> tests/ui/infinite_iter.rs:107:31 + --> tests/ui/infinite_iter.rs:104:31 | LL | let _: HashSet = (0..).collect(); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/ip_constant_from_external.rs b/tests/ui/ip_constant_from_external.rs index 7fd27022f127..dae15623018a 100644 --- a/tests/ui/ip_constant_from_external.rs +++ b/tests/ui/ip_constant_from_external.rs @@ -7,6 +7,4 @@ fn external_constant_test() { // lint in external file `localhost.txt` } -fn main() { - external_constant_test(); -} +fn main() {} diff --git a/tests/ui/iter_kv_map.fixed b/tests/ui/iter_kv_map.fixed index 189d76bc9431..e3ab5fd1e9ef 100644 --- a/tests/ui/iter_kv_map.fixed +++ b/tests/ui/iter_kv_map.fixed @@ -1,5 +1,11 @@ #![warn(clippy::iter_kv_map)] -#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)] +#![allow( + unused_mut, + clippy::redundant_clone, + clippy::redundant_closure, + clippy::suspicious_map, + clippy::map_identity +)] use std::collections::{BTreeMap, HashMap}; @@ -195,3 +201,33 @@ fn issue16340() { let _ = hm.keys().map(|key| vec![key]); //~^ iter_kv_map } + +fn issue16515() { + let hash_map: HashMap = HashMap::new(); + hash_map.keys().flat_map(|k| Some(*k)); + //~^ iter_kv_map + + hash_map.values().flat_map(|v| Some(*v)); + //~^ iter_kv_map + + hash_map.keys().filter_map(|k| (k > &0).then_some(1)); + //~^ iter_kv_map + + hash_map.values().filter_map(|v| (v > &0).then_some(1)); + //~^ iter_kv_map + + hash_map.into_keys().flat_map(|k| Some(k)); + //~^ iter_kv_map + + let hash_map: HashMap = HashMap::new(); + hash_map.into_values().flat_map(|v| Some(v)); + //~^ iter_kv_map + + let hash_map: HashMap = HashMap::new(); + hash_map.into_keys().filter_map(|k| (k > 0).then_some(1)); + //~^ iter_kv_map + + let hash_map: HashMap = HashMap::new(); + hash_map.into_values().filter_map(|v| (v > 0).then_some(1)); + //~^ iter_kv_map +} diff --git a/tests/ui/iter_kv_map.rs b/tests/ui/iter_kv_map.rs index cfc303447004..903813b1bf62 100644 --- a/tests/ui/iter_kv_map.rs +++ b/tests/ui/iter_kv_map.rs @@ -1,5 +1,11 @@ #![warn(clippy::iter_kv_map)] -#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)] +#![allow( + unused_mut, + clippy::redundant_clone, + clippy::redundant_closure, + clippy::suspicious_map, + clippy::map_identity +)] use std::collections::{BTreeMap, HashMap}; @@ -199,3 +205,33 @@ fn issue16340() { let _ = hm.iter().map(|(key, _)| vec![key]); //~^ iter_kv_map } + +fn issue16515() { + let hash_map: HashMap = HashMap::new(); + hash_map.iter().flat_map(|(k, _)| Some(*k)); + //~^ iter_kv_map + + hash_map.iter().flat_map(|(_, v)| Some(*v)); + //~^ iter_kv_map + + hash_map.iter().filter_map(|(k, _)| (k > &0).then_some(1)); + //~^ iter_kv_map + + hash_map.iter().filter_map(|(_, v)| (v > &0).then_some(1)); + //~^ iter_kv_map + + hash_map.into_iter().flat_map(|(k, _)| Some(k)); + //~^ iter_kv_map + + let hash_map: HashMap = HashMap::new(); + hash_map.into_iter().flat_map(|(_, v)| Some(v)); + //~^ iter_kv_map + + let hash_map: HashMap = HashMap::new(); + hash_map.into_iter().filter_map(|(k, _)| (k > 0).then_some(1)); + //~^ iter_kv_map + + let hash_map: HashMap = HashMap::new(); + hash_map.into_iter().filter_map(|(_, v)| (v > 0).then_some(1)); + //~^ iter_kv_map +} diff --git a/tests/ui/iter_kv_map.stderr b/tests/ui/iter_kv_map.stderr index 866e69ea1922..cdfd05fdd09e 100644 --- a/tests/ui/iter_kv_map.stderr +++ b/tests/ui/iter_kv_map.stderr @@ -1,5 +1,5 @@ error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:14:13 + --> tests/ui/iter_kv_map.rs:20:13 | LL | let _ = map.iter().map(|(key, _)| key).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` @@ -8,174 +8,73 @@ LL | let _ = map.iter().map(|(key, _)| key).collect::>(); = help: to override `-D warnings` add `#[allow(clippy::iter_kv_map)]` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:16:13 + --> tests/ui/iter_kv_map.rs:22:13 | LL | let _ = map.iter().map(|(_, value)| value).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:18:13 + --> tests/ui/iter_kv_map.rs:24:13 | LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:21:13 + --> tests/ui/iter_kv_map.rs:27:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:23:13 + --> tests/ui/iter_kv_map.rs:29:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:26:13 + --> tests/ui/iter_kv_map.rs:32:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:28:13 + --> tests/ui/iter_kv_map.rs:34:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:31:13 + --> tests/ui/iter_kv_map.rs:37:13 | LL | let _ = map.clone().iter().map(|(_, val)| val).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:33:13 + --> tests/ui/iter_kv_map.rs:39:13 | LL | let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:48:13 - | -LL | let _ = map.iter().map(|(key, _value)| key * 9).count(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)` - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:50:13 - | -LL | let _ = map.iter().map(|(_key, value)| value * 17).count(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)` - -error: iterating on a map's values --> tests/ui/iter_kv_map.rs:54:13 | -LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))` - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:58:13 - | -LL | let _ = map - | _____________^ -LL | | -LL | | .clone() -LL | | .into_iter() -... | -LL | | val -LL | | }) - | |__________^ - | -help: try - | -LL ~ let _ = map -LL + -LL + .clone().into_values().map(|mut val| { -LL + val += 2; -LL + val -LL + }) - | - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:69:13 - | -LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` - -error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:74:13 - | -LL | let _ = map.iter().map(|(key, _)| key).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:76:13 - | -LL | let _ = map.iter().map(|(_, value)| value).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:78:13 - | -LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` - -error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:81:13 - | -LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` - -error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:83:13 - | -LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:86:13 - | -LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:88:13 - | -LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:91:13 - | -LL | let _ = map.clone().iter().map(|(_, val)| val).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()` - -error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:93:13 - | -LL | let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` - -error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:108:13 - | LL | let _ = map.iter().map(|(key, _value)| key * 9).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:110:13 + --> tests/ui/iter_kv_map.rs:56:13 | LL | let _ = map.iter().map(|(_key, value)| value * 17).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:114:13 + --> tests/ui/iter_kv_map.rs:60:13 | LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:118:13 + --> tests/ui/iter_kv_map.rs:64:13 | LL | let _ = map | _____________^ @@ -198,82 +97,231 @@ LL + }) | error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:129:13 + --> tests/ui/iter_kv_map.rs:75:13 | LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:145:13 + --> tests/ui/iter_kv_map.rs:80:13 | LL | let _ = map.iter().map(|(key, _)| key).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:148:13 + --> tests/ui/iter_kv_map.rs:82:13 | LL | let _ = map.iter().map(|(_, value)| value).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:151:13 + --> tests/ui/iter_kv_map.rs:84:13 | LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:160:13 + --> tests/ui/iter_kv_map.rs:87:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:163:13 + --> tests/ui/iter_kv_map.rs:89:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:166:13 + --> tests/ui/iter_kv_map.rs:92:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:169:13 + --> tests/ui/iter_kv_map.rs:94:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:97:13 + | +LL | let _ = map.clone().iter().map(|(_, val)| val).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()` + error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:172:13 + --> tests/ui/iter_kv_map.rs:99:13 + | +LL | let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:114:13 + | +LL | let _ = map.iter().map(|(key, _value)| key * 9).count(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:116:13 + | +LL | let _ = map.iter().map(|(_key, value)| value * 17).count(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:120:13 + | +LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:124:13 + | +LL | let _ = map + | _____________^ +LL | | +LL | | .clone() +LL | | .into_iter() +... | +LL | | val +LL | | }) + | |__________^ + | +help: try + | +LL ~ let _ = map +LL + +LL + .clone().into_values().map(|mut val| { +LL + val += 2; +LL + val +LL + }) + | + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:135:13 + | +LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:151:13 | LL | let _ = map.iter().map(|(key, _)| key).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:154:13 + | +LL | let _ = map.iter().map(|(_, value)| value).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:157:13 + | +LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:166:13 + | +LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:169:13 + | +LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:172:13 + | +LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` + error: iterating on a map's values --> tests/ui/iter_kv_map.rs:175:13 | +LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:178:13 + | +LL | let _ = map.iter().map(|(key, _)| key).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:181:13 + | LL | let _ = map.iter().map(|(_, value)| value).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:178:13 + --> tests/ui/iter_kv_map.rs:184:13 | LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:193:13 + --> tests/ui/iter_kv_map.rs:199:13 | LL | let _ = map.as_ref().iter().map(|(_, v)| v).copied().collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.as_ref().values()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:199:13 + --> tests/ui/iter_kv_map.rs:205:13 | LL | let _ = hm.iter().map(|(key, _)| vec![key]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hm.keys().map(|key| vec![key])` -error: aborting due to 40 previous errors +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:211:5 + | +LL | hash_map.iter().flat_map(|(k, _)| Some(*k)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.keys().flat_map(|k| Some(*k))` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:214:5 + | +LL | hash_map.iter().flat_map(|(_, v)| Some(*v)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.values().flat_map(|v| Some(*v))` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:217:5 + | +LL | hash_map.iter().filter_map(|(k, _)| (k > &0).then_some(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.keys().filter_map(|k| (k > &0).then_some(1))` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:220:5 + | +LL | hash_map.iter().filter_map(|(_, v)| (v > &0).then_some(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.values().filter_map(|v| (v > &0).then_some(1))` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:223:5 + | +LL | hash_map.into_iter().flat_map(|(k, _)| Some(k)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.into_keys().flat_map(|k| Some(k))` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:227:5 + | +LL | hash_map.into_iter().flat_map(|(_, v)| Some(v)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.into_values().flat_map(|v| Some(v))` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:231:5 + | +LL | hash_map.into_iter().filter_map(|(k, _)| (k > 0).then_some(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.into_keys().filter_map(|k| (k > 0).then_some(1))` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:235:5 + | +LL | hash_map.into_iter().filter_map(|(_, v)| (v > 0).then_some(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.into_values().filter_map(|v| (v > 0).then_some(1))` + +error: aborting due to 48 previous errors diff --git a/tests/ui/iter_on_empty_collections.fixed b/tests/ui/iter_on_empty_collections.fixed index 0c2100034e18..f4c2bc43a679 100644 --- a/tests/ui/iter_on_empty_collections.fixed +++ b/tests/ui/iter_on_empty_collections.fixed @@ -84,8 +84,4 @@ mod custom_option { } } -fn main() { - array(); - custom_option::custom_option(); - in_macros!(); -} +fn main() {} diff --git a/tests/ui/iter_on_empty_collections.rs b/tests/ui/iter_on_empty_collections.rs index 0fb7a32d3691..f5852d97c93c 100644 --- a/tests/ui/iter_on_empty_collections.rs +++ b/tests/ui/iter_on_empty_collections.rs @@ -84,8 +84,4 @@ pub fn custom_option() { } } -fn main() { - array(); - custom_option::custom_option(); - in_macros!(); -} +fn main() {} diff --git a/tests/ui/iter_on_single_items.fixed b/tests/ui/iter_on_single_items.fixed index 044037aac2e3..c5f85122aa76 100644 --- a/tests/ui/iter_on_single_items.fixed +++ b/tests/ui/iter_on_single_items.fixed @@ -61,11 +61,7 @@ mod custom_option { } } -fn main() { - array(); - custom_option::custom_option(); - in_macros!(); -} +fn main() {} mod issue14981 { use std::option::IntoIter; diff --git a/tests/ui/iter_on_single_items.rs b/tests/ui/iter_on_single_items.rs index c925d0e480fa..ffeb76d627b0 100644 --- a/tests/ui/iter_on_single_items.rs +++ b/tests/ui/iter_on_single_items.rs @@ -61,11 +61,7 @@ pub fn custom_option() { } } -fn main() { - array(); - custom_option::custom_option(); - in_macros!(); -} +fn main() {} mod issue14981 { use std::option::IntoIter; diff --git a/tests/ui/iter_overeager_cloned.fixed b/tests/ui/iter_overeager_cloned.fixed index 4171f19469a4..520b4f8be8cf 100644 --- a/tests/ui/iter_overeager_cloned.fixed +++ b/tests/ui/iter_overeager_cloned.fixed @@ -102,3 +102,63 @@ fn main() { fn cloned_flatten(x: Option<&Option>) -> Option { x.cloned().flatten() } + +mod issue_16428 { + #[derive(Clone)] + struct Foo; + + impl Foo { + async fn do_async(&self) {} + } + + fn async_move_map() -> Vec> { + let map: std::collections::HashMap<(), Foo> = std::collections::HashMap::new(); + + // Should NOT lint: async move block captures `item` by value + map.values() + .cloned() + .map(|item| async move { item.do_async().await }) + .collect::>() + } + + fn async_move_for_each() { + let map: std::collections::HashMap<(), Foo> = std::collections::HashMap::new(); + + // Should NOT lint: async move block captures `item` by value + map.values() + .cloned() + .for_each(|item| drop(async move { item.do_async().await })); + } + + fn move_closure() { + let vec = vec!["1".to_string(), "2".to_string()]; + + // Should NOT lint: move closure captures `x` by value + let _: Vec<_> = vec.iter().cloned().map(|x| move || x.len()).collect(); + } + + fn async_move_not_capturing_param() { + let vec = vec!["1".to_string(), "2".to_string()]; + + // Should lint: async move captures `y`, not `x` + let _ = vec.iter().map(|x| { + //~^ redundant_iter_cloned + let y = x.len(); + async move { y } + }); + } + + fn move_closure_not_capturing_param() { + let vec = vec!["1".to_string(), "2".to_string()]; + + // Should lint: move closure captures `y`, not `x` + let _: Vec<_> = vec + //~^ redundant_iter_cloned + .iter() + .map(|x| { + let y = x.len(); + move || y + }) + .collect(); + } +} diff --git a/tests/ui/iter_overeager_cloned.rs b/tests/ui/iter_overeager_cloned.rs index fe6aba24dd3e..3e79675dd7c6 100644 --- a/tests/ui/iter_overeager_cloned.rs +++ b/tests/ui/iter_overeager_cloned.rs @@ -103,3 +103,64 @@ fn bar<'a>(iter: impl Iterator> + 'a, target: String) -> impl I fn cloned_flatten(x: Option<&Option>) -> Option { x.cloned().flatten() } + +mod issue_16428 { + #[derive(Clone)] + struct Foo; + + impl Foo { + async fn do_async(&self) {} + } + + fn async_move_map() -> Vec> { + let map: std::collections::HashMap<(), Foo> = std::collections::HashMap::new(); + + // Should NOT lint: async move block captures `item` by value + map.values() + .cloned() + .map(|item| async move { item.do_async().await }) + .collect::>() + } + + fn async_move_for_each() { + let map: std::collections::HashMap<(), Foo> = std::collections::HashMap::new(); + + // Should NOT lint: async move block captures `item` by value + map.values() + .cloned() + .for_each(|item| drop(async move { item.do_async().await })); + } + + fn move_closure() { + let vec = vec!["1".to_string(), "2".to_string()]; + + // Should NOT lint: move closure captures `x` by value + let _: Vec<_> = vec.iter().cloned().map(|x| move || x.len()).collect(); + } + + fn async_move_not_capturing_param() { + let vec = vec!["1".to_string(), "2".to_string()]; + + // Should lint: async move captures `y`, not `x` + let _ = vec.iter().cloned().map(|x| { + //~^ redundant_iter_cloned + let y = x.len(); + async move { y } + }); + } + + fn move_closure_not_capturing_param() { + let vec = vec!["1".to_string(), "2".to_string()]; + + // Should lint: move closure captures `y`, not `x` + let _: Vec<_> = vec + //~^ redundant_iter_cloned + .iter() + .cloned() + .map(|x| { + let y = x.len(); + move || y + }) + .collect(); + } +} diff --git a/tests/ui/iter_overeager_cloned.stderr b/tests/ui/iter_overeager_cloned.stderr index f234d19e4aaa..72b00ca2e32c 100644 --- a/tests/ui/iter_overeager_cloned.stderr +++ b/tests/ui/iter_overeager_cloned.stderr @@ -165,5 +165,47 @@ LL | let _ = vec.iter().cloned().any(|x| x.len() == 1); | | | help: try: `.any(|x| x.len() == 1)` -error: aborting due to 19 previous errors +error: unneeded cloning of iterator items + --> tests/ui/iter_overeager_cloned.rs:145:17 + | +LL | let _ = vec.iter().cloned().map(|x| { + | _________________^ +LL | | +LL | | let y = x.len(); +LL | | async move { y } +LL | | }); + | |__________^ + | +help: try + | +LL ~ let _ = vec.iter().map(|x| { +LL + +LL + let y = x.len(); +LL + async move { y } +LL ~ }); + | + +error: unneeded cloning of iterator items + --> tests/ui/iter_overeager_cloned.rs:156:25 + | +LL | let _: Vec<_> = vec + | _________________________^ +LL | | +LL | | .iter() +LL | | .cloned() +... | +LL | | move || y +LL | | }) + | |______________^ + | +help: try + | +LL ~ .iter() +LL + .map(|x| { +LL + let y = x.len(); +LL + move || y +LL + }) + | + +error: aborting due to 21 previous errors diff --git a/tests/ui/iter_with_drain.fixed b/tests/ui/iter_with_drain.fixed index b0661ffb981b..9e0a03f580c0 100644 --- a/tests/ui/iter_with_drain.fixed +++ b/tests/ui/iter_with_drain.fixed @@ -62,9 +62,4 @@ fn should_not_help_0(bomb: &mut Bomb) { let _: Vec = bomb.fire.drain(..).collect(); } -fn main() { - full(); - closed(); - should_not_help(); - should_not_help_0(&mut Bomb::default()); -} +fn main() {} diff --git a/tests/ui/iter_with_drain.rs b/tests/ui/iter_with_drain.rs index 746b0f9a5eda..6546c93071af 100644 --- a/tests/ui/iter_with_drain.rs +++ b/tests/ui/iter_with_drain.rs @@ -62,9 +62,4 @@ fn should_not_help_0(bomb: &mut Bomb) { let _: Vec = bomb.fire.drain(..).collect(); } -fn main() { - full(); - closed(); - should_not_help(); - should_not_help_0(&mut Bomb::default()); -} +fn main() {} diff --git a/tests/ui/join_absolute_paths.1.fixed b/tests/ui/join_absolute_paths.1.fixed new file mode 100644 index 000000000000..ff524b529b18 --- /dev/null +++ b/tests/ui/join_absolute_paths.1.fixed @@ -0,0 +1,36 @@ +#![allow(clippy::needless_raw_string_hashes)] +#![warn(clippy::join_absolute_paths)] + +use std::path::{Path, PathBuf}; + +fn main() { + let path = Path::new("/bin"); + path.join("sh"); + //~^ join_absolute_paths + + let path = PathBuf::from("/bin"); + path.join("sh"); + //~^ join_absolute_paths + + let path = PathBuf::from("/bin"); + path.join(r#"sh"#); + //~^ join_absolute_paths + + let path = Path::new("C:\\Users"); + path.join("user"); + //~^ join_absolute_paths + + let path = PathBuf::from("C:\\Users"); + path.join("user"); + //~^ join_absolute_paths + + let path = PathBuf::from("C:\\Users"); + path.join(r#"user"#); + //~^ join_absolute_paths + + let path: &[&str] = &["/bin"]; + path.join("/sh"); + + let path = Path::new("/bin"); + path.join("sh"); +} diff --git a/tests/ui/join_absolute_paths.2.fixed b/tests/ui/join_absolute_paths.2.fixed new file mode 100644 index 000000000000..372647ecde64 --- /dev/null +++ b/tests/ui/join_absolute_paths.2.fixed @@ -0,0 +1,36 @@ +#![allow(clippy::needless_raw_string_hashes)] +#![warn(clippy::join_absolute_paths)] + +use std::path::{Path, PathBuf}; + +fn main() { + let path = Path::new("/bin"); + PathBuf::from("/sh"); + //~^ join_absolute_paths + + let path = PathBuf::from("/bin"); + PathBuf::from("/sh"); + //~^ join_absolute_paths + + let path = PathBuf::from("/bin"); + PathBuf::from(r#"/sh"#); + //~^ join_absolute_paths + + let path = Path::new("C:\\Users"); + PathBuf::from("\\user"); + //~^ join_absolute_paths + + let path = PathBuf::from("C:\\Users"); + PathBuf::from("\\user"); + //~^ join_absolute_paths + + let path = PathBuf::from("C:\\Users"); + PathBuf::from(r#"\user"#); + //~^ join_absolute_paths + + let path: &[&str] = &["/bin"]; + path.join("/sh"); + + let path = Path::new("/bin"); + path.join("sh"); +} diff --git a/tests/ui/join_absolute_paths.rs b/tests/ui/join_absolute_paths.rs index 144c9147c2a1..dffc4a5f10ed 100644 --- a/tests/ui/join_absolute_paths.rs +++ b/tests/ui/join_absolute_paths.rs @@ -1,5 +1,3 @@ -//@no-rustfix - #![allow(clippy::needless_raw_string_hashes)] #![warn(clippy::join_absolute_paths)] @@ -10,10 +8,6 @@ fn main() { path.join("/sh"); //~^ join_absolute_paths - let path = Path::new("C:\\Users"); - path.join("\\user"); - //~^ join_absolute_paths - let path = PathBuf::from("/bin"); path.join("/sh"); //~^ join_absolute_paths @@ -22,6 +16,18 @@ fn main() { path.join(r#"/sh"#); //~^ join_absolute_paths + let path = Path::new("C:\\Users"); + path.join("\\user"); + //~^ join_absolute_paths + + let path = PathBuf::from("C:\\Users"); + path.join("\\user"); + //~^ join_absolute_paths + + let path = PathBuf::from("C:\\Users"); + path.join(r#"\user"#); + //~^ join_absolute_paths + let path: &[&str] = &["/bin"]; path.join("/sh"); diff --git a/tests/ui/join_absolute_paths.stderr b/tests/ui/join_absolute_paths.stderr index 300946bf3b5f..c44292276d27 100644 --- a/tests/ui/join_absolute_paths.stderr +++ b/tests/ui/join_absolute_paths.stderr @@ -1,5 +1,5 @@ error: argument to `Path::join` starts with a path separator - --> tests/ui/join_absolute_paths.rs:10:15 + --> tests/ui/join_absolute_paths.rs:8:15 | LL | path.join("/sh"); | ^^^^^ @@ -19,25 +19,7 @@ LL + PathBuf::from("/sh"); | error: argument to `Path::join` starts with a path separator - --> tests/ui/join_absolute_paths.rs:14:15 - | -LL | path.join("\\user"); - | ^^^^^^^^ - | - = note: joining a path starting with separator will replace the path instead -help: if this is unintentional, try removing the starting separator - | -LL - path.join("\\user"); -LL + path.join("\user"); - | -help: if this is intentional, consider using `Path::new` - | -LL - path.join("\\user"); -LL + PathBuf::from("\\user"); - | - -error: argument to `Path::join` starts with a path separator - --> tests/ui/join_absolute_paths.rs:18:15 + --> tests/ui/join_absolute_paths.rs:12:15 | LL | path.join("/sh"); | ^^^^^ @@ -55,7 +37,7 @@ LL + PathBuf::from("/sh"); | error: argument to `Path::join` starts with a path separator - --> tests/ui/join_absolute_paths.rs:22:15 + --> tests/ui/join_absolute_paths.rs:16:15 | LL | path.join(r#"/sh"#); | ^^^^^^^^ @@ -72,5 +54,59 @@ LL - path.join(r#"/sh"#); LL + PathBuf::from(r#"/sh"#); | -error: aborting due to 4 previous errors +error: argument to `Path::join` starts with a path separator + --> tests/ui/join_absolute_paths.rs:20:15 + | +LL | path.join("\\user"); + | ^^^^^^^^ + | + = note: joining a path starting with separator will replace the path instead +help: if this is unintentional, try removing the starting separator + | +LL - path.join("\\user"); +LL + path.join("user"); + | +help: if this is intentional, consider using `Path::new` + | +LL - path.join("\\user"); +LL + PathBuf::from("\\user"); + | + +error: argument to `Path::join` starts with a path separator + --> tests/ui/join_absolute_paths.rs:24:15 + | +LL | path.join("\\user"); + | ^^^^^^^^ + | + = note: joining a path starting with separator will replace the path instead +help: if this is unintentional, try removing the starting separator + | +LL - path.join("\\user"); +LL + path.join("user"); + | +help: if this is intentional, consider using `Path::new` + | +LL - path.join("\\user"); +LL + PathBuf::from("\\user"); + | + +error: argument to `Path::join` starts with a path separator + --> tests/ui/join_absolute_paths.rs:28:15 + | +LL | path.join(r#"\user"#); + | ^^^^^^^^^^ + | + = note: joining a path starting with separator will replace the path instead +help: if this is unintentional, try removing the starting separator + | +LL - path.join(r#"\user"#); +LL + path.join(r#"user"#); + | +help: if this is intentional, consider using `Path::new` + | +LL - path.join(r#"\user"#); +LL + PathBuf::from(r#"\user"#); + | + +error: aborting due to 6 previous errors diff --git a/tests/ui/len_without_is_empty_expect.rs b/tests/ui/len_without_is_empty_expect.rs index 9d1245e2d02a..4c427904a82b 100644 --- a/tests/ui/len_without_is_empty_expect.rs +++ b/tests/ui/len_without_is_empty_expect.rs @@ -1,4 +1,3 @@ -//@no-rustfix #![allow(clippy::len_without_is_empty)] // Check that the lint expectation is fulfilled even if the lint is allowed at the type level. diff --git a/tests/ui/len_without_is_empty_expect.stderr b/tests/ui/len_without_is_empty_expect.stderr index e96870f054e4..f8fecf5a6995 100644 --- a/tests/ui/len_without_is_empty_expect.stderr +++ b/tests/ui/len_without_is_empty_expect.stderr @@ -1,5 +1,5 @@ error: this lint expectation is unfulfilled - --> tests/ui/len_without_is_empty_expect.rs:18:14 + --> tests/ui/len_without_is_empty_expect.rs:17:14 | LL | #[expect(clippy::len_without_is_empty)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs index 69d6319fa8bf..ebd9cfe4b8d5 100644 --- a/tests/ui/let_if_seq.rs +++ b/tests/ui/let_if_seq.rs @@ -69,11 +69,6 @@ fn allow_works() -> i32 { } fn main() { - early_return(); - issue975(); - issue985(); - issue985_alt(); - let mut foo = 0; //~^ useless_let_if_seq diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr index b86bca6b384b..417d9287ad9c 100644 --- a/tests/ui/let_if_seq.stderr +++ b/tests/ui/let_if_seq.stderr @@ -1,5 +1,5 @@ error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:77:5 + --> tests/ui/let_if_seq.rs:72:5 | LL | / let mut foo = 0; LL | | @@ -14,7 +14,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::useless_let_if_seq)]` error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:84:5 + --> tests/ui/let_if_seq.rs:79:5 | LL | / let mut bar = 0; LL | | @@ -28,7 +28,7 @@ LL | | } = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:94:5 + --> tests/ui/let_if_seq.rs:89:5 | LL | / let quz; LL | | @@ -40,7 +40,7 @@ LL | | } | |_____^ help: it is more idiomatic to write: `let quz = if f() { 42 } else { 0 };` error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:125:5 + --> tests/ui/let_if_seq.rs:120:5 | LL | / let mut baz = 0; LL | | @@ -53,7 +53,7 @@ LL | | } = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:144:5 + --> tests/ui/let_if_seq.rs:139:5 | LL | / let foo; LL | | @@ -65,7 +65,7 @@ LL | | } | |_____^ help: it is more idiomatic to write: `let foo = if bar() { 42 } else { 0 };` error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:163:5 + --> tests/ui/let_if_seq.rs:158:5 | LL | / let foo; LL | | diff --git a/tests/ui/let_underscore_future.rs b/tests/ui/let_underscore_future.rs index 6347c792280e..eb1a985a9117 100644 --- a/tests/ui/let_underscore_future.rs +++ b/tests/ui/let_underscore_future.rs @@ -1,5 +1,5 @@ use std::future::Future; -//@no-rustfix + async fn some_async_fn() {} fn sync_side_effects() {} diff --git a/tests/ui/let_underscore_must_use.rs b/tests/ui/let_underscore_must_use.rs index 5cf31ec63c66..1ef43c343fb8 100644 --- a/tests/ui/let_underscore_must_use.rs +++ b/tests/ui/let_underscore_must_use.rs @@ -109,4 +109,14 @@ fn main() { #[allow(clippy::let_underscore_must_use)] let _ = a; + + // No lint because this type should behave as `()` + let _ = Result::<_, std::convert::Infallible>::Ok(()); + + #[must_use] + struct T; + + // Lint because this type should behave as `T` + let _ = Result::<_, std::convert::Infallible>::Ok(T); + //~^ let_underscore_must_use } diff --git a/tests/ui/let_underscore_must_use.stderr b/tests/ui/let_underscore_must_use.stderr index 130ea11646fd..23e929b5bf89 100644 --- a/tests/ui/let_underscore_must_use.stderr +++ b/tests/ui/let_underscore_must_use.stderr @@ -96,5 +96,13 @@ LL | let _ = a; | = help: consider explicitly using expression value -error: aborting due to 12 previous errors +error: non-binding `let` on an expression with `#[must_use]` type + --> tests/ui/let_underscore_must_use.rs:120:5 + | +LL | let _ = Result::<_, std::convert::Infallible>::Ok(T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider explicitly using expression value + +error: aborting due to 13 previous errors diff --git a/tests/ui/manual_is_variant_and.fixed b/tests/ui/manual_is_variant_and.fixed index 884bef6af5f9..e0ac240edbe5 100644 --- a/tests/ui/manual_is_variant_and.fixed +++ b/tests/ui/manual_is_variant_and.fixed @@ -1,5 +1,6 @@ //@aux-build:option_helpers.rs #![warn(clippy::manual_is_variant_and)] +#![allow(clippy::redundant_closure)] #[macro_use] extern crate option_helpers; @@ -112,10 +113,7 @@ fn result_methods() { let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint } -fn main() { - option_methods(); - result_methods(); -} +fn main() {} fn issue15202() { let xs = [None, Some(b'_'), Some(b'1')]; @@ -245,3 +243,19 @@ fn issue16419_msrv() { let _ = opt.is_some_and(then_fn) || opt.is_none(); } + +fn issue16518(opt: Option) { + let condition = |x: &i32| *x > 10; + + opt.as_ref().is_some_and(|x| condition(x)); + //~^ manual_is_variant_and + opt.as_ref().is_none_or(|x| !condition(x)); + //~^ manual_is_variant_and +} + +#[clippy::msrv = "1.75.0"] +fn issue16518_msrv(opt: Option) { + let condition = |x: &i32| *x > 10; + + opt.filter(|x| condition(x)).is_none(); +} diff --git a/tests/ui/manual_is_variant_and.rs b/tests/ui/manual_is_variant_and.rs index 53aca94ea370..98069cab4557 100644 --- a/tests/ui/manual_is_variant_and.rs +++ b/tests/ui/manual_is_variant_and.rs @@ -1,5 +1,6 @@ //@aux-build:option_helpers.rs #![warn(clippy::manual_is_variant_and)] +#![allow(clippy::redundant_closure)] #[macro_use] extern crate option_helpers; @@ -121,10 +122,7 @@ fn result_methods() { let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint } -fn main() { - option_methods(); - result_methods(); -} +fn main() {} fn issue15202() { let xs = [None, Some(b'_'), Some(b'1')]; @@ -254,3 +252,19 @@ fn issue16419_msrv() { let _ = opt.is_some_and(then_fn) || opt.is_none(); } + +fn issue16518(opt: Option) { + let condition = |x: &i32| *x > 10; + + opt.filter(|x| condition(x)).is_some(); + //~^ manual_is_variant_and + opt.filter(|x| condition(x)).is_none(); + //~^ manual_is_variant_and +} + +#[clippy::msrv = "1.75.0"] +fn issue16518_msrv(opt: Option) { + let condition = |x: &i32| *x > 10; + + opt.filter(|x| condition(x)).is_none(); +} diff --git a/tests/ui/manual_is_variant_and.stderr b/tests/ui/manual_is_variant_and.stderr index 56c3b80c0aa5..88aa3bb4eed8 100644 --- a/tests/ui/manual_is_variant_and.stderr +++ b/tests/ui/manual_is_variant_and.stderr @@ -1,5 +1,5 @@ error: called `map().unwrap_or_default()` on an `Option` value - --> tests/ui/manual_is_variant_and.rs:51:17 + --> tests/ui/manual_is_variant_and.rs:52:17 | LL | let _ = opt.map(|x| x > 1) | _________________^ @@ -11,7 +11,7 @@ LL | | .unwrap_or_default(); = help: to override `-D warnings` add `#[allow(clippy::manual_is_variant_and)]` error: called `map().unwrap_or_default()` on an `Option` value - --> tests/ui/manual_is_variant_and.rs:56:17 + --> tests/ui/manual_is_variant_and.rs:57:17 | LL | let _ = opt.map(|x| { | _________________^ @@ -30,13 +30,13 @@ LL ~ }); | error: called `map().unwrap_or_default()` on an `Option` value - --> tests/ui/manual_is_variant_and.rs:61:17 + --> tests/ui/manual_is_variant_and.rs:62:17 | LL | let _ = opt.map(|x| x > 1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(|x| x > 1)` error: called `map().unwrap_or_default()` on an `Option` value - --> tests/ui/manual_is_variant_and.rs:64:10 + --> tests/ui/manual_is_variant_and.rs:65:10 | LL | .map(|x| x > 1) | __________^ @@ -45,37 +45,37 @@ LL | | .unwrap_or_default(); | |____________________________^ help: use: `is_some_and(|x| x > 1)` error: called `.map() == Some()` - --> tests/ui/manual_is_variant_and.rs:68:13 + --> tests/ui/manual_is_variant_and.rs:69:13 | LL | let _ = Some(2).map(|x| x % 2 == 0) == Some(true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_some_and(|x| x % 2 == 0)` error: called `.map() != Some()` - --> tests/ui/manual_is_variant_and.rs:70:13 + --> tests/ui/manual_is_variant_and.rs:71:13 | LL | let _ = Some(2).map(|x| x % 2 == 0) != Some(true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_none_or(|x| x % 2 != 0)` error: called `.map() == Some()` - --> tests/ui/manual_is_variant_and.rs:72:13 + --> tests/ui/manual_is_variant_and.rs:73:13 | LL | let _ = Some(2).map(|x| x % 2 == 0) == some_true!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_some_and(|x| x % 2 == 0)` error: called `.map() != Some()` - --> tests/ui/manual_is_variant_and.rs:74:13 + --> tests/ui/manual_is_variant_and.rs:75:13 | LL | let _ = Some(2).map(|x| x % 2 == 0) != some_false!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_none_or(|x| x % 2 == 0)` error: called `map().unwrap_or_default()` on an `Option` value - --> tests/ui/manual_is_variant_and.rs:81:18 + --> tests/ui/manual_is_variant_and.rs:82:18 | LL | let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(char::is_alphanumeric)` error: called `map().unwrap_or_default()` on a `Result` value - --> tests/ui/manual_is_variant_and.rs:99:17 + --> tests/ui/manual_is_variant_and.rs:100:17 | LL | let _ = res.map(|x| { | _________________^ @@ -94,7 +94,7 @@ LL ~ }); | error: called `map().unwrap_or_default()` on a `Result` value - --> tests/ui/manual_is_variant_and.rs:104:17 + --> tests/ui/manual_is_variant_and.rs:105:17 | LL | let _ = res.map(|x| x > 1) | _________________^ @@ -103,136 +103,148 @@ LL | | .unwrap_or_default(); | |____________________________^ help: use: `is_ok_and(|x| x > 1)` error: called `.map() == Ok()` - --> tests/ui/manual_is_variant_and.rs:108:13 + --> tests/ui/manual_is_variant_and.rs:109:13 | LL | let _ = Ok::(2).map(|x| x.is_multiple_of(2)) == Ok(true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Ok::(2).is_ok_and(|x| x.is_multiple_of(2))` error: called `.map() != Ok()` - --> tests/ui/manual_is_variant_and.rs:110:13 + --> tests/ui/manual_is_variant_and.rs:111:13 | LL | let _ = Ok::(2).map(|x| x.is_multiple_of(2)) != Ok(true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::(2).is_ok_and(|x| x.is_multiple_of(2))` error: called `.map() != Ok()` - --> tests/ui/manual_is_variant_and.rs:112:13 + --> tests/ui/manual_is_variant_and.rs:113:13 | LL | let _ = Ok::(2).map(|x| x.is_multiple_of(2)) != Ok(true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::(2).is_ok_and(|x| x.is_multiple_of(2))` error: called `map().unwrap_or_default()` on a `Result` value - --> tests/ui/manual_is_variant_and.rs:119:18 + --> tests/ui/manual_is_variant_and.rs:120:18 | LL | let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_ok_and(char::is_alphanumeric)` error: called `.map() != Some()` - --> tests/ui/manual_is_variant_and.rs:132:18 + --> tests/ui/manual_is_variant_and.rs:130:18 | LL | let a1 = x.map(|b| b.is_ascii_digit()) != Some(true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_none_or(|b| !b.is_ascii_digit())` error: called `.map() != Some()` - --> tests/ui/manual_is_variant_and.rs:139:18 + --> tests/ui/manual_is_variant_and.rs:137:18 | LL | let a1 = x.map(|b| b.is_ascii_digit()) != Some(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_none_or(|b| b.is_ascii_digit())` error: called `.map() == Some()` - --> tests/ui/manual_is_variant_and.rs:146:18 + --> tests/ui/manual_is_variant_and.rs:144:18 | LL | let a1 = x.map(|b| b.is_ascii_digit()) == Some(true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_some_and(|b| b.is_ascii_digit())` error: called `.map() == Some()` - --> tests/ui/manual_is_variant_and.rs:153:18 + --> tests/ui/manual_is_variant_and.rs:151:18 | LL | let a1 = x.map(|b| b.is_ascii_digit()) == Some(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_some_and(|b| !b.is_ascii_digit())` error: called `.map() != Ok()` - --> tests/ui/manual_is_variant_and.rs:161:18 + --> tests/ui/manual_is_variant_and.rs:159:18 | LL | let a1 = x.map(|b| b.is_ascii_digit()) != Ok(true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!x.is_ok_and(|b| b.is_ascii_digit())` error: called `.map() != Ok()` - --> tests/ui/manual_is_variant_and.rs:168:18 + --> tests/ui/manual_is_variant_and.rs:166:18 | LL | let a1 = x.map(|b| b.is_ascii_digit()) != Ok(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!x.is_ok_and(|b| !b.is_ascii_digit())` error: called `.map() == Ok()` - --> tests/ui/manual_is_variant_and.rs:175:18 + --> tests/ui/manual_is_variant_and.rs:173:18 | LL | let a1 = x.map(|b| b.is_ascii_digit()) == Ok(true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_ok_and(|b| b.is_ascii_digit())` error: called `.map() == Ok()` - --> tests/ui/manual_is_variant_and.rs:182:18 + --> tests/ui/manual_is_variant_and.rs:180:18 | LL | let a1 = x.map(|b| b.is_ascii_digit()) == Ok(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_ok_and(|b| !b.is_ascii_digit())` error: called `.map() == Some()` - --> tests/ui/manual_is_variant_and.rs:195:18 + --> tests/ui/manual_is_variant_and.rs:193:18 | LL | let a1 = b.map(iad) == Some(true); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_some_and(iad)` error: called `.map() == Some()` - --> tests/ui/manual_is_variant_and.rs:200:18 + --> tests/ui/manual_is_variant_and.rs:198:18 | LL | let a1 = b.map(iad) == Some(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_some_and(|x| !iad(x))` error: called `.map() != Some()` - --> tests/ui/manual_is_variant_and.rs:205:18 + --> tests/ui/manual_is_variant_and.rs:203:18 | LL | let a1 = b.map(iad) != Some(true); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_none_or(|x| !iad(x))` error: called `.map() != Some()` - --> tests/ui/manual_is_variant_and.rs:210:18 + --> tests/ui/manual_is_variant_and.rs:208:18 | LL | let a1 = b.map(iad) != Some(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_none_or(iad)` error: called `.map() == Ok()` - --> tests/ui/manual_is_variant_and.rs:217:18 + --> tests/ui/manual_is_variant_and.rs:215:18 | LL | let a1 = b.map(iad) == Ok(true); | ^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_ok_and(iad)` error: called `.map() == Ok()` - --> tests/ui/manual_is_variant_and.rs:222:18 + --> tests/ui/manual_is_variant_and.rs:220:18 | LL | let a1 = b.map(iad) == Ok(false); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_ok_and(|x| !iad(x))` error: called `.map() != Ok()` - --> tests/ui/manual_is_variant_and.rs:227:18 + --> tests/ui/manual_is_variant_and.rs:225:18 | LL | let a1 = b.map(iad) != Ok(true); | ^^^^^^^^^^^^^^^^^^^^^^ help: use: `!b.is_ok_and(iad)` error: called `.map() != Ok()` - --> tests/ui/manual_is_variant_and.rs:232:18 + --> tests/ui/manual_is_variant_and.rs:230:18 | LL | let a1 = b.map(iad) != Ok(false); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!b.is_ok_and(|x| !iad(x))` error: manual implementation of `Option::is_none_or` - --> tests/ui/manual_is_variant_and.rs:242:13 + --> tests/ui/manual_is_variant_and.rs:240:13 | LL | let _ = opt.is_none() || opt.is_some_and(then_fn); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `opt.is_none_or(then_fn)` error: manual implementation of `Option::is_none_or` - --> tests/ui/manual_is_variant_and.rs:245:13 + --> tests/ui/manual_is_variant_and.rs:243:13 | LL | let _ = opt.is_some_and(then_fn) || opt.is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `opt.is_none_or(then_fn)` -error: aborting due to 33 previous errors +error: manual implementation of `Option::is_some_and` + --> tests/ui/manual_is_variant_and.rs:259:5 + | +LL | opt.filter(|x| condition(x)).is_some(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `opt.as_ref().is_some_and(|x| condition(x))` + +error: manual implementation of `Option::is_none_or` + --> tests/ui/manual_is_variant_and.rs:261:5 + | +LL | opt.filter(|x| condition(x)).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `opt.as_ref().is_none_or(|x| !condition(x))` + +error: aborting due to 35 previous errors diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index 4523edec3c76..8271671645ef 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -571,3 +571,21 @@ fn foo() { }; } } + +fn issue16602(i: Result) { + //~v manual_let_else + _ = match i { + Ok(i) => i, + Err(_) => unsafe { + core::hint::unreachable_unchecked(); + }, + }; + + //~v manual_let_else + _ = match i { + Ok(i) => i, + Err(_) => 'useless_label: { + panic!(); + }, + }; +} diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index f4b1644c44ba..8e988cf189b5 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -585,5 +585,41 @@ LL + return; LL + }; | -error: aborting due to 37 previous errors +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else.rs:577:5 + | +LL | / _ = match i { +LL | | Ok(i) => i, +LL | | Err(_) => unsafe { +LL | | core::hint::unreachable_unchecked(); +LL | | }, +LL | | }; + | |_____^ + | +help: consider writing + | +LL ~ let Ok(_) = i else { unsafe { +LL + core::hint::unreachable_unchecked(); +LL ~ } };; + | + +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else.rs:585:5 + | +LL | / _ = match i { +LL | | Ok(i) => i, +LL | | Err(_) => 'useless_label: { +LL | | panic!(); +LL | | }, +LL | | }; + | |_____^ + | +help: consider writing + | +LL ~ let Ok(_) = i else { 'useless_label: { +LL + panic!(); +LL ~ } };; + | + +error: aborting due to 39 previous errors diff --git a/tests/ui/manual_memcpy/with_loop_counters.fixed b/tests/ui/manual_memcpy/with_loop_counters.fixed new file mode 100644 index 000000000000..8fd8b9cd0ffd --- /dev/null +++ b/tests/ui/manual_memcpy/with_loop_counters.fixed @@ -0,0 +1,55 @@ +#![warn(clippy::needless_range_loop, clippy::manual_memcpy)] +#![allow(clippy::redundant_slicing, clippy::identity_op)] + +pub fn manual_copy_with_counters(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { + let mut count = 0; + dst[3..src.len()].copy_from_slice(&src[..(src.len() - 3)]); + + let mut count = 0; + dst[..(src.len() - 3)].copy_from_slice(&src[3..]); + + let mut count = 3; + dst[3..(src.len() + 3)].copy_from_slice(&src[..]); + + let mut count = 3; + dst[..src.len()].copy_from_slice(&src[3..(src.len() + 3)]); + + let mut count = 0; + dst[3..(3 + src.len())].copy_from_slice(&src[..(3 + src.len() - 3)]); + + let mut count = 3; + dst[5..src.len()].copy_from_slice(&src[(3 - 2)..((src.len() - 2) + 3 - 5)]); + + let mut count = 2; + dst.copy_from_slice(&src[2..(dst.len() + 2)]); + + let mut count = 5; + dst[3..10].copy_from_slice(&src[5..(10 + 5 - 3)]); + + let mut count = 3; + let mut count2 = 30; + dst[3..(src.len() + 3)].copy_from_slice(&src[..]); + dst2[30..(src.len() + 30)].copy_from_slice(&src[..]); + + // make sure parentheses are added properly to bitwise operators, which have lower precedence than + // arithmetic ones + let mut count = 0 << 1; + dst[(0 << 1)..((1 << 1) + (0 << 1))].copy_from_slice(&src[2..((1 << 1) + 2)]); + + // make sure incrementing expressions without semicolons at the end of loops are handled correctly. + let mut count = 0; + dst[3..src.len()].copy_from_slice(&src[..(src.len() - 3)]); + + // make sure ones where the increment is not at the end of the loop. + // As a possible enhancement, one could adjust the offset in the suggestion according to + // the position. For example, if the increment is at the top of the loop; + // treating the loop counter as if it were initialized 1 greater than the original value. + let mut count = 0; + #[allow(clippy::needless_range_loop)] + for i in 0..src.len() { + count += 1; + dst[i] = src[count]; + } +} + +fn main() {} diff --git a/tests/ui/manual_memcpy/with_loop_counters.rs b/tests/ui/manual_memcpy/with_loop_counters.rs index c83a26cab21a..9296cefef4f0 100644 --- a/tests/ui/manual_memcpy/with_loop_counters.rs +++ b/tests/ui/manual_memcpy/with_loop_counters.rs @@ -1,5 +1,6 @@ #![warn(clippy::needless_range_loop, clippy::manual_memcpy)] -//@no-rustfix +#![allow(clippy::redundant_slicing, clippy::identity_op)] + pub fn manual_copy_with_counters(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { let mut count = 0; for i in 3..src.len() { diff --git a/tests/ui/manual_memcpy/with_loop_counters.stderr b/tests/ui/manual_memcpy/with_loop_counters.stderr index 70da8309f398..fafa855bad79 100644 --- a/tests/ui/manual_memcpy/with_loop_counters.stderr +++ b/tests/ui/manual_memcpy/with_loop_counters.stderr @@ -1,5 +1,5 @@ error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:5:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:6:5 | LL | / for i in 3..src.len() { LL | | @@ -13,7 +13,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::manual_memcpy)]` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:13:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:14:5 | LL | / for i in 3..src.len() { LL | | @@ -24,7 +24,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..(src.len() - 3)].copy_from_slice(&src[3..]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:21:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:22:5 | LL | / for i in 0..src.len() { LL | | @@ -35,7 +35,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[3..(src.len() + 3)].copy_from_slice(&src[..]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:29:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:30:5 | LL | / for i in 0..src.len() { LL | | @@ -46,7 +46,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[3..(src.len() + 3)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:37:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:38:5 | LL | / for i in 3..(3 + src.len()) { LL | | @@ -57,7 +57,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[3..(3 + src.len())].copy_from_slice(&src[..(3 + src.len() - 3)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:45:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:46:5 | LL | / for i in 5..src.len() { LL | | @@ -68,7 +68,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[5..src.len()].copy_from_slice(&src[(3 - 2)..((src.len() - 2) + 3 - 5)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:53:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:54:5 | LL | / for i in 0..dst.len() { LL | | @@ -79,7 +79,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[2..(dst.len() + 2)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:61:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:62:5 | LL | / for i in 3..10 { LL | | @@ -90,7 +90,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[3..10].copy_from_slice(&src[5..(10 + 5 - 3)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:70:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:71:5 | LL | / for i in 0..src.len() { LL | | @@ -108,7 +108,7 @@ LL + dst2[30..(src.len() + 30)].copy_from_slice(&src[..]); | error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:82:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:83:5 | LL | / for i in 0..1 << 1 { LL | | @@ -119,7 +119,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[(0 << 1)..((1 << 1) + (0 << 1))].copy_from_slice(&src[2..((1 << 1) + 2)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:91:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:92:5 | LL | / for i in 3..src.len() { LL | | diff --git a/tests/ui/manual_memcpy/without_loop_counters.fixed b/tests/ui/manual_memcpy/without_loop_counters.fixed new file mode 100644 index 000000000000..8502c740b712 --- /dev/null +++ b/tests/ui/manual_memcpy/without_loop_counters.fixed @@ -0,0 +1,175 @@ +#![warn(clippy::manual_memcpy)] +#![allow( + clippy::assigning_clones, + clippy::useless_vec, + clippy::needless_range_loop, + clippy::manual_slice_fill, + clippy::redundant_slicing +)] + +const LOOP_OFFSET: usize = 5000; + +pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { + // plain manual memcpy + dst[..src.len()].copy_from_slice(&src[..]); + + // dst offset memcpy + dst[10..(src.len() + 10)].copy_from_slice(&src[..]); + + // src offset memcpy + dst[..src.len()].copy_from_slice(&src[10..(src.len() + 10)]); + + // src offset memcpy + dst[11..src.len()].copy_from_slice(&src[(11 - 10)..(src.len() - 10)]); + + // overwrite entire dst + dst.copy_from_slice(&src[..dst.len()]); + + // manual copy with branch - can't easily convert to memcpy! + for i in 0..src.len() { + dst[i] = src[i]; + if dst[i] > 5 { + break; + } + } + + // multiple copies - suggest two memcpy statements + dst[10..256].copy_from_slice(&src[(10 - 5)..(256 - 5)]); + dst2[(10 + 500)..(256 + 500)].copy_from_slice(&src[10..256]); + + // this is a reversal - the copy lint shouldn't be triggered + for i in 10..LOOP_OFFSET { + dst[i + LOOP_OFFSET] = src[LOOP_OFFSET - i]; + } + + let some_var = 5; + // Offset in variable + dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].copy_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)]); + + // Non continuous copy - don't trigger lint + for i in 0..10 { + dst[i + i] = src[i]; + } + + let src_vec = vec![1, 2, 3, 4, 5]; + let mut dst_vec = vec![0, 0, 0, 0, 0]; + + // make sure vectors are supported + dst_vec[..src_vec.len()].copy_from_slice(&src_vec[..]); + + // lint should not trigger when either + // source or destination type is not + // slice-like, like DummyStruct + struct DummyStruct(i32); + + impl ::std::ops::Index for DummyStruct { + type Output = i32; + + fn index(&self, _: usize) -> &i32 { + &self.0 + } + } + + let src = DummyStruct(5); + let mut dst_vec = vec![0; 10]; + + for i in 0..10 { + dst_vec[i] = src[i]; + } + + // Simplify suggestion (issue #3004) + let src = [0, 1, 2, 3, 4]; + let mut dst = [0, 0, 0, 0, 0, 0]; + let from = 1; + + dst[from..(from + src.len())].copy_from_slice(&src[..(from + src.len() - from)]); + + dst[from..(from + 3)].copy_from_slice(&src[..(from + 3 - from)]); + + #[allow(clippy::identity_op)] + dst[..5].copy_from_slice(&src); + + #[allow(clippy::reversed_empty_ranges)] + dst[..0].copy_from_slice(&src[..0]); + + // `RangeTo` `for` loop - don't trigger lint + for i in 0.. { + dst[i] = src[i]; + } + + // VecDeque - ideally this would work, but would require something like `range_as_slices` + let mut dst = std::collections::VecDeque::from_iter([0; 5]); + let src = std::collections::VecDeque::from_iter([0, 1, 2, 3, 4]); + for i in 0..dst.len() { + dst[i] = src[i]; + } + let src = vec![0, 1, 2, 3, 4]; + for i in 0..dst.len() { + dst[i] = src[i]; + } + + // Range is equal to array length + let src = [0, 1, 2, 3, 4]; + let mut dst = [0; 4]; + dst.copy_from_slice(&src[..4]); + + let mut dst = [0; 6]; + dst[..5].copy_from_slice(&src); + + let mut dst = [0; 5]; + dst.copy_from_slice(&src); + + // Don't trigger lint for following multi-dimensional arrays + let src = [[0; 5]; 5]; + for i in 0..4 { + dst[i] = src[i + 1][i]; + } + for i in 0..5 { + dst[i] = src[i][i]; + } + for i in 0..5 { + dst[i] = src[i][3]; + } + + let src = [0; 5]; + let mut dst = [[0; 5]; 5]; + for i in 0..5 { + dst[i][i] = src[i]; + } + + let src = [[[0; 5]; 5]; 5]; + let mut dst = [0; 5]; + for i in 0..5 { + dst[i] = src[i][i][i]; + } + for i in 0..5 { + dst[i] = src[i][i][0]; + } + for i in 0..5 { + dst[i] = src[i][0][i]; + } + for i in 0..5 { + dst[i] = src[0][i][i]; + } + for i in 0..5 { + dst[i] = src[0][i][1]; + } + for i in 0..5 { + dst[i] = src[i][0][1]; + } + + // Trigger lint + let src = [[0; 5]; 5]; + let mut dst = [0; 5]; + dst.copy_from_slice(&src[0]); + + let src = [[[0; 5]; 5]; 5]; + dst.copy_from_slice(&src[0][1]); +} + +#[warn(clippy::needless_range_loop, clippy::manual_memcpy)] +pub fn manual_clone(src: &[String], dst: &mut [String]) { + dst[..src.len()].clone_from_slice(&src[..]); +} + +fn main() {} diff --git a/tests/ui/manual_memcpy/without_loop_counters.rs b/tests/ui/manual_memcpy/without_loop_counters.rs index a3b8763812d7..fc55102fca45 100644 --- a/tests/ui/manual_memcpy/without_loop_counters.rs +++ b/tests/ui/manual_memcpy/without_loop_counters.rs @@ -3,10 +3,10 @@ clippy::assigning_clones, clippy::useless_vec, clippy::needless_range_loop, - clippy::manual_slice_fill + clippy::manual_slice_fill, + clippy::redundant_slicing )] -//@no-rustfix const LOOP_OFFSET: usize = 5000; pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { diff --git a/tests/ui/manual_option_as_slice.fixed b/tests/ui/manual_option_as_slice.fixed index 48337d7654de..3f8674ce0e26 100644 --- a/tests/ui/manual_option_as_slice.fixed +++ b/tests/ui/manual_option_as_slice.fixed @@ -56,7 +56,4 @@ fn check_msrv(x: Option) { _ = x.as_ref().map_or(&[][..], std::slice::from_ref); } -fn main() { - check(Some(1)); - check_msrv(Some(175)); -} +fn main() {} diff --git a/tests/ui/manual_option_as_slice.rs b/tests/ui/manual_option_as_slice.rs index e1a97a6b2711..1dd6caea4879 100644 --- a/tests/ui/manual_option_as_slice.rs +++ b/tests/ui/manual_option_as_slice.rs @@ -66,7 +66,4 @@ fn check_msrv(x: Option) { _ = x.as_ref().map_or(&[][..], std::slice::from_ref); } -fn main() { - check(Some(1)); - check_msrv(Some(175)); -} +fn main() {} diff --git a/tests/ui/manual_retain.fixed b/tests/ui/manual_retain.fixed index 016f520e216c..ea97c488a9ad 100644 --- a/tests/ui/manual_retain.fixed +++ b/tests/ui/manual_retain.fixed @@ -2,22 +2,7 @@ #![allow(unused, clippy::needless_borrowed_reference, clippy::redundant_clone)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; -fn main() { - binary_heap_retain(); - btree_set_retain(); - btree_map_retain(); - hash_set_retain(); - hash_map_retain(); - string_retain(); - vec_deque_retain(); - vec_retain(); - _msrv_153(); - _msrv_126(); - _msrv_118(); - - issue_10393(); - issue_12081(); -} +fn main() {} fn binary_heap_retain() { let mut binary_heap = BinaryHeap::from([1, 2, 3]); diff --git a/tests/ui/manual_retain.rs b/tests/ui/manual_retain.rs index 62f9b7b0595d..5cee4cefa038 100644 --- a/tests/ui/manual_retain.rs +++ b/tests/ui/manual_retain.rs @@ -2,22 +2,7 @@ #![allow(unused, clippy::needless_borrowed_reference, clippy::redundant_clone)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; -fn main() { - binary_heap_retain(); - btree_set_retain(); - btree_map_retain(); - hash_set_retain(); - hash_map_retain(); - string_retain(); - vec_deque_retain(); - vec_retain(); - _msrv_153(); - _msrv_126(); - _msrv_118(); - - issue_10393(); - issue_12081(); -} +fn main() {} fn binary_heap_retain() { let mut binary_heap = BinaryHeap::from([1, 2, 3]); diff --git a/tests/ui/manual_retain.stderr b/tests/ui/manual_retain.stderr index e7d3e34b5d7d..fc562d32d79f 100644 --- a/tests/ui/manual_retain.stderr +++ b/tests/ui/manual_retain.stderr @@ -1,5 +1,5 @@ error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:25:5 + --> tests/ui/manual_retain.rs:10:5 | LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` @@ -8,43 +8,43 @@ LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect(); = help: to override `-D warnings` add `#[allow(clippy::manual_retain)]` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:27:5 + --> tests/ui/manual_retain.rs:12:5 | LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:29:5 + --> tests/ui/manual_retain.rs:14:5 | LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:34:5 + --> tests/ui/manual_retain.rs:19:5 | LL | tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|&(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:36:5 + --> tests/ui/manual_retain.rs:21:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:67:5 + --> tests/ui/manual_retain.rs:52:5 | LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:69:5 + --> tests/ui/manual_retain.rs:54:5 | LL | btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:71:5 + --> tests/ui/manual_retain.rs:56:5 | LL | / btree_map = btree_map LL | | @@ -54,49 +54,49 @@ LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:97:5 + --> tests/ui/manual_retain.rs:82:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:99:5 + --> tests/ui/manual_retain.rs:84:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:101:5 + --> tests/ui/manual_retain.rs:86:5 | LL | btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:106:5 + --> tests/ui/manual_retain.rs:91:5 | LL | tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|&(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:108:5 + --> tests/ui/manual_retain.rs:93:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:139:5 + --> tests/ui/manual_retain.rs:124:5 | LL | hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:141:5 + --> tests/ui/manual_retain.rs:126:5 | LL | hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:143:5 + --> tests/ui/manual_retain.rs:128:5 | LL | / hash_map = hash_map LL | | @@ -106,133 +106,133 @@ LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:168:5 + --> tests/ui/manual_retain.rs:153:5 | LL | hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:170:5 + --> tests/ui/manual_retain.rs:155:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:172:5 + --> tests/ui/manual_retain.rs:157:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:177:5 + --> tests/ui/manual_retain.rs:162:5 | LL | tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|&(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:179:5 + --> tests/ui/manual_retain.rs:164:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:209:5 + --> tests/ui/manual_retain.rs:194:5 | LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:222:5 + --> tests/ui/manual_retain.rs:207:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:224:5 + --> tests/ui/manual_retain.rs:209:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:226:5 + --> tests/ui/manual_retain.rs:211:5 | LL | vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:231:5 + --> tests/ui/manual_retain.rs:216:5 | LL | tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|&(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:233:5 + --> tests/ui/manual_retain.rs:218:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:256:5 + --> tests/ui/manual_retain.rs:241:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:258:5 + --> tests/ui/manual_retain.rs:243:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:260:5 + --> tests/ui/manual_retain.rs:245:5 | LL | vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:318:5 + --> tests/ui/manual_retain.rs:303:5 | LL | vec = vec.into_iter().filter(|(x, y)| *x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:323:5 + --> tests/ui/manual_retain.rs:308:5 | LL | tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(_, n)| *n > 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:341:5 + --> tests/ui/manual_retain.rs:326:5 | LL | vec = vec.iter().filter(|&&x| x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:343:5 + --> tests/ui/manual_retain.rs:328:5 | LL | vec = vec.iter().filter(|&&x| x == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:345:5 + --> tests/ui/manual_retain.rs:330:5 | LL | vec = vec.into_iter().filter(|&x| x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:349:5 + --> tests/ui/manual_retain.rs:334:5 | LL | vec = vec.iter().filter(|&x| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:351:5 + --> tests/ui/manual_retain.rs:336:5 | LL | vec = vec.iter().filter(|&x| *x == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:353:5 + --> tests/ui/manual_retain.rs:338:5 | LL | vec = vec.into_iter().filter(|x| *x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` diff --git a/tests/ui/manual_take.fixed b/tests/ui/manual_take.fixed index 5891bd49c81c..b8f7ca86dfea 100644 --- a/tests/ui/manual_take.fixed +++ b/tests/ui/manual_take.fixed @@ -1,8 +1,6 @@ #![warn(clippy::manual_take)] fn main() { - msrv_1_39(); - msrv_1_40(); let mut x = true; let mut y = false; diff --git a/tests/ui/manual_take.rs b/tests/ui/manual_take.rs index 89903fcb2416..39637a8f2e17 100644 --- a/tests/ui/manual_take.rs +++ b/tests/ui/manual_take.rs @@ -1,8 +1,6 @@ #![warn(clippy::manual_take)] fn main() { - msrv_1_39(); - msrv_1_40(); let mut x = true; let mut y = false; diff --git a/tests/ui/manual_take.stderr b/tests/ui/manual_take.stderr index 69ba7778a275..207711a5a183 100644 --- a/tests/ui/manual_take.stderr +++ b/tests/ui/manual_take.stderr @@ -1,5 +1,5 @@ error: manual implementation of `mem::take` - --> tests/ui/manual_take.rs:9:25 + --> tests/ui/manual_take.rs:7:25 | LL | let _lint_negated = if x { | _________________________^ @@ -26,7 +26,7 @@ LL + let _lint_negated = !std::mem::take(&mut x); | error: manual implementation of `mem::take` - --> tests/ui/manual_take.rs:62:5 + --> tests/ui/manual_take.rs:60:5 | LL | / if x { LL | | diff --git a/tests/ui/map_flatten.fixed b/tests/ui/map_flatten.fixed new file mode 100644 index 000000000000..12fca6706e41 --- /dev/null +++ b/tests/ui/map_flatten.fixed @@ -0,0 +1,67 @@ +#![warn(clippy::map_flatten)] +#![allow(clippy::unnecessary_filter_map)] + +// issue #8506, multi-line +#[rustfmt::skip] +fn long_span() { + let _: Option = Some(1) + .and_then(|x| { + //~^ map_flatten + + + if x <= 5 { + Some(x) + } else { + None + } + }); + + let _: Result = Ok(1) + .and_then(|x| { + //~^ map_flatten + + if x == 1 { + Ok(x) + } else { + Err(0) + } + }); + + let result: Result = Ok(2); + fn do_something() { } + let _: Result = result + .and_then(|res| { + //~^ map_flatten + + if res > 0 { + do_something(); + Ok(res) + } else { + Err(0) + } + }); + + let _: Vec<_> = vec![5_i8; 6] + .into_iter() + .filter_map(|some_value| { + //~^ map_flatten + + if some_value > 3 { + Some(some_value) + } else { + None + } + }) + .collect(); +} + +#[allow(clippy::useless_vec)] +fn no_suggestion_if_comments_present() { + let vec = vec![vec![1, 2, 3]]; + let _ = vec + .iter() + // a lovely comment explaining the code in very detail + .flat_map(|x| x.iter()); +} + +fn main() {} diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index 0970da8039a4..3f1b7a268822 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -1,6 +1,6 @@ #![warn(clippy::map_flatten)] +#![allow(clippy::unnecessary_filter_map)] -//@no-rustfix // issue #8506, multi-line #[rustfmt::skip] fn long_span() { @@ -43,7 +43,7 @@ fn do_something() { } } }) .flatten(); - + let _: Vec<_> = vec![5_i8; 6] .into_iter() .map(|some_value| { @@ -71,6 +71,4 @@ fn no_suggestion_if_comments_present() { .flatten(); } -fn main() { - long_span(); -} +fn main() {} diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index dccacd7df8af..37470a50cfbe 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -92,10 +92,7 @@ fn result_methods() { let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|_e| 0); // should not lint } -fn main() { - option_methods(); - result_methods(); -} +fn main() {} #[clippy::msrv = "1.40"] fn msrv_1_40() { diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index bd9e0eeb0bda..a90da4a97e0c 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -203,13 +203,13 @@ LL ~ }, |x| x + 1); | error: called `map().unwrap_or_else()` on a `Result` value - --> tests/ui/map_unwrap_or.rs:111:13 + --> tests/ui/map_unwrap_or.rs:108:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or_else(|_e| 0, |x| x + 1)` error: called `map().unwrap_or()` on an `Option` value - --> tests/ui/map_unwrap_or.rs:119:13 + --> tests/ui/map_unwrap_or.rs:116:13 | LL | let _ = opt.map(|x| x > 5).unwrap_or(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -221,7 +221,7 @@ LL + let _ = opt.map_or(false, |x| x > 5); | error: called `map().unwrap_or(false)` on an `Option` value - --> tests/ui/map_unwrap_or.rs:127:13 + --> tests/ui/map_unwrap_or.rs:124:13 | LL | let _ = opt.map(|x| x > 5).unwrap_or(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL + let _ = opt.is_some_and(|x| x > 5); | error: called `map().unwrap_or()` on an `Option` value - --> tests/ui/map_unwrap_or.rs:164:5 + --> tests/ui/map_unwrap_or.rs:161:5 | LL | x.map(|y| y.0).unwrap_or(&[]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/map_unwrap_or_fixable.fixed b/tests/ui/map_unwrap_or_fixable.fixed index dca2536132d7..efdb7cf27669 100644 --- a/tests/ui/map_unwrap_or_fixable.fixed +++ b/tests/ui/map_unwrap_or_fixable.fixed @@ -52,10 +52,7 @@ fn result_methods() { let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|_e| 0); // should not lint } -fn main() { - option_methods(); - result_methods(); -} +fn main() {} fn issue15714() { let o: Option = Some(3); diff --git a/tests/ui/map_unwrap_or_fixable.rs b/tests/ui/map_unwrap_or_fixable.rs index c60cb082ae3c..5c3f13c2844b 100644 --- a/tests/ui/map_unwrap_or_fixable.rs +++ b/tests/ui/map_unwrap_or_fixable.rs @@ -58,10 +58,7 @@ fn result_methods() { let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|_e| 0); // should not lint } -fn main() { - option_methods(); - result_methods(); -} +fn main() {} fn issue15714() { let o: Option = Some(3); diff --git a/tests/ui/map_unwrap_or_fixable.stderr b/tests/ui/map_unwrap_or_fixable.stderr index 33a865d6769c..90bb625d7a2a 100644 --- a/tests/ui/map_unwrap_or_fixable.stderr +++ b/tests/ui/map_unwrap_or_fixable.stderr @@ -20,7 +20,7 @@ LL | | .unwrap_or_else(|_e| 0); | |_______________________________^ help: try: `res.map_or_else(|_e| 0, |x| x + 1)` error: called `map().unwrap_or()` on an `Option` value - --> tests/ui/map_unwrap_or_fixable.rs:69:20 + --> tests/ui/map_unwrap_or_fixable.rs:66:20 | LL | println!("{}", o.map(|y| y + 1).unwrap_or(3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,13 +32,13 @@ LL + println!("{}", o.map_or(3, |y| y + 1)); | error: called `map().unwrap_or_else()` on an `Option` value - --> tests/ui/map_unwrap_or_fixable.rs:71:20 + --> tests/ui/map_unwrap_or_fixable.rs:68:20 | LL | println!("{}", o.map(|y| y + 1).unwrap_or_else(|| 3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `o.map_or_else(|| 3, |y| y + 1)` error: called `map().unwrap_or()` on a `Result` value - --> tests/ui/map_unwrap_or_fixable.rs:73:20 + --> tests/ui/map_unwrap_or_fixable.rs:70:20 | LL | println!("{}", r.map(|y| y + 1).unwrap_or(3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,13 +50,13 @@ LL + println!("{}", r.map_or(3, |y| y + 1)); | error: called `map().unwrap_or_else()` on a `Result` value - --> tests/ui/map_unwrap_or_fixable.rs:75:20 + --> tests/ui/map_unwrap_or_fixable.rs:72:20 | LL | println!("{}", r.map(|y| y + 1).unwrap_or_else(|()| 3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r.map_or_else(|()| 3, |y| y + 1)` error: called `map().unwrap_or(false)` on a `Result` value - --> tests/ui/map_unwrap_or_fixable.rs:78:20 + --> tests/ui/map_unwrap_or_fixable.rs:75:20 | LL | println!("{}", r.map(|y| y == 1).unwrap_or(false)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL + println!("{}", r.is_ok_and(|y| y == 1)); | error: called `map().unwrap_or()` on an `Option` value - --> tests/ui/map_unwrap_or_fixable.rs:84:20 + --> tests/ui/map_unwrap_or_fixable.rs:81:20 | LL | println!("{}", x.map(|y| y + 1).unwrap_or(3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL + println!("{}", x.map_or(3, |y| y + 1)); | error: called `map().unwrap_or()` on a `Result` value - --> tests/ui/map_unwrap_or_fixable.rs:88:20 + --> tests/ui/map_unwrap_or_fixable.rs:85:20 | LL | println!("{}", x.map(|y| y + 1).unwrap_or(3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -92,13 +92,13 @@ LL + println!("{}", x.map_or(3, |y| y + 1)); | error: called `map().unwrap_or_else()` on an `Option` value - --> tests/ui/map_unwrap_or_fixable.rs:92:20 + --> tests/ui/map_unwrap_or_fixable.rs:89:20 | LL | println!("{}", x.map(|y| y + 1).unwrap_or_else(|| 3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map_or_else(|| 3, |y| y + 1)` error: called `map().unwrap_or_else()` on a `Result` value - --> tests/ui/map_unwrap_or_fixable.rs:96:20 + --> tests/ui/map_unwrap_or_fixable.rs:93:20 | LL | println!("{}", x.map(|y| y + 1).unwrap_or_else(|_| 3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map_or_else(|_| 3, |y| y + 1)` diff --git a/tests/ui/mem_replace.fixed b/tests/ui/mem_replace.fixed index 94ad1aad3eb7..26aa7aa1b270 100644 --- a/tests/ui/mem_replace.fixed +++ b/tests/ui/mem_replace.fixed @@ -101,11 +101,7 @@ fn dont_lint_not_used() { std::mem::replace(&mut s, String::default()); } -fn main() { - replace_option_with_none(); - replace_with_default(); - dont_lint_primitive(); -} +fn main() {} #[clippy::msrv = "1.39"] fn msrv_1_39() { diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index ac79660f0f1e..cd675f5735a1 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -101,11 +101,7 @@ fn dont_lint_not_used() { std::mem::replace(&mut s, String::default()); } -fn main() { - replace_option_with_none(); - replace_with_default(); - dont_lint_primitive(); -} +fn main() {} #[clippy::msrv = "1.39"] fn msrv_1_39() { diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index 104c98540028..bc374930cf0f 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -131,37 +131,37 @@ LL | let _ = std::mem::replace(&mut slice, &[]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut slice)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:119:13 + --> tests/ui/mem_replace.rs:115:13 | LL | let _ = std::mem::replace(&mut s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` error: replacing an `Option` with `None` - --> tests/ui/mem_replace.rs:150:13 + --> tests/ui/mem_replace.rs:146:13 | LL | let _ = std::mem::replace(&mut f.0, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `f.0.take()` error: replacing an `Option` with `None` - --> tests/ui/mem_replace.rs:152:13 + --> tests/ui/mem_replace.rs:148:13 | LL | let _ = std::mem::replace(&mut *f, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `(*f).take()` error: replacing an `Option` with `None` - --> tests/ui/mem_replace.rs:154:13 + --> tests/ui/mem_replace.rs:150:13 | LL | let _ = std::mem::replace(&mut b.opt, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `b.opt.take()` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:157:13 + --> tests/ui/mem_replace.rs:153:13 | LL | let _ = std::mem::replace(&mut b.val, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut b.val)` error: replacing an `Option` with `Some(..)` - --> tests/ui/mem_replace.rs:164:20 + --> tests/ui/mem_replace.rs:160:20 | LL | let replaced = mem::replace(&mut an_option, Some(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::replace()` instead: `an_option.replace(1)` @@ -170,19 +170,19 @@ LL | let replaced = mem::replace(&mut an_option, Some(1)); = help: to override `-D warnings` add `#[allow(clippy::mem_replace_option_with_some)]` error: replacing an `Option` with `Some(..)` - --> tests/ui/mem_replace.rs:168:20 + --> tests/ui/mem_replace.rs:164:20 | LL | let replaced = mem::replace(an_option, Some(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::replace()` instead: `an_option.replace(1)` error: replacing an `Option` with `Some(..)` - --> tests/ui/mem_replace.rs:173:20 + --> tests/ui/mem_replace.rs:169:20 | LL | let replaced = mem::replace(if b { &mut opt1 } else { &mut opt2 }, Some(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::replace()` instead: `(if b { &mut opt1 } else { &mut opt2 }).replace(1)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:185:20 + --> tests/ui/mem_replace.rs:181:20 | LL | let replaced = std::mem::replace(dbg!(&mut text), String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(dbg!(&mut text))` diff --git a/tests/ui/mem_replace_no_std.fixed b/tests/ui/mem_replace_no_std.fixed index 669450e59d8b..4e2d413af6cd 100644 --- a/tests/ui/mem_replace_no_std.fixed +++ b/tests/ui/mem_replace_no_std.fixed @@ -47,11 +47,7 @@ fn dont_lint_primitive() { let _ = mem::replace(&mut pint, 0); } -fn main() { - replace_option_with_none(); - replace_with_default(); - dont_lint_primitive(); -} +fn main() {} fn issue9824() { struct Foo<'a>(Option<&'a str>); diff --git a/tests/ui/mem_replace_no_std.rs b/tests/ui/mem_replace_no_std.rs index 2cdf1df5196a..c0892304aba8 100644 --- a/tests/ui/mem_replace_no_std.rs +++ b/tests/ui/mem_replace_no_std.rs @@ -47,11 +47,7 @@ fn dont_lint_primitive() { let _ = mem::replace(&mut pint, 0); } -fn main() { - replace_option_with_none(); - replace_with_default(); - dont_lint_primitive(); -} +fn main() {} fn issue9824() { struct Foo<'a>(Option<&'a str>); diff --git a/tests/ui/mem_replace_no_std.stderr b/tests/ui/mem_replace_no_std.stderr index 926a8288fd31..34e81a9f0750 100644 --- a/tests/ui/mem_replace_no_std.stderr +++ b/tests/ui/mem_replace_no_std.stderr @@ -29,19 +29,19 @@ LL | let _ = mem::replace(&mut slice, &[]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::mem::take(&mut slice)` error: replacing an `Option` with `None` - --> tests/ui/mem_replace_no_std.rs:80:13 + --> tests/ui/mem_replace_no_std.rs:76:13 | LL | let _ = mem::replace(&mut f.0, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `f.0.take()` error: replacing an `Option` with `None` - --> tests/ui/mem_replace_no_std.rs:82:13 + --> tests/ui/mem_replace_no_std.rs:78:13 | LL | let _ = mem::replace(&mut *f, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `(*f).take()` error: replacing an `Option` with `None` - --> tests/ui/mem_replace_no_std.rs:84:13 + --> tests/ui/mem_replace_no_std.rs:80:13 | LL | let _ = mem::replace(&mut b.opt, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `b.opt.take()` diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 9595888b99f8..f73ec563dceb 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -145,7 +145,7 @@ fn filter_next_back() { *x < 0 } ).next_back(); - + // Check that we don't lint if the caller is not an `Iterator`. let foo = IteratorFalsePositives { foo: 0 }; let _ = foo.filter().next_back(); @@ -154,7 +154,4 @@ fn filter_next_back() { let _ = foo.filter(42).next_back(); } -fn main() { - filter_next(); - filter_next_back(); -} +fn main() {} diff --git a/tests/ui/methods_unfixable.rs b/tests/ui/methods_unfixable.rs index c19a769f7974..46a5d95eb1b7 100644 --- a/tests/ui/methods_unfixable.rs +++ b/tests/ui/methods_unfixable.rs @@ -1,8 +1,6 @@ #![warn(clippy::filter_next)] //@no-rustfix -fn main() { - issue10029(); -} +fn main() {} pub fn issue10029() { let iter = (0..10); diff --git a/tests/ui/methods_unfixable.stderr b/tests/ui/methods_unfixable.stderr index 76691860f819..137112ae4179 100644 --- a/tests/ui/methods_unfixable.stderr +++ b/tests/ui/methods_unfixable.stderr @@ -1,11 +1,11 @@ error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead - --> tests/ui/methods_unfixable.rs:9:13 + --> tests/ui/methods_unfixable.rs:7:13 | LL | let _ = iter.filter(|_| true).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `iter.find(|_| true)` | help: you will also need to make `iter` mutable, because `find` takes `&mut self` - --> tests/ui/methods_unfixable.rs:8:9 + --> tests/ui/methods_unfixable.rs:6:9 | LL | let iter = (0..10); | ^^^^ diff --git a/tests/ui/missing_assert_message.stderr b/tests/ui/missing_assert_message.edition2015.stderr similarity index 81% rename from tests/ui/missing_assert_message.stderr rename to tests/ui/missing_assert_message.edition2015.stderr index c4fb7e3b154e..c5978d706ecb 100644 --- a/tests/ui/missing_assert_message.stderr +++ b/tests/ui/missing_assert_message.edition2015.stderr @@ -1,5 +1,5 @@ error: assert without any message - --> tests/ui/missing_assert_message.rs:12:5 + --> tests/ui/missing_assert_message.rs:15:5 | LL | assert!(foo()); | ^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | assert!(foo()); = help: to override `-D warnings` add `#[allow(clippy::missing_assert_message)]` error: assert without any message - --> tests/ui/missing_assert_message.rs:14:5 + --> tests/ui/missing_assert_message.rs:17:5 | LL | assert_eq!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | assert_eq!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:16:5 + --> tests/ui/missing_assert_message.rs:19:5 | LL | assert_ne!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | assert_ne!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:18:5 + --> tests/ui/missing_assert_message.rs:21:5 | LL | debug_assert!(foo()); | ^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | debug_assert!(foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:20:5 + --> tests/ui/missing_assert_message.rs:23:5 | LL | debug_assert_eq!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | debug_assert_eq!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:22:5 + --> tests/ui/missing_assert_message.rs:25:5 | LL | debug_assert_ne!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | debug_assert_ne!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:28:5 + --> tests/ui/missing_assert_message.rs:31:5 | LL | assert!(bar!(true)); | ^^^^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | assert!(bar!(true)); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:30:5 + --> tests/ui/missing_assert_message.rs:33:5 | LL | assert!(bar!(true, false)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | assert!(bar!(true, false)); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:32:5 + --> tests/ui/missing_assert_message.rs:35:5 | LL | assert_eq!(bar!(true), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | assert_eq!(bar!(true), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:34:5 + --> tests/ui/missing_assert_message.rs:37:5 | LL | assert_ne!(bar!(true, true), bar!(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | assert_ne!(bar!(true, true), bar!(true)); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:40:5 + --> tests/ui/missing_assert_message.rs:43:5 | LL | assert!(foo(),); | ^^^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | assert!(foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:42:5 + --> tests/ui/missing_assert_message.rs:45:5 | LL | assert_eq!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | assert_eq!(foo(), foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:44:5 + --> tests/ui/missing_assert_message.rs:47:5 | LL | assert_ne!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | assert_ne!(foo(), foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:46:5 + --> tests/ui/missing_assert_message.rs:49:5 | LL | debug_assert!(foo(),); | ^^^^^^^^^^^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | debug_assert!(foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:48:5 + --> tests/ui/missing_assert_message.rs:51:5 | LL | debug_assert_eq!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | debug_assert_eq!(foo(), foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> tests/ui/missing_assert_message.rs:50:5 + --> tests/ui/missing_assert_message.rs:53:5 | LL | debug_assert_ne!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/missing_assert_message.edition2021.stderr b/tests/ui/missing_assert_message.edition2021.stderr new file mode 100644 index 000000000000..c5978d706ecb --- /dev/null +++ b/tests/ui/missing_assert_message.edition2021.stderr @@ -0,0 +1,132 @@ +error: assert without any message + --> tests/ui/missing_assert_message.rs:15:5 + | +LL | assert!(foo()); + | ^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + = note: `-D clippy::missing-assert-message` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::missing_assert_message)]` + +error: assert without any message + --> tests/ui/missing_assert_message.rs:17:5 + | +LL | assert_eq!(foo(), foo()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:19:5 + | +LL | assert_ne!(foo(), foo()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:21:5 + | +LL | debug_assert!(foo()); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:23:5 + | +LL | debug_assert_eq!(foo(), foo()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:25:5 + | +LL | debug_assert_ne!(foo(), foo()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:31:5 + | +LL | assert!(bar!(true)); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:33:5 + | +LL | assert!(bar!(true, false)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:35:5 + | +LL | assert_eq!(bar!(true), foo()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:37:5 + | +LL | assert_ne!(bar!(true, true), bar!(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:43:5 + | +LL | assert!(foo(),); + | ^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:45:5 + | +LL | assert_eq!(foo(), foo(),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:47:5 + | +LL | assert_ne!(foo(), foo(),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:49:5 + | +LL | debug_assert!(foo(),); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:51:5 + | +LL | debug_assert_eq!(foo(), foo(),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: assert without any message + --> tests/ui/missing_assert_message.rs:53:5 + | +LL | debug_assert_ne!(foo(), foo(),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider describing why the failing assert is problematic + +error: aborting due to 16 previous errors + diff --git a/tests/ui/missing_assert_message.rs b/tests/ui/missing_assert_message.rs index 2ad8e0127edf..20ef40af170c 100644 --- a/tests/ui/missing_assert_message.rs +++ b/tests/ui/missing_assert_message.rs @@ -1,4 +1,7 @@ -#![allow(unused)] +//@revisions: edition2015 edition2021 +//@[edition2015] edition:2015 +//@[edition2021] edition:2021 + #![warn(clippy::missing_assert_message)] macro_rules! bar { diff --git a/tests/ui/mixed_attributes_style/mod_declaration.rs b/tests/ui/mixed_attributes_style/mod_declaration.rs index 8cef6a80048a..43b49c6d8b02 100644 --- a/tests/ui/mixed_attributes_style/mod_declaration.rs +++ b/tests/ui/mixed_attributes_style/mod_declaration.rs @@ -1,5 +1,5 @@ //@error-in-other-file: item has both inner and outer attributes -//@no-rustfix + #[path = "auxiliary/submodule.rs"] // don't lint. /// This doc comment should not lint, it could be used to add context to the original module doc mod submodule; diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed index a53e6e9b85be..10dc5f9157b7 100644 --- a/tests/ui/must_use_candidates.fixed +++ b/tests/ui/must_use_candidates.fixed @@ -108,3 +108,15 @@ pub fn main() -> std::process::ExitCode { assert_eq!(1, pure(1)); std::process::ExitCode::SUCCESS } + +//~v must_use_candidate +#[must_use] +pub fn result_uninhabited() -> Result { + todo!() +} + +//~v must_use_candidate +#[must_use] +pub fn controlflow_uninhabited() -> std::ops::ControlFlow { + todo!() +} diff --git a/tests/ui/must_use_candidates.rs b/tests/ui/must_use_candidates.rs index 6593d6c68a13..8b898533d01b 100644 --- a/tests/ui/must_use_candidates.rs +++ b/tests/ui/must_use_candidates.rs @@ -103,3 +103,13 @@ pub fn main() -> std::process::ExitCode { assert_eq!(1, pure(1)); std::process::ExitCode::SUCCESS } + +//~v must_use_candidate +pub fn result_uninhabited() -> Result { + todo!() +} + +//~v must_use_candidate +pub fn controlflow_uninhabited() -> std::ops::ControlFlow { + todo!() +} diff --git a/tests/ui/must_use_candidates.stderr b/tests/ui/must_use_candidates.stderr index 5ddbd0260629..f2ec9b265c45 100644 --- a/tests/ui/must_use_candidates.stderr +++ b/tests/ui/must_use_candidates.stderr @@ -60,5 +60,31 @@ LL + #[must_use] LL | pub fn arcd(_x: Arc) -> bool { | -error: aborting due to 5 previous errors +error: this function could have a `#[must_use]` attribute + --> tests/ui/must_use_candidates.rs:108:8 + | +LL | pub fn result_uninhabited() -> Result { + | ^^^^^^^^^^^^^^^^^^ + | + = note: a future version of Rust will treat `Result` as `T` when `E` is uninhabited wrt `#[must_use]` +help: add the attribute + | +LL + #[must_use] +LL | pub fn result_uninhabited() -> Result { + | + +error: this function could have a `#[must_use]` attribute + --> tests/ui/must_use_candidates.rs:113:8 + | +LL | pub fn controlflow_uninhabited() -> std::ops::ControlFlow { + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a future version of Rust will treat `ControlFlow` as `C` when `B` is uninhabited wrt `#[must_use]` +help: add the attribute + | +LL + #[must_use] +LL | pub fn controlflow_uninhabited() -> std::ops::ControlFlow { + | + +error: aborting due to 7 previous errors diff --git a/tests/ui/must_use_unit.fixed b/tests/ui/must_use_unit.fixed index 683754a98c82..b9871991b16f 100644 --- a/tests/ui/must_use_unit.fixed +++ b/tests/ui/must_use_unit.fixed @@ -15,14 +15,10 @@ pub fn must_use_unit() -> () {} pub fn must_use_with_note() {} //~^ must_use_unit -fn main() { - must_use_default(); - must_use_unit(); - must_use_with_note(); +// We should not lint in external macros +external!( + #[must_use] + fn foo() {} +); - // We should not lint in external macros - external!( - #[must_use] - fn foo() {} - ); -} +fn main() {} diff --git a/tests/ui/must_use_unit.rs b/tests/ui/must_use_unit.rs index 519b8fa36821..a5865681c8a8 100644 --- a/tests/ui/must_use_unit.rs +++ b/tests/ui/must_use_unit.rs @@ -18,14 +18,10 @@ pub fn must_use_unit() -> () {} pub fn must_use_with_note() {} //~^ must_use_unit -fn main() { - must_use_default(); - must_use_unit(); - must_use_with_note(); +// We should not lint in external macros +external!( + #[must_use] + fn foo() {} +); - // We should not lint in external macros - external!( - #[must_use] - fn foo() {} - ); -} +fn main() {} diff --git a/tests/ui/needless_collect_indirect.fixed b/tests/ui/needless_collect_indirect.fixed new file mode 100644 index 000000000000..22b9bb6f6a20 --- /dev/null +++ b/tests/ui/needless_collect_indirect.fixed @@ -0,0 +1,344 @@ +#![allow( + clippy::uninlined_format_args, + clippy::useless_vec, + clippy::needless_ifs, + clippy::iter_next_slice, + clippy::iter_count +)] +#![warn(clippy::needless_collect)] + +use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; + +fn main() { + let sample = [1; 5]; + + //~^ needless_collect + + sample.iter().map(|x| (x, x + 1)).collect::>(); + + //~^ needless_collect + + sample.iter().count(); + + //~^ needless_collect + + sample.iter().next().is_none(); + + //~^ needless_collect + + sample.iter().any(|x| x == &5); + let indirect_negative = sample.iter().collect::>(); + indirect_negative.len(); + indirect_negative + .into_iter() + .map(|x| (*x, *x + 1)) + .collect::>(); + + // #6202 + let a = "a".to_string(); + let sample = vec![a.clone(), "b".to_string(), "c".to_string()]; + + //~^ needless_collect + + sample.into_iter().any(|x| x == a); + + // Fix #5991 + let vec_a = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let vec_b = vec_a.iter().collect::>(); + if vec_b.len() > 3 {} + let other_vec = vec![1, 3, 12, 4, 16, 2]; + let we_got_the_same_numbers = other_vec.iter().filter(|item| vec_b.contains(item)).collect::>(); + + // Fix #6297 + let sample = [1; 5]; + let multiple_indirect = sample.iter().collect::>(); + let sample2 = vec![2, 3]; + if multiple_indirect.is_empty() { + // do something + } else { + let found = sample2 + .iter() + .filter(|i| multiple_indirect.iter().any(|s| **s % **i == 0)) + .collect::>(); + } +} + +mod issue7110 { + // #7110 - lint for type annotation cases + use super::*; + + fn lint_vec(string: &str) -> usize { + + //~^ needless_collect + + string.split('/').count() + } + fn lint_vec_deque() -> usize { + let sample = [1; 5]; + + //~^ needless_collect + + sample.iter().count() + } + fn lint_linked_list() -> usize { + let sample = [1; 5]; + + //~^ needless_collect + + sample.iter().count() + } + fn lint_binary_heap() -> usize { + let sample = [1; 5]; + + //~^ needless_collect + + sample.iter().count() + } + fn dont_lint(string: &str) -> usize { + let buffer: Vec<&str> = string.split('/').collect(); + for buff in &buffer { + println!("{}", buff); + } + buffer.len() + } +} + +mod issue7975 { + use super::*; + + fn direct_mapping_with_used_mutable_reference() -> Vec<()> { + let test_vec: Vec<()> = vec![]; + let mut vec_2: Vec<()> = vec![]; + let mut_ref = &mut vec_2; + let collected_vec: Vec<_> = test_vec.into_iter().map(|_| mut_ref.push(())).collect(); + collected_vec.into_iter().map(|_| mut_ref.push(())).collect() + } + + fn indirectly_mapping_with_used_mutable_reference() -> Vec<()> { + let test_vec: Vec<()> = vec![]; + let mut vec_2: Vec<()> = vec![]; + let mut_ref = &mut vec_2; + let collected_vec: Vec<_> = test_vec.into_iter().map(|_| mut_ref.push(())).collect(); + let iter = collected_vec.into_iter(); + iter.map(|_| mut_ref.push(())).collect() + } + + fn indirect_collect_after_indirect_mapping_with_used_mutable_reference() -> Vec<()> { + let test_vec: Vec<()> = vec![]; + let mut vec_2: Vec<()> = vec![]; + let mut_ref = &mut vec_2; + let collected_vec: Vec<_> = test_vec.into_iter().map(|_| mut_ref.push(())).collect(); + let iter = collected_vec.into_iter(); + let mapped_iter = iter.map(|_| mut_ref.push(())); + mapped_iter.collect() + } +} + +fn allow_test() { + #[allow(clippy::needless_collect)] + let v = [1].iter().collect::>(); + v.into_iter().collect::>(); +} + +mod issue_8553 { + fn test_for() { + let vec = vec![1, 2]; + let w: Vec = vec.iter().map(|i| i * i).collect(); + + for i in 0..2 { + // Do not lint, because this method call is in the loop + w.contains(&i); + } + + for i in 0..2 { + + //~^ needless_collect + + let z: Vec = vec.iter().map(|k| k * k).collect(); + // Do lint + vec.iter().map(|k| k * k).any(|x| x == i); + for j in 0..2 { + // Do not lint, because this method call is in the loop + z.contains(&j); + } + } + + // Do not lint, because this variable is used. + w.contains(&0); + } + + fn test_while() { + let vec = vec![1, 2]; + let x: Vec = vec.iter().map(|i| i * i).collect(); + let mut n = 0; + while n > 1 { + // Do not lint, because this method call is in the loop + x.contains(&n); + n += 1; + } + + while n > 2 { + + //~^ needless_collect + + let z: Vec = vec.iter().map(|k| k * k).collect(); + // Do lint + vec.iter().map(|k| k * k).any(|x| x == n); + n += 1; + while n > 4 { + // Do not lint, because this method call is in the loop + z.contains(&n); + n += 1; + } + } + } + + fn test_loop() { + let vec = vec![1, 2]; + let x: Vec = vec.iter().map(|i| i * i).collect(); + let mut n = 0; + loop { + if n < 1 { + // Do not lint, because this method call is in the loop + x.contains(&n); + n += 1; + } else { + break; + } + } + + loop { + if n < 2 { + + //~^ needless_collect + + let z: Vec = vec.iter().map(|k| k * k).collect(); + // Do lint + vec.iter().map(|k| k * k).any(|x| x == n); + n += 1; + loop { + if n < 4 { + // Do not lint, because this method call is in the loop + z.contains(&n); + n += 1; + } else { + break; + } + } + } else { + break; + } + } + } + + fn test_while_let() { + let vec = vec![1, 2]; + let x: Vec = vec.iter().map(|i| i * i).collect(); + let optional = Some(0); + let mut n = 0; + while let Some(value) = optional { + if n < 1 { + // Do not lint, because this method call is in the loop + x.contains(&n); + n += 1; + } else { + break; + } + } + + while let Some(value) = optional { + + //~^ needless_collect + + let z: Vec = vec.iter().map(|k| k * k).collect(); + if n < 2 { + // Do lint + vec.iter().map(|k| k * k).any(|x| x == n); + n += 1; + } else { + break; + } + + while let Some(value) = optional { + if n < 4 { + // Do not lint, because this method call is in the loop + z.contains(&n); + n += 1; + } else { + break; + } + } + } + } + + fn test_if_cond() { + let vec = vec![1, 2]; + let v: Vec = vec.iter().map(|i| i * i).collect(); + + //~^ needless_collect + + // Do lint + for _ in 0..v.iter().count() { + todo!(); + } + } + + fn test_if_cond_false_case() { + let vec = vec![1, 2]; + let v: Vec = vec.iter().map(|i| i * i).collect(); + let w = v.iter().collect::>(); + // Do not lint, because w is used. + for _ in 0..w.len() { + todo!(); + } + + w.len(); + } + + fn test_while_cond() { + let mut vec = vec![1, 2]; + let mut v: Vec = vec.iter().map(|i| i * i).collect(); + + //~^ needless_collect + + // Do lint + while 1 == v.iter().count() { + todo!(); + } + } + + fn test_while_cond_false_case() { + let mut vec = vec![1, 2]; + let mut v: Vec = vec.iter().map(|i| i * i).collect(); + let mut w = v.iter().collect::>(); + // Do not lint, because w is used. + while 1 == w.len() { + todo!(); + } + + w.len(); + } + + fn test_while_let_cond() { + let mut vec = vec![1, 2]; + let mut v: Vec = vec.iter().map(|i| i * i).collect(); + + //~^ needless_collect + + // Do lint + while let Some(i) = Some(v.iter().count()) { + todo!(); + } + } + + fn test_while_let_cond_false_case() { + let mut vec = vec![1, 2]; + let mut v: Vec = vec.iter().map(|i| i * i).collect(); + let mut w = v.iter().collect::>(); + // Do not lint, because w is used. + while let Some(i) = Some(w.len()) { + todo!(); + } + w.len(); + } +} diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs index 69764becfe66..20b7ae91a6b8 100644 --- a/tests/ui/needless_collect_indirect.rs +++ b/tests/ui/needless_collect_indirect.rs @@ -1,6 +1,12 @@ -#![allow(clippy::uninlined_format_args, clippy::useless_vec, clippy::needless_ifs)] +#![allow( + clippy::uninlined_format_args, + clippy::useless_vec, + clippy::needless_ifs, + clippy::iter_next_slice, + clippy::iter_count +)] #![warn(clippy::needless_collect)] -//@no-rustfix + use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; fn main() { diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr index 24523c9f97b0..d34f1c37558d 100644 --- a/tests/ui/needless_collect_indirect.stderr +++ b/tests/ui/needless_collect_indirect.stderr @@ -1,5 +1,5 @@ error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:8:39 + --> tests/ui/needless_collect_indirect.rs:14:39 | LL | let indirect_iter = sample.iter().collect::>(); | ^^^^^^^ @@ -18,7 +18,7 @@ LL ~ sample.iter().map(|x| (x, x + 1)).collect::>(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:12:38 + --> tests/ui/needless_collect_indirect.rs:18:38 | LL | let indirect_len = sample.iter().collect::>(); | ^^^^^^^ @@ -35,7 +35,7 @@ LL ~ sample.iter().count(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:16:40 + --> tests/ui/needless_collect_indirect.rs:22:40 | LL | let indirect_empty = sample.iter().collect::>(); | ^^^^^^^ @@ -52,7 +52,7 @@ LL ~ sample.iter().next().is_none(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:20:43 + --> tests/ui/needless_collect_indirect.rs:26:43 | LL | let indirect_contains = sample.iter().collect::>(); | ^^^^^^^ @@ -69,7 +69,7 @@ LL ~ sample.iter().any(|x| x == &5); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:34:48 + --> tests/ui/needless_collect_indirect.rs:40:48 | LL | let non_copy_contains = sample.into_iter().collect::>(); | ^^^^^^^ @@ -86,7 +86,7 @@ LL ~ sample.into_iter().any(|x| x == a); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:65:51 + --> tests/ui/needless_collect_indirect.rs:71:51 | LL | let buffer: Vec<&str> = string.split('/').collect(); | ^^^^^^^ @@ -103,7 +103,7 @@ LL ~ string.split('/').count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:72:55 + --> tests/ui/needless_collect_indirect.rs:78:55 | LL | let indirect_len: VecDeque<_> = sample.iter().collect(); | ^^^^^^^ @@ -120,7 +120,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:79:57 + --> tests/ui/needless_collect_indirect.rs:85:57 | LL | let indirect_len: LinkedList<_> = sample.iter().collect(); | ^^^^^^^ @@ -137,7 +137,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:86:57 + --> tests/ui/needless_collect_indirect.rs:92:57 | LL | let indirect_len: BinaryHeap<_> = sample.iter().collect(); | ^^^^^^^ @@ -154,7 +154,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:148:59 + --> tests/ui/needless_collect_indirect.rs:154:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -172,7 +172,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == i); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:175:59 + --> tests/ui/needless_collect_indirect.rs:181:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -190,7 +190,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:206:63 + --> tests/ui/needless_collect_indirect.rs:212:63 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -208,7 +208,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:244:59 + --> tests/ui/needless_collect_indirect.rs:250:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -226,7 +226,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:271:26 + --> tests/ui/needless_collect_indirect.rs:277:26 | LL | let w = v.iter().collect::>(); | ^^^^^^^ @@ -244,7 +244,7 @@ LL ~ for _ in 0..v.iter().count() { | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:295:30 + --> tests/ui/needless_collect_indirect.rs:301:30 | LL | let mut w = v.iter().collect::>(); | ^^^^^^^ @@ -262,7 +262,7 @@ LL ~ while 1 == v.iter().count() { | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:319:30 + --> tests/ui/needless_collect_indirect.rs:325:30 | LL | let mut w = v.iter().collect::>(); | ^^^^^^^ diff --git a/tests/ui/needless_doc_main.rs b/tests/ui/needless_doc_main.rs index afecd4b47f5e..803b0bbb0aef 100644 --- a/tests/ui/needless_doc_main.rs +++ b/tests/ui/needless_doc_main.rs @@ -134,7 +134,4 @@ fn no_false_positives() {} /// ``` fn issue_6022() {} -fn main() { - bad_doctests(); - no_false_positives(); -} +fn main() {} diff --git a/tests/ui/needless_maybe_sized.fixed b/tests/ui/needless_maybe_sized.fixed index f8b164396990..92840a888ada 100644 --- a/tests/ui/needless_maybe_sized.fixed +++ b/tests/ui/needless_maybe_sized.fixed @@ -133,4 +133,13 @@ struct InDerive { struct Refined(T); impl Refined {} +// in proc-macros +fn issue13360() { + #[derive(serde::Serialize)] + #[serde(bound = "T: A")] + struct Foo { + t: std::marker::PhantomData, + } +} + fn main() {} diff --git a/tests/ui/needless_maybe_sized.rs b/tests/ui/needless_maybe_sized.rs index e4312b40563f..02242260af1f 100644 --- a/tests/ui/needless_maybe_sized.rs +++ b/tests/ui/needless_maybe_sized.rs @@ -136,4 +136,13 @@ struct InDerive { struct Refined(T); impl Refined {} +// in proc-macros +fn issue13360() { + #[derive(serde::Serialize)] + #[serde(bound = "T: A")] + struct Foo { + t: std::marker::PhantomData, + } +} + fn main() {} diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 52470c6ee81b..7b2d66450f17 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -447,22 +447,7 @@ fn loop_label() { } } -fn main() { - test1(); - test2(); - test3(); - test4(); - test5(); - test6(); - test7(); - test8(); - test9(); - test10(); - test11(|| 0); - test12(true, false); - test13(); - test14(); -} +fn main() {} fn issue15059() { 'a: for _ in 0..1 { diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 49392d971ee3..815758107884 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -248,7 +248,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> tests/ui/never_loop.rs:468:5 + --> tests/ui/never_loop.rs:453:5 | LL | / 'a: for _ in 0..1 { LL | | @@ -264,7 +264,7 @@ LL ~ | error: this loop never actually loops - --> tests/ui/never_loop.rs:474:5 + --> tests/ui/never_loop.rs:459:5 | LL | / 'a: for i in 0..1 { LL | | @@ -288,7 +288,7 @@ LL ~ | error: this loop never actually loops - --> tests/ui/never_loop.rs:489:5 + --> tests/ui/never_loop.rs:474:5 | LL | / for v in 0..10 { LL | | @@ -311,7 +311,7 @@ LL ~ | error: this loop never actually loops - --> tests/ui/never_loop.rs:500:5 + --> tests/ui/never_loop.rs:485:5 | LL | / 'bar: for _ in 0..100 { LL | | @@ -321,7 +321,7 @@ LL | | } | |_____^ | help: this code is unreachable. Consider moving the reachable parts out - --> tests/ui/never_loop.rs:502:9 + --> tests/ui/never_loop.rs:487:9 | LL | / loop { LL | | @@ -336,7 +336,7 @@ LL + if let Some(_) = (0..100).next() { | error: this loop never actually loops - --> tests/ui/never_loop.rs:502:9 + --> tests/ui/never_loop.rs:487:9 | LL | / loop { LL | | @@ -346,7 +346,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> tests/ui/never_loop.rs:509:5 + --> tests/ui/never_loop.rs:494:5 | LL | / 'foo: for _ in 0..100 { LL | | @@ -356,7 +356,7 @@ LL | | } | |_____^ | help: this code is unreachable. Consider moving the reachable parts out - --> tests/ui/never_loop.rs:511:9 + --> tests/ui/never_loop.rs:496:9 | LL | / loop { LL | | @@ -372,7 +372,7 @@ LL + if let Some(_) = (0..100).next() { | error: this loop never actually loops - --> tests/ui/never_loop.rs:511:9 + --> tests/ui/never_loop.rs:496:9 | LL | / loop { LL | | @@ -383,7 +383,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> tests/ui/never_loop.rs:514:13 + --> tests/ui/never_loop.rs:499:13 | LL | / loop { LL | | @@ -393,7 +393,7 @@ LL | | } | |_____________^ error: this loop never actually loops - --> tests/ui/never_loop.rs:537:5 + --> tests/ui/never_loop.rs:522:5 | LL | / loop { LL | | unsafe { diff --git a/tests/ui/panicking_macros.rs b/tests/ui/panicking_macros.rs index b044be7d54ac..a9728d4708e6 100644 --- a/tests/ui/panicking_macros.rs +++ b/tests/ui/panicking_macros.rs @@ -126,15 +126,4 @@ fn debug_assert_msg() { debug_assert_ne!(true, false, "test"); } -fn main() { - panic(); - panic_const(); - todo(); - unimplemented(); - unreachable(); - core_versions(); - assert(); - assert_msg(); - debug_assert(); - debug_assert_msg(); -} +fn main() {} diff --git a/tests/ui/panicking_overflow_checks.rs b/tests/ui/panicking_overflow_checks.rs index 61dfca8b3728..ecae3130fd50 100644 --- a/tests/ui/panicking_overflow_checks.rs +++ b/tests/ui/panicking_overflow_checks.rs @@ -28,6 +28,4 @@ fn test(a: u32, b: u32, c: u32) { if i - j < i {} } -fn main() { - test(1, 2, 3) -} +fn main() {} diff --git a/tests/ui/println_empty_string.fixed b/tests/ui/println_empty_string.fixed index 6b1039ee8020..2c2901bc715a 100644 --- a/tests/ui/println_empty_string.fixed +++ b/tests/ui/println_empty_string.fixed @@ -1,4 +1,4 @@ -#![allow(clippy::match_single_binding)] +#![allow(clippy::match_single_binding, clippy::unnecessary_trailing_comma)] fn main() { println!(); diff --git a/tests/ui/println_empty_string.rs b/tests/ui/println_empty_string.rs index db3b8e1a0eac..bc2971f54f2c 100644 --- a/tests/ui/println_empty_string.rs +++ b/tests/ui/println_empty_string.rs @@ -1,4 +1,4 @@ -#![allow(clippy::match_single_binding)] +#![allow(clippy::match_single_binding, clippy::unnecessary_trailing_comma)] fn main() { println!(); diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index c63d549b7553..699256f22c01 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -152,8 +152,4 @@ fn regex_creation_in_loops() { } } -fn main() { - syntax_error(); - trivial_regex(); - regex_creation_in_loops(); -} +fn main() {} diff --git a/tests/ui/result_map_unit_fn_fixable.stderr b/tests/ui/result_map_unit_fn_fixable.stderr index d8f6239764d1..1af70ce5a1f2 100644 --- a/tests/ui/result_map_unit_fn_fixable.stderr +++ b/tests/ui/result_map_unit_fn_fixable.stderr @@ -1,4 +1,4 @@ -error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a function that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:32:5 | LL | x.field.map(do_nothing); @@ -12,7 +12,7 @@ LL - x.field.map(do_nothing); LL + if let Ok(x_field) = x.field { do_nothing(x_field) } | -error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a function that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:35:5 | LL | x.field.map(do_nothing); @@ -24,7 +24,7 @@ LL - x.field.map(do_nothing); LL + if let Ok(x_field) = x.field { do_nothing(x_field) } | -error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a function that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:38:5 | LL | x.field.map(diverge); @@ -36,7 +36,7 @@ LL - x.field.map(diverge); LL + if let Ok(x_field) = x.field { diverge(x_field) } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:45:5 | LL | x.field.map(|value| x.do_result_nothing(value + captured)); @@ -48,7 +48,7 @@ LL - x.field.map(|value| x.do_result_nothing(value + captured)); LL + if let Ok(value) = x.field { x.do_result_nothing(value + captured) } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:48:5 | LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); @@ -60,7 +60,7 @@ LL - x.field.map(|value| { x.do_result_plus_one(value + captured); }); LL + if let Ok(value) = x.field { x.do_result_plus_one(value + captured); } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:52:5 | LL | x.field.map(|value| do_nothing(value + captured)); @@ -72,7 +72,7 @@ LL - x.field.map(|value| do_nothing(value + captured)); LL + if let Ok(value) = x.field { do_nothing(value + captured) } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:55:5 | LL | x.field.map(|value| { do_nothing(value + captured) }); @@ -84,7 +84,7 @@ LL - x.field.map(|value| { do_nothing(value + captured) }); LL + if let Ok(value) = x.field { do_nothing(value + captured) } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:58:5 | LL | x.field.map(|value| { do_nothing(value + captured); }); @@ -96,7 +96,7 @@ LL - x.field.map(|value| { do_nothing(value + captured); }); LL + if let Ok(value) = x.field { do_nothing(value + captured); } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:61:5 | LL | x.field.map(|value| { { do_nothing(value + captured); } }); @@ -108,7 +108,7 @@ LL - x.field.map(|value| { { do_nothing(value + captured); } }); LL + if let Ok(value) = x.field { do_nothing(value + captured); } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:65:5 | LL | x.field.map(|value| diverge(value + captured)); @@ -120,7 +120,7 @@ LL - x.field.map(|value| diverge(value + captured)); LL + if let Ok(value) = x.field { diverge(value + captured) } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:68:5 | LL | x.field.map(|value| { diverge(value + captured) }); @@ -132,7 +132,7 @@ LL - x.field.map(|value| { diverge(value + captured) }); LL + if let Ok(value) = x.field { diverge(value + captured) } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:71:5 | LL | x.field.map(|value| { diverge(value + captured); }); @@ -144,7 +144,7 @@ LL - x.field.map(|value| { diverge(value + captured); }); LL + if let Ok(value) = x.field { diverge(value + captured); } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:74:5 | LL | x.field.map(|value| { { diverge(value + captured); } }); @@ -156,7 +156,7 @@ LL - x.field.map(|value| { { diverge(value + captured); } }); LL + if let Ok(value) = x.field { diverge(value + captured); } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:80:5 | LL | x.field.map(|value| { let y = plus_one(value + captured); }); @@ -168,7 +168,7 @@ LL - x.field.map(|value| { let y = plus_one(value + captured); }); LL + if let Ok(value) = x.field { let y = plus_one(value + captured); } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:83:5 | LL | x.field.map(|value| { plus_one(value + captured); }); @@ -180,7 +180,7 @@ LL - x.field.map(|value| { plus_one(value + captured); }); LL + if let Ok(value) = x.field { plus_one(value + captured); } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:86:5 | LL | x.field.map(|value| { { plus_one(value + captured); } }); @@ -192,7 +192,7 @@ LL - x.field.map(|value| { { plus_one(value + captured); } }); LL + if let Ok(value) = x.field { plus_one(value + captured); } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:90:5 | LL | x.field.map(|ref value| { do_nothing(value + captured) }); @@ -204,7 +204,7 @@ LL - x.field.map(|ref value| { do_nothing(value + captured) }); LL + if let Ok(ref value) = x.field { do_nothing(value + captured) } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_fixable.rs:93:5 | LL | x.field.map(|value| println!("{value:?}")); diff --git a/tests/ui/result_map_unit_fn_unfixable.stderr b/tests/ui/result_map_unit_fn_unfixable.stderr index 9f80ec1bbbd0..c7bca9e9e02b 100644 --- a/tests/ui/result_map_unit_fn_unfixable.stderr +++ b/tests/ui/result_map_unit_fn_unfixable.stderr @@ -1,4 +1,4 @@ -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_unfixable.rs:24:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); @@ -12,7 +12,7 @@ LL - x.field.map(|value| { do_nothing(value); do_nothing(value) }); LL + if let Ok(value) = x.field { ... } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_unfixable.rs:29:5 | LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); @@ -24,7 +24,7 @@ LL - x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) LL + if let Ok(value) = x.field { ... } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_unfixable.rs:35:5 | LL | / x.field.map(|value| { @@ -46,7 +46,7 @@ LL - }); LL + if let Ok(value) = x.field { ... } | -error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_unfixable.rs:41:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); @@ -58,7 +58,7 @@ LL - x.field.map(|value| { do_nothing(value); do_nothing(value); }); LL + if let Ok(value) = x.field { ... } | -error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a function that returns the unit type `()` --> tests/ui/result_map_unit_fn_unfixable.rs:47:5 | LL | "12".parse::().map(diverge); @@ -70,7 +70,7 @@ LL - "12".parse::().map(diverge); LL + if let Ok(a) = "12".parse::() { diverge(a) } | -error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` +error: called `map(f)` on a `Result` value where `f` is a function that returns the unit type `()` --> tests/ui/result_map_unit_fn_unfixable.rs:55:5 | LL | y.map(do_nothing); diff --git a/tests/ui/set_contains_or_insert.rs b/tests/ui/set_contains_or_insert.rs index ac1d74f8afa4..b9480cd9172a 100644 --- a/tests/ui/set_contains_or_insert.rs +++ b/tests/ui/set_contains_or_insert.rs @@ -157,13 +157,7 @@ fn simply_true() -> bool { true } -// This is placed last in order to be able to add new tests without changing line numbers -fn main() { - should_warn_hashset(); - should_warn_btreeset(); - should_not_warn_hashset(); - should_not_warn_btreeset(); -} +fn main() {} fn issue15990(s: &mut HashSet, v: usize) { if !s.contains(&v) { diff --git a/tests/ui/set_contains_or_insert.stderr b/tests/ui/set_contains_or_insert.stderr index 3b06b63182ab..85331514be7a 100644 --- a/tests/ui/set_contains_or_insert.stderr +++ b/tests/ui/set_contains_or_insert.stderr @@ -128,7 +128,7 @@ LL | borrow_set.insert(value); | ^^^^^^^^^^^^^ error: usage of `HashSet::insert` after `HashSet::contains` - --> tests/ui/set_contains_or_insert.rs:182:11 + --> tests/ui/set_contains_or_insert.rs:176:11 | LL | if !s.contains(&v) { | ^^^^^^^^^^^^ diff --git a/tests/ui/should_impl_trait/method_list_2.rs b/tests/ui/should_impl_trait/method_list_2.rs index 4dfbe7e0f9f4..4c6d7df236ef 100644 --- a/tests/ui/should_impl_trait/method_list_2.rs +++ b/tests/ui/should_impl_trait/method_list_2.rs @@ -12,7 +12,7 @@ clippy::missing_panics_doc, clippy::return_self_not_must_use )] -//@no-rustfix + use std::ops::Mul; use std::rc::{self, Rc}; use std::sync::{self, Arc}; diff --git a/tests/ui/skip_while_next.rs b/tests/ui/skip_while_next.rs index 96f4604ad42d..6dbb6a2ebb9a 100644 --- a/tests/ui/skip_while_next.rs +++ b/tests/ui/skip_while_next.rs @@ -26,6 +26,4 @@ fn skip_while_next() { let _ = foo.skip_while().next(); } -fn main() { - skip_while_next(); -} +fn main() {} diff --git a/tests/ui/slow_vector_initialization.fixed b/tests/ui/slow_vector_initialization.fixed index a8570366e646..a13be693e4ec 100644 --- a/tests/ui/slow_vector_initialization.fixed +++ b/tests/ui/slow_vector_initialization.fixed @@ -1,12 +1,8 @@ #![allow(clippy::useless_vec, clippy::manual_repeat_n)] use std::iter::repeat; -fn main() { - resize_vector(); - extend_vector(); - mixed_extend_resize_vector(); - from_empty_vec(); -} + +fn main() {} fn extend_vector() { // Extend with constant expression diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs index 52f2a52fbbb8..eda96d0a0f82 100644 --- a/tests/ui/slow_vector_initialization.rs +++ b/tests/ui/slow_vector_initialization.rs @@ -1,12 +1,8 @@ #![allow(clippy::useless_vec, clippy::manual_repeat_n)] use std::iter::repeat; -fn main() { - resize_vector(); - extend_vector(); - mixed_extend_resize_vector(); - from_empty_vec(); -} + +fn main() {} fn extend_vector() { // Extend with constant expression diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index e83eef826472..320f2cacf61b 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -1,5 +1,5 @@ error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:14:20 + --> tests/ui/slow_vector_initialization.rs:10:20 | LL | let mut vec1 = Vec::with_capacity(len); | ____________________^ @@ -11,7 +11,7 @@ LL | | vec1.extend(repeat(0).take(len)); = help: to override `-D warnings` add `#[allow(clippy::slow_vector_initialization)]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:20:20 + --> tests/ui/slow_vector_initialization.rs:16:20 | LL | let mut vec2 = Vec::with_capacity(len - 10); | ____________________^ @@ -20,7 +20,7 @@ LL | | vec2.extend(repeat(0).take(len - 10)); | |_________________________________________^ help: consider replacing this with: `vec![0; len - 10]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:29:20 + --> tests/ui/slow_vector_initialization.rs:25:20 | LL | let mut vec4 = Vec::with_capacity(len); | ____________________^ @@ -29,7 +29,7 @@ LL | | vec4.extend(repeat(0).take(vec4.capacity())); | |________________________________________________^ help: consider replacing this with: `vec![0; len]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:41:27 + --> tests/ui/slow_vector_initialization.rs:37:27 | LL | let mut resized_vec = Vec::with_capacity(30); | ___________________________^ @@ -38,7 +38,7 @@ LL | | resized_vec.resize(30, 0); | |_____________________________^ help: consider replacing this with: `vec![0; 30]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:46:26 + --> tests/ui/slow_vector_initialization.rs:42:26 | LL | let mut extend_vec = Vec::with_capacity(30); | __________________________^ @@ -47,7 +47,7 @@ LL | | extend_vec.extend(repeat(0).take(30)); | |_________________________________________^ help: consider replacing this with: `vec![0; 30]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:55:20 + --> tests/ui/slow_vector_initialization.rs:51:20 | LL | let mut vec1 = Vec::with_capacity(len); | ____________________^ @@ -56,7 +56,7 @@ LL | | vec1.resize(len, 0); | |_______________________^ help: consider replacing this with: `vec![0; len]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:65:20 + --> tests/ui/slow_vector_initialization.rs:61:20 | LL | let mut vec3 = Vec::with_capacity(len - 10); | ____________________^ @@ -65,7 +65,7 @@ LL | | vec3.resize(len - 10, 0); | |____________________________^ help: consider replacing this with: `vec![0; len - 10]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:70:20 + --> tests/ui/slow_vector_initialization.rs:66:20 | LL | let mut vec4 = Vec::with_capacity(len); | ____________________^ @@ -74,7 +74,7 @@ LL | | vec4.resize(vec4.capacity(), 0); | |___________________________________^ help: consider replacing this with: `vec![0; len]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:76:12 + --> tests/ui/slow_vector_initialization.rs:72:12 | LL | vec1 = Vec::with_capacity(10); | ____________^ @@ -83,7 +83,7 @@ LL | | vec1.resize(10, 0); | |______________________^ help: consider replacing this with: `vec![0; 10]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:85:20 + --> tests/ui/slow_vector_initialization.rs:81:20 | LL | let mut vec1 = Vec::new(); | ____________________^ @@ -92,7 +92,7 @@ LL | | vec1.resize(len, 0); | |_______________________^ help: consider replacing this with: `vec![0; len]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:91:20 + --> tests/ui/slow_vector_initialization.rs:87:20 | LL | let mut vec3 = Vec::new(); | ____________________^ @@ -101,7 +101,7 @@ LL | | vec3.resize(len - 10, 0); | |____________________________^ help: consider replacing this with: `vec![0; len - 10]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:97:12 + --> tests/ui/slow_vector_initialization.rs:93:12 | LL | vec1 = Vec::new(); | ____________^ @@ -110,7 +110,7 @@ LL | | vec1.resize(10, 0); | |______________________^ help: consider replacing this with: `vec![0; 10]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:102:12 + --> tests/ui/slow_vector_initialization.rs:98:12 | LL | vec1 = vec![]; | ____________^ diff --git a/tests/ui/std_instead_of_core_unfixable.rs b/tests/ui/std_instead_of_core_unfixable.rs index 957f472a4544..5e71159ac6c5 100644 --- a/tests/ui/std_instead_of_core_unfixable.rs +++ b/tests/ui/std_instead_of_core_unfixable.rs @@ -1,5 +1,3 @@ -//@no-rustfix - #![warn(clippy::std_instead_of_core)] #![warn(clippy::std_instead_of_alloc)] #![allow(unused_imports)] diff --git a/tests/ui/std_instead_of_core_unfixable.stderr b/tests/ui/std_instead_of_core_unfixable.stderr index 0cdec56c9927..147b46022126 100644 --- a/tests/ui/std_instead_of_core_unfixable.stderr +++ b/tests/ui/std_instead_of_core_unfixable.stderr @@ -1,5 +1,5 @@ error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core_unfixable.rs:9:43 + --> tests/ui/std_instead_of_core_unfixable.rs:7:43 | LL | use std::{collections::HashMap, hash::Hash}; | ^^^^ @@ -9,7 +9,7 @@ LL | use std::{collections::HashMap, hash::Hash}; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core_unfixable.rs:15:22 + --> tests/ui/std_instead_of_core_unfixable.rs:13:22 | LL | use std::{error::Error, vec::Vec, fs::File}; | ^^^^^ @@ -17,7 +17,7 @@ LL | use std::{error::Error, vec::Vec, fs::File}; = help: consider importing the item from `core` error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core_unfixable.rs:15:34 + --> tests/ui/std_instead_of_core_unfixable.rs:13:34 | LL | use std::{error::Error, vec::Vec, fs::File}; | ^^^ diff --git a/tests/ui/str_to_string.fixed b/tests/ui/str_to_string.fixed index 5b76cf78f069..a8950ab70e56 100644 --- a/tests/ui/str_to_string.fixed +++ b/tests/ui/str_to_string.fixed @@ -1,10 +1,10 @@ #![warn(clippy::str_to_string)] fn main() { - let hello = "hello world".to_owned(); + let hello: String = "hello world".to_owned(); //~^ str_to_string - let msg = &hello[..]; + let msg: &str = &hello[..]; msg.to_owned(); //~^ str_to_string } @@ -19,7 +19,7 @@ fn issue16271(key: &[u8]) { }; } - let _value = t!(str::from_utf8(key)).to_owned(); + let _value: String = t!(str::from_utf8(key)).to_owned(); //~^ str_to_string } @@ -32,22 +32,27 @@ impl GenericWrapper { } fn issue16511(x: Option<&str>) { - let _ = x.map(ToOwned::to_owned); + let _: Option = x.map(str::to_owned); //~^ str_to_string - let _ = x.map(ToOwned::to_owned); + let _: Option = x.map(str::to_owned); //~^ str_to_string - let _ = ["a", "b"].iter().map(ToOwned::to_owned); - //~^ str_to_string + // This should not trigger the lint because ToOwned::to_owned would produce &str, not String. + let _: Vec = ["a", "b"].iter().map(ToString::to_string).collect(); fn mapper String>(f: F) -> String { f("hello") } - let _ = mapper(ToOwned::to_owned); + let _: String = mapper(str::to_owned); //~^ str_to_string - let w = GenericWrapper("hello"); - let _ = w.mapper(ToOwned::to_owned); + let w: GenericWrapper<&str> = GenericWrapper("hello"); + let _: String = w.mapper(str::to_owned); //~^ str_to_string } + +// No lint: non-str types should not trigger str_to_string. See #16569 +fn no_lint_non_str() { + let _: Vec = [1, 2].iter().map(i32::to_string).collect(); +} diff --git a/tests/ui/str_to_string.rs b/tests/ui/str_to_string.rs index f099eb29b1b5..5d78893f53f6 100644 --- a/tests/ui/str_to_string.rs +++ b/tests/ui/str_to_string.rs @@ -1,10 +1,10 @@ #![warn(clippy::str_to_string)] fn main() { - let hello = "hello world".to_string(); + let hello: String = "hello world".to_string(); //~^ str_to_string - let msg = &hello[..]; + let msg: &str = &hello[..]; msg.to_string(); //~^ str_to_string } @@ -19,7 +19,7 @@ macro_rules! t { }; } - let _value = t!(str::from_utf8(key)).to_string(); + let _value: String = t!(str::from_utf8(key)).to_string(); //~^ str_to_string } @@ -32,22 +32,27 @@ fn mapper U>(self, f: F) -> U { } fn issue16511(x: Option<&str>) { - let _ = x.map(ToString::to_string); + let _: Option = x.map(ToString::to_string); //~^ str_to_string - let _ = x.map(str::to_string); + let _: Option = x.map(str::to_string); //~^ str_to_string - let _ = ["a", "b"].iter().map(ToString::to_string); - //~^ str_to_string + // This should not trigger the lint because ToOwned::to_owned would produce &str, not String. + let _: Vec = ["a", "b"].iter().map(ToString::to_string).collect(); fn mapper String>(f: F) -> String { f("hello") } - let _ = mapper(ToString::to_string); + let _: String = mapper(ToString::to_string); //~^ str_to_string - let w = GenericWrapper("hello"); - let _ = w.mapper(ToString::to_string); + let w: GenericWrapper<&str> = GenericWrapper("hello"); + let _: String = w.mapper(ToString::to_string); //~^ str_to_string } + +// No lint: non-str types should not trigger str_to_string. See #16569 +fn no_lint_non_str() { + let _: Vec = [1, 2].iter().map(i32::to_string).collect(); +} diff --git a/tests/ui/str_to_string.stderr b/tests/ui/str_to_string.stderr index 296b8e36f28c..cd4db83e6370 100644 --- a/tests/ui/str_to_string.stderr +++ b/tests/ui/str_to_string.stderr @@ -1,8 +1,8 @@ error: `to_string()` called on a `&str` - --> tests/ui/str_to_string.rs:4:17 + --> tests/ui/str_to_string.rs:4:25 | -LL | let hello = "hello world".to_string(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"hello world".to_owned()` +LL | let hello: String = "hello world".to_string(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"hello world".to_owned()` | = note: `-D clippy::str-to-string` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::str_to_string)]` @@ -14,40 +14,34 @@ LL | msg.to_string(); | ^^^^^^^^^^^^^^^ help: try: `msg.to_owned()` error: `to_string()` called on a `&str` - --> tests/ui/str_to_string.rs:22:18 + --> tests/ui/str_to_string.rs:22:26 | -LL | let _value = t!(str::from_utf8(key)).to_string(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t!(str::from_utf8(key)).to_owned()` +LL | let _value: String = t!(str::from_utf8(key)).to_string(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t!(str::from_utf8(key)).to_owned()` error: `ToString::to_string` used as `&str` to `String` converter - --> tests/ui/str_to_string.rs:35:19 + --> tests/ui/str_to_string.rs:35:35 | -LL | let _ = x.map(ToString::to_string); - | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` +LL | let _: Option = x.map(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `str::to_owned` error: `ToString::to_string` used as `&str` to `String` converter - --> tests/ui/str_to_string.rs:38:19 + --> tests/ui/str_to_string.rs:38:35 | -LL | let _ = x.map(str::to_string); - | ^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` +LL | let _: Option = x.map(str::to_string); + | ^^^^^^^^^^^^^^ help: try: `str::to_owned` error: `ToString::to_string` used as `&str` to `String` converter - --> tests/ui/str_to_string.rs:41:35 + --> tests/ui/str_to_string.rs:47:28 | -LL | let _ = ["a", "b"].iter().map(ToString::to_string); - | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` +LL | let _: String = mapper(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `str::to_owned` error: `ToString::to_string` used as `&str` to `String` converter - --> tests/ui/str_to_string.rs:47:20 + --> tests/ui/str_to_string.rs:51:30 | -LL | let _ = mapper(ToString::to_string); - | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` +LL | let _: String = w.mapper(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `str::to_owned` -error: `ToString::to_string` used as `&str` to `String` converter - --> tests/ui/str_to_string.rs:51:22 - | -LL | let _ = w.mapper(ToString::to_string); - | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/string_add.rs b/tests/ui/string_add.rs index 5c7d13ebcd58..50627a1921a4 100644 --- a/tests/ui/string_add.rs +++ b/tests/ui/string_add.rs @@ -1,5 +1,5 @@ //@aux-build:proc_macros.rs -//@no-rustfix + extern crate proc_macros; use proc_macros::external; diff --git a/tests/ui/track-diagnostics-clippy.fixed b/tests/ui/track-diagnostics-clippy.fixed new file mode 100644 index 000000000000..f25ffa7e9afd --- /dev/null +++ b/tests/ui/track-diagnostics-clippy.fixed @@ -0,0 +1,22 @@ +//@compile-flags: -Z track-diagnostics + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +//@normalize-stderr-test: ".rs:\d+:\d+" -> ".rs:LL:CC" +//@normalize-stderr-test: "src/tools/clippy/" -> "" + +#![warn(clippy::let_and_return, clippy::unnecessary_cast)] + +fn main() { + // Check the provenance of a lint sent through `LintContext::span_lint()` + let a = 3u32; + let b = a; + //~^ unnecessary_cast + + // Check the provenance of a lint sent through `TyCtxt::node_span_lint()` + let c = { + + 42 + //~^ let_and_return + }; +} diff --git a/tests/ui/track-diagnostics-clippy.rs b/tests/ui/track-diagnostics-clippy.rs index 3bae23f19849..8fc1d996c002 100644 --- a/tests/ui/track-diagnostics-clippy.rs +++ b/tests/ui/track-diagnostics-clippy.rs @@ -1,5 +1,4 @@ //@compile-flags: -Z track-diagnostics -//@no-rustfix // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. diff --git a/tests/ui/transmute_null_to_fn.rs b/tests/ui/transmute_null_to_fn.rs index 4712374af934..9ce097d124ab 100644 --- a/tests/ui/transmute_null_to_fn.rs +++ b/tests/ui/transmute_null_to_fn.rs @@ -41,7 +41,4 @@ fn issue_11485() { } } -fn main() { - one_liners(); - transmute_const(); -} +fn main() {} diff --git a/tests/ui/transmute_ref_to_ref.fixed b/tests/ui/transmute_ref_to_ref.fixed new file mode 100644 index 000000000000..0ec59ea810ae --- /dev/null +++ b/tests/ui/transmute_ref_to_ref.fixed @@ -0,0 +1,38 @@ +#![deny(clippy::transmute_ptr_to_ptr)] +#![allow(dead_code, clippy::missing_transmute_annotations, clippy::cast_slice_different_sizes)] + +fn main() { + unsafe { + let single_u64: &[u64] = &[0xDEAD_BEEF_DEAD_BEEF]; + let bools: &[bool] = unsafe { &*(single_u64 as *const [u64] as *const [bool]) }; + //~^ transmute_ptr_to_ptr + + let a: &[u32] = &[0x12345678, 0x90ABCDEF, 0xFEDCBA09, 0x87654321]; + let b: &[u8] = unsafe { &*(a as *const [u32] as *const [u8]) }; + //~^ transmute_ptr_to_ptr + + let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8]; + let alt_slice: &[u32] = unsafe { &*(bytes as *const [u8] as *const [u32]) }; + //~^ transmute_ptr_to_ptr + } +} + +fn issue16104(make_ptr: fn() -> *const u32) { + macro_rules! call { + ($x:expr) => { + $x() + }; + } + macro_rules! take_ref { + ($x:expr) => { + &$x + }; + } + + unsafe { + let _: *const f32 = call!(make_ptr).cast::(); + //~^ transmute_ptr_to_ptr + let _: &f32 = &*(take_ref!(1u32) as *const u32 as *const f32); + //~^ transmute_ptr_to_ptr + } +} diff --git a/tests/ui/transmute_ref_to_ref.rs b/tests/ui/transmute_ref_to_ref.rs index ed8fb8083291..78f3d1fe0bb2 100644 --- a/tests/ui/transmute_ref_to_ref.rs +++ b/tests/ui/transmute_ref_to_ref.rs @@ -1,7 +1,5 @@ -//@no-rustfix - #![deny(clippy::transmute_ptr_to_ptr)] -#![allow(dead_code, clippy::missing_transmute_annotations)] +#![allow(dead_code, clippy::missing_transmute_annotations, clippy::cast_slice_different_sizes)] fn main() { unsafe { diff --git a/tests/ui/transmute_ref_to_ref.stderr b/tests/ui/transmute_ref_to_ref.stderr index 1b845ef859d8..13ee64574f7b 100644 --- a/tests/ui/transmute_ref_to_ref.stderr +++ b/tests/ui/transmute_ref_to_ref.stderr @@ -1,29 +1,29 @@ error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref.rs:9:39 + --> tests/ui/transmute_ref_to_ref.rs:7:39 | LL | let bools: &[bool] = unsafe { std::mem::transmute(single_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(single_u64 as *const [u64] as *const [bool])` | note: the lint level is defined here - --> tests/ui/transmute_ref_to_ref.rs:3:9 + --> tests/ui/transmute_ref_to_ref.rs:1:9 | LL | #![deny(clippy::transmute_ptr_to_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref.rs:13:33 + --> tests/ui/transmute_ref_to_ref.rs:11:33 | LL | let b: &[u8] = unsafe { std::mem::transmute(a) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const [u32] as *const [u8])` error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref.rs:17:42 + --> tests/ui/transmute_ref_to_ref.rs:15:42 | LL | let alt_slice: &[u32] = unsafe { std::mem::transmute(bytes) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])` error: transmute from a pointer to a pointer - --> tests/ui/transmute_ref_to_ref.rs:35:29 + --> tests/ui/transmute_ref_to_ref.rs:33:29 | LL | let _: *const f32 = std::mem::transmute(call!(make_ptr)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL + let _: *const f32 = call!(make_ptr).cast::(); | error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref.rs:37:23 + --> tests/ui/transmute_ref_to_ref.rs:35:23 | LL | let _: &f32 = std::mem::transmute(take_ref!(1u32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(take_ref!(1u32) as *const u32 as *const f32)` diff --git a/tests/ui/transmute_ref_to_ref_no_std.fixed b/tests/ui/transmute_ref_to_ref_no_std.fixed new file mode 100644 index 000000000000..3a1c75f16854 --- /dev/null +++ b/tests/ui/transmute_ref_to_ref_no_std.fixed @@ -0,0 +1,30 @@ +#![deny(clippy::transmute_ptr_to_ptr)] +#![allow(dead_code, clippy::missing_transmute_annotations, clippy::cast_slice_different_sizes)] +#![feature(lang_items)] +#![no_std] + +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +fn main() { + unsafe { + let single_u64: &[u64] = &[0xDEAD_BEEF_DEAD_BEEF]; + let bools: &[bool] = unsafe { &*(single_u64 as *const [u64] as *const [bool]) }; + //~^ transmute_ptr_to_ptr + + let a: &[u32] = &[0x12345678, 0x90ABCDEF, 0xFEDCBA09, 0x87654321]; + let b: &[u8] = unsafe { &*(a as *const [u32] as *const [u8]) }; + //~^ transmute_ptr_to_ptr + + let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8]; + let alt_slice: &[u32] = unsafe { &*(bytes as *const [u8] as *const [u32]) }; + //~^ transmute_ptr_to_ptr + } +} diff --git a/tests/ui/transmute_ref_to_ref_no_std.rs b/tests/ui/transmute_ref_to_ref_no_std.rs index faa776f2afce..7ed885bbbb07 100644 --- a/tests/ui/transmute_ref_to_ref_no_std.rs +++ b/tests/ui/transmute_ref_to_ref_no_std.rs @@ -1,7 +1,5 @@ -//@no-rustfix - #![deny(clippy::transmute_ptr_to_ptr)] -#![allow(dead_code, clippy::missing_transmute_annotations)] +#![allow(dead_code, clippy::missing_transmute_annotations, clippy::cast_slice_different_sizes)] #![feature(lang_items)] #![no_std] diff --git a/tests/ui/transmute_ref_to_ref_no_std.stderr b/tests/ui/transmute_ref_to_ref_no_std.stderr index 9aa9ed928a4d..136a9b21fb9e 100644 --- a/tests/ui/transmute_ref_to_ref_no_std.stderr +++ b/tests/ui/transmute_ref_to_ref_no_std.stderr @@ -1,23 +1,23 @@ error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref_no_std.rs:21:39 + --> tests/ui/transmute_ref_to_ref_no_std.rs:19:39 | LL | let bools: &[bool] = unsafe { core::mem::transmute(single_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(single_u64 as *const [u64] as *const [bool])` | note: the lint level is defined here - --> tests/ui/transmute_ref_to_ref_no_std.rs:3:9 + --> tests/ui/transmute_ref_to_ref_no_std.rs:1:9 | LL | #![deny(clippy::transmute_ptr_to_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref_no_std.rs:25:33 + --> tests/ui/transmute_ref_to_ref_no_std.rs:23:33 | LL | let b: &[u8] = unsafe { core::mem::transmute(a) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const [u32] as *const [u8])` error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref_no_std.rs:29:42 + --> tests/ui/transmute_ref_to_ref_no_std.rs:27:42 | LL | let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])` diff --git a/tests/ui/transmuting_null.rs b/tests/ui/transmuting_null.rs index efa4c5cfdc2d..c2de798ab308 100644 --- a/tests/ui/transmuting_null.rs +++ b/tests/ui/transmuting_null.rs @@ -57,10 +57,4 @@ fn transmute_pointer_creators() { } } -fn main() { - one_liners(); - transmute_const(); - transmute_const_int(); - transumute_single_expr_blocks(); - transmute_pointer_creators(); -} +fn main() {} diff --git a/tests/ui/try_err.fixed b/tests/ui/try_err.fixed index ea509f9a2da8..bec366f4fd60 100644 --- a/tests/ui/try_err.fixed +++ b/tests/ui/try_err.fixed @@ -107,24 +107,17 @@ fn calling_macro() -> Result { Ok(5) } -fn main() { - basic_test().unwrap(); - into_test().unwrap(); - negative_test().unwrap(); - closure_matches_test().unwrap(); - closure_into_test().unwrap(); - calling_macro().unwrap(); - - // We don't want to lint in external macros - external! { - pub fn try_err_fn() -> Result { - let err: i32 = 1; - // To avoid warnings during rustfix - if true { Err(err)? } else { Ok(2) } - } +// We don't want to lint in external macros +external! { + pub fn try_err_fn() -> Result { + let err: i32 = 1; + // To avoid warnings during rustfix + if true { Err(err)? } else { Ok(2) } } } +fn main() {} + #[inline_macros] pub fn macro_inside(fail: bool) -> Result { if fail { diff --git a/tests/ui/try_err.rs b/tests/ui/try_err.rs index 295f7bd7089b..9c10acd2ce0a 100644 --- a/tests/ui/try_err.rs +++ b/tests/ui/try_err.rs @@ -107,24 +107,17 @@ fn calling_macro() -> Result { Ok(5) } -fn main() { - basic_test().unwrap(); - into_test().unwrap(); - negative_test().unwrap(); - closure_matches_test().unwrap(); - closure_into_test().unwrap(); - calling_macro().unwrap(); - - // We don't want to lint in external macros - external! { - pub fn try_err_fn() -> Result { - let err: i32 = 1; - // To avoid warnings during rustfix - if true { Err(err)? } else { Ok(2) } - } +// We don't want to lint in external macros +external! { + pub fn try_err_fn() -> Result { + let err: i32 = 1; + // To avoid warnings during rustfix + if true { Err(err)? } else { Ok(2) } } } +fn main() {} + #[inline_macros] pub fn macro_inside(fail: bool) -> Result { if fail { diff --git a/tests/ui/try_err.stderr b/tests/ui/try_err.stderr index 50c2b092d6c8..3ca51e9d8891 100644 --- a/tests/ui/try_err.stderr +++ b/tests/ui/try_err.stderr @@ -45,31 +45,31 @@ LL | Err(_) => Err(inline!(1))?, = note: this error originates in the macro `__inline_mac_fn_calling_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:131:9 + --> tests/ui/try_err.rs:124:9 | LL | Err(inline!(inline!(String::from("aasdfasdfasdfa"))))?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Err(inline!(inline!(String::from("aasdfasdfasdfa"))))` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:139:9 + --> tests/ui/try_err.rs:132:9 | LL | Err(io::ErrorKind::WriteZero)? | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Poll::Ready(Err(io::ErrorKind::WriteZero.into()))` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:142:9 + --> tests/ui/try_err.rs:135:9 | LL | Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))? | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error")))` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:151:9 + --> tests/ui/try_err.rs:144:9 | LL | Err(io::ErrorKind::NotFound)? | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into())))` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:161:16 + --> tests/ui/try_err.rs:154:16 | LL | return Err(42)?; | ^^^^^^^^ help: try: `Err(42)` diff --git a/tests/ui/unchecked_time_subtraction.fixed b/tests/ui/unchecked_time_subtraction.fixed index 830b737f18e7..5fe51dd5ba7c 100644 --- a/tests/ui/unchecked_time_subtraction.fixed +++ b/tests/ui/unchecked_time_subtraction.fixed @@ -25,8 +25,7 @@ fn main() { let _ = dur1.checked_sub(dur2).unwrap(); //~^ unchecked_time_subtraction - let _ = Duration::from_secs(10).checked_sub(Duration::from_secs(5)).unwrap(); - //~^ unchecked_time_subtraction + let _ = Duration::from_secs(10) - Duration::from_secs(5); let _ = second.checked_sub(dur1).unwrap(); //~^ unchecked_time_subtraction @@ -55,8 +54,17 @@ fn issue16234() { }; } - duration!(0).checked_sub(duration!(1)).unwrap(); + let d = duration!(0); + d.checked_sub(duration!(1)).unwrap(); //~^ unchecked_time_subtraction - let _ = duration!(0).checked_sub(duration!(1)).unwrap(); + let _ = d.checked_sub(duration!(1)).unwrap(); //~^ unchecked_time_subtraction } + +fn issue16499() { + let _ = Duration::from_millis(2) - Duration::from_millis(1); + let _ = Duration::new(10000, 0) - Duration::from_secs(1); + let _ = Duration::from_nanos_u128(1000) - Duration::from_nanos(100); + let _ = Duration::from_secs_f32(1.5) - Duration::from_secs_f64(0.5); + let _ = Duration::from_mins(70) - Duration::from_hours(1); +} diff --git a/tests/ui/unchecked_time_subtraction.rs b/tests/ui/unchecked_time_subtraction.rs index e41860157c41..466d96a9a606 100644 --- a/tests/ui/unchecked_time_subtraction.rs +++ b/tests/ui/unchecked_time_subtraction.rs @@ -26,7 +26,6 @@ fn main() { //~^ unchecked_time_subtraction let _ = Duration::from_secs(10) - Duration::from_secs(5); - //~^ unchecked_time_subtraction let _ = second - dur1; //~^ unchecked_time_subtraction @@ -55,8 +54,17 @@ macro_rules! duration { }; } - duration!(0).sub(duration!(1)); + let d = duration!(0); + d.sub(duration!(1)); //~^ unchecked_time_subtraction - let _ = duration!(0) - duration!(1); + let _ = d - duration!(1); //~^ unchecked_time_subtraction } + +fn issue16499() { + let _ = Duration::from_millis(2) - Duration::from_millis(1); + let _ = Duration::new(10000, 0) - Duration::from_secs(1); + let _ = Duration::from_nanos_u128(1000) - Duration::from_nanos(100); + let _ = Duration::from_secs_f32(1.5) - Duration::from_secs_f64(0.5); + let _ = Duration::from_mins(70) - Duration::from_hours(1); +} diff --git a/tests/ui/unchecked_time_subtraction.stderr b/tests/ui/unchecked_time_subtraction.stderr index fa4bd1db81ae..b71e2c474f2e 100644 --- a/tests/ui/unchecked_time_subtraction.stderr +++ b/tests/ui/unchecked_time_subtraction.stderr @@ -32,31 +32,25 @@ LL | let _ = dur1 - dur2; | ^^^^^^^^^^^ help: try: `dur1.checked_sub(dur2).unwrap()` error: unchecked subtraction of a `Duration` - --> tests/ui/unchecked_time_subtraction.rs:28:13 - | -LL | let _ = Duration::from_secs(10) - Duration::from_secs(5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::from_secs(10).checked_sub(Duration::from_secs(5)).unwrap()` - -error: unchecked subtraction of a `Duration` - --> tests/ui/unchecked_time_subtraction.rs:31:13 + --> tests/ui/unchecked_time_subtraction.rs:30:13 | LL | let _ = second - dur1; | ^^^^^^^^^^^^^ help: try: `second.checked_sub(dur1).unwrap()` error: unchecked subtraction of a `Duration` - --> tests/ui/unchecked_time_subtraction.rs:35:13 + --> tests/ui/unchecked_time_subtraction.rs:34:13 | LL | let _ = 2 * dur1 - dur2; | ^^^^^^^^^^^^^^^ help: try: `(2 * dur1).checked_sub(dur2).unwrap()` error: unchecked subtraction of a `Duration` - --> tests/ui/unchecked_time_subtraction.rs:42:5 + --> tests/ui/unchecked_time_subtraction.rs:41:5 | LL | Duration::ZERO.sub(Duration::MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::ZERO.checked_sub(Duration::MAX).unwrap()` error: unchecked subtraction of a `Duration` - --> tests/ui/unchecked_time_subtraction.rs:45:13 + --> tests/ui/unchecked_time_subtraction.rs:44:13 | LL | let _ = Duration::ZERO - Duration::MAX; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::ZERO.checked_sub(Duration::MAX).unwrap()` @@ -64,14 +58,14 @@ LL | let _ = Duration::ZERO - Duration::MAX; error: unchecked subtraction of a `Duration` --> tests/ui/unchecked_time_subtraction.rs:58:5 | -LL | duration!(0).sub(duration!(1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `duration!(0).checked_sub(duration!(1)).unwrap()` +LL | d.sub(duration!(1)); + | ^^^^^^^^^^^^^^^^^^^ help: try: `d.checked_sub(duration!(1)).unwrap()` error: unchecked subtraction of a `Duration` --> tests/ui/unchecked_time_subtraction.rs:60:13 | -LL | let _ = duration!(0) - duration!(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `duration!(0).checked_sub(duration!(1)).unwrap()` +LL | let _ = d - duration!(1); + | ^^^^^^^^^^^^^^^^ help: try: `d.checked_sub(duration!(1)).unwrap()` -error: aborting due to 12 previous errors +error: aborting due to 11 previous errors diff --git a/tests/ui/unchecked_time_subtraction_unfixable.rs b/tests/ui/unchecked_time_subtraction_unfixable.rs index 4b6a5ca15620..6c3777eec915 100644 --- a/tests/ui/unchecked_time_subtraction_unfixable.rs +++ b/tests/ui/unchecked_time_subtraction_unfixable.rs @@ -20,3 +20,12 @@ fn main() { //~^ unchecked_time_subtraction //~| unchecked_time_subtraction } + +fn issue16499() { + let _ = Duration::from_millis(1) - Duration::from_millis(2); + //~^ unchecked_time_subtraction + let _ = Duration::from_millis(1) - Duration::from_mins(2); + //~^ unchecked_time_subtraction + let _ = Duration::from_nanos(1) - Duration::from_secs(1); + //~^ unchecked_time_subtraction +} diff --git a/tests/ui/unchecked_time_subtraction_unfixable.stderr b/tests/ui/unchecked_time_subtraction_unfixable.stderr index 017e5b1c7c11..a48676bf5c16 100644 --- a/tests/ui/unchecked_time_subtraction_unfixable.stderr +++ b/tests/ui/unchecked_time_subtraction_unfixable.stderr @@ -25,5 +25,29 @@ error: unchecked subtraction of a `Duration` LL | let _ = instant1 - dur2 - dur3; | ^^^^^^^^^^^^^^^ help: try: `instant1.checked_sub(dur2).unwrap()` -error: aborting due to 4 previous errors +error: unchecked subtraction of two `Duration` that will underflow + --> tests/ui/unchecked_time_subtraction_unfixable.rs:25:13 + | +LL | let _ = Duration::from_millis(1) - Duration::from_millis(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this is intentional, consider allowing the lint + +error: unchecked subtraction of two `Duration` that will underflow + --> tests/ui/unchecked_time_subtraction_unfixable.rs:27:13 + | +LL | let _ = Duration::from_millis(1) - Duration::from_mins(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this is intentional, consider allowing the lint + +error: unchecked subtraction of two `Duration` that will underflow + --> tests/ui/unchecked_time_subtraction_unfixable.rs:29:13 + | +LL | let _ = Duration::from_nanos(1) - Duration::from_secs(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this is intentional, consider allowing the lint + +error: aborting due to 7 previous errors diff --git a/tests/ui/unconditional_recursion.rs b/tests/ui/unconditional_recursion.rs index e4dd33a8eeea..20b4198d6392 100644 --- a/tests/ui/unconditional_recursion.rs +++ b/tests/ui/unconditional_recursion.rs @@ -1,5 +1,3 @@ -//@no-rustfix - #![warn(clippy::unconditional_recursion)] #![allow( clippy::partialeq_ne_impl, diff --git a/tests/ui/unconditional_recursion.stderr b/tests/ui/unconditional_recursion.stderr index c6eaa6a0775c..5edccf9593da 100644 --- a/tests/ui/unconditional_recursion.stderr +++ b/tests/ui/unconditional_recursion.stderr @@ -1,5 +1,5 @@ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:51:5 + --> tests/ui/unconditional_recursion.rs:49:5 | LL | fn ne(&self, other: &Self) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -12,7 +12,7 @@ LL | self.ne(other) = help: to override `-D warnings` add `#[allow(unconditional_recursion)]` error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:56:5 + --> tests/ui/unconditional_recursion.rs:54:5 | LL | fn eq(&self, other: &Self) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -23,7 +23,7 @@ LL | self.eq(other) = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:235:5 + --> tests/ui/unconditional_recursion.rs:233:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -34,7 +34,7 @@ LL | self.to_string() = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:245:5 + --> tests/ui/unconditional_recursion.rs:243:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -45,7 +45,7 @@ LL | x.to_string() = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:256:5 + --> tests/ui/unconditional_recursion.rs:254:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -56,7 +56,7 @@ LL | (self as &Self).to_string() = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:17:5 + --> tests/ui/unconditional_recursion.rs:15:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | @@ -66,7 +66,7 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:20:9 + --> tests/ui/unconditional_recursion.rs:18:9 | LL | self != other | ^^^^^^^^^^^^^ @@ -74,7 +74,7 @@ LL | self != other = help: to override `-D warnings` add `#[allow(clippy::unconditional_recursion)]` error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:22:5 + --> tests/ui/unconditional_recursion.rs:20:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -84,13 +84,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:25:9 + --> tests/ui/unconditional_recursion.rs:23:9 | LL | self == other | ^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:35:5 + --> tests/ui/unconditional_recursion.rs:33:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | @@ -99,13 +99,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:37:9 + --> tests/ui/unconditional_recursion.rs:35:9 | LL | self != &Foo2::B // no error here | ^^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:39:5 + --> tests/ui/unconditional_recursion.rs:37:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -114,13 +114,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:41:9 + --> tests/ui/unconditional_recursion.rs:39:9 | LL | self == &Foo2::B // no error here | ^^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:51:5 + --> tests/ui/unconditional_recursion.rs:49:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | @@ -130,13 +130,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:54:9 + --> tests/ui/unconditional_recursion.rs:52:9 | LL | self.ne(other) | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:56:5 + --> tests/ui/unconditional_recursion.rs:54:5 | LL | / fn eq(&self, other: &Self) -> bool { ... | @@ -144,13 +144,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:60:9 + --> tests/ui/unconditional_recursion.rs:58:9 | LL | self.eq(other) | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:102:5 + --> tests/ui/unconditional_recursion.rs:100:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | @@ -160,13 +160,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:105:9 + --> tests/ui/unconditional_recursion.rs:103:9 | LL | other != self | ^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:107:5 + --> tests/ui/unconditional_recursion.rs:105:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -176,13 +176,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:110:9 + --> tests/ui/unconditional_recursion.rs:108:9 | LL | other == self | ^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:118:5 + --> tests/ui/unconditional_recursion.rs:116:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | @@ -193,13 +193,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:121:9 + --> tests/ui/unconditional_recursion.rs:119:9 | LL | other != other | ^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> tests/ui/unconditional_recursion.rs:121:9 + --> tests/ui/unconditional_recursion.rs:119:9 | LL | other != other | ^^^^^^^^^^^^^^ @@ -207,7 +207,7 @@ LL | other != other = note: `#[deny(clippy::eq_op)]` on by default error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:124:5 + --> tests/ui/unconditional_recursion.rs:122:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -218,19 +218,19 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:127:9 + --> tests/ui/unconditional_recursion.rs:125:9 | LL | other == other | ^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/unconditional_recursion.rs:127:9 + --> tests/ui/unconditional_recursion.rs:125:9 | LL | other == other | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:135:5 + --> tests/ui/unconditional_recursion.rs:133:5 | LL | / fn ne(&self, _other: &Self) -> bool { LL | | @@ -241,19 +241,19 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:138:9 + --> tests/ui/unconditional_recursion.rs:136:9 | LL | self != self | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> tests/ui/unconditional_recursion.rs:138:9 + --> tests/ui/unconditional_recursion.rs:136:9 | LL | self != self | ^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:141:5 + --> tests/ui/unconditional_recursion.rs:139:5 | LL | / fn eq(&self, _other: &Self) -> bool { LL | | @@ -264,19 +264,19 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:144:9 + --> tests/ui/unconditional_recursion.rs:142:9 | LL | self == self | ^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/unconditional_recursion.rs:144:9 + --> tests/ui/unconditional_recursion.rs:142:9 | LL | self == self | ^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:171:13 + --> tests/ui/unconditional_recursion.rs:169:13 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -289,7 +289,7 @@ LL | impl_partial_eq!(S5); | -------------------- in this macro invocation | note: recursive call site - --> tests/ui/unconditional_recursion.rs:174:17 + --> tests/ui/unconditional_recursion.rs:172:17 | LL | self == other | ^^^^^^^^^^^^^ @@ -299,7 +299,7 @@ LL | impl_partial_eq!(S5); = note: this error originates in the macro `impl_partial_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:201:5 + --> tests/ui/unconditional_recursion.rs:199:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -311,13 +311,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:206:9 + --> tests/ui/unconditional_recursion.rs:204:9 | LL | mine == theirs | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:271:5 + --> tests/ui/unconditional_recursion.rs:269:5 | LL | / fn new() -> Self { LL | | @@ -327,13 +327,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:274:9 + --> tests/ui/unconditional_recursion.rs:272:9 | LL | Self::default() | ^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:311:5 + --> tests/ui/unconditional_recursion.rs:309:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -345,13 +345,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:316:9 + --> tests/ui/unconditional_recursion.rs:314:9 | LL | mine.eq(theirs) | ^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:383:5 + --> tests/ui/unconditional_recursion.rs:381:5 | LL | / fn from(f: BadFromTy1<'a>) -> Self { LL | | @@ -360,13 +360,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:385:9 + --> tests/ui/unconditional_recursion.rs:383:9 | LL | f.into() | ^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:393:5 + --> tests/ui/unconditional_recursion.rs:391:5 | LL | / fn from(f: BadFromTy2<'a>) -> Self { LL | | @@ -375,7 +375,7 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:395:9 + --> tests/ui/unconditional_recursion.rs:393:9 | LL | Into::into(f) | ^^^^^^^^^^^^^ diff --git a/tests/ui/unicode.fixed b/tests/ui/unicode.fixed index 9234b440d964..8fd25d1b48f5 100644 --- a/tests/ui/unicode.fixed +++ b/tests/ui/unicode.fixed @@ -60,7 +60,4 @@ mod non_ascii_literal { } } -fn main() { - zero(); - canon(); -} +fn main() {} diff --git a/tests/ui/unicode.rs b/tests/ui/unicode.rs index ada8bac8e049..6447a704a356 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -60,7 +60,4 @@ fn denied() { } } -fn main() { - zero(); - canon(); -} +fn main() {} diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index 7b609d9163a9..6e999a48595c 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -238,9 +238,7 @@ fn tester(fn_arg: i32) { } } -fn main() { - tester(42); -} +fn main() {} #[clippy::msrv = "1.57"] fn _under_msrv() { diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index 14e0b6caabc0..58bbe41b97bf 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -243,9 +243,7 @@ fn tester(fn_arg: i32) { } } -fn main() { - tester(42); -} +fn main() {} #[clippy::msrv = "1.57"] fn _under_msrv() { diff --git a/tests/ui/uninlined_format_args.stderr b/tests/ui/uninlined_format_args.stderr index 7e62a095eadf..45994fdc9588 100644 --- a/tests/ui/uninlined_format_args.stderr +++ b/tests/ui/uninlined_format_args.stderr @@ -836,7 +836,7 @@ LL + panic!("p3 {local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:259:5 + --> tests/ui/uninlined_format_args.rs:257:5 | LL | println!("expand='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -848,7 +848,7 @@ LL + println!("expand='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:362:5 + --> tests/ui/uninlined_format_args.rs:360:5 | LL | usr_println!(true, "val='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -860,7 +860,7 @@ LL + usr_println!(true, "val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:364:5 + --> tests/ui/uninlined_format_args.rs:362:5 | LL | usr_println!(true, "{}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -872,7 +872,7 @@ LL + usr_println!(true, "{local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:366:5 + --> tests/ui/uninlined_format_args.rs:364:5 | LL | usr_println!(true, "{:#010x}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -884,7 +884,7 @@ LL + usr_println!(true, "{local_i32:#010x}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:368:5 + --> tests/ui/uninlined_format_args.rs:366:5 | LL | usr_println!(true, "{:.1}", local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 4208efad6774..3cba0735b362 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -147,10 +147,7 @@ fn proc_macro() { with_span!(span taking_multiple_units(unsafe { (); }, 'x: loop { break 'x (); })); } -fn main() { - bad(); - ok(); -} +fn main() {} fn issue14857() { let fn_take_unit = |_: ()| {}; diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index eb7c56c45b59..ed1310863157 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -200,19 +200,19 @@ LL + Some(()) | error: passing a unit value to a function - --> tests/ui/unit_arg.rs:171:5 + --> tests/ui/unit_arg.rs:168:5 | LL | fn_take_unit(mac!(def)); | ^^^^^^^^^^^^^^^^^^^^^^^ error: passing a unit value to a function - --> tests/ui/unit_arg.rs:173:5 + --> tests/ui/unit_arg.rs:170:5 | LL | fn_take_unit(mac!(func Default::default)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: passing a unit value to a function - --> tests/ui/unit_arg.rs:175:5 + --> tests/ui/unit_arg.rs:172:5 | LL | fn_take_unit(mac!(nonempty_block Default::default())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unit_arg_fixable.fixed b/tests/ui/unit_arg_fixable.fixed index 03353a14081b..3bbc62ca0bca 100644 --- a/tests/ui/unit_arg_fixable.fixed +++ b/tests/ui/unit_arg_fixable.fixed @@ -29,9 +29,7 @@ fn bad() { fn taking_two_units(a: (), b: ()) {} fn taking_three_units(a: (), b: (), c: ()) {} -fn main() { - bad(); -} +fn main() {} fn issue14857() { let fn_take_unit = |_: ()| {}; diff --git a/tests/ui/unit_arg_fixable.rs b/tests/ui/unit_arg_fixable.rs index 03fd96efdf90..12d6cbcf61d9 100644 --- a/tests/ui/unit_arg_fixable.rs +++ b/tests/ui/unit_arg_fixable.rs @@ -26,9 +26,7 @@ fn bad() { fn taking_two_units(a: (), b: ()) {} fn taking_three_units(a: (), b: (), c: ()) {} -fn main() { - bad(); -} +fn main() {} fn issue14857() { let fn_take_unit = |_: ()| {}; diff --git a/tests/ui/unit_arg_fixable.stderr b/tests/ui/unit_arg_fixable.stderr index 0e348c81c0d4..9f6bc671bf55 100644 --- a/tests/ui/unit_arg_fixable.stderr +++ b/tests/ui/unit_arg_fixable.stderr @@ -50,7 +50,7 @@ LL ~ taking_three_units((), (), ()); | error: passing a unit value to a function - --> tests/ui/unit_arg_fixable.rs:35:5 + --> tests/ui/unit_arg_fixable.rs:33:5 | LL | fn_take_unit(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL + fn_take_unit(()); | error: passing a unit value to a function - --> tests/ui/unit_arg_fixable.rs:49:5 + --> tests/ui/unit_arg_fixable.rs:47:5 | LL | fn_take_unit(another_mac!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,7 +74,7 @@ LL ~ fn_take_unit(()); | error: passing a unit value to a function - --> tests/ui/unit_arg_fixable.rs:51:5 + --> tests/ui/unit_arg_fixable.rs:49:5 | LL | fn_take_unit(another_mac!(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -86,7 +86,7 @@ LL ~ fn_take_unit(()); | error: passing a unit value to a function - --> tests/ui/unit_arg_fixable.rs:60:5 + --> tests/ui/unit_arg_fixable.rs:58:5 | LL | fn_take_unit(mac!(nondef Default::default())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -98,7 +98,7 @@ LL + fn_take_unit(mac!(nondef ())); | error: passing a unit value to a function - --> tests/ui/unit_arg_fixable.rs:62:5 + --> tests/ui/unit_arg_fixable.rs:60:5 | LL | fn_take_unit(mac!(empty_block)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -110,7 +110,7 @@ LL ~ fn_take_unit(()); | error: passing a unit value to a function - --> tests/ui/unit_arg_fixable.rs:69:5 + --> tests/ui/unit_arg_fixable.rs:67:5 | LL | fn_take_unit(def()); | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index 91ff4b9ee771..c6e9bc3cba07 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -133,12 +133,13 @@ fn main() { aaa(); //~^ unnecessary_cast let x = aaa(); - aaa(); + x; + //~^ unnecessary_cast + bbb(); //~^ unnecessary_cast - // Will not lint currently. - bbb() as u32; let x = bbb(); - bbb() as u32; + x; + //~^ unnecessary_cast let i8_ptr: *const i8 = &1; let u8_ptr: *const u8 = &1; diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index 5444a914db16..6936a23d4286 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -133,12 +133,13 @@ pub fn $a() -> $b { aaa() as u32; //~^ unnecessary_cast let x = aaa(); - aaa() as u32; + x as u32; //~^ unnecessary_cast - // Will not lint currently. bbb() as u32; + //~^ unnecessary_cast let x = bbb(); - bbb() as u32; + x as u32; + //~^ unnecessary_cast let i8_ptr: *const i8 = &1; let u8_ptr: *const u8 = &1; diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index 3e3c5eb81c10..e4f4309ea716 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -100,170 +100,182 @@ LL | aaa() as u32; error: casting to the same type is unnecessary (`u32` -> `u32`) --> tests/ui/unnecessary_cast.rs:136:5 | -LL | aaa() as u32; - | ^^^^^^^^^^^^ help: try: `aaa()` +LL | x as u32; + | ^^^^^^^^ help: try: `x` + +error: casting to the same type is unnecessary (`u32` -> `u32`) + --> tests/ui/unnecessary_cast.rs:138:5 + | +LL | bbb() as u32; + | ^^^^^^^^^^^^ help: try: `bbb()` + +error: casting to the same type is unnecessary (`u32` -> `u32`) + --> tests/ui/unnecessary_cast.rs:141:5 + | +LL | x as u32; + | ^^^^^^^^ help: try: `x` error: casting integer literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:173:9 + --> tests/ui/unnecessary_cast.rs:174:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:175:9 + --> tests/ui/unnecessary_cast.rs:176:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:177:9 + --> tests/ui/unnecessary_cast.rs:178:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:179:17 + --> tests/ui/unnecessary_cast.rs:180:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:181:17 + --> tests/ui/unnecessary_cast.rs:182:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:183:17 + --> tests/ui/unnecessary_cast.rs:184:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:185:9 + --> tests/ui/unnecessary_cast.rs:186:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:187:9 + --> tests/ui/unnecessary_cast.rs:188:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> tests/ui/unnecessary_cast.rs:200:9 + --> tests/ui/unnecessary_cast.rs:201:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:202:9 + --> tests/ui/unnecessary_cast.rs:203:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> tests/ui/unnecessary_cast.rs:204:9 + --> tests/ui/unnecessary_cast.rs:205:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> tests/ui/unnecessary_cast.rs:206:9 + --> tests/ui/unnecessary_cast.rs:207:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> tests/ui/unnecessary_cast.rs:208:9 + --> tests/ui/unnecessary_cast.rs:209:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:211:9 + --> tests/ui/unnecessary_cast.rs:212:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:213:9 + --> tests/ui/unnecessary_cast.rs:214:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:218:17 + --> tests/ui/unnecessary_cast.rs:219:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:220:17 + --> tests/ui/unnecessary_cast.rs:221:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> tests/ui/unnecessary_cast.rs:227:18 + --> tests/ui/unnecessary_cast.rs:228:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:234:22 + --> tests/ui/unnecessary_cast.rs:235:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> tests/ui/unnecessary_cast.rs:237:22 + --> tests/ui/unnecessary_cast.rs:238:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:245:22 + --> tests/ui/unnecessary_cast.rs:246:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:248:23 + --> tests/ui/unnecessary_cast.rs:249:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> tests/ui/unnecessary_cast.rs:258:20 + --> tests/ui/unnecessary_cast.rs:259:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` error: casting to the same type is unnecessary (`usize` -> `usize`) - --> tests/ui/unnecessary_cast.rs:269:9 + --> tests/ui/unnecessary_cast.rs:270:9 | LL | (*x as usize).pow(2) | ^^^^^^^^^^^^^ help: try: `(*x)` error: casting to the same type is unnecessary (`usize` -> `usize`) - --> tests/ui/unnecessary_cast.rs:277:31 + --> tests/ui/unnecessary_cast.rs:278:31 | LL | assert_eq!(vec.len(), x as usize); | ^^^^^^^^^^ help: try: `x` error: casting to the same type is unnecessary (`i64` -> `i64`) - --> tests/ui/unnecessary_cast.rs:280:17 + --> tests/ui/unnecessary_cast.rs:281:17 | LL | let _ = (5i32 as i64 as i64).abs(); | ^^^^^^^^^^^^^^^^^^^^ help: try: `(5i32 as i64)` error: casting to the same type is unnecessary (`i64` -> `i64`) - --> tests/ui/unnecessary_cast.rs:283:17 + --> tests/ui/unnecessary_cast.rs:284:17 | LL | let _ = 5i32 as i64 as i64; | ^^^^^^^^^^^^^^^^^^ help: try: `5i32 as i64` -error: aborting due to 44 previous errors +error: aborting due to 46 previous errors diff --git a/tests/ui/unnecessary_fold.fixed b/tests/ui/unnecessary_fold.fixed index d51359349cb9..a8370ed03b74 100644 --- a/tests/ui/unnecessary_fold.fixed +++ b/tests/ui/unnecessary_fold.fixed @@ -88,16 +88,6 @@ fn unnecessary_fold_should_ignore() { let _: i32 = (0..3).fold(0, FakeAdd::add); let _: i32 = (0..3).fold(1, FakeMul::mul); - // We only match against an accumulator on the left - // hand side. We could lint for .sum and .product when - // it's on the right, but don't for now (and this wouldn't - // be valid if we extended the lint to cover arbitrary numeric - // types). - let _ = (0..3).fold(false, |acc, x| x > 2 || acc); - let _ = (0..3).fold(true, |acc, x| x > 2 && acc); - let _ = (0..3).fold(0, |acc, x| x + acc); - let _ = (0..3).fold(1, |acc, x| x * acc); - let _ = [(0..2), (0..3)].iter().fold(0, |a, b| a + b.len()); let _ = [(0..2), (0..3)].iter().fold(1, |a, b| a * b.len()); } @@ -178,6 +168,26 @@ fn issue10000() { } } +fn issue16581() { + let _ = (2..=3).product::(); + //~^ unnecessary_fold + let _ = (1..=3).sum::(); + //~^ unnecessary_fold + let _ = (2..=3).product::(); + //~^ unnecessary_fold + let _ = (1..=3).sum::(); + //~^ unnecessary_fold + + let _ = (0..3).any(|x| x > 2); + //~^ unnecessary_fold + let _ = (0..3).all(|x| x > 2); + //~^ unnecessary_fold + let _ = (0..3).sum::(); + //~^ unnecessary_fold + let _ = (0..3).product::(); + //~^ unnecessary_fold +} + fn wrongly_unmangled_macros() { macro_rules! test_expr { ($e:expr) => { diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index c6eb7157ab12..f495da6e720b 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -88,16 +88,6 @@ fn mul(self, other: i32) -> Self::Output { let _: i32 = (0..3).fold(0, FakeAdd::add); let _: i32 = (0..3).fold(1, FakeMul::mul); - // We only match against an accumulator on the left - // hand side. We could lint for .sum and .product when - // it's on the right, but don't for now (and this wouldn't - // be valid if we extended the lint to cover arbitrary numeric - // types). - let _ = (0..3).fold(false, |acc, x| x > 2 || acc); - let _ = (0..3).fold(true, |acc, x| x > 2 && acc); - let _ = (0..3).fold(0, |acc, x| x + acc); - let _ = (0..3).fold(1, |acc, x| x * acc); - let _ = [(0..2), (0..3)].iter().fold(0, |a, b| a + b.len()); let _ = [(0..2), (0..3)].iter().fold(1, |a, b| a * b.len()); } @@ -178,6 +168,26 @@ fn mul_turbofish_necessary() -> impl Mul { } } +fn issue16581() { + let _ = (2..=3).fold(1, |a, b| a * b); + //~^ unnecessary_fold + let _ = (1..=3).fold(0, |a, b| a + b); + //~^ unnecessary_fold + let _ = (2..=3).fold(1, |b, a| a * b); + //~^ unnecessary_fold + let _ = (1..=3).fold(0, |b, a| a + b); + //~^ unnecessary_fold + + let _ = (0..3).fold(false, |acc, x| x > 2 || acc); + //~^ unnecessary_fold + let _ = (0..3).fold(true, |acc, x| x > 2 && acc); + //~^ unnecessary_fold + let _ = (0..3).fold(0, |acc, x| x + acc); + //~^ unnecessary_fold + let _ = (0..3).fold(1, |acc, x| x * acc); + //~^ unnecessary_fold +} + fn wrongly_unmangled_macros() { macro_rules! test_expr { ($e:expr) => { diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr index 560427a681a9..266ced07eb82 100644 --- a/tests/ui/unnecessary_fold.stderr +++ b/tests/ui/unnecessary_fold.stderr @@ -70,7 +70,7 @@ LL | let _: bool = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); = note: the `any` method is short circuiting and may change the program semantics if the iterator has side effects error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:110:10 + --> tests/ui/unnecessary_fold.rs:100:10 | LL | .fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)` @@ -78,138 +78,190 @@ LL | .fold(false, |acc, x| acc || x > 2); = note: the `any` method is short circuiting and may change the program semantics if the iterator has side effects error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:123:33 + --> tests/ui/unnecessary_fold.rs:113:33 | LL | assert_eq!(map.values().fold(0, |x, y| x + y), 0); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:127:30 + --> tests/ui/unnecessary_fold.rs:117:30 | LL | let _ = map.values().fold(0, |x, y| x + y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:129:30 + --> tests/ui/unnecessary_fold.rs:119:30 | LL | let _ = map.values().fold(0, Add::add); | ^^^^^^^^^^^^^^^^^ help: try: `sum::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:131:30 + --> tests/ui/unnecessary_fold.rs:121:30 | LL | let _ = map.values().fold(1, |x, y| x * y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:133:30 + --> tests/ui/unnecessary_fold.rs:123:30 | LL | let _ = map.values().fold(1, Mul::mul); | ^^^^^^^^^^^^^^^^^ help: try: `product::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:135:35 + --> tests/ui/unnecessary_fold.rs:125:35 | LL | let _: i32 = map.values().fold(0, |x, y| x + y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:137:35 + --> tests/ui/unnecessary_fold.rs:127:35 | LL | let _: i32 = map.values().fold(0, Add::add); | ^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:139:35 + --> tests/ui/unnecessary_fold.rs:129:35 | LL | let _: i32 = map.values().fold(1, |x, y| x * y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:141:35 + --> tests/ui/unnecessary_fold.rs:131:35 | LL | let _: i32 = map.values().fold(1, Mul::mul); | ^^^^^^^^^^^^^^^^^ help: try: `product()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:143:31 + --> tests/ui/unnecessary_fold.rs:133:31 | LL | anything(map.values().fold(0, |x, y| x + y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:145:31 + --> tests/ui/unnecessary_fold.rs:135:31 | LL | anything(map.values().fold(0, Add::add)); | ^^^^^^^^^^^^^^^^^ help: try: `sum::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:147:31 + --> tests/ui/unnecessary_fold.rs:137:31 | LL | anything(map.values().fold(1, |x, y| x * y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:149:31 + --> tests/ui/unnecessary_fold.rs:139:31 | LL | anything(map.values().fold(1, Mul::mul)); | ^^^^^^^^^^^^^^^^^ help: try: `product::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:151:26 + --> tests/ui/unnecessary_fold.rs:141:26 | LL | num(map.values().fold(0, |x, y| x + y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:153:26 + --> tests/ui/unnecessary_fold.rs:143:26 | LL | num(map.values().fold(0, Add::add)); | ^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:155:26 + --> tests/ui/unnecessary_fold.rs:145:26 | LL | num(map.values().fold(1, |x, y| x * y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:157:26 + --> tests/ui/unnecessary_fold.rs:147:26 | LL | num(map.values().fold(1, Mul::mul)); | ^^^^^^^^^^^^^^^^^ help: try: `product()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:164:16 + --> tests/ui/unnecessary_fold.rs:154:16 | LL | (0..3).fold(0, |acc, x| acc + x) | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:168:16 + --> tests/ui/unnecessary_fold.rs:158:16 | LL | (0..3).fold(1, |acc, x| acc * x) | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:172:16 + --> tests/ui/unnecessary_fold.rs:162:16 | LL | (0..3).fold(0, |acc, x| acc + x) | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:176:16 + --> tests/ui/unnecessary_fold.rs:166:16 | LL | (0..3).fold(1, |acc, x| acc * x) | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:188:20 + --> tests/ui/unnecessary_fold.rs:172:21 + | +LL | let _ = (2..=3).fold(1, |a, b| a * b); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:174:21 + | +LL | let _ = (1..=3).fold(0, |a, b| a + b); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:176:21 + | +LL | let _ = (2..=3).fold(1, |b, a| a * b); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:178:21 + | +LL | let _ = (1..=3).fold(0, |b, a| a + b); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:181:20 + | +LL | let _ = (0..3).fold(false, |acc, x| x > 2 || acc); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)` + | + = note: the `any` method is short circuiting and may change the program semantics if the iterator has side effects + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:183:20 + | +LL | let _ = (0..3).fold(true, |acc, x| x > 2 && acc); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `all(|x| x > 2)` + | + = note: the `all` method is short circuiting and may change the program semantics if the iterator has side effects + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:185:20 + | +LL | let _ = (0..3).fold(0, |acc, x| x + acc); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:187:20 + | +LL | let _ = (0..3).fold(1, |acc, x| x * acc); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:198:20 | LL | let _ = (0..3).fold(false, |acc: bool, x| acc || test_expr!(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| test_expr!(x))` | = note: the `any` method is short circuiting and may change the program semantics if the iterator has side effects -error: aborting due to 33 previous errors +error: aborting due to 41 previous errors diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index 877f4ad41c7e..05ffdeb1dcc5 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -152,12 +152,4 @@ fn unwrap_unchecked() { //~^ unnecessary_literal_unwrap } -fn main() { - unwrap_option_some(); - unwrap_option_none(); - unwrap_result_ok(); - unwrap_result_err(); - unwrap_methods_option(); - unwrap_methods_result(); - unwrap_unchecked(); -} +fn main() {} diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index c0a35ae78a71..5efefb24530b 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -152,12 +152,4 @@ fn unwrap_unchecked() { //~^ unnecessary_literal_unwrap } -fn main() { - unwrap_option_some(); - unwrap_option_none(); - unwrap_result_ok(); - unwrap_result_err(); - unwrap_methods_option(); - unwrap_methods_result(); - unwrap_unchecked(); -} +fn main() {} diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.rs b/tests/ui/unnecessary_literal_unwrap_unfixable.rs index b6cba4e6a568..2680d0a6697b 100644 --- a/tests/ui/unnecessary_literal_unwrap_unfixable.rs +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.rs @@ -191,16 +191,4 @@ fn unwrap_methods_result_context() { //~^ unnecessary_literal_unwrap } -fn main() { - unwrap_option_some(); - unwrap_option_some_context(); - unwrap_option_none(); - unwrap_result_ok(); - unwrap_result_ok_context(); - unwrap_result_err(); - unwrap_result_err_context(); - unwrap_methods_option(); - unwrap_methods_option_context(); - unwrap_methods_result(); - unwrap_methods_result_context(); -} +fn main() {} diff --git a/tests/ui/unnecessary_min_or_max.fixed b/tests/ui/unnecessary_min_or_max.fixed index 2650cae5baf4..e2e1700e28b9 100644 --- a/tests/ui/unnecessary_min_or_max.fixed +++ b/tests/ui/unnecessary_min_or_max.fixed @@ -77,6 +77,32 @@ fn main() { let _ = (X + 1).min(12); let _ = 12.min(X - 1); let _ = 12.max(X - 1); + + let n: usize = 42; + + let _ = 0; + //~^ unnecessary_min_or_max + + let _ = 0usize; + //~^ unnecessary_min_or_max + + let _ = (0usize); + //~^ unnecessary_min_or_max + + let _ = usize::MIN; + //~^ unnecessary_min_or_max + + let _ = usize::MAX; + //~^ unnecessary_min_or_max + + let _ = (usize::MAX); + //~^ unnecessary_min_or_max + + let _ = !0usize; + //~^ unnecessary_min_or_max + + let _ = n; + //~^ unnecessary_min_or_max } fn random_u32() -> u32 { // random number generator diff --git a/tests/ui/unnecessary_min_or_max.rs b/tests/ui/unnecessary_min_or_max.rs index 2f3c480b3d15..dd71ee208030 100644 --- a/tests/ui/unnecessary_min_or_max.rs +++ b/tests/ui/unnecessary_min_or_max.rs @@ -77,6 +77,32 @@ fn main() { let _ = (X + 1).min(12); let _ = 12.min(X - 1); let _ = 12.max(X - 1); + + let n: usize = 42; + + let _ = n.min(0); + //~^ unnecessary_min_or_max + + let _ = n.min(0usize); + //~^ unnecessary_min_or_max + + let _ = (0usize).min(n); + //~^ unnecessary_min_or_max + + let _ = n.min(usize::MIN); + //~^ unnecessary_min_or_max + + let _ = n.max(usize::MAX); + //~^ unnecessary_min_or_max + + let _ = (usize::MAX).max(n); + //~^ unnecessary_min_or_max + + let _ = n.max(!0usize); + //~^ unnecessary_min_or_max + + let _ = n.max(0); + //~^ unnecessary_min_or_max } fn random_u32() -> u32 { // random number generator diff --git a/tests/ui/unnecessary_min_or_max.stderr b/tests/ui/unnecessary_min_or_max.stderr index dfe6910dfa5c..b391d21d3bf4 100644 --- a/tests/ui/unnecessary_min_or_max.stderr +++ b/tests/ui/unnecessary_min_or_max.stderr @@ -103,5 +103,53 @@ error: `x` is never smaller than `i32::MIN - 0` and has therefore no effect LL | let _ = x.min(i32::MIN - 0); | ^^^^^^^^^^^^^^^^^^^ help: try: `i32::MIN - 0` -error: aborting due to 17 previous errors +error: `n` is never smaller than `0` and has therefore no effect + --> tests/ui/unnecessary_min_or_max.rs:83:13 + | +LL | let _ = n.min(0); + | ^^^^^^^^ help: try: `0` + +error: `n` is never smaller than `0usize` and has therefore no effect + --> tests/ui/unnecessary_min_or_max.rs:86:13 + | +LL | let _ = n.min(0usize); + | ^^^^^^^^^^^^^ help: try: `0usize` + +error: `(0usize)` is never greater than `n` and has therefore no effect + --> tests/ui/unnecessary_min_or_max.rs:89:13 + | +LL | let _ = (0usize).min(n); + | ^^^^^^^^^^^^^^^ help: try: `(0usize)` + +error: `n` is never smaller than `usize::MIN` and has therefore no effect + --> tests/ui/unnecessary_min_or_max.rs:92:13 + | +LL | let _ = n.min(usize::MIN); + | ^^^^^^^^^^^^^^^^^ help: try: `usize::MIN` + +error: `n` is never greater than `usize::MAX` and has therefore no effect + --> tests/ui/unnecessary_min_or_max.rs:95:13 + | +LL | let _ = n.max(usize::MAX); + | ^^^^^^^^^^^^^^^^^ help: try: `usize::MAX` + +error: `(usize::MAX)` is never smaller than `n` and has therefore no effect + --> tests/ui/unnecessary_min_or_max.rs:98:13 + | +LL | let _ = (usize::MAX).max(n); + | ^^^^^^^^^^^^^^^^^^^ help: try: `(usize::MAX)` + +error: `n` is never greater than `!0usize` and has therefore no effect + --> tests/ui/unnecessary_min_or_max.rs:101:13 + | +LL | let _ = n.max(!0usize); + | ^^^^^^^^^^^^^^ help: try: `!0usize` + +error: `n` is never smaller than `0` and has therefore no effect + --> tests/ui/unnecessary_min_or_max.rs:104:13 + | +LL | let _ = n.max(0); + | ^^^^^^^^ help: try: `n` + +error: aborting due to 25 previous errors diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index 6870470e74c5..317140eacc78 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -106,11 +106,7 @@ mod issue_6001 { } } -fn main() { - unnecessary_sort_by(); - issue_5754::test(); - issue_6001::test(); -} +fn main() {} fn issue16405() { let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index d95306176817..a31cf2967999 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -106,11 +106,7 @@ pub fn test() { } } -fn main() { - unnecessary_sort_by(); - issue_5754::test(); - issue_6001::test(); -} +fn main() {} fn issue16405() { let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; diff --git a/tests/ui/unnecessary_sort_by.stderr b/tests/ui/unnecessary_sort_by.stderr index cc545d604ff3..56d4831eb70a 100644 --- a/tests/ui/unnecessary_sort_by.stderr +++ b/tests/ui/unnecessary_sort_by.stderr @@ -145,7 +145,7 @@ LL + args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name())); | error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:118:5 + --> tests/ui/unnecessary_sort_by.rs:114:5 | LL | v.sort_by(|a, b| a.0.cmp(&b.0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + v.sort_by_key(|a| a.0); | error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:136:5 + --> tests/ui/unnecessary_sort_by.rs:132:5 | LL | items.sort_by(|item1, item2| item1.key.cmp(&item2.key)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + items.sort_by_key(|item1| item1.key); | error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:141:5 + --> tests/ui/unnecessary_sort_by.rs:137:5 | LL | items.sort_by(|item1, item2| item1.value.clone().cmp(&item2.value.clone())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + items.sort_by_key(|item1| item1.value.clone()); | error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:147:5 + --> tests/ui/unnecessary_sort_by.rs:143:5 | LL | v.sort_by(|(_, s1), (_, s2)| s1.cmp(s2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + v.sort_by_key(|(_, s1)| *s1); | error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:154:5 + --> tests/ui/unnecessary_sort_by.rs:150:5 | LL | v.sort_by(|Foo { bar: b1 }, Foo { bar: b2 }| b1.cmp(b2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + v.sort_by_key(|Foo { bar: b1 }| *b1); | error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:159:5 + --> tests/ui/unnecessary_sort_by.rs:155:5 | LL | v.sort_by(|Baz(b1), Baz(b2)| b1.cmp(b2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL + v.sort_by_key(|Baz(b1)| *b1); | error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:162:5 + --> tests/ui/unnecessary_sort_by.rs:158:5 | LL | v.sort_by(|&Baz(b1), &Baz(b2)| b1.cmp(&b2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + v.sort_by_key(|&Baz(b1)| b1); | error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:166:5 + --> tests/ui/unnecessary_sort_by.rs:162:5 | LL | v.sort_by(|&&b1, &&b2| b1.cmp(&b2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + v.sort_by_key(|&&b1| b1); | error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:170:5 + --> tests/ui/unnecessary_sort_by.rs:166:5 | LL | v.sort_by(|[a1, b1], [a2, b2]| a1.cmp(a2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL + v.sort_by_key(|[a1, b1]| *a1); | error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:173:5 + --> tests/ui/unnecessary_sort_by.rs:169:5 | LL | v.sort_by(|[a1, b1], [a2, b2]| (a1 - b1).cmp(&(a2 - b2))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_trailing_comma.fixed b/tests/ui/unnecessary_trailing_comma.fixed new file mode 100644 index 000000000000..499d9ee1ca23 --- /dev/null +++ b/tests/ui/unnecessary_trailing_comma.fixed @@ -0,0 +1,86 @@ +// run-rustfix +#![warn(clippy::unnecessary_trailing_comma)] + +fn main() {} + +// fmt breaks - https://github.com/rust-lang/rustfmt/issues/6797 +#[rustfmt::skip] +fn simple() { + println!["Foo(,)"]; + println!("Foo"); //~ unnecessary_trailing_comma + println!{"Foo"}; //~ unnecessary_trailing_comma + println!["Foo"]; //~ unnecessary_trailing_comma + println!("Foo={}", 1); //~ unnecessary_trailing_comma + println!(concat!("b", "o", "o")); //~ unnecessary_trailing_comma + println!("Foo(,)"); //~ unnecessary_trailing_comma + println!("Foo[,]"); //~ unnecessary_trailing_comma + println!["Foo(,)"]; //~ unnecessary_trailing_comma + println!["Foo[,]"]; //~ unnecessary_trailing_comma + println!["Foo{{,}}"]; //~ unnecessary_trailing_comma + println!{"Foo{{,}}"}; //~ unnecessary_trailing_comma + println!{"Foo(,)"}; //~ unnecessary_trailing_comma + println!{"Foo[,]"}; //~ unnecessary_trailing_comma + println!["Foo(,"]; //~ unnecessary_trailing_comma + println!["Foo[,"]; //~ unnecessary_trailing_comma + println!["Foo{{,}}"]; //~ unnecessary_trailing_comma + println!{"Foo{{,}}"}; //~ unnecessary_trailing_comma + println!{"Foo(,"}; //~ unnecessary_trailing_comma + println!{"Foo[,"}; //~ unnecessary_trailing_comma + + // This should eventually work, but requires more work + println!(concat!("Foo", "=", "{}"), 1,); + println!("No params", /*"a,){ */); + println!("No params" /* "a,){*/, /*"a,){ */); + + // No trailing comma - no lint + println!("{}", 1); + println!(concat!("b", "o", "o")); + println!(concat!("Foo", "=", "{}"), 1); + + println!("Foo" ); + println!{"Foo" }; + println!["Foo" ]; + println!("Foo={}", 1); + println!(concat!("b", "o", "o")); + println!("Foo(,)"); + println!("Foo[,]"); + println!["Foo(,)"]; + println!["Foo[,]"]; + println!["Foo{{,}}"]; + println!{"Foo{{,}}"}; + println!{"Foo(,)"}; + println!{"Foo[,]"}; + println!["Foo(,"]; + println!["Foo[,"]; + println!["Foo{{,}}"]; + println!{"Foo{{,}}"}; + println!{"Foo(,"}; + println!{"Foo[,"}; + + // Multi-line macro - must NOT lint (single-line only) + println!( + "very long string to prevent fmt from making it into a single line: {}", + 1, + ); + + print!("{}" + , 1 + ,); +} + +// The macro invocation itself should never be fixed +// The call to println! on the other hand might be ok to suggest in the future + +macro_rules! from_macro { + (0,) => { + println!("Foo",); + }; + (1,) => { + println!("Foo={}", 1,); + }; +} + +fn from_macro() { + from_macro!(0,); + from_macro!(1,); +} diff --git a/tests/ui/unnecessary_trailing_comma.rs b/tests/ui/unnecessary_trailing_comma.rs new file mode 100644 index 000000000000..15dea27b887b --- /dev/null +++ b/tests/ui/unnecessary_trailing_comma.rs @@ -0,0 +1,86 @@ +// run-rustfix +#![warn(clippy::unnecessary_trailing_comma)] + +fn main() {} + +// fmt breaks - https://github.com/rust-lang/rustfmt/issues/6797 +#[rustfmt::skip] +fn simple() { + println!["Foo(,)"]; + println!("Foo" , ); //~ unnecessary_trailing_comma + println!{"Foo" , }; //~ unnecessary_trailing_comma + println!["Foo" , ]; //~ unnecessary_trailing_comma + println!("Foo={}", 1 , ); //~ unnecessary_trailing_comma + println!(concat!("b", "o", "o") , ); //~ unnecessary_trailing_comma + println!("Foo(,)",); //~ unnecessary_trailing_comma + println!("Foo[,]" , ); //~ unnecessary_trailing_comma + println!["Foo(,)", ]; //~ unnecessary_trailing_comma + println!["Foo[,]", ]; //~ unnecessary_trailing_comma + println!["Foo{{,}}", ]; //~ unnecessary_trailing_comma + println!{"Foo{{,}}", }; //~ unnecessary_trailing_comma + println!{"Foo(,)", }; //~ unnecessary_trailing_comma + println!{"Foo[,]", }; //~ unnecessary_trailing_comma + println!["Foo(,", ]; //~ unnecessary_trailing_comma + println!["Foo[,", ]; //~ unnecessary_trailing_comma + println!["Foo{{,}}", ]; //~ unnecessary_trailing_comma + println!{"Foo{{,}}", }; //~ unnecessary_trailing_comma + println!{"Foo(,", }; //~ unnecessary_trailing_comma + println!{"Foo[,", }; //~ unnecessary_trailing_comma + + // This should eventually work, but requires more work + println!(concat!("Foo", "=", "{}"), 1,); + println!("No params", /*"a,){ */); + println!("No params" /* "a,){*/, /*"a,){ */); + + // No trailing comma - no lint + println!("{}", 1); + println!(concat!("b", "o", "o")); + println!(concat!("Foo", "=", "{}"), 1); + + println!("Foo" ); + println!{"Foo" }; + println!["Foo" ]; + println!("Foo={}", 1); + println!(concat!("b", "o", "o")); + println!("Foo(,)"); + println!("Foo[,]"); + println!["Foo(,)"]; + println!["Foo[,]"]; + println!["Foo{{,}}"]; + println!{"Foo{{,}}"}; + println!{"Foo(,)"}; + println!{"Foo[,]"}; + println!["Foo(,"]; + println!["Foo[,"]; + println!["Foo{{,}}"]; + println!{"Foo{{,}}"}; + println!{"Foo(,"}; + println!{"Foo[,"}; + + // Multi-line macro - must NOT lint (single-line only) + println!( + "very long string to prevent fmt from making it into a single line: {}", + 1, + ); + + print!("{}" + , 1 + ,); +} + +// The macro invocation itself should never be fixed +// The call to println! on the other hand might be ok to suggest in the future + +macro_rules! from_macro { + (0,) => { + println!("Foo",); + }; + (1,) => { + println!("Foo={}", 1,); + }; +} + +fn from_macro() { + from_macro!(0,); + from_macro!(1,); +} diff --git a/tests/ui/unnecessary_trailing_comma.stderr b/tests/ui/unnecessary_trailing_comma.stderr new file mode 100644 index 000000000000..06fd5b1861a5 --- /dev/null +++ b/tests/ui/unnecessary_trailing_comma.stderr @@ -0,0 +1,119 @@ +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:10:19 + | +LL | println!("Foo" , ); + | ^^^ help: remove the trailing comma + | + = note: `-D clippy::unnecessary-trailing-comma` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_trailing_comma)]` + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:11:19 + | +LL | println!{"Foo" , }; + | ^^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:12:19 + | +LL | println!["Foo" , ]; + | ^^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:13:27 + | +LL | println!("Foo={}", 1 , ); + | ^^^^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:14:36 + | +LL | println!(concat!("b", "o", "o") , ); + | ^^^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:15:22 + | +LL | println!("Foo(,)",); + | ^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:16:22 + | +LL | println!("Foo[,]" , ); + | ^^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:17:22 + | +LL | println!["Foo(,)", ]; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:18:22 + | +LL | println!["Foo[,]", ]; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:19:24 + | +LL | println!["Foo{{,}}", ]; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:20:24 + | +LL | println!{"Foo{{,}}", }; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:21:22 + | +LL | println!{"Foo(,)", }; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:22:22 + | +LL | println!{"Foo[,]", }; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:23:21 + | +LL | println!["Foo(,", ]; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:24:21 + | +LL | println!["Foo[,", ]; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:25:24 + | +LL | println!["Foo{{,}}", ]; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:26:24 + | +LL | println!{"Foo{{,}}", }; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:27:21 + | +LL | println!{"Foo(,", }; + | ^^ help: remove the trailing comma + +error: unnecessary trailing comma + --> tests/ui/unnecessary_trailing_comma.rs:28:21 + | +LL | println!{"Foo[,", }; + | ^^ help: remove the trailing comma + +error: aborting due to 19 previous errors + diff --git a/tests/ui/unused_async.rs b/tests/ui/unused_async.rs index 7a0be825a2de..3f9244ab4970 100644 --- a/tests/ui/unused_async.rs +++ b/tests/ui/unused_async.rs @@ -115,10 +115,7 @@ async fn unused() -> i32 { } async_trait_impl!(); -fn main() { - foo(); - bar(); -} +fn main() {} mod issue14704 { use std::sync::Arc; diff --git a/tests/ui/unused_peekable.rs b/tests/ui/unused_peekable.rs index e7fe297764eb..29e830fefb87 100644 --- a/tests/ui/unused_peekable.rs +++ b/tests/ui/unused_peekable.rs @@ -3,10 +3,7 @@ use std::iter::{Empty, Peekable}; -fn main() { - invalid(); - valid(); -} +fn main() {} #[allow(clippy::unused_unit)] fn invalid() { diff --git a/tests/ui/unused_peekable.stderr b/tests/ui/unused_peekable.stderr index 9330d8c58001..376c896a1c57 100644 --- a/tests/ui/unused_peekable.stderr +++ b/tests/ui/unused_peekable.stderr @@ -1,5 +1,5 @@ error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:13:9 + --> tests/ui/unused_peekable.rs:10:9 | LL | let peekable = std::iter::empty::().peekable(); | ^^^^^^^^ @@ -9,7 +9,7 @@ LL | let peekable = std::iter::empty::().peekable(); = help: to override `-D warnings` add `#[allow(clippy::unused_peekable)]` error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:18:9 + --> tests/ui/unused_peekable.rs:15:9 | LL | let new_local = old_local; | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let new_local = old_local; = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:23:9 + --> tests/ui/unused_peekable.rs:20:9 | LL | let by_mut_ref = &mut by_mut_ref_test; | ^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let by_mut_ref = &mut by_mut_ref_test; = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:31:9 + --> tests/ui/unused_peekable.rs:28:9 | LL | let peekable_from_fn = returns_peekable(); | ^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let peekable_from_fn = returns_peekable(); = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:35:13 + --> tests/ui/unused_peekable.rs:32:13 | LL | let mut peekable_using_iterator_method = std::iter::empty::().peekable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let mut peekable_using_iterator_method = std::iter::empty::().peek = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:42:9 + --> tests/ui/unused_peekable.rs:39:9 | LL | let passed_along_ref = std::iter::empty::().peekable(); | ^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let passed_along_ref = std::iter::empty::().peekable(); = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:49:9 + --> tests/ui/unused_peekable.rs:46:9 | LL | let _by_ref = by_ref_test.by_ref(); | ^^^^^^^ @@ -57,7 +57,7 @@ LL | let _by_ref = by_ref_test.by_ref(); = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:52:13 + --> tests/ui/unused_peekable.rs:49:13 | LL | let mut peekable_in_for_loop = std::iter::empty::().peekable(); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/useless_asref.fixed b/tests/ui/useless_asref.fixed index 54a7c0a8c080..5131ae113d18 100644 --- a/tests/ui/useless_asref.fixed +++ b/tests/ui/useless_asref.fixed @@ -293,7 +293,4 @@ fn issue16098(exts: Vec<&str>) { //~^ useless_asref } -fn main() { - not_ok(); - ok(); -} +fn main() {} diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index 1b9ce1d46233..e1c2a1d81d04 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -293,7 +293,4 @@ impl Identity for &str {} //~^ useless_asref } -fn main() { - not_ok(); - ok(); -} +fn main() {} diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index dbe4b6fb50f3..ff40f51c0205 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -96,9 +96,7 @@ mod module { #[allow(unused_braces)] use module::{Struct}; -fn main() { - test_indented_attr(); -} +fn main() {} // Regression test for https://github.com/rust-lang/rust-clippy/issues/4467 #[allow(dead_code)] diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 44fb6733f054..426c720b4429 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -96,9 +96,7 @@ mod module { #[allow(unused_braces)] use module::{Struct}; -fn main() { - test_indented_attr(); -} +fn main() {} // Regression test for https://github.com/rust-lang/rust-clippy/issues/4467 #[allow(dead_code)] diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed index 4832e922fa8e..d0297ef6bcdc 100644 --- a/tests/ui/useless_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -117,21 +117,6 @@ fn dont_lint_into_iter_on_static_copy_iter() { } fn main() { - test_generic(10i32); - test_generic2::(10i32); - test_questionmark().unwrap(); - test_issue_3913().unwrap(); - - dont_lint_on_type_alias(); - dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr(); - lint_into_iter_on_mutable_local_implementing_iterator_in_expr(); - lint_into_iter_on_expr_implementing_iterator(); - lint_into_iter_on_expr_implementing_iterator_2(); - lint_into_iter_on_const_implementing_iterator(); - lint_into_iter_on_const_implementing_iterator_2(); - dont_lint_into_iter_on_copy_iter(); - dont_lint_into_iter_on_static_copy_iter(); - { // triggers the IntoIterator trait fn consume(_: impl IntoIterator) {} @@ -463,3 +448,34 @@ fn issue16165() { for _ in mac!(iter [1, 2]) {} //~^ useless_conversion } + +fn takes_into_iter_usize(_: impl IntoIterator) {} +fn takes_into_iter_usize_result(_: impl IntoIterator) -> Result<(), ()> { + Ok(()) +} + +async fn issue16590() { + let a: Vec = vec![]; + let b: Vec = vec![]; + + takes_into_iter_usize(b); + //~^ useless_conversion +} + +fn in_for_loop() { + let a: Vec = vec![1, 2, 3]; + let b: Vec = vec![4, 5, 6]; + + for _ in &a { + takes_into_iter_usize(b.clone()); + //~^ useless_conversion + } +} + +fn after_question_mark() -> Result<(), ()> { + let b: Vec = vec![4, 5, 6]; + + takes_into_iter_usize_result(b.clone())?; + //~^ useless_conversion + Ok(()) +} diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs index 6ef1f93a5606..20a0f6d72f9a 100644 --- a/tests/ui/useless_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -117,21 +117,6 @@ fn dont_lint_into_iter_on_static_copy_iter() { } fn main() { - test_generic(10i32); - test_generic2::(10i32); - test_questionmark().unwrap(); - test_issue_3913().unwrap(); - - dont_lint_on_type_alias(); - dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr(); - lint_into_iter_on_mutable_local_implementing_iterator_in_expr(); - lint_into_iter_on_expr_implementing_iterator(); - lint_into_iter_on_expr_implementing_iterator_2(); - lint_into_iter_on_const_implementing_iterator(); - lint_into_iter_on_const_implementing_iterator_2(); - dont_lint_into_iter_on_copy_iter(); - dont_lint_into_iter_on_static_copy_iter(); - { // triggers the IntoIterator trait fn consume(_: impl IntoIterator) {} @@ -463,3 +448,34 @@ macro_rules! mac { for _ in mac!(iter [1, 2]).into_iter() {} //~^ useless_conversion } + +fn takes_into_iter_usize(_: impl IntoIterator) {} +fn takes_into_iter_usize_result(_: impl IntoIterator) -> Result<(), ()> { + Ok(()) +} + +async fn issue16590() { + let a: Vec = vec![]; + let b: Vec = vec![]; + + takes_into_iter_usize(b.into_iter()); + //~^ useless_conversion +} + +fn in_for_loop() { + let a: Vec = vec![1, 2, 3]; + let b: Vec = vec![4, 5, 6]; + + for _ in &a { + takes_into_iter_usize(b.clone().into_iter()); + //~^ useless_conversion + } +} + +fn after_question_mark() -> Result<(), ()> { + let b: Vec = vec![4, 5, 6]; + + takes_into_iter_usize_result(b.clone().into_iter())?; + //~^ useless_conversion + Ok(()) +} diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index 24772af3818e..18d5c9d28c0d 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -53,13 +53,13 @@ LL | let mut n = NUMBERS.into_iter(); | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:141:17 + --> tests/ui/useless_conversion.rs:126:17 | LL | consume(items.into_iter()); | ^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:137:28 + --> tests/ui/useless_conversion.rs:122:28 | LL | fn consume(_: impl IntoIterator) {} | ^^^^^^^^^^^^ @@ -70,79 +70,79 @@ LL + consume(*items); | error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:154:21 + --> tests/ui/useless_conversion.rs:139:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:156:21 + --> tests/ui/useless_conversion.rs:141:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:158:13 + --> tests/ui/useless_conversion.rs:143:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:160:13 + --> tests/ui/useless_conversion.rs:145:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:162:13 + --> tests/ui/useless_conversion.rs:147:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: useless conversion to the same type: `std::vec::IntoIter` - --> tests/ui/useless_conversion.rs:164:13 + --> tests/ui/useless_conversion.rs:149:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:166:21 + --> tests/ui/useless_conversion.rs:151:21 | LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` error: useless conversion to the same type: `i32` - --> tests/ui/useless_conversion.rs:172:13 + --> tests/ui/useless_conversion.rs:157:13 | LL | let _ = i32::from(a + b) * 3; | ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)` error: useless conversion to the same type: `Foo<'a'>` - --> tests/ui/useless_conversion.rs:179:23 + --> tests/ui/useless_conversion.rs:164:23 | LL | let _: Foo<'a'> = s2.into(); | ^^^^^^^^^ help: consider removing `.into()`: `s2` error: useless conversion to the same type: `Foo<'a'>` - --> tests/ui/useless_conversion.rs:182:13 + --> tests/ui/useless_conversion.rs:167:13 | LL | let _ = Foo::<'a'>::from(s3); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3` error: useless conversion to the same type: `std::vec::IntoIter>` - --> tests/ui/useless_conversion.rs:185:13 + --> tests/ui/useless_conversion.rs:170:13 | LL | let _ = vec![s4, s4, s4].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()` error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:218:7 + --> tests/ui/useless_conversion.rs:203:7 | LL | b(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:208:13 + --> tests/ui/useless_conversion.rs:193:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -153,13 +153,13 @@ LL + b(vec![1, 2]); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:220:7 + --> tests/ui/useless_conversion.rs:205:7 | LL | c(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:209:18 + --> tests/ui/useless_conversion.rs:194:18 | LL | fn c(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -170,13 +170,13 @@ LL + c(vec![1, 2]); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:222:7 + --> tests/ui/useless_conversion.rs:207:7 | LL | d(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:212:12 + --> tests/ui/useless_conversion.rs:197:12 | LL | T: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -187,13 +187,13 @@ LL + d(vec![1, 2]); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:226:7 + --> tests/ui/useless_conversion.rs:211:7 | LL | b(vec![1, 2].into_iter().into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:208:13 + --> tests/ui/useless_conversion.rs:193:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -204,13 +204,13 @@ LL + b(vec![1, 2]); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:228:7 + --> tests/ui/useless_conversion.rs:213:7 | LL | b(vec![1, 2].into_iter().into_iter().into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:208:13 + --> tests/ui/useless_conversion.rs:193:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -221,13 +221,13 @@ LL + b(vec![1, 2]); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:275:24 + --> tests/ui/useless_conversion.rs:260:24 | LL | foo2::([1, 2, 3].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:254:12 + --> tests/ui/useless_conversion.rs:239:12 | LL | I: IntoIterator + Helper, | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -238,13 +238,13 @@ LL + foo2::([1, 2, 3]); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:284:14 + --> tests/ui/useless_conversion.rs:269:14 | LL | foo3([1, 2, 3].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:263:12 + --> tests/ui/useless_conversion.rs:248:12 | LL | I: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -255,13 +255,13 @@ LL + foo3([1, 2, 3]); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:294:16 + --> tests/ui/useless_conversion.rs:279:16 | LL | S1.foo([1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:291:27 + --> tests/ui/useless_conversion.rs:276:27 | LL | pub fn foo(&self, _: I) {} | ^^^^^^^^^^^^ @@ -272,13 +272,13 @@ LL + S1.foo([1, 2]); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:314:44 + --> tests/ui/useless_conversion.rs:299:44 | LL | v0.into_iter().interleave_shortest(v1.into_iter()); | ^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:301:20 + --> tests/ui/useless_conversion.rs:286:20 | LL | J: IntoIterator, | ^^^^^^^^^^^^ @@ -289,61 +289,61 @@ LL + v0.into_iter().interleave_shortest(v1); | error: useless conversion to the same type: `()` - --> tests/ui/useless_conversion.rs:342:58 + --> tests/ui/useless_conversion.rs:327:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map(Into::into); | ^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `std::io::Error` - --> tests/ui/useless_conversion.rs:345:58 + --> tests/ui/useless_conversion.rs:330:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map_err(Into::into); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `()` - --> tests/ui/useless_conversion.rs:348:58 + --> tests/ui/useless_conversion.rs:333:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map(From::from); | ^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `std::io::Error` - --> tests/ui/useless_conversion.rs:351:58 + --> tests/ui/useless_conversion.rs:336:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map_err(From::from); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `()` - --> tests/ui/useless_conversion.rs:355:31 + --> tests/ui/useless_conversion.rs:340:31 | LL | let _: ControlFlow<()> = c.map_break(Into::into); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `()` - --> tests/ui/useless_conversion.rs:359:31 + --> tests/ui/useless_conversion.rs:344:31 | LL | let _: ControlFlow<()> = c.map_continue(Into::into); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `u32` - --> tests/ui/useless_conversion.rs:373:41 + --> tests/ui/useless_conversion.rs:358:41 | LL | let _: Vec = [1u32].into_iter().map(Into::into).collect(); | ^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `T` - --> tests/ui/useless_conversion.rs:384:18 + --> tests/ui/useless_conversion.rs:369:18 | LL | x.into_iter().map(Into::into).collect() | ^^^^^^^^^^^^^^^^ help: consider removing error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:400:29 + --> tests/ui/useless_conversion.rs:385:29 | LL | takes_into_iter(self.my_field.into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:389:32 + --> tests/ui/useless_conversion.rs:374:32 | LL | fn takes_into_iter(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -354,13 +354,13 @@ LL + takes_into_iter(&self.my_field); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:408:29 + --> tests/ui/useless_conversion.rs:393:29 | LL | takes_into_iter(self.my_field.into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:389:32 + --> tests/ui/useless_conversion.rs:374:32 | LL | fn takes_into_iter(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -371,13 +371,13 @@ LL + takes_into_iter(&mut self.my_field); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:417:29 + --> tests/ui/useless_conversion.rs:402:29 | LL | takes_into_iter(self.my_field.into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:389:32 + --> tests/ui/useless_conversion.rs:374:32 | LL | fn takes_into_iter(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -388,13 +388,13 @@ LL + takes_into_iter(*self.my_field); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:426:29 + --> tests/ui/useless_conversion.rs:411:29 | LL | takes_into_iter(self.my_field.into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:389:32 + --> tests/ui/useless_conversion.rs:374:32 | LL | fn takes_into_iter(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -405,13 +405,13 @@ LL + takes_into_iter(&*self.my_field); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:435:29 + --> tests/ui/useless_conversion.rs:420:29 | LL | takes_into_iter(self.my_field.into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:389:32 + --> tests/ui/useless_conversion.rs:374:32 | LL | fn takes_into_iter(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -422,22 +422,73 @@ LL + takes_into_iter(&mut *self.my_field); | error: useless conversion to the same type: `std::ops::Range` - --> tests/ui/useless_conversion.rs:450:5 + --> tests/ui/useless_conversion.rs:435:5 | LL | R.into_iter().for_each(|_x| {}); | ^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `R` error: useless conversion to the same type: `std::ops::Range` - --> tests/ui/useless_conversion.rs:452:13 + --> tests/ui/useless_conversion.rs:437:13 | LL | let _ = R.into_iter().map(|_x| 0); | ^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `R` error: useless conversion to the same type: `std::slice::Iter<'_, i32>` - --> tests/ui/useless_conversion.rs:463:14 + --> tests/ui/useless_conversion.rs:448:14 | LL | for _ in mac!(iter [1, 2]).into_iter() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `mac!(iter [1, 2])` -error: aborting due to 45 previous errors +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> tests/ui/useless_conversion.rs:461:27 + | +LL | takes_into_iter_usize(b.into_iter()); + | ^^^^^^^^^^^^^ + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> tests/ui/useless_conversion.rs:452:34 + | +LL | fn takes_into_iter_usize(_: impl IntoIterator) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider removing the `.into_iter()` + | +LL - takes_into_iter_usize(b.into_iter()); +LL + takes_into_iter_usize(b); + | + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> tests/ui/useless_conversion.rs:470:31 + | +LL | takes_into_iter_usize(b.clone().into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> tests/ui/useless_conversion.rs:452:34 + | +LL | fn takes_into_iter_usize(_: impl IntoIterator) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider removing the `.into_iter()` + | +LL - takes_into_iter_usize(b.clone().into_iter()); +LL + takes_into_iter_usize(b.clone()); + | + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> tests/ui/useless_conversion.rs:478:34 + | +LL | takes_into_iter_usize_result(b.clone().into_iter())?; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> tests/ui/useless_conversion.rs:453:41 + | +LL | fn takes_into_iter_usize_result(_: impl IntoIterator) -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider removing the `.into_iter()` + | +LL - takes_into_iter_usize_result(b.clone().into_iter())?; +LL + takes_into_iter_usize_result(b.clone())?; + | + +error: aborting due to 48 previous errors diff --git a/tests/ui/while_immutable_condition.rs b/tests/ui/while_immutable_condition.rs index 5c18cd41ff79..569a0c006aba 100644 --- a/tests/ui/while_immutable_condition.rs +++ b/tests/ui/while_immutable_condition.rs @@ -226,16 +226,4 @@ fn immutable_condition_false_positive(mut n: u64) -> u32 { count } -fn main() { - immutable_condition(); - unused_var(); - used_immutable(); - internally_mutable(); - immutable_condition_false_positive(5); - - let mut c = Counter { count: 0 }; - c.inc_n(5); - c.print_n(2); - - while_loop_with_break_and_return(); -} +fn main() {} From b26ef2a45d867135135f7fbe2d2545f95454b952 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Tue, 24 Feb 2026 05:08:42 +0000 Subject: [PATCH 13/38] fix: `cmp_owned` suggests wrongly on `PathBuf` --- clippy_lints/src/operators/cmp_owned.rs | 6 +++--- tests/ui/cmp_owned/with_suggestion.fixed | 8 ++++++++ tests/ui/cmp_owned/with_suggestion.rs | 8 ++++++++ tests/ui/cmp_owned/with_suggestion.stderr | 8 +++++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/operators/cmp_owned.rs b/clippy_lints/src/operators/cmp_owned.rs index db55772f4e01..7536db67b93c 100644 --- a/clippy_lints/src/operators/cmp_owned.rs +++ b/clippy_lints/src/operators/cmp_owned.rs @@ -100,10 +100,10 @@ fn check_op(cx: &LateContext<'_>, outer: &Expr<'_>, expr: &Expr<'_>, other: &Exp let mut applicability = Applicability::MachineApplicable; let (arg_snip, _) = snippet_with_context(cx, arg_span, expr.span.ctxt(), "..", &mut applicability); - let (expr_snip, eq_impl) = if with_deref.is_implemented() && !arg_ty.peel_refs().is_str() { - (format!("*{arg_snip}"), with_deref) - } else { + let (expr_snip, eq_impl) = if without_deref.is_implemented() { (arg_snip.to_string(), without_deref) + } else { + (format!("*{arg_snip}"), with_deref) }; let (span, hint) = if (eq_impl.ty_eq_other && left) || (eq_impl.other_eq_ty && !left) { diff --git a/tests/ui/cmp_owned/with_suggestion.fixed b/tests/ui/cmp_owned/with_suggestion.fixed index 471905b47df7..1a1f3ff1194b 100644 --- a/tests/ui/cmp_owned/with_suggestion.fixed +++ b/tests/ui/cmp_owned/with_suggestion.fixed @@ -150,3 +150,11 @@ fn issue16458() { required_version: String, m!().to_string(); } } + +fn issue16564(path: std::path::PathBuf) { + const ROOT: &str = "root"; + if path != *ROOT { + //~^ cmp_owned + todo!() + } +} diff --git a/tests/ui/cmp_owned/with_suggestion.rs b/tests/ui/cmp_owned/with_suggestion.rs index 3323176d34e3..185c56893787 100644 --- a/tests/ui/cmp_owned/with_suggestion.rs +++ b/tests/ui/cmp_owned/with_suggestion.rs @@ -150,3 +150,11 @@ macro_rules! all_comes_from_macro { required_version: String, m!().to_string(); } } + +fn issue16564(path: std::path::PathBuf) { + const ROOT: &str = "root"; + if path != std::path::PathBuf::from(ROOT) { + //~^ cmp_owned + todo!() + } +} diff --git a/tests/ui/cmp_owned/with_suggestion.stderr b/tests/ui/cmp_owned/with_suggestion.stderr index 3797810e3b98..7d9a12b1ddd3 100644 --- a/tests/ui/cmp_owned/with_suggestion.stderr +++ b/tests/ui/cmp_owned/with_suggestion.stderr @@ -68,5 +68,11 @@ LL | | } | = note: this error originates in the macro `all_comes_from_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 10 previous errors +error: this creates an owned instance just for comparison + --> tests/ui/cmp_owned/with_suggestion.rs:156:16 + | +LL | if path != std::path::PathBuf::from(ROOT) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `*ROOT` + +error: aborting due to 11 previous errors From 6d483b6b7687ef83c0e0097bb4dab2d7f3c48477 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sun, 22 Feb 2026 23:16:58 +0800 Subject: [PATCH 14/38] Remove redundant self usages --- clippy_lints/src/methods/iter_out_of_bounds.rs | 2 +- clippy_lints/src/methods/manual_contains.rs | 2 +- clippy_lints/src/types/linked_list.rs | 2 +- clippy_lints/src/types/owned_cow.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods/iter_out_of_bounds.rs b/clippy_lints/src/methods/iter_out_of_bounds.rs index f7d7df267967..a8ea43cf73e3 100644 --- a/clippy_lints/src/methods/iter_out_of_bounds.rs +++ b/clippy_lints/src/methods/iter_out_of_bounds.rs @@ -5,7 +5,7 @@ use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; -use rustc_middle::ty::{self}; +use rustc_middle::ty; use super::ITER_OUT_OF_BOUNDS; diff --git a/clippy_lints/src/methods/manual_contains.rs b/clippy_lints/src/methods/manual_contains.rs index 8ba0f835d3dd..d2906b2776f8 100644 --- a/clippy_lints/src/methods/manual_contains.rs +++ b/clippy_lints/src/methods/manual_contains.rs @@ -8,7 +8,7 @@ use rustc_hir::def::Res; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, HirId, QPath}; use rustc_lint::LateContext; -use rustc_middle::ty::{self}; +use rustc_middle::ty; use rustc_span::source_map::Spanned; use super::MANUAL_CONTAINS; diff --git a/clippy_lints/src/types/linked_list.rs b/clippy_lints/src/types/linked_list.rs index 96126d3d4320..abd6138655d7 100644 --- a/clippy_lints/src/types/linked_list.rs +++ b/clippy_lints/src/types/linked_list.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::sym; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir}; +use rustc_hir as hir; use rustc_lint::LateContext; use super::LINKEDLIST; diff --git a/clippy_lints/src/types/owned_cow.rs b/clippy_lints/src/types/owned_cow.rs index e70348b481c8..3a806cfef691 100644 --- a/clippy_lints/src/types/owned_cow.rs +++ b/clippy_lints/src/types/owned_cow.rs @@ -4,7 +4,7 @@ use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir}; +use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::Span; From c311ea2c1ce2726551a55c4b3b5f22760e76b338 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 25 Feb 2026 16:14:05 +0100 Subject: [PATCH 15/38] refactor: simplify `clippy_utils::mir::is_local_assignment` using `Body::stmt_at` --- clippy_utils/src/mir/mod.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/clippy_utils/src/mir/mod.rs b/clippy_utils/src/mir/mod.rs index a066427d6bc1..35adc51ee24c 100644 --- a/clippy_utils/src/mir/mod.rs +++ b/clippy_utils/src/mir/mod.rs @@ -1,3 +1,4 @@ +use rustc_data_structures::either::Either; use rustc_hir::{Expr, HirId}; use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; @@ -175,18 +176,15 @@ pub fn local_assignments(mir: &Body<'_>, local: Local) -> Vec { // `is_local_assignment` is based on `is_place_assignment`: // https://github.com/rust-lang/rust/blob/b7413511dc85ec01ef4b91785f86614589ac6103/compiler/rustc_middle/src/mir/visit.rs#L1350 fn is_local_assignment(mir: &Body<'_>, local: Local, location: Location) -> bool { - let Location { block, statement_index } = location; - let basic_block = &mir.basic_blocks[block]; - if statement_index < basic_block.statements.len() { - let statement = &basic_block.statements[statement_index]; - if let StatementKind::Assign(box (place, _)) = statement.kind { - place.as_local() == Some(local) - } else { - false - } - } else { - let terminator = basic_block.terminator(); - match &terminator.kind { + match mir.stmt_at(location) { + Either::Left(statement) => { + if let StatementKind::Assign(box (place, _)) = statement.kind { + place.as_local() == Some(local) + } else { + false + } + }, + Either::Right(terminator) => match &terminator.kind { TerminatorKind::Call { destination, .. } => destination.as_local() == Some(local), TerminatorKind::InlineAsm { operands, .. } => operands.iter().any(|operand| { if let InlineAsmOperand::Out { place: Some(place), .. } = operand { @@ -196,6 +194,6 @@ fn is_local_assignment(mir: &Body<'_>, local: Local, location: Location) -> bool } }), _ => false, - } + }, } } From c91298aaa0b246ecbd7905cefeae374e95a5a661 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 25 Feb 2026 16:14:05 +0100 Subject: [PATCH 16/38] refactor(`clippy_utils::mir::visit_local_usage`): use const generics encodes the direct relationship between the lengths of `locals` and the returned list, making the code more type-safe --- .../src/methods/readonly_write_lock.rs | 5 +-- clippy_lints/src/redundant_clone.rs | 28 ++++++------- clippy_utils/src/mir/mod.rs | 39 +++++++++++-------- 3 files changed, 38 insertions(+), 34 deletions(-) diff --git a/clippy_lints/src/methods/readonly_write_lock.rs b/clippy_lints/src/methods/readonly_write_lock.rs index a98a807d1a3c..b89aa8dfb4db 100644 --- a/clippy_lints/src/methods/readonly_write_lock.rs +++ b/clippy_lints/src/methods/readonly_write_lock.rs @@ -38,15 +38,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, receiver .local_decls .iter_enumerated() .find(|(_, decl)| local.span.contains(decl.source_info.span)) - && let Some(usages) = visit_local_usage( - &[local], + && let Some([usage]) = visit_local_usage( + [local], mir, Location { block: START_BLOCK, statement_index: 0, }, ) - && let [usage] = usages.as_slice() { let writer_never_mutated = usage.local_consume_or_mutate_locs.is_empty(); diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 13c1b10bf2e8..232f0e0ec4c4 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -368,25 +368,25 @@ struct CloneUsage { } fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>, bb: mir::BasicBlock) -> CloneUsage { - if let Some(( - LocalUsage { - local_use_locs: cloned_use_locs, - local_consume_or_mutate_locs: cloned_consume_or_mutate_locs, - }, - LocalUsage { - local_use_locs: _, - local_consume_or_mutate_locs: clone_consume_or_mutate_locs, - }, - )) = visit_local_usage( - &[cloned, clone], + if let Some( + [ + LocalUsage { + local_use_locs: cloned_use_locs, + local_consume_or_mutate_locs: cloned_consume_or_mutate_locs, + }, + LocalUsage { + local_use_locs: _, + local_consume_or_mutate_locs: clone_consume_or_mutate_locs, + }, + ], + ) = visit_local_usage( + [cloned, clone], mir, mir::Location { block: bb, statement_index: mir.basic_blocks[bb].statements.len(), }, - ) - .map(|mut vec| (vec.remove(0), vec.remove(0))) - { + ) { CloneUsage { cloned_use_loc: cloned_use_locs.first().copied().into(), cloned_consume_or_mutate_loc: cloned_consume_or_mutate_locs.first().copied(), diff --git a/clippy_utils/src/mir/mod.rs b/clippy_utils/src/mir/mod.rs index 35adc51ee24c..40c553d1c9e6 100644 --- a/clippy_utils/src/mir/mod.rs +++ b/clippy_utils/src/mir/mod.rs @@ -1,3 +1,5 @@ +use std::iter; + use rustc_data_structures::either::Either; use rustc_hir::{Expr, HirId}; use rustc_index::bit_set::DenseBitSet; @@ -22,14 +24,17 @@ pub struct LocalUsage { pub local_consume_or_mutate_locs: Vec, } -pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) -> Option> { - let init = vec![ +pub fn visit_local_usage( + locals: [Local; N], + mir: &Body<'_>, + location: Location, +) -> Option<[LocalUsage; N]> { + let init = [const { LocalUsage { local_use_locs: Vec::new(), local_consume_or_mutate_locs: Vec::new(), - }; - locals.len() - ]; + } + }; N]; traversal::Postorder::new(&mir.basic_blocks, location.block, None) .collect::>() @@ -44,7 +49,7 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) - } let mut v = V { - locals, + locals: &locals, location, results: usage, }; @@ -53,13 +58,13 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) - }) } -struct V<'a> { - locals: &'a [Local], +struct V<'a, const N: usize> { + locals: &'a [Local; N], location: Location, - results: Vec, + results: [LocalUsage; N], } -impl<'tcx> Visitor<'tcx> for V<'_> { +impl<'tcx, const N: usize> Visitor<'tcx> for V<'_, N> { fn visit_place(&mut self, place: &Place<'tcx>, ctx: PlaceContext, loc: Location) { if loc.block == self.location.block && loc.statement_index <= self.location.statement_index { return; @@ -67,20 +72,20 @@ fn visit_place(&mut self, place: &Place<'tcx>, ctx: PlaceContext, loc: Location) let local = place.local; - for (i, self_local) in self.locals.iter().enumerate() { + for (self_local, result) in iter::zip(self.locals, &mut self.results) { if local == *self_local { if !matches!( ctx, PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_) ) { - self.results[i].local_use_locs.push(loc); + result.local_use_locs.push(loc); } if matches!( ctx, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move | NonMutatingUseContext::Inspect) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) ) { - self.results[i].local_consume_or_mutate_locs.push(loc); + result.local_consume_or_mutate_locs.push(loc); } } } @@ -114,16 +119,16 @@ pub fn block_in_cycle(body: &Body<'_>, block: BasicBlock) -> bool { /// Convenience wrapper around `visit_local_usage`. pub fn used_exactly_once(mir: &Body<'_>, local: Local) -> Option { visit_local_usage( - &[local], + [local], mir, Location { block: START_BLOCK, statement_index: 0, }, ) - .map(|mut vec| { - let LocalUsage { local_use_locs, .. } = vec.remove(0); - let mut locations = local_use_locs + .map(|[local_usage]| { + let mut locations = local_usage + .local_use_locs .into_iter() .filter(|&location| !is_local_assignment(mir, local, location)); if let Some(location) = locations.next() { From 55225173f206c0b49f008066afd2cf4625bdacf1 Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 23 Feb 2026 12:54:00 +0900 Subject: [PATCH 17/38] Fix `infinite_loop` wrong suggestion inside conditional branches --- clippy_lints/src/loops/infinite_loop.rs | 12 ++- tests/ui/infinite_loops.rs | 53 ++++++++++ tests/ui/infinite_loops.stderr | 131 +++++++++++++++++++----- 3 files changed, 166 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/loops/infinite_loop.rs b/clippy_lints/src/loops/infinite_loop.rs index 74c0b1780189..f3d5611b0479 100644 --- a/clippy_lints/src/loops/infinite_loop.rs +++ b/clippy_lints/src/loops/infinite_loop.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{fn_def_id, is_from_proc_macro, is_lint_allowed}; +use clippy_utils::{RequiresSemi, fn_def_id, is_from_proc_macro, is_lint_allowed, is_never_expr}; use hir::intravisit::{Visitor, walk_expr}; use rustc_ast::Label; use rustc_errors::Applicability; @@ -52,16 +52,20 @@ pub(super) fn check<'tcx>( if !is_finite_loop { span_lint_and_then(cx, INFINITE_LOOP, expr.span, "infinite loop detected", |diag| { - if let FnRetTy::DefaultReturn(ret_span) = parent_fn_ret { + if let FnRetTy::DefaultReturn(ret_span) = parent_fn_ret + && cx + .enclosing_body + .is_some_and(|id| matches!(is_never_expr(cx, cx.tcx.hir_body(id).value), Some(RequiresSemi::No))) + { diag.span_suggestion( ret_span, "if this is intentional, consider specifying `!` as function return", " -> !", Applicability::MaybeIncorrect, ); - } else { - diag.help("if this is not intended, try adding a `break` or `return` condition in the loop"); } + + diag.help("if this is not intended, try adding a `break` or `return` to the loop"); }); } } diff --git a/tests/ui/infinite_loops.rs b/tests/ui/infinite_loops.rs index 0bde31aca030..88e3328d662e 100644 --- a/tests/ui/infinite_loops.rs +++ b/tests/ui/infinite_loops.rs @@ -536,4 +536,57 @@ async fn bad() { } } +mod issue16155 { + #![allow(clippy::empty_loop)] + + use super::do_something; + + fn let_then_else(cond: bool) { + let true = cond else { loop {} }; + //~^ infinite_loop + } + + fn loop_in_one_if_branch(cond: bool) { + if cond { + loop {} + //~^ infinite_loop + } + } + + fn loop_in_one_match_arm(x: Option) { + match x { + Some(_) => {}, + None => loop {}, + //~^ infinite_loop + } + } + + fn loop_in_if_let_else(x: Option) { + if let Some(_val) = x { + do_something(); + } else { + loop {} + //~^ infinite_loop + } + } + + #[expect(clippy::if_same_then_else)] + fn all_branches_diverge_if(cond: bool) { + if cond { + loop {} + //~^ infinite_loop + } else { + loop {} + //~^ infinite_loop + } + } + + fn all_branches_diverge_match(x: Option) { + match x { + Some(_) => loop {}, //~ infinite_loop + None => loop {}, //~ infinite_loop + } + } +} + fn main() {} diff --git a/tests/ui/infinite_loops.stderr b/tests/ui/infinite_loops.stderr index 319f1e5012b6..9c2b4667b979 100644 --- a/tests/ui/infinite_loops.stderr +++ b/tests/ui/infinite_loops.stderr @@ -7,6 +7,7 @@ LL | | do_something(); LL | | } | |_____^ | + = help: if this is not intended, try adding a `break` or `return` to the loop = note: `-D clippy::infinite-loop` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::infinite_loop)]` help: if this is intentional, consider specifying `!` as function return @@ -25,6 +26,7 @@ LL | | do_something(); LL | | } | |_____^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn all_inf() -> ! { @@ -40,6 +42,7 @@ LL | | loop { LL | | } | |_________^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn all_inf() -> ! { @@ -54,6 +57,7 @@ LL | | do_something(); LL | | } | |_____________^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn all_inf() -> ! { @@ -68,7 +72,7 @@ LL | | do_something(); LL | | } | |_____^ | - = help: if this is not intended, try adding a `break` or `return` condition in the loop + = help: if this is not intended, try adding a `break` or `return` to the loop error: infinite loop detected --> tests/ui/infinite_loops.rs:51:5 @@ -82,6 +86,7 @@ LL | | do_something(); LL | | } | |_____^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn no_break_never_ret_noise() -> ! { @@ -98,6 +103,7 @@ LL | | if cond { LL | | } | |_____^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn break_inner_but_not_outer_1(cond: bool) -> ! { @@ -114,6 +120,7 @@ LL | | loop { LL | | } | |_____^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn break_inner_but_not_outer_2(cond: bool) -> ! { @@ -128,10 +135,7 @@ LL | | do_something(); LL | | } | |_________^ | -help: if this is intentional, consider specifying `!` as function return - | -LL | fn break_outer_but_not_inner() -> ! { - | ++++ + = help: if this is not intended, try adding a `break` or `return` to the loop error: infinite loop detected --> tests/ui/infinite_loops.rs:143:9 @@ -144,10 +148,7 @@ LL | | loop { LL | | } | |_________^ | -help: if this is intentional, consider specifying `!` as function return - | -LL | fn break_wrong_loop(cond: bool) -> ! { - | ++++ + = help: if this is not intended, try adding a `break` or `return` to the loop error: infinite loop detected --> tests/ui/infinite_loops.rs:183:5 @@ -160,10 +161,7 @@ LL | | Some(v) => { LL | | } | |_____^ | -help: if this is intentional, consider specifying `!` as function return - | -LL | fn match_like() -> ! { - | ++++ + = help: if this is not intended, try adding a `break` or `return` to the loop error: infinite loop detected --> tests/ui/infinite_loops.rs:224:5 @@ -174,10 +172,7 @@ LL | | let _x = matches!(result, Ok(v) if v != 0).then_some(0); LL | | } | |_____^ | -help: if this is intentional, consider specifying `!` as function return - | -LL | fn match_like() -> ! { - | ++++ + = help: if this is not intended, try adding a `break` or `return` to the loop error: infinite loop detected --> tests/ui/infinite_loops.rs:229:5 @@ -191,10 +186,7 @@ LL | | }); LL | | } | |_____^ | -help: if this is intentional, consider specifying `!` as function return - | -LL | fn match_like() -> ! { - | ++++ + = help: if this is not intended, try adding a `break` or `return` to the loop error: infinite loop detected --> tests/ui/infinite_loops.rs:334:9 @@ -205,6 +197,7 @@ LL | | do_something(); LL | | } | |_________^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn problematic_trait_method() -> ! { @@ -219,6 +212,7 @@ LL | | do_something(); LL | | } | |_________^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn could_be_problematic() -> ! { @@ -233,6 +227,7 @@ LL | | do_something(); LL | | } | |_________^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | let _loop_forever = || -> ! { @@ -248,7 +243,7 @@ LL | | do_something() LL | | }) | |_____^ | - = help: if this is not intended, try adding a `break` or `return` condition in the loop + = help: if this is not intended, try adding a `break` or `return` to the loop error: infinite loop detected --> tests/ui/infinite_loops.rs:410:5 @@ -261,6 +256,7 @@ LL | | } LL | | } | |_____^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn continue_outer() -> ! { @@ -276,6 +272,7 @@ LL | | 'inner: loop { LL | | } | |_____^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn continue_outer() -> ! { @@ -292,6 +289,7 @@ LL | | } LL | | } | |_________^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn continue_outer() -> ! { @@ -306,6 +304,7 @@ LL | | continue; LL | | } | |_____^ | + = help: if this is not intended, try adding a `break` or `return` to the loop help: if this is intentional, consider specifying `!` as function return | LL | fn continue_outer() -> ! { @@ -320,7 +319,7 @@ LL | | do_something(); LL | | } | |_____________^ | - = help: if this is not intended, try adding a `break` or `return` condition in the loop + = help: if this is not intended, try adding a `break` or `return` to the loop error: infinite loop detected --> tests/ui/infinite_loops.rs:466:13 @@ -331,7 +330,7 @@ LL | | continue; LL | | } | |_____________^ | - = help: if this is not intended, try adding a `break` or `return` condition in the loop + = help: if this is not intended, try adding a `break` or `return` to the loop error: infinite loop detected --> tests/ui/infinite_loops.rs:533:9 @@ -341,7 +340,87 @@ LL | | std::future::pending().await LL | | } | |_________^ | - = help: if this is not intended, try adding a `break` or `return` condition in the loop + = help: if this is not intended, try adding a `break` or `return` to the loop -error: aborting due to 24 previous errors +error: infinite loop detected + --> tests/ui/infinite_loops.rs:545:32 + | +LL | let true = cond else { loop {} }; + | ^^^^^^^ + | + = help: if this is not intended, try adding a `break` or `return` to the loop + +error: infinite loop detected + --> tests/ui/infinite_loops.rs:551:13 + | +LL | loop {} + | ^^^^^^^ + | + = help: if this is not intended, try adding a `break` or `return` to the loop + +error: infinite loop detected + --> tests/ui/infinite_loops.rs:559:21 + | +LL | None => loop {}, + | ^^^^^^^ + | + = help: if this is not intended, try adding a `break` or `return` to the loop + +error: infinite loop detected + --> tests/ui/infinite_loops.rs:568:13 + | +LL | loop {} + | ^^^^^^^ + | + = help: if this is not intended, try adding a `break` or `return` to the loop + +error: infinite loop detected + --> tests/ui/infinite_loops.rs:576:13 + | +LL | loop {} + | ^^^^^^^ + | + = help: if this is not intended, try adding a `break` or `return` to the loop +help: if this is intentional, consider specifying `!` as function return + | +LL | fn all_branches_diverge_if(cond: bool) -> ! { + | ++++ + +error: infinite loop detected + --> tests/ui/infinite_loops.rs:579:13 + | +LL | loop {} + | ^^^^^^^ + | + = help: if this is not intended, try adding a `break` or `return` to the loop +help: if this is intentional, consider specifying `!` as function return + | +LL | fn all_branches_diverge_if(cond: bool) -> ! { + | ++++ + +error: infinite loop detected + --> tests/ui/infinite_loops.rs:586:24 + | +LL | Some(_) => loop {}, + | ^^^^^^^ + | + = help: if this is not intended, try adding a `break` or `return` to the loop +help: if this is intentional, consider specifying `!` as function return + | +LL | fn all_branches_diverge_match(x: Option) -> ! { + | ++++ + +error: infinite loop detected + --> tests/ui/infinite_loops.rs:587:21 + | +LL | None => loop {}, + | ^^^^^^^ + | + = help: if this is not intended, try adding a `break` or `return` to the loop +help: if this is intentional, consider specifying `!` as function return + | +LL | fn all_branches_diverge_match(x: Option) -> ! { + | ++++ + +error: aborting due to 32 previous errors From 4b2e965f8e7c8bdc91f38820e140e3f9886a0ebd Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Fri, 27 Feb 2026 02:32:14 +0000 Subject: [PATCH 18/38] fix: `redundant_closure` suggests wrongly when local is derefed to callable --- clippy_lints/src/eta_reduction.rs | 24 ++++++++++++------------ tests/ui/eta.fixed | 9 +++++++++ tests/ui/eta.rs | 9 +++++++++ tests/ui/eta.stderr | 8 +++++++- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 3e46c370fb70..172b0bc0f9ed 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -216,6 +216,18 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx "redundant closure", |diag| { if let Some(mut snippet) = snippet_opt(cx, callee.span) { + let n_refs = callee_ty_adjustments + .iter() + .rev() + .fold(0, |acc, adjustment| match adjustment.kind { + Adjust::Deref(DerefAdjustKind::Overloaded(_)) => acc + 1, + Adjust::Deref(_) if acc > 0 => acc + 1, + _ => acc, + }); + if n_refs > 0 { + snippet = format!("{}{snippet}", "*".repeat(n_refs)); + } + if callee.res_local_id().is_some_and(|l| { // FIXME: Do we really need this `local_used_in` check? // Isn't it checking something like... `callee(callee)`? @@ -231,18 +243,6 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx }, _ => (), } - } else if let n_refs = - callee_ty_adjustments - .iter() - .rev() - .fold(0, |acc, adjustment| match adjustment.kind { - Adjust::Deref(DerefAdjustKind::Overloaded(_)) => acc + 1, - Adjust::Deref(_) if acc > 0 => acc + 1, - _ => acc, - }) - && n_refs > 0 - { - snippet = format!("{}{snippet}", "*".repeat(n_refs)); } let replace_with = match callee_ty_adjusted.kind() { diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index fdaf1c37b201..41e5bbe3cbed 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -652,3 +652,12 @@ trait Issue16360: Sized { //~^ redundant_closure_for_method_calls } } + +fn issue16641() { + use std::cell::LazyCell; + + let closure = LazyCell::new(|| |x: usize| println!("{x}")); + + (0..10).flat_map(|x| (0..10).map(&*closure)).count(); + //~^ redundant_closure +} diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 1054060db449..de0d3fb63c51 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -652,3 +652,12 @@ trait Issue16360: Sized { //~^ redundant_closure_for_method_calls } } + +fn issue16641() { + use std::cell::LazyCell; + + let closure = LazyCell::new(|| |x: usize| println!("{x}")); + + (0..10).flat_map(|x| (0..10).map(|y| closure(y))).count(); + //~^ redundant_closure +} diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 2e0ccc557915..c19947cddafa 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -262,5 +262,11 @@ error: redundant closure LL | array.iter().for_each(|item| item.method()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `Self::method` -error: aborting due to 43 previous errors +error: redundant closure + --> tests/ui/eta.rs:661:38 + | +LL | (0..10).flat_map(|x| (0..10).map(|y| closure(y))).count(); + | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&*closure` + +error: aborting due to 44 previous errors From 5218b85416f8480a17f0e08758de06dae794b9c1 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Fri, 27 Feb 2026 02:21:32 +0000 Subject: [PATCH 19/38] fix: `explicit_counter_loop` FP when the initializer is not integral --- .../src/loops/explicit_counter_loop.rs | 133 +++++++++--------- tests/ui/explicit_counter_loop.rs | 15 ++ 2 files changed, 84 insertions(+), 64 deletions(-) diff --git a/clippy_lints/src/loops/explicit_counter_loop.rs b/clippy_lints/src/loops/explicit_counter_loop.rs index bfd4d4bcd564..9bfc3aa56648 100644 --- a/clippy_lints/src/loops/explicit_counter_loop.rs +++ b/clippy_lints/src/loops/explicit_counter_loop.rs @@ -28,72 +28,77 @@ pub(super) fn check<'tcx>( // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. - if let Some(block) = get_enclosing_block(cx, expr.hir_id) { - for id in increment_visitor.into_results() { - let mut initialize_visitor = InitializeVisitor::new(cx, expr, id); - walk_block(&mut initialize_visitor, block); + let Some(block) = get_enclosing_block(cx, expr.hir_id) else { + return; + }; - if let Some((name, ty, initializer)) = initialize_visitor.get_result() { - let is_zero = is_integer_const(cx, initializer, 0); - let mut applicability = Applicability::MaybeIncorrect; - let span = expr.span.with_hi(arg.span.hi()); - let loop_label = label.map_or(String::new(), |l| format!("{}: ", l.ident.name)); + for id in increment_visitor.into_results() { + let mut initialize_visitor = InitializeVisitor::new(cx, expr, id); + walk_block(&mut initialize_visitor, block); - span_lint_and_then( - cx, - EXPLICIT_COUNTER_LOOP, - span, - format!("the variable `{name}` is used as a loop counter"), - |diag| { - let pat_snippet = snippet_with_applicability(cx, pat.span, "item", &mut applicability); - let iter_snippet = make_iterator_snippet(cx, arg, &mut applicability); - let int_name = match ty.map(Ty::kind) { - Some(ty::Uint(UintTy::Usize)) | None => { - if is_zero { - diag.span_suggestion( - span, - "consider using", - format!( - "{loop_label}for ({name}, {pat_snippet}) in {iter_snippet}.enumerate()", - ), - applicability, - ); - return; - } - None - }, - Some(ty::Int(int_ty)) => Some(int_ty.name_str()), - Some(ty::Uint(uint_ty)) => Some(uint_ty.name_str()), - _ => None, - } - .filter(|_| is_integer_literal_untyped(initializer)); - - let initializer = Sugg::hir_from_snippet(cx, initializer, |span| { - let snippet = snippet_with_applicability(cx, span, "..", &mut applicability); - if let Some(int_name) = int_name { - return Cow::Owned(format!("{snippet}_{int_name}")); - } - snippet - }); - - diag.span_suggestion( - span, - "consider using", - format!( - "{loop_label}for ({name}, {pat_snippet}) in ({}).zip({iter_snippet})", - initializer.range(&EMPTY, RangeLimits::HalfOpen) - ), - applicability, - ); - - if is_zero && let Some(int_name) = int_name { - diag.note(format!( - "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`" - )); - } - }, - ); - } + let Some((name, ty, initializer)) = initialize_visitor.get_result() else { + continue; + }; + if !cx.typeck_results().expr_ty(initializer).is_integral() { + continue; } + + let is_zero = is_integer_const(cx, initializer, 0); + let mut applicability = Applicability::MaybeIncorrect; + let span = expr.span.with_hi(arg.span.hi()); + let loop_label = label.map_or(String::new(), |l| format!("{}: ", l.ident.name)); + + span_lint_and_then( + cx, + EXPLICIT_COUNTER_LOOP, + span, + format!("the variable `{name}` is used as a loop counter"), + |diag| { + let pat_snippet = snippet_with_applicability(cx, pat.span, "item", &mut applicability); + let iter_snippet = make_iterator_snippet(cx, arg, &mut applicability); + let int_name = match ty.map(Ty::kind) { + Some(ty::Uint(UintTy::Usize)) | None => { + if is_zero { + diag.span_suggestion( + span, + "consider using", + format!("{loop_label}for ({name}, {pat_snippet}) in {iter_snippet}.enumerate()"), + applicability, + ); + return; + } + None + }, + Some(ty::Int(int_ty)) => Some(int_ty.name_str()), + Some(ty::Uint(uint_ty)) => Some(uint_ty.name_str()), + _ => None, + } + .filter(|_| is_integer_literal_untyped(initializer)); + + let initializer = Sugg::hir_from_snippet(cx, initializer, |span| { + let snippet = snippet_with_applicability(cx, span, "..", &mut applicability); + if let Some(int_name) = int_name { + return Cow::Owned(format!("{snippet}_{int_name}")); + } + snippet + }); + + diag.span_suggestion( + span, + "consider using", + format!( + "{loop_label}for ({name}, {pat_snippet}) in ({}).zip({iter_snippet})", + initializer.range(&EMPTY, RangeLimits::HalfOpen) + ), + applicability, + ); + + if is_zero && let Some(int_name) = int_name { + diag.note(format!( + "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`" + )); + } + }, + ); } } diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs index ebb261a0d97a..79968700f8e4 100644 --- a/tests/ui/explicit_counter_loop.rs +++ b/tests/ui/explicit_counter_loop.rs @@ -317,3 +317,18 @@ fn issue16612(v: Vec, s: i64) { j += 1; } } + +fn issue16640(x: &[u8]) { + struct Priority(u8); + + impl core::ops::AddAssign for Priority { + fn add_assign(&mut self, rhs: u8) { + self.0 += rhs + } + } + + let mut priority = Priority(1); + for _val in x { + priority += 1; + } +} From 5904d42592f57c306648182814f6ed1cdb69abe1 Mon Sep 17 00:00:00 2001 From: BenjaminBrienen Date: Thu, 5 Feb 2026 14:07:47 +0100 Subject: [PATCH 20/38] fix(doc_paragraphs_missing_punctuation): Trim emojis and picture symbols when looking for punctuation --- .../doc/doc_paragraphs_missing_punctuation.rs | 22 ++++++++++++++----- ...oc_paragraphs_missing_punctuation_emoji.rs | 12 ++++++++++ ...aragraphs_missing_punctuation_emoji.stderr | 11 ++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 tests/ui/doc/doc_paragraphs_missing_punctuation_emoji.rs create mode 100644 tests/ui/doc/doc_paragraphs_missing_punctuation_emoji.stderr diff --git a/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs b/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs index 605d35f48baf..cafb33aaa881 100644 --- a/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs +++ b/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs @@ -94,17 +94,14 @@ fn is_missing_punctuation(doc_string: &str) -> Vec { Event::Code(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) if no_report_depth == 0 && !offset.is_empty() => { - if doc_string[..offset.end] - .trim_end() - .ends_with(TERMINAL_PUNCTUATION_MARKS) - { + if trim_trailing_symbols(&doc_string[..offset.end]).ends_with(TERMINAL_PUNCTUATION_MARKS) { current_paragraph = None; } else { current_paragraph = Some(MissingPunctuation::Fixable(offset.end)); } }, Event::Text(..) if no_report_depth == 0 && !offset.is_empty() => { - let trimmed = doc_string[..offset.end].trim_end(); + let trimmed = trim_trailing_symbols(&doc_string[..offset.end]); if trimmed.ends_with(TERMINAL_PUNCTUATION_MARKS) { current_paragraph = None; } else if let Some(t) = trimmed.strip_suffix(|c| c == ')' || c == '"') { @@ -125,6 +122,21 @@ fn is_missing_punctuation(doc_string: &str) -> Vec { missing_punctuation } +fn trim_trailing_symbols(s: &str) -> &str { + s.trim_end_matches(|c: char| + // Source: https://unicodeplus.com + matches!(c as u32, + 0x1F300..=0x1F5FF | // Miscellaneous Symbols and Pictographs + 0x1F600..=0x1F64F | // Emoticons + 0x1F900..=0x1F9FF | // Supplemental Symbols and Pictographs + 0x2700..=0x27BF | // Dingbats + 0x1FA70..=0x1FAFF | // Symbols and Pictographs Extended-A + 0x1F680..=0x1F6FF | // Transport and Map Symbols + 0x2600..=0x26FF | // Miscellaneous Symbols + 0xFE00..=0xFE0F // Variation selectors + ) || c.is_whitespace()) +} + #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum MissingPunctuation { Fixable(usize), diff --git a/tests/ui/doc/doc_paragraphs_missing_punctuation_emoji.rs b/tests/ui/doc/doc_paragraphs_missing_punctuation_emoji.rs new file mode 100644 index 000000000000..361e09b554a5 --- /dev/null +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation_emoji.rs @@ -0,0 +1,12 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] +#![warn(clippy::doc_paragraphs_missing_punctuation)] +//@no-rustfix + +enum EmojiTrailers { + /// Sometimes the doc comment ends with an emoji! 😅 + ExistingPunctuationBeforeEmoji, + /// But it may still be missing punctuation 😢 + //~^ doc_paragraphs_missing_punctuation + MissingPunctuationBeforeEmoji, +} diff --git a/tests/ui/doc/doc_paragraphs_missing_punctuation_emoji.stderr b/tests/ui/doc/doc_paragraphs_missing_punctuation_emoji.stderr new file mode 100644 index 000000000000..1eb1a77e4017 --- /dev/null +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation_emoji.stderr @@ -0,0 +1,11 @@ +error: doc paragraphs should end with a terminal punctuation mark + --> tests/ui/doc/doc_paragraphs_missing_punctuation_emoji.rs:9:50 + | +LL | /// But it may still be missing punctuation 😢 + | ^ help: end the paragraph with some punctuation: `.` + | + = note: `-D clippy::doc-paragraphs-missing-punctuation` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_paragraphs_missing_punctuation)]` + +error: aborting due to 1 previous error + From 05f6bc90411a53a1acfcfd76697003e58bfd431d Mon Sep 17 00:00:00 2001 From: Benno Lossin Date: Fri, 20 Feb 2026 15:13:17 +0100 Subject: [PATCH 21/38] add field representing types --- clippy_lints/src/dereference.rs | 1 + clippy_utils/src/check_proc_macro.rs | 1 + clippy_utils/src/hir_utils.rs | 9 ++++++++- clippy_utils/src/sym.rs | 1 - 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 954f071b4068..3433ab511b07 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -852,6 +852,7 @@ fn for_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Self { | TyKind::Ptr(_) | TyKind::FnPtr(_) | TyKind::Pat(..) + | TyKind::FieldOf(..) | TyKind::Never | TyKind::Tup(_) | TyKind::Path(_) => Self::Deref, diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index def5d968b063..14389b0d29bb 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -531,6 +531,7 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { // experimental | TyKind::Pat(..) + | TyKind::FieldOf(..) // unused | TyKind::CVarArgs diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 3ff40f2fb722..11d0cee00d0d 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -14,7 +14,7 @@ GenericParam, GenericParamKind, GenericParamSource, Generics, HirId, HirIdMap, InlineAsmOperand, ItemId, ItemKind, LetExpr, Lifetime, LifetimeKind, LifetimeParamKind, Node, ParamName, Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PreciseCapturingArgKind, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, TraitBoundModifiers, Ty, - TyKind, TyPat, TyPatKind, UseKind, WherePredicate, WherePredicateKind, + TyFieldPath, TyKind, TyPat, TyPatKind, UseKind, WherePredicate, WherePredicateKind, }; use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize}; use rustc_lint::LateContext; @@ -1529,6 +1529,13 @@ pub fn hash_tykind(&mut self, ty: &TyKind<'_>) { self.hash_ty(ty); self.hash_ty_pat(pat); }, + TyKind::FieldOf(base, TyFieldPath { variant, field }) => { + self.hash_ty(base); + if let Some(variant) = variant { + self.hash_name(variant.name); + } + self.hash_name(field.name); + }, TyKind::Ptr(mut_ty) => { self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index 6965225c12ab..a2c87fe913d6 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -257,7 +257,6 @@ macro_rules! generate { f64_legacy_const_nan, f64_legacy_const_neg_infinity, f64_legacy_const_radix, - field, file_options, filter, filter_map, From b7e135a3197bfa0191cbb950256226c6537f677f Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 28 Feb 2026 01:12:38 +0100 Subject: [PATCH 22/38] Remove extra space in `must_use_candidate` lint output --- clippy_lints/src/functions/must_use.rs | 2 +- tests/ui/must_use_candidates.fixed | 14 +++++++------- tests/ui/must_use_candidates.stderr | 14 +++++++------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index 9ba5d203a427..a98d206e9d5c 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -221,7 +221,7 @@ fn check_must_use_candidate<'tcx>( diag.span_suggestion( item_span.shrink_to_lo(), "add the attribute", - format!("#[must_use] \n{indent}"), + format!("#[must_use]\n{indent}"), Applicability::MachineApplicable, ); if let Some(msg) = match return_ty(cx, item_id).opt_diag_name(cx) { diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed index 10dc5f9157b7..17569884658b 100644 --- a/tests/ui/must_use_candidates.fixed +++ b/tests/ui/must_use_candidates.fixed @@ -13,14 +13,14 @@ use std::sync::atomic::{AtomicBool, Ordering}; pub struct MyAtomic(AtomicBool); pub struct MyPure; -#[must_use] +#[must_use] pub fn pure(i: u8) -> u8 { //~^ must_use_candidate i } impl MyPure { - #[must_use] + #[must_use] pub fn inherent_pure(&self) -> u8 { //~^ must_use_candidate 0 @@ -53,7 +53,7 @@ pub fn with_callback bool>(f: &F) -> bool { f(0) } -#[must_use] +#[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { //~^ must_use_candidate true @@ -67,7 +67,7 @@ pub fn atomics(b: &AtomicBool) -> bool { b.load(Ordering::SeqCst) } -#[must_use] +#[must_use] pub fn rcd(_x: Rc) -> bool { //~^ must_use_candidate true @@ -77,7 +77,7 @@ pub fn rcmut(_x: Rc<&mut u32>) -> bool { true } -#[must_use] +#[must_use] pub fn arcd(_x: Arc) -> bool { //~^ must_use_candidate false @@ -110,13 +110,13 @@ pub fn main() -> std::process::ExitCode { } //~v must_use_candidate -#[must_use] +#[must_use] pub fn result_uninhabited() -> Result { todo!() } //~v must_use_candidate -#[must_use] +#[must_use] pub fn controlflow_uninhabited() -> std::ops::ControlFlow { todo!() } diff --git a/tests/ui/must_use_candidates.stderr b/tests/ui/must_use_candidates.stderr index f2ec9b265c45..38c733432250 100644 --- a/tests/ui/must_use_candidates.stderr +++ b/tests/ui/must_use_candidates.stderr @@ -8,7 +8,7 @@ LL | pub fn pure(i: u8) -> u8 { = help: to override `-D warnings` add `#[allow(clippy::must_use_candidate)]` help: add the attribute | -LL + #[must_use] +LL + #[must_use] LL | pub fn pure(i: u8) -> u8 { | @@ -20,7 +20,7 @@ LL | pub fn inherent_pure(&self) -> u8 { | help: add the attribute | -LL ~ #[must_use] +LL ~ #[must_use] LL ~ pub fn inherent_pure(&self) -> u8 { | @@ -32,7 +32,7 @@ LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { | help: add the attribute | -LL + #[must_use] +LL + #[must_use] LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { | @@ -44,7 +44,7 @@ LL | pub fn rcd(_x: Rc) -> bool { | help: add the attribute | -LL + #[must_use] +LL + #[must_use] LL | pub fn rcd(_x: Rc) -> bool { | @@ -56,7 +56,7 @@ LL | pub fn arcd(_x: Arc) -> bool { | help: add the attribute | -LL + #[must_use] +LL + #[must_use] LL | pub fn arcd(_x: Arc) -> bool { | @@ -69,7 +69,7 @@ LL | pub fn result_uninhabited() -> Result { = note: a future version of Rust will treat `Result` as `T` when `E` is uninhabited wrt `#[must_use]` help: add the attribute | -LL + #[must_use] +LL + #[must_use] LL | pub fn result_uninhabited() -> Result { | @@ -82,7 +82,7 @@ LL | pub fn controlflow_uninhabited() -> std::ops::ControlFlow` as `C` when `B` is uninhabited wrt `#[must_use]` help: add the attribute | -LL + #[must_use] +LL + #[must_use] LL | pub fn controlflow_uninhabited() -> std::ops::ControlFlow { | From 3ebcade8ff84bb58b996ab3c39a330bde659bf9d Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Mon, 23 Feb 2026 12:31:24 +0900 Subject: [PATCH 23/38] Add `eq_impl_restriction` to clippy_utils --- clippy_utils/src/ast_utils/mod.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index 67ae1dcef81b..50cfb0ed89de 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -449,6 +449,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { constness: lc, is_auto: la, safety: lu, + impl_restriction: liprt, ident: li, generics: lg, bounds: lb, @@ -458,6 +459,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { constness: rc, is_auto: ra, safety: ru, + impl_restriction: riprt, ident: ri, generics: rg, bounds: rb, @@ -467,6 +469,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { matches!(lc, ast::Const::No) == matches!(rc, ast::Const::No) && la == ra && matches!(lu, Safety::Default) == matches!(ru, Safety::Default) + && eq_impl_restriction(liprt, riprt) && eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) @@ -834,6 +837,29 @@ pub fn eq_vis(l: &Visibility, r: &Visibility) -> bool { } } +pub fn eq_impl_restriction(l: &ImplRestriction, r: &ImplRestriction) -> bool { + eq_restriction_kind(&l.kind, &r.kind) +} + +fn eq_restriction_kind(l: &RestrictionKind, r: &RestrictionKind) -> bool { + match (l, r) { + (RestrictionKind::Unrestricted, RestrictionKind::Unrestricted) => true, + ( + RestrictionKind::Restricted { + path: l_path, + shorthand: l_short, + id: _, + }, + RestrictionKind::Restricted { + path: r_path, + shorthand: r_short, + id: _, + }, + ) => l_short == r_short && eq_path(l_path, r_path), + _ => false, + } +} + pub fn eq_fn_decl(l: &FnDecl, r: &FnDecl) -> bool { eq_fn_ret_ty(&l.output, &r.output) && over(&l.inputs, &r.inputs, |l, r| { From 900bfa15eba65dd5597e5b51892e5e4f2bd21eab Mon Sep 17 00:00:00 2001 From: JayanAXHF Date: Sat, 28 Feb 2026 17:27:46 +0000 Subject: [PATCH 24/38] refactor(mgca): Change `DefKind::Const` and `DefKind::AssocConst` to have a `is_type_const` flag * refactor: add `is_type_const` flag to `DefKind::Const` and `AssocConst` * refactor(cleanup) remove the `rhs_is_type_const` query * style: fix formatting * refactor: refactor stuff in librustdoc for new Const and AssocConst * refactor: refactor clippy for the changes * chore: formatting * fix: fix test * fix: fix suggestions * Update context.rs Co-authored-by: Boxy * changed AssocKind::Const to store data about being a type const --- clippy_lints/src/loops/needless_range_loop.rs | 2 +- clippy_lints/src/loops/same_item_push.rs | 4 ++-- clippy_lints/src/manual_float_methods.rs | 4 ++-- clippy_lints/src/manual_main_separator_str.rs | 4 ++-- clippy_lints/src/matches/match_wild_enum.rs | 2 +- clippy_lints/src/non_copy_const.rs | 12 ++++++------ .../src/operators/float_equality_without_abs.rs | 2 +- clippy_lints_internal/src/symbols.rs | 2 +- clippy_utils/src/ast_utils/mod.rs | 4 ++-- clippy_utils/src/consts.rs | 8 +++++--- clippy_utils/src/hir_utils.rs | 4 ++-- clippy_utils/src/lib.rs | 2 +- clippy_utils/src/res.rs | 2 +- clippy_utils/src/visitors.rs | 4 ++-- 14 files changed, 29 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs index a0de464ff7f8..f1b7d4bdfa93 100644 --- a/clippy_lints/src/loops/needless_range_loop.rs +++ b/clippy_lints/src/loops/needless_range_loop.rs @@ -308,7 +308,7 @@ fn check(&mut self, idx: &'tcx Expr<'_>, seqexpr: &'tcx Expr<'_>, expr: &'tcx Ex } return false; // no need to walk further *on the variable* }, - Res::Def(DefKind::Static { .. } | DefKind::Const, ..) => { + Res::Def(DefKind::Static { .. } | DefKind::Const { .. }, ..) => { if index_used_directly { self.indexed_directly.insert( seqvar.segments[0].ident.name, diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs index 4135c63d4d7f..ba309d94608c 100644 --- a/clippy_lints/src/loops/same_item_push.rs +++ b/clippy_lints/src/loops/same_item_push.rs @@ -82,7 +82,7 @@ fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>, ctxt: ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt, msrv), // immutable bindings that are initialized with constant ExprKind::Path(ref path) => { - if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) { + if let Res::Def(DefKind::Const { .. }, ..) = cx.qpath_res(path, init.hir_id) { emit_lint(cx, vec, pushed_item, ctxt, msrv); } }, @@ -91,7 +91,7 @@ fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>, ctxt: } }, // constant - Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item, ctxt, msrv), + Res::Def(DefKind::Const { .. }, ..) => emit_lint(cx, vec, pushed_item, ctxt, msrv), _ => {}, } }, diff --git a/clippy_lints/src/manual_float_methods.rs b/clippy_lints/src/manual_float_methods.rs index a81c4dc6a793..8a3acde166c5 100644 --- a/clippy_lints/src/manual_float_methods.rs +++ b/clippy_lints/src/manual_float_methods.rs @@ -121,11 +121,11 @@ fn is_not_const(tcx: TyCtxt<'_>, def_id: DefId) -> bool { DefKind::AnonConst | DefKind::InlineConst - | DefKind::Const + | DefKind::Const { .. } | DefKind::ConstParam | DefKind::Static { .. } | DefKind::Ctor(..) - | DefKind::AssocConst => false, + | DefKind::AssocConst { .. } => false, DefKind::Fn | DefKind::AssocFn | DefKind::Closure => tcx.constness(def_id) == Constness::NotConst, } diff --git a/clippy_lints/src/manual_main_separator_str.rs b/clippy_lints/src/manual_main_separator_str.rs index 93a0ab5b60af..d4a7c190feca 100644 --- a/clippy_lints/src/manual_main_separator_str.rs +++ b/clippy_lints/src/manual_main_separator_str.rs @@ -1,8 +1,8 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::{peel_hir_expr_refs, sym}; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; +use clippy_utils::{peel_hir_expr_refs, sym}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, Mutability, QPath}; @@ -51,7 +51,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if let ExprKind::MethodCall(path, receiver, &[], _) = target.kind && path.ident.name == sym::to_string && let ExprKind::Path(QPath::Resolved(None, path)) = receiver.kind - && let Res::Def(DefKind::Const, receiver_def_id) = path.res + && let Res::Def(DefKind::Const { .. }, receiver_def_id) = path.res && cx.ty_based_def(target).opt_parent(cx).is_diag_item(cx, sym::ToString) && cx.tcx.is_diagnostic_item(sym::path_main_separator, receiver_def_id) && let ty::Ref(_, ty, Mutability::Not) = cx.typeck_results().expr_ty_adjusted(expr).kind() diff --git a/clippy_lints/src/matches/match_wild_enum.rs b/clippy_lints/src/matches/match_wild_enum.rs index 768d0e8e268c..6b46791eb117 100644 --- a/clippy_lints/src/matches/match_wild_enum.rs +++ b/clippy_lints/src/matches/match_wild_enum.rs @@ -68,7 +68,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { // FIXME(clippy): don't you want to use the hir id of the peeled pat? let id = match cx.qpath_res(path, *hir_id) { Res::Def( - DefKind::Const | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst, + DefKind::Const { .. } | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst, _, ) => return, Res::Def(_, id) => id, diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 79fcc5decfa1..f591a1be1f80 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -20,10 +20,10 @@ use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant, const_item_rhs_to_expr}; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::{is_in_const_context, sym}; use clippy_utils::macros::macro_backtrace; use clippy_utils::paths::{PathNS, lookup_path_str}; use clippy_utils::ty::{get_field_idx_by_name, implements_trait}; +use clippy_utils::{is_in_const_context, sym}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, DefIdSet}; @@ -394,14 +394,14 @@ fn is_init_expr_freeze( let res = typeck.qpath_res(p, e.hir_id); let gen_args = EarlyBinder::bind(typeck.node_args(e.hir_id)).instantiate(tcx, gen_args); match res { - Res::Def(DefKind::Const | DefKind::AssocConst, did) + Res::Def(DefKind::Const { .. } | DefKind::AssocConst { .. }, did) if let Ok(val) = tcx.const_eval_resolve(typing_env, UnevaluatedConst::new(did, gen_args), DUMMY_SP) && let Ok(is_freeze) = self.is_value_freeze(tcx, typing_env, ty, val) => { is_freeze }, - Res::Def(DefKind::Const | DefKind::AssocConst, did) + Res::Def(DefKind::Const { .. } | DefKind::AssocConst { .. }, did) if let Some((typeck, init)) = get_const_hir_value(tcx, typing_env, did, gen_args) => { self.is_init_expr_freeze(tcx, typing_env, typeck, gen_args, init) @@ -588,7 +588,7 @@ fn is_non_freeze_init_borrowed( EarlyBinder::bind(init_typeck.node_args(init_expr.hir_id)).instantiate(tcx, init_args); match init_typeck.qpath_res(init_path, init_expr.hir_id) { Res::Def(DefKind::Ctor(..), _) => return None, - Res::Def(DefKind::Const | DefKind::AssocConst, did) + Res::Def(DefKind::Const { .. } | DefKind::AssocConst { .. }, did) if let Ok(val) = tcx.const_eval_resolve( typing_env, UnevaluatedConst::new(did, next_init_args), @@ -598,7 +598,7 @@ fn is_non_freeze_init_borrowed( { return res; }, - Res::Def(DefKind::Const | DefKind::AssocConst, did) + Res::Def(DefKind::Const { .. } | DefKind::AssocConst { .. }, did) if let Some((next_typeck, value)) = get_const_hir_value(tcx, typing_env, did, next_init_args) => { @@ -831,7 +831,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Path(qpath) = &e.kind && let typeck = cx.typeck_results() - && let Res::Def(DefKind::Const | DefKind::AssocConst, did) = typeck.qpath_res(qpath, e.hir_id) + && let Res::Def(DefKind::Const { .. } | DefKind::AssocConst { .. }, did) = typeck.qpath_res(qpath, e.hir_id) // As of `1.80` constant contexts can't borrow any type with interior mutability && !is_in_const_context(cx) && !self.is_ty_freeze(cx.tcx, cx.typing_env(), typeck.expr_ty(e)).is_freeze() diff --git a/clippy_lints/src/operators/float_equality_without_abs.rs b/clippy_lints/src/operators/float_equality_without_abs.rs index c5eb7d24c30d..97b3c0d02e84 100644 --- a/clippy_lints/src/operators/float_equality_without_abs.rs +++ b/clippy_lints/src/operators/float_equality_without_abs.rs @@ -35,7 +35,7 @@ pub(crate) fn check<'tcx>( // right hand side matches _::EPSILON && let ExprKind::Path(ref epsilon_path) = rhs.kind - && let Res::Def(DefKind::AssocConst, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id) + && let Res::Def(DefKind::AssocConst { .. }, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id) && let Some(sym) = cx.tcx.get_diagnostic_name(def_id) && matches!(sym, sym::f16_epsilon | sym::f32_epsilon | sym::f64_epsilon | sym::f128_epsilon) diff --git a/clippy_lints_internal/src/symbols.rs b/clippy_lints_internal/src/symbols.rs index 74712097e716..38c95666e211 100644 --- a/clippy_lints_internal/src/symbols.rs +++ b/clippy_lints_internal/src/symbols.rs @@ -113,7 +113,7 @@ fn check_crate(&mut self, cx: &LateContext<'_>) { } for item in cx.tcx.module_children(def_id) { - if let Res::Def(DefKind::Const, item_def_id) = item.res + if let Res::Def(DefKind::Const { .. }, item_def_id) = item.res && let ty = cx.tcx.type_of(item_def_id).instantiate_identity() && internal_paths::SYMBOL.matches_ty(cx, ty) && let Ok(ConstValue::Scalar(value)) = cx.tcx.const_eval_poly(item_def_id) diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index 239f721ae05b..67ae1dcef81b 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -820,8 +820,8 @@ pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool { matches!( (l, r), (Defaultness::Implicit, Defaultness::Implicit) - | (Defaultness::Default(_), Defaultness::Default(_)) - | (Defaultness::Final(_), Defaultness::Final(_)) + | (Defaultness::Default(_), Defaultness::Default(_)) + | (Defaultness::Final(_), Defaultness::Final(_)) ) } diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 8177a5806d78..1a75bdff8124 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -753,7 +753,7 @@ fn fetch_path(&self, qpath: &QPath<'_>, id: HirId) -> Option { QPath::Resolved(None, path) if path.span.ctxt() == self.ctxt.get() && path.segments.iter().all(|s| self.ctxt.get() == s.ident.span.ctxt()) - && let Res::Def(DefKind::Const, did) = path.res + && let Res::Def(DefKind::Const { .. }, did) = path.res && (matches!( self.tcx.get_diagnostic_name(did), Some( @@ -841,11 +841,13 @@ fn fetch_path(&self, qpath: &QPath<'_>, id: HirId) -> Option { && ty.span.ctxt() == self.ctxt.get() && ty_name.ident.span.ctxt() == self.ctxt.get() && matches!(ty_path.res, Res::PrimTy(_)) - && let Some((DefKind::AssocConst, did)) = self.typeck.type_dependent_def(id) => + && let Some((DefKind::AssocConst { .. }, did)) = self.typeck.type_dependent_def(id) => { did }, - _ if let Res::Def(DefKind::Const | DefKind::AssocConst, did) = self.typeck.qpath_res(qpath, id) => { + _ if let Res::Def(DefKind::Const { .. } | DefKind::AssocConst { .. }, did) = + self.typeck.qpath_res(qpath, id) => + { self.source.set(ConstantSource::NonLocal); did }, diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 3ff40f2fb722..2da25f7452a0 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -799,7 +799,7 @@ pub fn eq_path(&mut self, left: &Path<'_>, right: &Path<'_>) -> bool { (Res::Local(_), _) | (_, Res::Local(_)) => false, (Res::Def(l_kind, l), Res::Def(r_kind, r)) if l_kind == r_kind - && let DefKind::Const + && let DefKind::Const { .. } | DefKind::Static { .. } | DefKind::Fn | DefKind::TyAlias @@ -1035,7 +1035,7 @@ pub fn eq_expr_value(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>) -> /// item, in which case it is the last two fn generic_path_segments<'tcx>(segments: &'tcx [PathSegment<'tcx>]) -> Option<&'tcx [PathSegment<'tcx>]> { match segments.last()?.res { - Res::Def(DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy, _) => { + Res::Def(DefKind::AssocConst { .. } | DefKind::AssocFn | DefKind::AssocTy, _) => { // >::assoc:: // ^^^^^^^^^^^^^^^^ ^^^^^^^^^^ segments: [module, Trait, assoc] Some(&segments[segments.len().checked_sub(2)?..]) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index fdd270c2774a..ab946f96e995 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2337,7 +2337,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl FnOnce(& Entry::Vacant(entry) => { let mut names = Vec::new(); for id in tcx.hir_module_free_items(module) { - if matches!(tcx.def_kind(id.owner_id), DefKind::Const) + if matches!(tcx.def_kind(id.owner_id), DefKind::Const { .. }) && let item = tcx.hir_item(id) && let ItemKind::Const(ident, _generics, ty, _body) = item.kind && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind diff --git a/clippy_utils/src/res.rs b/clippy_utils/src/res.rs index e890a73620a5..23afb25f1bbf 100644 --- a/clippy_utils/src/res.rs +++ b/clippy_utils/src/res.rs @@ -519,7 +519,7 @@ fn ctor_parent<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option { #[inline] fn assoc_parent<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option { match self.opt_def(tcx) { - Some((DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy, id)) => tcx.tcx().opt_parent(id), + Some((DefKind::AssocConst { .. } | DefKind::AssocFn | DefKind::AssocTy, id)) => tcx.tcx().opt_parent(id), _ => None, } } diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 84e4f043e34f..6ac979d595f4 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -367,8 +367,8 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result { if matches!( self.cx.qpath_res(p, e.hir_id), Res::Def( - DefKind::Const - | DefKind::AssocConst + DefKind::Const { .. } + | DefKind::AssocConst { .. } | DefKind::AnonConst | DefKind::ConstParam | DefKind::Ctor(..) From fa94367a2ea010bf012eea6d09cbef48c610a963 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sat, 28 Feb 2026 17:25:41 -0800 Subject: [PATCH 25/38] Remember whether a struct literal had syntax errors. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a variant `NoneWithError` to AST and HIR representations of the “rest” or “tail”, which is currently always treated identically to the `None` variant. --- clippy_lints/src/no_effect.rs | 4 ++-- clippy_lints/src/utils/author.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index fdb8e1b475c1..3620e5425a94 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -242,7 +242,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { !expr_ty_has_significant_drop(cx, expr) && fields.iter().all(|field| has_no_effect(cx, field.expr)) && match &base { - StructTailExpr::None | StructTailExpr::DefaultFields(_) => true, + StructTailExpr::None | StructTailExpr::NoneWithError(_) | StructTailExpr::DefaultFields(_) => true, StructTailExpr::Base(base) => has_no_effect(cx, base), } }, @@ -353,7 +353,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option Some(base), - StructTailExpr::None | StructTailExpr::DefaultFields(_) => None, + StructTailExpr::None | StructTailExpr::NoneWithError(_) | StructTailExpr::DefaultFields(_) => None, }; Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect()) } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index d5191794b6b0..7ba28f95a719 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -673,7 +673,7 @@ macro_rules! kind { bind!(self, qpath, fields); let base = OptionPat::new(match base { StructTailExpr::Base(base) => Some(self.bind("base", base)), - StructTailExpr::None | StructTailExpr::DefaultFields(_) => None, + StructTailExpr::None | StructTailExpr::NoneWithError(_) | StructTailExpr::DefaultFields(_) => None, }); kind!("Struct({qpath}, {fields}, {base})"); self.qpath(qpath, &expr.name, expr.value.hir_id); From 1380fa60210f131e9426fc33224e1fdad9f9ba3c Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 25 Feb 2026 17:17:17 +0100 Subject: [PATCH 26/38] update references to `Atomic` in diagnostics ... and remove some unused diagnostic items. --- clippy_lints/src/loops/missing_spin_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/loops/missing_spin_loop.rs b/clippy_lints/src/loops/missing_spin_loop.rs index d5dbcbe9dc70..ca8383070d70 100644 --- a/clippy_lints/src/loops/missing_spin_loop.rs +++ b/clippy_lints/src/loops/missing_spin_loop.rs @@ -40,7 +40,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &' && let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind && [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name) && let callee_ty = cx.typeck_results().expr_ty(callee) - && callee_ty.is_diag_item(cx, sym::AtomicBool) + && callee_ty.is_diag_item(cx, sym::Atomic) && let Some(std_or_core) = std_or_core(cx) { span_lint_and_sugg( From 9f97c53f1cde6cef35c91577057557b6f1ecfb19 Mon Sep 17 00:00:00 2001 From: joboet Date: Tue, 24 Feb 2026 00:35:23 +0100 Subject: [PATCH 27/38] bless UI tests referencing atomic primitives --- tests/ui/mut_key.stderr | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ui/mut_key.stderr b/tests/ui/mut_key.stderr index 0d504584fbae..e7a1d6833847 100644 --- a/tests/ui/mut_key.stderr +++ b/tests/ui/mut_key.stderr @@ -5,8 +5,8 @@ LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> Hash | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ... because it contains `Key`, which has interior mutability - = note: ... because it contains `AtomicUsize`, which has interior mutability - = note: ... because it contains `UnsafeCell`, which has interior mutability + = note: ... because it contains `Atomic`, which has interior mutability + = note: ... because it contains `UnsafeCell<::Storage>`, which has interior mutability = note: `-D clippy::mutable-key-type` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::mutable_key_type)]` @@ -17,8 +17,8 @@ LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> Hash | ^^^^^^^^^^^^ | = note: ... because it contains `Key`, which has interior mutability - = note: ... because it contains `AtomicUsize`, which has interior mutability - = note: ... because it contains `UnsafeCell`, which has interior mutability + = note: ... because it contains `Atomic`, which has interior mutability + = note: ... because it contains `UnsafeCell<::Storage>`, which has interior mutability error: mutable key type --> tests/ui/mut_key.rs:35:5 @@ -27,8 +27,8 @@ LL | let _other: HashMap = HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ... because it contains `Key`, which has interior mutability - = note: ... because it contains `AtomicUsize`, which has interior mutability - = note: ... because it contains `UnsafeCell`, which has interior mutability + = note: ... because it contains `Atomic`, which has interior mutability + = note: ... because it contains `UnsafeCell<::Storage>`, which has interior mutability error: mutable key type --> tests/ui/mut_key.rs:64:22 @@ -38,8 +38,8 @@ LL | fn tuples_bad(_m: &mut HashMap<(Key, U), bool>) {} | = note: ... because it contains `(Key, U)`, which has interior mutability = note: ... because it contains `Key`, which has interior mutability - = note: ... because it contains `AtomicUsize`, which has interior mutability - = note: ... because it contains `UnsafeCell`, which has interior mutability + = note: ... because it contains `Atomic`, which has interior mutability + = note: ... because it contains `UnsafeCell<::Storage>`, which has interior mutability error: mutable key type --> tests/ui/mut_key.rs:77:5 From 611ff0992d83e99943dba20c90a6fb10ac88382a Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Mon, 2 Mar 2026 18:11:13 -0800 Subject: [PATCH 28/38] Comments and docs: add missing periods to "ie." "i.e." is short for the Latin "id est" and thus both letters should be followed by periods. --- clippy_lints/src/trait_bounds.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 352b8526b021..819185775505 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -110,7 +110,7 @@ fn check_generics(&mut self, cx: &LateContext<'tcx>, generics: &'tcx Generics<'_ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { // special handling for self trait bounds as these are not considered generics - // ie. trait Foo: Display {} + // i.e. trait Foo: Display {} if let Item { kind: ItemKind::Trait(_, _, _, _, _, bounds, ..), .. From 7ac8be4a488d9bec532ca4f6c1cc6eaec75fa3ea Mon Sep 17 00:00:00 2001 From: kawkoi Date: Tue, 3 Mar 2026 20:34:21 +0530 Subject: [PATCH 29/38] optimize allow unwrap types --- clippy_lints/src/methods/mod.rs | 32 ++++++-- .../src/methods/unwrap_expect_used.rs | 80 +++++++++---------- 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 74db7ae03ba0..994ad446593a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4761,6 +4761,8 @@ pub struct Methods { allowed_dotfiles: FxHashSet<&'static str>, format_args: FormatArgsStorage, allow_unwrap_types: Vec, + unwrap_allowed_ids: FxHashSet, + unwrap_allowed_aliases: Vec, } impl Methods { @@ -4778,6 +4780,8 @@ pub fn new(conf: &'static Conf, format_args: FormatArgsStorage) -> Self { allowed_dotfiles, format_args, allow_unwrap_types: conf.allow_unwrap_types.clone(), + unwrap_allowed_ids: FxHashSet::default(), + unwrap_allowed_aliases: Vec::new(), } } } @@ -4953,6 +4957,19 @@ pub fn method_call<'tcx>(recv: &'tcx Expr<'tcx>) -> Option<(Symbol, &'tcx Expr<' } impl<'tcx> LateLintPass<'tcx> for Methods { + fn check_crate(&mut self, cx: &LateContext<'tcx>) { + for s in &self.allow_unwrap_types { + let def_ids = clippy_utils::paths::lookup_path_str(cx.tcx, clippy_utils::paths::PathNS::Type, s); + for def_id in def_ids { + if cx.tcx.def_kind(def_id) == rustc_hir::def::DefKind::TyAlias { + self.unwrap_allowed_aliases.push(def_id); + } else { + self.unwrap_allowed_ids.insert(def_id); + } + } + } + } + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if expr.span.from_expansion() { return; @@ -4976,7 +4993,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { self.allow_expect_in_tests, self.allow_unwrap_in_consts, self.allow_expect_in_consts, - &self.allow_unwrap_types, + &self.unwrap_allowed_ids, + &self.unwrap_allowed_aliases, ); }, ExprKind::MethodCall(..) => { @@ -5730,7 +5748,8 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { false, self.allow_expect_in_consts, self.allow_expect_in_tests, - &self.allow_unwrap_types, + &self.unwrap_allowed_ids, + &self.unwrap_allowed_aliases, unwrap_expect_used::Variant::Expect, ); expect_fun_call::check(cx, &self.format_args, expr, method_span, recv, arg); @@ -5743,7 +5762,8 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { true, self.allow_expect_in_consts, self.allow_expect_in_tests, - &self.allow_unwrap_types, + &self.unwrap_allowed_ids, + &self.unwrap_allowed_aliases, unwrap_expect_used::Variant::Expect, ); }, @@ -5764,7 +5784,8 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { false, self.allow_unwrap_in_consts, self.allow_unwrap_in_tests, - &self.allow_unwrap_types, + &self.unwrap_allowed_ids, + &self.unwrap_allowed_aliases, unwrap_expect_used::Variant::Unwrap, ); }, @@ -5776,7 +5797,8 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { true, self.allow_unwrap_in_consts, self.allow_unwrap_in_tests, - &self.allow_unwrap_types, + &self.unwrap_allowed_ids, + &self.unwrap_allowed_aliases, unwrap_expect_used::Variant::Unwrap, ); }, diff --git a/clippy_lints/src/methods/unwrap_expect_used.rs b/clippy_lints/src/methods/unwrap_expect_used.rs index 6d8777cbc23f..c07c93217646 100644 --- a/clippy_lints/src/methods/unwrap_expect_used.rs +++ b/clippy_lints/src/methods/unwrap_expect_used.rs @@ -44,7 +44,8 @@ pub(super) fn check( is_err: bool, allow_unwrap_in_consts: bool, allow_unwrap_in_tests: bool, - allow_unwrap_types: &[String], + unwrap_allowed_ids: &rustc_data_structures::fx::FxHashSet, + unwrap_allowed_aliases: &[rustc_hir::def_id::DefId], variant: Variant, ) { let ty = cx.typeck_results().expr_ty(recv).peel_refs(); @@ -66,51 +67,39 @@ pub(super) fn check( let method_suffix = if is_err { "_err" } else { "" }; - let ty_name = ty.to_string(); - if allow_unwrap_types - .iter() - .any(|allowed_type| ty_name.starts_with(allowed_type) || ty_name == *allowed_type) + if let ty::Adt(adt, _) = ty.kind() + && unwrap_allowed_ids.contains(&adt.did()) { return; } - for s in allow_unwrap_types { - let def_ids = clippy_utils::paths::lookup_path_str(cx.tcx, clippy_utils::paths::PathNS::Type, s); - for def_id in def_ids { - if let ty::Adt(adt, _) = ty.kind() - && adt.did() == def_id - { - return; - } - if cx.tcx.def_kind(def_id) == DefKind::TyAlias { - let alias_ty = cx.tcx.type_of(def_id).instantiate_identity(); - if let (ty::Adt(adt, substs), ty::Adt(alias_adt, alias_substs)) = (ty.kind(), alias_ty.kind()) - && adt.did() == alias_adt.did() - { - let mut all_match = true; - for (arg, alias_arg) in substs.iter().zip(alias_substs.iter()) { - if let (Some(arg_ty), Some(alias_arg_ty)) = (arg.as_type(), alias_arg.as_type()) { - if matches!(alias_arg_ty.kind(), ty::Param(_)) { - continue; - } - if let (ty::Adt(arg_adt, _), ty::Adt(alias_arg_adt, _)) = - (arg_ty.peel_refs().kind(), alias_arg_ty.peel_refs().kind()) - { - if arg_adt.did() != alias_arg_adt.did() { - all_match = false; - break; - } - } else if arg_ty != alias_arg_ty { - all_match = false; - break; - } - } + for &def_id in unwrap_allowed_aliases { + let alias_ty = cx.tcx.type_of(def_id).instantiate_identity(); + if let (ty::Adt(adt, substs), ty::Adt(alias_adt, alias_substs)) = (ty.kind(), alias_ty.kind()) + && adt.did() == alias_adt.did() + { + let mut all_match = true; + for (arg, alias_arg) in substs.iter().zip(alias_substs.iter()) { + if let (Some(arg_ty), Some(alias_arg_ty)) = (arg.as_type(), alias_arg.as_type()) { + if matches!(alias_arg_ty.kind(), ty::Param(_)) { + continue; } - if all_match { - return; + if let (ty::Adt(arg_adt, _), ty::Adt(alias_arg_adt, _)) = + (arg_ty.peel_refs().kind(), alias_arg_ty.peel_refs().kind()) + { + if arg_adt.did() != alias_arg_adt.did() { + all_match = false; + break; + } + } else if arg_ty != alias_arg_ty { + all_match = false; + break; } } } + if all_match { + return; + } } } @@ -149,7 +138,8 @@ pub(super) fn check_call( allow_unwrap_in_tests: bool, allow_expect_in_consts: bool, allow_expect_in_tests: bool, - allow_unwrap_types: &[String], + unwrap_allowed_ids: &rustc_data_structures::fx::FxHashSet, + unwrap_allowed_aliases: &[rustc_hir::def_id::DefId], ) { let Some(recv) = args.first() else { return; @@ -167,7 +157,8 @@ pub(super) fn check_call( false, allow_unwrap_in_consts, allow_unwrap_in_tests, - allow_unwrap_types, + unwrap_allowed_ids, + unwrap_allowed_aliases, Variant::Unwrap, ); }, @@ -179,7 +170,8 @@ pub(super) fn check_call( false, allow_expect_in_consts, allow_expect_in_tests, - allow_unwrap_types, + unwrap_allowed_ids, + unwrap_allowed_aliases, Variant::Expect, ); }, @@ -191,7 +183,8 @@ pub(super) fn check_call( true, allow_unwrap_in_consts, allow_unwrap_in_tests, - allow_unwrap_types, + unwrap_allowed_ids, + unwrap_allowed_aliases, Variant::Unwrap, ); }, @@ -203,7 +196,8 @@ pub(super) fn check_call( true, allow_expect_in_consts, allow_expect_in_tests, - allow_unwrap_types, + unwrap_allowed_ids, + unwrap_allowed_aliases, Variant::Expect, ); }, From 9798fafcb72490edde615fba603e595d8436d190 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Tue, 14 Oct 2025 10:48:53 -0400 Subject: [PATCH 30/38] `clippy_dev`: Rename `update_lints` module to `generate` --- clippy_dev/src/edit_lints.rs | 2 +- clippy_dev/src/{update_lints.rs => generate.rs} | 0 clippy_dev/src/lib.rs | 2 +- clippy_dev/src/main.rs | 10 ++++++---- 4 files changed, 8 insertions(+), 6 deletions(-) rename clippy_dev/src/{update_lints.rs => generate.rs} (100%) diff --git a/clippy_dev/src/edit_lints.rs b/clippy_dev/src/edit_lints.rs index 411bf530b22b..3dd667165d58 100644 --- a/clippy_dev/src/edit_lints.rs +++ b/clippy_dev/src/edit_lints.rs @@ -1,6 +1,6 @@ +use crate::generate::generate_lint_files; use crate::parse::cursor::{self, Capture, Cursor}; use crate::parse::{ActiveLint, DeprecatedLint, Lint, LintData, LintName, ParseCx, RenamedLint}; -use crate::update_lints::generate_lint_files; use crate::utils::{ ErrAction, FileUpdater, UpdateMode, UpdateStatus, Version, delete_dir_if_exists, delete_file_if_exists, expect_action, try_rename_dir, try_rename_file, walk_dir_no_dot_or_target, diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/generate.rs similarity index 100% rename from clippy_dev/src/update_lints.rs rename to clippy_dev/src/generate.rs diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index cff51d34c30e..c3f4ed08bf67 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -27,13 +27,13 @@ pub mod dogfood; pub mod edit_lints; pub mod fmt; +pub mod generate; pub mod lint; pub mod new_lint; pub mod release; pub mod serve; pub mod setup; pub mod sync; -pub mod update_lints; mod parse; mod utils; diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 8dc2290df8e4..ba470d90014a 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -4,8 +4,8 @@ use clap::{Args, Parser, Subcommand}; use clippy_dev::{ - ClippyInfo, UpdateMode, dogfood, edit_lints, fmt, lint, new_lint, new_parse_cx, release, serve, setup, sync, - update_lints, + ClippyInfo, UpdateMode, dogfood, edit_lints, fmt, generate, lint, new_lint, new_parse_cx, release, serve, setup, + sync, }; use std::env; @@ -27,7 +27,9 @@ fn main() { allow_no_vcs, } => dogfood::dogfood(fix, allow_dirty, allow_staged, allow_no_vcs), DevCommand::Fmt { check } => fmt::run(UpdateMode::from_check(check)), - DevCommand::UpdateLints { check } => new_parse_cx(|cx| update_lints::update(cx, UpdateMode::from_check(check))), + DevCommand::UpdateLints { check } => { + new_parse_cx(|cx| generate::generate_lint_files(UpdateMode::from_check(check), &cx.parse_lint_decls())); + }, DevCommand::NewLint { pass, name, @@ -35,7 +37,7 @@ fn main() { r#type, msrv, } => match new_lint::create(clippy.version, pass, &name, &category, r#type.as_deref(), msrv) { - Ok(()) => new_parse_cx(|cx| update_lints::update(cx, UpdateMode::Change)), + Ok(()) => new_parse_cx(|cx| generate::generate_lint_files(UpdateMode::Change, &cx.parse_lint_decls())), Err(e) => eprintln!("Unable to create lint: {e}"), }, DevCommand::Setup(SetupCommand { subcommand }) => match subcommand { From 1f2be4e71b06e2f37ef52dd08821023d3f34ca15 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Fri, 24 Oct 2025 21:24:35 -0400 Subject: [PATCH 31/38] `clippy_dev`: Parse and format lint pass macros. --- clippy_dev/src/edit_lints.rs | 11 +- clippy_dev/src/fmt.rs | 27 +- clippy_dev/src/generate.rs | 396 ++++++++++-------- clippy_dev/src/lib.rs | 2 +- clippy_dev/src/main.rs | 7 +- clippy_dev/src/parse.rs | 161 ++++++- clippy_dev/src/parse/cursor.rs | 86 +++- clippy_dev/src/utils.rs | 24 ++ clippy_lints/src/attrs/mod.rs | 17 +- clippy_lints/src/await_holding_invalid.rs | 6 +- clippy_lints/src/cargo/mod.rs | 8 +- clippy_lints/src/casts/mod.rs | 46 +- clippy_lints/src/collapsible_if.rs | 2 +- .../src/default_constructed_unit_structs.rs | 4 +- clippy_lints/src/dereference.rs | 2 +- clippy_lints/src/derive/mod.rs | 4 +- clippy_lints/src/doc/mod.rs | 22 +- clippy_lints/src/drop_forget_ref.rs | 6 +- clippy_lints/src/empty_line_after.rs | 2 +- clippy_lints/src/empty_with_brackets.rs | 5 +- clippy_lints/src/endian_bytes.rs | 6 +- clippy_lints/src/eta_reduction.rs | 5 +- clippy_lints/src/excessive_bools.rs | 5 +- .../src/field_scoped_visibility_modifiers.rs | 4 +- clippy_lints/src/float_literal.rs | 4 +- .../src/floating_point_arithmetic/mod.rs | 5 +- clippy_lints/src/format_args.rs | 4 +- clippy_lints/src/format_impl.rs | 2 +- clippy_lints/src/formatting.rs | 8 +- clippy_lints/src/functions/mod.rs | 20 +- clippy_lints/src/ifs/mod.rs | 4 +- .../impl_hash_with_borrow_str_and_bytes.rs | 4 +- clippy_lints/src/implicit_saturating_sub.rs | 5 +- .../src/inconsistent_struct_constructor.rs | 4 +- clippy_lints/src/inherent_to_string.rs | 5 +- clippy_lints/src/item_name_repetitions.rs | 4 +- clippy_lints/src/iter_without_into_iter.rs | 5 +- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/let_underscore.rs | 7 +- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/literal_representation.rs | 2 +- .../literal_string_with_formatting_args.rs | 4 +- clippy_lints/src/loops/mod.rs | 36 +- clippy_lints/src/manual_float_methods.rs | 2 +- clippy_lints/src/matches/mod.rs | 44 +- clippy_lints/src/mem_replace.rs | 8 +- clippy_lints/src/methods/mod.rs | 248 +++++------ clippy_lints/src/misc.rs | 2 +- clippy_lints/src/misc_early/mod.rs | 14 +- .../src/mixed_read_write_in_expression.rs | 5 +- clippy_lints/src/mut_key.rs | 2 +- .../src/needless_borrows_for_generic_args.rs | 4 +- .../src/needless_parens_on_range_literals.rs | 4 +- clippy_lints/src/no_effect.rs | 6 +- clippy_lints/src/non_canonical_impls.rs | 5 +- clippy_lints/src/non_copy_const.rs | 5 +- clippy_lints/src/non_expressive_names.rs | 6 +- clippy_lints/src/only_used_in_recursion.rs | 5 +- clippy_lints/src/operators/mod.rs | 40 +- clippy_lints/src/panic_in_result_fn.rs | 2 +- clippy_lints/src/panic_unimplemented.rs | 2 +- clippy_lints/src/pass_by_ref_or_value.rs | 5 +- .../src/permissions_set_readonly_false.rs | 4 +- clippy_lints/src/ptr/mod.rs | 2 +- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/ranges.rs | 6 +- clippy_lints/src/redundant_slicing.rs | 2 +- clippy_lints/src/regex.rs | 2 +- clippy_lints/src/returns/mod.rs | 6 +- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/std_instead_of_core.rs | 6 +- clippy_lints/src/string_patterns.rs | 5 +- clippy_lints/src/strings.rs | 5 +- .../src/suspicious_operation_groupings.rs | 4 +- clippy_lints/src/suspicious_trait_impl.rs | 5 +- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/time_subtraction.rs | 5 +- clippy_lints/src/trait_bounds.rs | 5 +- clippy_lints/src/transmute/mod.rs | 18 +- clippy_lints/src/types/mod.rs | 12 +- .../src/undocumented_unsafe_blocks.rs | 5 +- clippy_lints/src/unicode.rs | 6 +- clippy_lints/src/unit_types/mod.rs | 2 +- .../src/unnecessary_map_on_constructor.rs | 4 +- .../src/unnecessary_owned_empty_strings.rs | 4 +- clippy_lints/src/unwrap_in_result.rs | 2 +- clippy_lints/src/visibility.rs | 6 +- clippy_lints/src/write/mod.rs | 10 +- 88 files changed, 962 insertions(+), 564 deletions(-) diff --git a/clippy_dev/src/edit_lints.rs b/clippy_dev/src/edit_lints.rs index 3dd667165d58..70c096783af8 100644 --- a/clippy_dev/src/edit_lints.rs +++ b/clippy_dev/src/edit_lints.rs @@ -1,4 +1,3 @@ -use crate::generate::generate_lint_files; use crate::parse::cursor::{self, Capture, Cursor}; use crate::parse::{ActiveLint, DeprecatedLint, Lint, LintData, LintName, ParseCx, RenamedLint}; use crate::utils::{ @@ -40,7 +39,7 @@ pub fn deprecate<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, name }; remove_lint_declaration(name, &prev_lint, &data, &mut FileUpdater::default()); - generate_lint_files(UpdateMode::Change, &data); + data.gen_decls(UpdateMode::Change); println!("info: `{name}` has successfully been deprecated"); println!("note: you must run `cargo uitest` to update the test results"); } @@ -74,7 +73,7 @@ pub fn uplift<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_nam updater.update_file(e.path(), &mut update_fn); } } - generate_lint_files(UpdateMode::Change, &data); + data.gen_decls(UpdateMode::Change); println!("info: `{old_name}` has successfully been uplifted as `{new_name}`"); println!("note: you must run `cargo uitest` to update the test results"); } @@ -151,7 +150,7 @@ pub fn rename<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_nam updater.update_file(e.path(), &mut update_fn); } } - generate_lint_files(UpdateMode::Change, &data); + data.gen_decls(UpdateMode::Change); println!("Renamed `{old_name}` to `{new_name}`"); println!("All code referencing the old name has been updated"); @@ -172,11 +171,11 @@ fn remove_lint_declaration(name: &str, lint: &ActiveLint<'_>, data: &LintData<'_ delete_file_if_exists(lint.path.as_ref()) } else { updater.update_file(&lint.path, &mut |_, src, dst| -> UpdateStatus { - let mut start = &src[..lint.declaration_range.start]; + let mut start = &src[..lint.declaration_range.start as usize]; if start.ends_with("\n\n") { start = &start[..start.len() - 1]; } - let mut end = &src[lint.declaration_range.end..]; + let mut end = &src[lint.declaration_range.end as usize..]; if end.starts_with("\n\n") { end = &end[1..]; } diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index 781e37e6144e..f4ee600dde04 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -1,6 +1,7 @@ +use crate::new_parse_cx; use crate::utils::{ - ErrAction, FileUpdater, UpdateMode, UpdateStatus, expect_action, run_with_output, split_args_for_threads, - walk_dir_no_dot_or_target, + ErrAction, FileUpdater, UpdateMode, UpdateStatus, expect_action, run_with_output, slice_groups, + split_args_for_threads, walk_dir_no_dot_or_target, }; use itertools::Itertools; use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize}; @@ -326,10 +327,30 @@ fn run_rustfmt(update_mode: UpdateMode) { // the "main" function of cargo dev fmt pub fn run(update_mode: UpdateMode) { - run_rustfmt(update_mode); fmt_syms(update_mode); if let Err(e) = fmt_conf(update_mode.is_check()) { e.display(); process::exit(1); } + + new_parse_cx(|cx| { + let data = cx.parse_lint_decls(); + let mut updater = FileUpdater::default(); + + for passes in slice_groups(&data.lint_passes, |head, tail| { + tail.iter().take_while(|&x| x.path == head.path).count() + }) { + updater.update_file_checked("cargo dev fmt", update_mode, &passes[0].path, &mut |_, src, dst| { + let pos = passes.iter().fold(0u32, |start, pass| { + dst.push_str(&src[start as usize..pass.decl_range.start as usize]); + pass.gen_mac(dst); + pass.decl_range.end + }); + dst.push_str(&src[pos as usize..]); + UpdateStatus::from_changed(src != dst) + }); + } + }); + + run_rustfmt(update_mode); } diff --git a/clippy_dev/src/generate.rs b/clippy_dev/src/generate.rs index a4cf15058986..0d86c0179cde 100644 --- a/clippy_dev/src/generate.rs +++ b/clippy_dev/src/generate.rs @@ -1,5 +1,5 @@ use crate::parse::cursor::Cursor; -use crate::parse::{Lint, LintData, ParseCx}; +use crate::parse::{Lint, LintData, LintPass}; use crate::utils::{FileUpdater, UpdateMode, UpdateStatus, update_text_region_fn}; use itertools::Itertools; use std::collections::HashSet; @@ -12,193 +12,247 @@ const DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html"; -/// Runs the `update_lints` command. -/// -/// This updates various generated values from the lint source code. -/// -/// `update_mode` indicates if the files should be updated or if updates should be checked for. -/// -/// # Panics -/// -/// Panics if a file path could not read from or then written to -pub fn update(cx: ParseCx<'_>, update_mode: UpdateMode) { - let data = cx.parse_lint_decls(); - generate_lint_files(update_mode, &data); -} +impl LintData<'_> { + #[expect(clippy::too_many_lines)] + pub fn gen_decls(&self, update_mode: UpdateMode) { + let mut updater = FileUpdater::default(); -#[expect(clippy::too_many_lines)] -pub fn generate_lint_files(update_mode: UpdateMode, data: &LintData<'_>) { - let mut updater = FileUpdater::default(); - - let mut lints: Vec<_> = data.lints.iter().map(|(&x, y)| (x, y)).collect(); - lints.sort_by_key(|&(x, _)| x); - updater.update_file_checked( - "cargo dev update_lints", - update_mode, - "CHANGELOG.md", - &mut update_text_region_fn( - "\n", - "", - |dst| { - for &(lint, _) in &lints { - writeln!(dst, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap(); - } - }, - ), - ); - - let mut active = Vec::with_capacity(lints.len()); - let mut deprecated = Vec::with_capacity(lints.len() / 8); - let mut renamed = Vec::with_capacity(lints.len() / 8); - for &(name, lint) in &lints { - match lint { - Lint::Active(lint) => active.push((name, lint)), - Lint::Deprecated(lint) => deprecated.push((name, lint)), - Lint::Renamed(lint) => renamed.push((name, lint)), - } - } - active.sort_by_key(|&(_, lint)| lint.module); - - // Round to avoid updating the readme every time a lint is added/deprecated. - let lint_count = active.len() / 50 * 50; - updater.update_file_checked( - "cargo dev update_lints", - update_mode, - "README.md", - &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| { - write!(dst, "{lint_count}").unwrap(); - }), - ); - updater.update_file_checked( - "cargo dev update_lints", - update_mode, - "book/src/README.md", - &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| { - write!(dst, "{lint_count}").unwrap(); - }), - ); - - updater.update_file_checked( - "cargo dev update_lints", - update_mode, - "clippy_lints/src/deprecated_lints.rs", - &mut |_, src, dst| { - let mut cursor = Cursor::new(src); - assert!( - cursor.find_ident("declare_with_version").is_some() - && cursor.find_ident("declare_with_version").is_some(), - "error reading deprecated lints" - ); - dst.push_str(&src[..cursor.pos() as usize]); - dst.push_str("! { DEPRECATED(DEPRECATED_VERSION) = [\n"); - for &(name, data) in &deprecated { - write!( - dst, - " #[clippy::version = \"{}\"]\n (\"clippy::{name}\", \"{}\"),\n", - data.version, data.reason, - ) - .unwrap(); - } - dst.push_str( - "]}\n\n\ - #[rustfmt::skip]\n\ - declare_with_version! { RENAMED(RENAMED_VERSION) = [\n\ - ", - ); - for &(name, data) in &renamed { - write!( - dst, - " #[clippy::version = \"{}\"]\n (\"clippy::{name}\", \"{}\"),\n", - data.version, data.new_name, - ) - .unwrap(); - } - dst.push_str("]}\n"); - UpdateStatus::from_changed(src != dst) - }, - ); - updater.update_file_checked( - "cargo dev update_lints", - update_mode, - "tests/ui/deprecated.rs", - &mut |_, src, dst| { - dst.push_str(GENERATED_FILE_COMMENT); - for &(lint, _) in &deprecated { - writeln!(dst, "#![warn(clippy::{lint})] //~ ERROR: lint `clippy::{lint}`").unwrap(); - } - dst.push_str("\nfn main() {}\n"); - UpdateStatus::from_changed(src != dst) - }, - ); - updater.update_file_checked( - "cargo dev update_lints", - update_mode, - "tests/ui/rename.rs", - &mut move |_, src, dst| { - let mut seen_lints = HashSet::new(); - dst.push_str(GENERATED_FILE_COMMENT); - dst.push_str("#![allow(clippy::duplicated_attributes)]\n"); - for &(_, lint) in &renamed { - if seen_lints.insert(lint.new_name) { - writeln!(dst, "#![allow({})]", lint.new_name).unwrap(); - } - } - for &(lint, _) in &renamed { - writeln!(dst, "#![warn(clippy::{lint})] //~ ERROR: lint `clippy::{lint}`").unwrap(); - } - dst.push_str("\nfn main() {}\n"); - UpdateStatus::from_changed(src != dst) - }, - ); - for (crate_name, lints) in active.iter().copied().into_group_map_by(|&(_, lint)| { - let Some(path::Component::Normal(name)) = lint.path.components().next() else { - // All paths should start with `{crate_name}/src` when parsed from `find_lint_decls` - panic!( - "internal error: can't read crate name from path `{}`", - lint.path.display() - ); - }; - name - }) { + let mut lints: Vec<_> = self.lints.iter().map(|(&x, y)| (x, y)).collect(); + lints.sort_by_key(|&(x, _)| x); updater.update_file_checked( "cargo dev update_lints", update_mode, - Path::new(crate_name).join("src/lib.rs"), + "CHANGELOG.md", &mut update_text_region_fn( - "// begin lints modules, do not remove this comment, it's used in `update_lints`\n", - "// end lints modules, do not remove this comment, it's used in `update_lints`", + "\n", + "", |dst| { - let mut prev = ""; - for &(_, lint) in &lints { - if lint.module != prev { - writeln!(dst, "mod {};", lint.module).unwrap(); - prev = lint.module; - } + for &(lint, _) in &lints { + writeln!(dst, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap(); } }, ), ); + + let mut active = Vec::with_capacity(lints.len()); + let mut deprecated = Vec::with_capacity(lints.len() / 8); + let mut renamed = Vec::with_capacity(lints.len() / 8); + for &(name, lint) in &lints { + match lint { + Lint::Active(lint) => active.push((name, lint)), + Lint::Deprecated(lint) => deprecated.push((name, lint)), + Lint::Renamed(lint) => renamed.push((name, lint)), + } + } + active.sort_by_key(|&(_, lint)| lint.module); + + // Round to avoid updating the readme every time a lint is added/deprecated. + let lint_count = active.len() / 50 * 50; updater.update_file_checked( "cargo dev update_lints", update_mode, - Path::new(crate_name).join("src/declared_lints.rs"), + "README.md", + &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| { + write!(dst, "{lint_count}").unwrap(); + }), + ); + updater.update_file_checked( + "cargo dev update_lints", + update_mode, + "book/src/README.md", + &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| { + write!(dst, "{lint_count}").unwrap(); + }), + ); + + updater.update_file_checked( + "cargo dev update_lints", + update_mode, + "clippy_lints/src/deprecated_lints.rs", &mut |_, src, dst| { - dst.push_str(GENERATED_FILE_COMMENT); - dst.push_str("pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[\n"); - let mut buf = String::new(); - for &(name, lint) in &lints { - buf.clear(); - buf.push_str(name); - buf.make_ascii_uppercase(); - if lint.module.is_empty() { - writeln!(dst, " crate::{buf}_INFO,").unwrap(); - } else { - writeln!(dst, " crate::{}::{buf}_INFO,", lint.module).unwrap(); - } + let mut cursor = Cursor::new(src); + assert!( + cursor.find_ident("declare_with_version").is_some() + && cursor.find_ident("declare_with_version").is_some(), + "error reading deprecated lints" + ); + dst.push_str(&src[..cursor.pos() as usize]); + dst.push_str("! { DEPRECATED(DEPRECATED_VERSION) = [\n"); + for &(name, data) in &deprecated { + write!( + dst, + " #[clippy::version = \"{}\"]\n (\"clippy::{name}\", \"{}\"),\n", + data.version, data.reason, + ) + .unwrap(); } - dst.push_str("];\n"); + dst.push_str( + "]}\n\n\ + #[rustfmt::skip]\n\ + declare_with_version! { RENAMED(RENAMED_VERSION) = [\n\ + ", + ); + for &(name, data) in &renamed { + write!( + dst, + " #[clippy::version = \"{}\"]\n (\"clippy::{name}\", \"{}\"),\n", + data.version, data.new_name, + ) + .unwrap(); + } + dst.push_str("]}\n"); UpdateStatus::from_changed(src != dst) }, ); + updater.update_file_checked( + "cargo dev update_lints", + update_mode, + "tests/ui/deprecated.rs", + &mut |_, src, dst| { + dst.push_str(GENERATED_FILE_COMMENT); + for &(lint, _) in &deprecated { + writeln!(dst, "#![warn(clippy::{lint})] //~ ERROR: lint `clippy::{lint}`").unwrap(); + } + dst.push_str("\nfn main() {}\n"); + UpdateStatus::from_changed(src != dst) + }, + ); + updater.update_file_checked( + "cargo dev update_lints", + update_mode, + "tests/ui/rename.rs", + &mut move |_, src, dst| { + let mut seen_lints = HashSet::new(); + dst.push_str(GENERATED_FILE_COMMENT); + dst.push_str("#![allow(clippy::duplicated_attributes)]\n"); + for &(_, lint) in &renamed { + if seen_lints.insert(lint.new_name) { + writeln!(dst, "#![allow({})]", lint.new_name).unwrap(); + } + } + for &(lint, _) in &renamed { + writeln!(dst, "#![warn(clippy::{lint})] //~ ERROR: lint `clippy::{lint}`").unwrap(); + } + dst.push_str("\nfn main() {}\n"); + UpdateStatus::from_changed(src != dst) + }, + ); + for (crate_name, lints) in active.iter().copied().into_group_map_by(|&(_, lint)| { + let Some(path::Component::Normal(name)) = lint.path.components().next() else { + // All paths should start with `{crate_name}/src` when parsed from `find_lint_decls` + panic!( + "internal error: can't read crate name from path `{}`", + lint.path.display() + ); + }; + name + }) { + updater.update_file_checked( + "cargo dev update_lints", + update_mode, + Path::new(crate_name).join("src/lib.rs"), + &mut update_text_region_fn( + "// begin lints modules, do not remove this comment, it's used in `update_lints`\n", + "// end lints modules, do not remove this comment, it's used in `update_lints`", + |dst| { + let mut prev = ""; + for &(_, lint) in &lints { + if lint.module != prev { + writeln!(dst, "mod {};", lint.module).unwrap(); + prev = lint.module; + } + } + }, + ), + ); + updater.update_file_checked( + "cargo dev update_lints", + update_mode, + Path::new(crate_name).join("src/declared_lints.rs"), + &mut |_, src, dst| { + dst.push_str(GENERATED_FILE_COMMENT); + dst.push_str("pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[\n"); + let mut buf = String::new(); + for &(name, lint) in &lints { + buf.clear(); + buf.push_str(name); + buf.make_ascii_uppercase(); + if lint.module.is_empty() { + writeln!(dst, " crate::{buf}_INFO,").unwrap(); + } else { + writeln!(dst, " crate::{}::{buf}_INFO,", lint.module).unwrap(); + } + } + dst.push_str("];\n"); + UpdateStatus::from_changed(src != dst) + }, + ); + } + } +} + +impl LintPass<'_> { + pub fn gen_mac(&self, dst: &mut String) { + let mut line_start = dst.len(); + dst.extend([self.mac.name(), "!("]); + let has_docs = write_comment_lines(self.docs, "\n ", dst); + let (list_indent, list_multi_end, end) = if has_docs { + dst.push_str("\n "); + line_start = dst.len() - 4; + (" ", "\n ", "]\n);") + } else { + (" ", "\n", "]);") + }; + dst.push_str(self.name); + if let Some(lt) = self.lt { + dst.extend(["<", lt, ">"]); + } + dst.push_str(" => ["); + let fmt = write_list( + self.lints.iter().copied(), + 80usize.saturating_sub(dst.len() - line_start), + list_indent, + dst, + ); + if matches!(fmt, ListFmt::MultiLine) { + dst.push_str(list_multi_end); + } + dst.push_str(end); + } +} + +fn write_comment_lines(s: &str, prefix: &str, dst: &mut String) -> bool { + let mut has_doc = false; + for line in s.split('\n') { + let line = line.trim_start(); + if !line.is_empty() { + has_doc = true; + dst.extend([prefix, line]); + } + } + has_doc +} + +#[derive(Clone, Copy)] +enum ListFmt { + SingleLine, + MultiLine, +} + +fn write_list<'a>( + items: impl Iterator + Clone, + single_line_limit: usize, + indent: &str, + dst: &mut String, +) -> ListFmt { + let len = items.clone().map(str::len).sum::(); + if len > single_line_limit { + for item in items { + dst.extend(["\n", indent, item, ","]); + } + ListFmt::MultiLine + } else { + let _ = write!(dst, "{}", items.format(", ")); + ListFmt::SingleLine } } diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index c3f4ed08bf67..27288cbdefd0 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -27,7 +27,6 @@ pub mod dogfood; pub mod edit_lints; pub mod fmt; -pub mod generate; pub mod lint; pub mod new_lint; pub mod release; @@ -35,6 +34,7 @@ pub mod setup; pub mod sync; +mod generate; mod parse; mod utils; diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index ba470d90014a..5fe2295a1e21 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -4,8 +4,7 @@ use clap::{Args, Parser, Subcommand}; use clippy_dev::{ - ClippyInfo, UpdateMode, dogfood, edit_lints, fmt, generate, lint, new_lint, new_parse_cx, release, serve, setup, - sync, + ClippyInfo, UpdateMode, dogfood, edit_lints, fmt, lint, new_lint, new_parse_cx, release, serve, setup, sync, }; use std::env; @@ -28,7 +27,7 @@ fn main() { } => dogfood::dogfood(fix, allow_dirty, allow_staged, allow_no_vcs), DevCommand::Fmt { check } => fmt::run(UpdateMode::from_check(check)), DevCommand::UpdateLints { check } => { - new_parse_cx(|cx| generate::generate_lint_files(UpdateMode::from_check(check), &cx.parse_lint_decls())); + new_parse_cx(|cx| cx.parse_lint_decls().gen_decls(UpdateMode::from_check(check))); }, DevCommand::NewLint { pass, @@ -37,7 +36,7 @@ fn main() { r#type, msrv, } => match new_lint::create(clippy.version, pass, &name, &category, r#type.as_deref(), msrv) { - Ok(()) => new_parse_cx(|cx| generate::generate_lint_files(UpdateMode::Change, &cx.parse_lint_decls())), + Ok(()) => new_parse_cx(|cx| cx.parse_lint_decls().gen_decls(UpdateMode::Change)), Err(e) => eprintln!("Unable to create lint: {e}"), }, DevCommand::Setup(SetupCommand { subcommand }) => match subcommand { diff --git a/clippy_dev/src/parse.rs b/clippy_dev/src/parse.rs index ffb50784a9a7..30eed05a4f8b 100644 --- a/clippy_dev/src/parse.rs +++ b/clippy_dev/src/parse.rs @@ -13,6 +13,7 @@ pub struct ParseCxImpl<'cx> { pub arena: &'cx DroplessArena, pub str_buf: StrBuf, + pub str_list_buf: VecBuf<&'cx str>, } pub type ParseCx<'cx> = &'cx mut ParseCxImpl<'cx>; @@ -22,6 +23,7 @@ pub fn new_parse_cx<'env, T>(f: impl for<'cx> FnOnce(&'cx mut Scoped<'cx, 'env, f(&mut Scoped::new(ParseCxImpl { arena: &arena, str_buf: StrBuf::with_capacity(128), + str_list_buf: VecBuf::with_capacity(128), })) } @@ -82,6 +84,20 @@ pub fn with(&mut self, f: impl FnOnce(&mut String) -> T) -> T { } } +pub struct VecBuf(Vec); +impl VecBuf { + /// Creates a new buffer with the specified initial capacity. + pub fn with_capacity(cap: usize) -> Self { + Self(Vec::with_capacity(cap)) + } + + /// Performs an operation with the freshly cleared buffer. + pub fn with(&mut self, f: impl FnOnce(&mut Vec) -> R) -> R { + self.0.clear(); + f(&mut self.0) + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub enum LintTool { Rustc, @@ -128,7 +144,7 @@ pub struct ActiveLint<'cx> { pub group: &'cx str, pub module: &'cx str, pub path: PathBuf, - pub declaration_range: Range, + pub declaration_range: Range, } pub struct DeprecatedLint<'cx> { @@ -147,8 +163,35 @@ pub enum Lint<'cx> { Renamed(RenamedLint<'cx>), } +#[derive(Clone, Copy)] +pub enum LintPassMac { + Declare, + Impl, +} +impl LintPassMac { + pub fn name(self) -> &'static str { + match self { + Self::Declare => "declare_lint_pass", + Self::Impl => "impl_lint_pass", + } + } +} + +pub struct LintPass<'cx> { + /// The raw text of the documentation comments. May include leading/trailing + /// whitespace and empty lines. + pub docs: &'cx str, + pub name: &'cx str, + pub lt: Option<&'cx str>, + pub mac: LintPassMac, + pub decl_range: Range, + pub lints: &'cx [&'cx str], + pub path: PathBuf, +} + pub struct LintData<'cx> { pub lints: FxHashMap<&'cx str, Lint<'cx>>, + pub lint_passes: Vec>, } impl<'cx> ParseCxImpl<'cx> { @@ -158,6 +201,7 @@ pub fn parse_lint_decls(&mut self) -> LintData<'cx> { let mut data = LintData { #[expect(clippy::default_trait_access)] lints: FxHashMap::with_capacity_and_hasher(1000, Default::default()), + lint_passes: Vec::with_capacity(400), }; let mut contents = String::new(); @@ -193,7 +237,7 @@ pub fn parse_lint_decls(&mut self) -> LintData<'cx> { self.str_buf .alloc_replaced(self.arena, path, path::MAIN_SEPARATOR, "::") }; - self.parse_clippy_lint_decls( + self.parse_lint_src_file( e.path(), File::open_read_to_cleared_string(e.path(), &mut contents), module, @@ -208,11 +252,11 @@ pub fn parse_lint_decls(&mut self) -> LintData<'cx> { } /// Parse a source file looking for `declare_clippy_lint` macro invocations. - fn parse_clippy_lint_decls(&mut self, path: &Path, contents: &str, module: &'cx str, data: &mut LintData<'cx>) { + fn parse_lint_src_file(&mut self, path: &Path, contents: &str, module: &'cx str, data: &mut LintData<'cx>) { #[allow(clippy::enum_glob_use)] use cursor::Pat::*; #[rustfmt::skip] - static DECL_TOKENS: &[cursor::Pat<'_>] = &[ + static LINT_DECL_TOKENS: &[cursor::Pat<'_>] = &[ // !{ /// docs Bang, OpenBrace, AnyComment, // #[clippy::version = "version"] @@ -220,24 +264,101 @@ fn parse_clippy_lint_decls(&mut self, path: &Path, contents: &str, module: &'cx // pub NAME, GROUP, Ident("pub"), CaptureIdent, Comma, AnyComment, CaptureIdent, Comma, ]; + #[rustfmt::skip] + static PASS_DECL_TOKENS: &[cursor::Pat<'_>] = &[ + // !( NAME <'lt> => [ + Bang, OpenParen, CaptureDocLines, CaptureIdent, CaptureOptLifetimeArg, FatArrow, OpenBracket, + ]; let mut cursor = Cursor::new(contents); - let mut captures = [Capture::EMPTY; 2]; - while let Some(start) = cursor.find_ident("declare_clippy_lint") { - if cursor.match_all(DECL_TOKENS, &mut captures) && cursor.find_pat(CloseBrace) { - assert!( - data.lints - .insert( - self.str_buf.alloc_ascii_lower(self.arena, cursor.get_text(captures[0])), - Lint::Active(ActiveLint { - group: self.arena.alloc_str(cursor.get_text(captures[1])), - module, - path: path.into(), - declaration_range: start as usize..cursor.pos() as usize, - }), - ) - .is_none() - ); + let mut captures = [Capture::EMPTY; 3]; + while let Some(mac_name) = cursor.find_any_ident() { + match cursor.get_text(mac_name) { + "declare_clippy_lint" + if cursor.match_all(LINT_DECL_TOKENS, &mut captures) && cursor.find_pat(CloseBrace) => + { + assert!( + data.lints + .insert( + self.str_buf.alloc_ascii_lower(self.arena, cursor.get_text(captures[0])), + Lint::Active(ActiveLint { + group: self.arena.alloc_str(cursor.get_text(captures[1])), + module, + path: path.into(), + declaration_range: mac_name.pos..cursor.pos(), + }), + ) + .is_none() + ); + }, + mac @ ("declare_lint_pass" | "impl_lint_pass") if cursor.match_all(PASS_DECL_TOKENS, &mut captures) => { + let mac = if matches!(mac, "declare_lint_pass") { + LintPassMac::Declare + } else { + LintPassMac::Impl + }; + let docs = match cursor.get_text(captures[0]) { + "" => "", + x => self.arena.alloc_str(x), + }; + let name = self.arena.alloc_str(cursor.get_text(captures[1])); + let lt = cursor.get_text(captures[2]); + let lt = if lt.is_empty() { + None + } else { + Some(self.arena.alloc_str(lt)) + }; + + let lints = self.str_list_buf.with(|buf| { + // Parses a comma separated list of paths and converts each path + // to a string with whitespace removed. + while !cursor.match_pat(CloseBracket) { + buf.push(self.str_buf.with(|buf| { + if cursor.match_pat(DoubleColon) { + buf.push_str("::"); + } + let capture = cursor.capture_ident()?; + buf.push_str(cursor.get_text(capture)); + while cursor.match_pat(DoubleColon) { + buf.push_str("::"); + let capture = cursor.capture_ident()?; + buf.push_str(cursor.get_text(capture)); + } + Some(self.arena.alloc_str(buf)) + })?); + + if !cursor.match_pat(Comma) { + if !cursor.match_pat(CloseBracket) { + return None; + } + break; + } + } + + // The arena panics when allocating a size of zero. + Some(if buf.is_empty() { + &[] + } else { + buf.sort_unstable(); + &*self.arena.alloc_slice(buf) + }) + }); + + if let Some(lints) = lints + && cursor.match_all(&[CloseParen, Semi], &mut []) + { + data.lint_passes.push(LintPass { + docs, + name, + lt, + mac, + decl_range: mac_name.pos..cursor.pos(), + lints, + path: path.into(), + }); + } + }, + _ => {}, } } } diff --git a/clippy_dev/src/parse/cursor.rs b/clippy_dev/src/parse/cursor.rs index 2c142af4883a..af840532c27b 100644 --- a/clippy_dev/src/parse/cursor.rs +++ b/clippy_dev/src/parse/cursor.rs @@ -12,6 +12,7 @@ pub enum Pat<'a> { /// Matches any number of comments and doc comments. AnyComment, Ident(&'a str), + CaptureDocLines, CaptureIdent, LitStr, CaptureLitStr, @@ -22,12 +23,14 @@ pub enum Pat<'a> { Comma, DoubleColon, Eq, + FatArrow, Lifetime, Lt, Gt, OpenBrace, OpenBracket, OpenParen, + CaptureOptLifetimeArg, Pound, Semi, } @@ -112,6 +115,7 @@ pub fn step(&mut self) { /// /// For each capture made by the pattern one item will be taken from the capture /// sequence with the result placed inside. + #[expect(clippy::too_many_lines)] fn match_impl(&mut self, pat: Pat<'_>, captures: &mut slice::IterMut<'_, Capture>) -> bool { loop { match (pat, self.next_token.kind) { @@ -121,7 +125,6 @@ fn match_impl(&mut self, pat: Pat<'_>, captures: &mut slice::IterMut<'_, Capture Pat::AnyComment, TokenKind::BlockComment { terminated: true, .. } | TokenKind::LineComment { .. }, ) => self.step(), - (Pat::AnyComment, _) => return true, (Pat::Bang, TokenKind::Bang) | (Pat::CloseBrace, TokenKind::CloseBrace) | (Pat::CloseBracket, TokenKind::CloseBracket) @@ -152,12 +155,48 @@ fn match_impl(&mut self, pat: Pat<'_>, captures: &mut slice::IterMut<'_, Capture }, (Pat::DoubleColon, TokenKind::Colon) => { self.step(); - if !self.at_end() && matches!(self.next_token.kind, TokenKind::Colon) { + if matches!(self.next_token.kind, TokenKind::Colon) { self.step(); return true; } return false; }, + (Pat::FatArrow, TokenKind::Eq) => { + self.step(); + if matches!(self.next_token.kind, TokenKind::Gt) { + self.step(); + return true; + } + return false; + }, + (Pat::CaptureOptLifetimeArg, TokenKind::Lt) => { + self.step(); + loop { + match self.next_token.kind { + TokenKind::Lifetime { .. } => break, + TokenKind::Whitespace => self.step(), + _ => return false, + } + } + *captures.next().unwrap() = Capture { + pos: self.pos, + len: self.next_token.len, + }; + self.step(); + loop { + match self.next_token.kind { + TokenKind::Gt => break, + TokenKind::Whitespace => self.step(), + _ => return false, + } + } + self.step(); + return true; + }, + (Pat::CaptureOptLifetimeArg, _) => { + *captures.next().unwrap() = Capture { pos: 0, len: 0 }; + return true; + }, #[rustfmt::skip] ( Pat::CaptureLitStr, @@ -173,6 +212,28 @@ fn match_impl(&mut self, pat: Pat<'_>, captures: &mut slice::IterMut<'_, Capture self.step(); return true; }, + (Pat::CaptureDocLines, TokenKind::LineComment { doc_style: Some(_) }) => { + let pos = self.pos; + loop { + self.step(); + if !matches!( + self.next_token.kind, + TokenKind::Whitespace | TokenKind::LineComment { doc_style: Some(_) } + ) { + break; + } + } + *captures.next().unwrap() = Capture { + pos, + len: self.pos - pos, + }; + return true; + }, + (Pat::CaptureDocLines, _) => { + *captures.next().unwrap() = Capture::EMPTY; + return true; + }, + (Pat::AnyComment, _) => return true, _ => return false, } } @@ -219,8 +280,8 @@ pub fn find_any_ident(&mut self) -> Option { } } - /// Consume the returns the position of the next non-whitespace token if it's an - /// identifier. Returns `None` otherwise. + /// Consume the returns the position of the next non-whitespace token if it's the + /// specified identifier. Returns `None` otherwise. pub fn match_ident(&mut self, s: &str) -> Option { loop { match self.next_token.kind { @@ -235,6 +296,23 @@ pub fn match_ident(&mut self, s: &str) -> Option { } } + /// Consumes and captures the next non-whitespace token if it's an identifier. Returns + /// `None` otherwise. + pub fn capture_ident(&mut self) -> Option { + loop { + match self.next_token.kind { + TokenKind::Ident => { + let pos = self.pos; + let len = self.next_token.len; + self.step(); + return Some(Capture { pos, len }); + }, + TokenKind::Whitespace => self.step(), + _ => return None, + } + } + } + /// Continually attempt to match the pattern on subsequent tokens until a match is /// found. Returns whether the pattern was successfully matched. /// diff --git a/clippy_dev/src/utils.rs b/clippy_dev/src/utils.rs index 52452dd86b49..98a3458d6c2a 100644 --- a/clippy_dev/src/utils.rs +++ b/clippy_dev/src/utils.rs @@ -600,3 +600,27 @@ pub fn walk_dir_no_dot_or_target(p: impl AsRef) -> impl Iterator( + slice: &'a [T], + split_idx: impl FnMut(&'a T, &'a [T]) -> usize, +) -> impl Iterator { + struct I<'a, T, F> { + slice: &'a [T], + split_idx: F, + } + impl<'a, T, F: FnMut(&'a T, &'a [T]) -> usize> Iterator for I<'a, T, F> { + type Item = &'a [T]; + fn next(&mut self) -> Option { + let (head, tail) = self.slice.split_first()?; + if let Some((head, tail)) = self.slice.split_at_checked((self.split_idx)(head, tail) + 1) { + self.slice = tail; + Some(head) + } else { + self.slice = &[]; + None + } + } + } + I { slice, split_idx } +} diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index fa2951d91934..694b6625ffaf 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -482,10 +482,7 @@ pub struct Attributes { msrv: Msrv, } -impl_lint_pass!(Attributes => [ - INLINE_ALWAYS, - REPR_PACKED_WITHOUT_ABI, -]); +impl_lint_pass!(Attributes => [INLINE_ALWAYS, REPR_PACKED_WITHOUT_ABI]); impl Attributes { pub fn new(conf: &'static Conf) -> Self { @@ -531,8 +528,8 @@ pub fn new(conf: &'static Conf) -> Self { impl_lint_pass!(EarlyAttributes => [ DEPRECATED_CFG_ATTR, - NON_MINIMAL_CFG, DEPRECATED_CLIPPY_CFG_ATTR, + NON_MINIMAL_CFG, UNNECESSARY_CLIPPY_CFG, ]); @@ -561,13 +558,13 @@ pub fn new(conf: &'static Conf) -> Self { impl_lint_pass!(PostExpansionEarlyAttributes => [ ALLOW_ATTRIBUTES, ALLOW_ATTRIBUTES_WITHOUT_REASON, - DEPRECATED_SEMVER, - IGNORE_WITHOUT_REASON, - USELESS_ATTRIBUTE, BLANKET_CLIPPY_RESTRICTION_LINTS, - SHOULD_PANIC_WITHOUT_EXPECT, - MIXED_ATTRIBUTES_STYLE, + DEPRECATED_SEMVER, DUPLICATED_ATTRIBUTES, + IGNORE_WITHOUT_REASON, + MIXED_ATTRIBUTES_STYLE, + SHOULD_PANIC_WITHOUT_EXPECT, + USELESS_ATTRIBUTE, ]); impl EarlyLintPass for PostExpansionEarlyAttributes { diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index 31cc004f6855..2d61c5e0b78a 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -171,7 +171,11 @@ "holding a type across an await point which is not allowed to be held as per the configuration" } -impl_lint_pass!(AwaitHolding => [AWAIT_HOLDING_LOCK, AWAIT_HOLDING_REFCELL_REF, AWAIT_HOLDING_INVALID_TYPE]); +impl_lint_pass!(AwaitHolding => [ + AWAIT_HOLDING_INVALID_TYPE, + AWAIT_HOLDING_LOCK, + AWAIT_HOLDING_REFCELL_REF, +]); pub struct AwaitHolding { def_ids: DefIdMap<(&'static str, &'static DisallowedPathWithoutReplacement)>, diff --git a/clippy_lints/src/cargo/mod.rs b/clippy_lints/src/cargo/mod.rs index 08d92adbacef..2fb468aed618 100644 --- a/clippy_lints/src/cargo/mod.rs +++ b/clippy_lints/src/cargo/mod.rs @@ -220,11 +220,11 @@ pub struct Cargo { impl_lint_pass!(Cargo => [ CARGO_COMMON_METADATA, - REDUNDANT_FEATURE_NAMES, - NEGATIVE_FEATURE_NAMES, - MULTIPLE_CRATE_VERSIONS, - WILDCARD_DEPENDENCIES, LINT_GROUPS_PRIORITY, + MULTIPLE_CRATE_VERSIONS, + NEGATIVE_FEATURE_NAMES, + REDUNDANT_FEATURE_NAMES, + WILDCARD_DEPENDENCIES, ]); impl Cargo { diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 3c9ebef73f0d..2e5e5dd252a4 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -857,34 +857,34 @@ pub fn new(conf: &'static Conf) -> Self { } impl_lint_pass!(Casts => [ - CAST_PRECISION_LOSS, - CAST_SIGN_LOSS, - CAST_POSSIBLE_TRUNCATION, - CAST_POSSIBLE_WRAP, - CAST_LOSSLESS, - CAST_PTR_ALIGNMENT, - CAST_SLICE_DIFFERENT_SIZES, - UNNECESSARY_CAST, - FN_TO_NUMERIC_CAST_ANY, - FN_TO_NUMERIC_CAST, - FN_TO_NUMERIC_CAST_WITH_TRUNCATION, - CHAR_LIT_AS_U8, - PTR_AS_PTR, - PTR_CAST_CONSTNESS, - CAST_ENUM_TRUNCATION, - CAST_ENUM_CONSTRUCTOR, - CAST_ABS_TO_UNSIGNED, + AS_POINTER_UNDERSCORE, + AS_PTR_CAST_MUT, AS_UNDERSCORE, BORROW_AS_PTR, - CAST_SLICE_FROM_RAW_PARTS, - AS_PTR_CAST_MUT, + CAST_ABS_TO_UNSIGNED, + CAST_ENUM_CONSTRUCTOR, + CAST_ENUM_TRUNCATION, + CAST_LOSSLESS, CAST_NAN_TO_INT, - ZERO_PTR, - REF_AS_PTR, - AS_POINTER_UNDERSCORE, - MANUAL_DANGLING_PTR, + CAST_POSSIBLE_TRUNCATION, + CAST_POSSIBLE_WRAP, + CAST_PRECISION_LOSS, + CAST_PTR_ALIGNMENT, + CAST_SIGN_LOSS, + CAST_SLICE_DIFFERENT_SIZES, + CAST_SLICE_FROM_RAW_PARTS, + CHAR_LIT_AS_U8, CONFUSING_METHOD_TO_NUMERIC_CAST, + FN_TO_NUMERIC_CAST, + FN_TO_NUMERIC_CAST_ANY, + FN_TO_NUMERIC_CAST_WITH_TRUNCATION, + MANUAL_DANGLING_PTR, NEEDLESS_TYPE_CAST, + PTR_AS_PTR, + PTR_CAST_CONSTNESS, + REF_AS_PTR, + UNNECESSARY_CAST, + ZERO_PTR, ]); impl<'tcx> LateLintPass<'tcx> for Casts { diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 17e11b8b281d..0f3ef054b865 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -259,7 +259,7 @@ fn check_significant_tokens_and_expect_attrs( } } -impl_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]); +impl_lint_pass!(CollapsibleIf => [COLLAPSIBLE_ELSE_IF, COLLAPSIBLE_IF]); impl LateLintPass<'_> for CollapsibleIf { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index 641f8ae03b72..95f0afcc3d88 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -45,7 +45,9 @@ complexity, "unit structs can be constructed without calling `default`" } -declare_lint_pass!(DefaultConstructedUnitStructs => [DEFAULT_CONSTRUCTED_UNIT_STRUCTS]); +declare_lint_pass!(DefaultConstructedUnitStructs => [ + DEFAULT_CONSTRUCTED_UNIT_STRUCTS, +]); fn is_alias(ty: hir::Ty<'_>) -> bool { if let hir::TyKind::Path(ref qpath) = ty.kind { diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 32fd4afb122e..8ad5d40b2dc7 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -144,10 +144,10 @@ } impl_lint_pass!(Dereferencing<'_> => [ + EXPLICIT_AUTO_DEREF, EXPLICIT_DEREF_METHODS, NEEDLESS_BORROW, REF_BINDING_TO_REFERENCE, - EXPLICIT_AUTO_DEREF, ]); #[derive(Default)] diff --git a/clippy_lints/src/derive/mod.rs b/clippy_lints/src/derive/mod.rs index 86614201c406..a18c7533196e 100644 --- a/clippy_lints/src/derive/mod.rs +++ b/clippy_lints/src/derive/mod.rs @@ -185,11 +185,11 @@ } declare_lint_pass!(Derive => [ - EXPL_IMPL_CLONE_ON_COPY, DERIVED_HASH_WITH_MANUAL_EQ, DERIVE_ORD_XOR_PARTIAL_ORD, + DERIVE_PARTIAL_EQ_WITHOUT_EQ, + EXPL_IMPL_CLONE_ON_COPY, UNSAFE_DERIVE_DESERIALIZE, - DERIVE_PARTIAL_EQ_WITHOUT_EQ ]); impl<'tcx> LateLintPass<'tcx> for Derive { diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 0a2871f23964..3863e6d4a681 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -719,26 +719,26 @@ pub fn new(conf: &'static Conf) -> Self { } impl_lint_pass!(Documentation => [ + DOC_BROKEN_LINK, + DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS, + DOC_INCLUDE_WITHOUT_CFG, + DOC_LAZY_CONTINUATION, DOC_LINK_CODE, DOC_LINK_WITH_QUOTES, - DOC_BROKEN_LINK, DOC_MARKDOWN, DOC_NESTED_REFDEFS, - MISSING_SAFETY_DOC, + DOC_OVERINDENTED_LIST_ITEMS, + DOC_PARAGRAPHS_MISSING_PUNCTUATION, + DOC_SUSPICIOUS_FOOTNOTES, + EMPTY_DOCS, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, + MISSING_SAFETY_DOC, NEEDLESS_DOCTEST_MAIN, - TEST_ATTR_IN_DOCTEST, - UNNECESSARY_SAFETY_DOC, SUSPICIOUS_DOC_COMMENTS, - EMPTY_DOCS, - DOC_LAZY_CONTINUATION, - DOC_OVERINDENTED_LIST_ITEMS, + TEST_ATTR_IN_DOCTEST, TOO_LONG_FIRST_DOC_PARAGRAPH, - DOC_INCLUDE_WITHOUT_CFG, - DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS, - DOC_SUSPICIOUS_FOOTNOTES, - DOC_PARAGRAPHS_MISSING_PUNCTUATION, + UNNECESSARY_SAFETY_DOC, ]); impl EarlyLintPass for Documentation { diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 3bb8c484ceec..db7414559769 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -75,11 +75,7 @@ const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value that does not implement `Drop`. \ Forgetting such a type is the same as dropping it"; -declare_lint_pass!(DropForgetRef => [ - DROP_NON_DROP, - FORGET_NON_DROP, - MEM_FORGET, -]); +declare_lint_pass!(DropForgetRef => [DROP_NON_DROP, FORGET_NON_DROP, MEM_FORGET]); impl<'tcx> LateLintPass<'tcx> for DropForgetRef { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { diff --git a/clippy_lints/src/empty_line_after.rs b/clippy_lints/src/empty_line_after.rs index 76e67b1154be..e3453c7be1d7 100644 --- a/clippy_lints/src/empty_line_after.rs +++ b/clippy_lints/src/empty_line_after.rs @@ -101,8 +101,8 @@ pub struct EmptyLineAfter { } impl_lint_pass!(EmptyLineAfter => [ - EMPTY_LINE_AFTER_OUTER_ATTR, EMPTY_LINE_AFTER_DOC_COMMENTS, + EMPTY_LINE_AFTER_OUTER_ATTR, ]); impl EmptyLineAfter { diff --git a/clippy_lints/src/empty_with_brackets.rs b/clippy_lints/src/empty_with_brackets.rs index 7e335d5c9809..c2d205010326 100644 --- a/clippy_lints/src/empty_with_brackets.rs +++ b/clippy_lints/src/empty_with_brackets.rs @@ -90,7 +90,10 @@ pub struct EmptyWithBrackets { empty_tuple_enum_variants: FxIndexMap, } -impl_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM_VARIANTS_WITH_BRACKETS]); +impl_lint_pass!(EmptyWithBrackets => [ + EMPTY_ENUM_VARIANTS_WITH_BRACKETS, + EMPTY_STRUCTS_WITH_BRACKETS, +]); impl LateLintPass<'_> for EmptyWithBrackets { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index 75db923b1c37..37a645756217 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -63,7 +63,11 @@ "disallows usage of the `to_be_bytes` method" } -declare_lint_pass!(EndianBytes => [HOST_ENDIAN_BYTES, LITTLE_ENDIAN_BYTES, BIG_ENDIAN_BYTES]); +declare_lint_pass!(EndianBytes => [ + BIG_ENDIAN_BYTES, + HOST_ENDIAN_BYTES, + LITTLE_ENDIAN_BYTES, +]); const HOST_NAMES: [Symbol; 2] = [sym::from_ne_bytes, sym::to_ne_bytes]; const LITTLE_NAMES: [Symbol; 2] = [sym::from_le_bytes, sym::to_le_bytes]; diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 3e46c370fb70..b5781441bce6 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -66,7 +66,10 @@ "redundant closures for method calls" } -declare_lint_pass!(EtaReduction => [REDUNDANT_CLOSURE, REDUNDANT_CLOSURE_FOR_METHOD_CALLS]); +declare_lint_pass!(EtaReduction => [ + REDUNDANT_CLOSURE, + REDUNDANT_CLOSURE_FOR_METHOD_CALLS, +]); impl<'tcx> LateLintPass<'tcx> for EtaReduction { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs index 686dc5c3c4fc..fdcb013bb71e 100644 --- a/clippy_lints/src/excessive_bools.rs +++ b/clippy_lints/src/excessive_bools.rs @@ -102,7 +102,10 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(ExcessiveBools => [STRUCT_EXCESSIVE_BOOLS, FN_PARAMS_EXCESSIVE_BOOLS]); +impl_lint_pass!(ExcessiveBools => [ + FN_PARAMS_EXCESSIVE_BOOLS, + STRUCT_EXCESSIVE_BOOLS, +]); fn has_n_bools<'tcx>(iter: impl Iterator>, mut count: u64) -> bool { iter.filter(|ty| is_bool(ty)).any(|_| { diff --git a/clippy_lints/src/field_scoped_visibility_modifiers.rs b/clippy_lints/src/field_scoped_visibility_modifiers.rs index dfb0b4f103c5..4b736c68cb86 100644 --- a/clippy_lints/src/field_scoped_visibility_modifiers.rs +++ b/clippy_lints/src/field_scoped_visibility_modifiers.rs @@ -47,7 +47,9 @@ "checks for usage of a scoped visibility modifier, like `pub(crate)`, on fields" } -declare_lint_pass!(FieldScopedVisibilityModifiers => [FIELD_SCOPED_VISIBILITY_MODIFIERS]); +declare_lint_pass!(FieldScopedVisibilityModifiers => [ + FIELD_SCOPED_VISIBILITY_MODIFIERS, +]); impl EarlyLintPass for FieldScopedVisibilityModifiers { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 6178addfff12..630291e4d836 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -65,9 +65,7 @@ pub struct FloatLiteral { const_literal_digits_threshold: usize, } -impl_lint_pass!(FloatLiteral => [ - EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL -]); +impl_lint_pass!(FloatLiteral => [EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL]); impl FloatLiteral { pub fn new(conf: &'static Conf) -> Self { diff --git a/clippy_lints/src/floating_point_arithmetic/mod.rs b/clippy_lints/src/floating_point_arithmetic/mod.rs index edc638c96bbf..0833761b32dc 100644 --- a/clippy_lints/src/floating_point_arithmetic/mod.rs +++ b/clippy_lints/src/floating_point_arithmetic/mod.rs @@ -103,10 +103,7 @@ "usage of sub-optimal floating point operations" } -declare_lint_pass!(FloatingPointArithmetic => [ - IMPRECISE_FLOPS, - SUBOPTIMAL_FLOPS -]); +declare_lint_pass!(FloatingPointArithmetic => [IMPRECISE_FLOPS, SUBOPTIMAL_FLOPS]); impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 3eb358917a0e..dfcae1c85ef9 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -260,12 +260,12 @@ impl_lint_pass!(FormatArgs<'_> => [ FORMAT_IN_FORMAT_ARGS, + POINTER_FORMAT, TO_STRING_IN_FORMAT_ARGS, UNINLINED_FORMAT_ARGS, UNNECESSARY_DEBUG_FORMATTING, - UNUSED_FORMAT_SPECS, - POINTER_FORMAT, UNNECESSARY_TRAILING_COMMA, + UNUSED_FORMAT_SPECS, ]); #[expect(clippy::struct_field_names)] diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs index 903d43e56c4b..744d087f4e0f 100644 --- a/clippy_lints/src/format_impl.rs +++ b/clippy_lints/src/format_impl.rs @@ -113,7 +113,7 @@ pub fn new(format_args: FormatArgsStorage) -> Self { } } -impl_lint_pass!(FormatImpl => [RECURSIVE_FORMAT_IMPL, PRINT_IN_FORMAT_IMPL]); +impl_lint_pass!(FormatImpl => [PRINT_IN_FORMAT_IMPL, RECURSIVE_FORMAT_IMPL]); impl<'tcx> LateLintPass<'tcx> for FormatImpl { fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 7a64d3135fa5..4bedbd378bf5 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -138,11 +138,11 @@ } declare_lint_pass!(Formatting => [ - SUSPICIOUS_ASSIGNMENT_FORMATTING, - SUSPICIOUS_UNARY_OP_FORMATTING, - SUSPICIOUS_ELSE_FORMATTING, + POSSIBLE_MISSING_COMMA, POSSIBLE_MISSING_ELSE, - POSSIBLE_MISSING_COMMA + SUSPICIOUS_ASSIGNMENT_FORMATTING, + SUSPICIOUS_ELSE_FORMATTING, + SUSPICIOUS_UNARY_OP_FORMATTING, ]); impl EarlyLintPass for Formatting { diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs index 9a7427ea1447..0a3af59e1f7f 100644 --- a/clippy_lints/src/functions/mod.rs +++ b/clippy_lints/src/functions/mod.rs @@ -516,18 +516,18 @@ pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { } impl_lint_pass!(Functions => [ + DOUBLE_MUST_USE, + IMPL_TRAIT_IN_PARAMS, + MISNAMED_GETTERS, + MUST_USE_CANDIDATE, + MUST_USE_UNIT, + NOT_UNSAFE_PTR_ARG_DEREF, + REF_OPTION, + RENAMED_FUNCTION_PARAMS, + RESULT_LARGE_ERR, + RESULT_UNIT_ERR, TOO_MANY_ARGUMENTS, TOO_MANY_LINES, - NOT_UNSAFE_PTR_ARG_DEREF, - MUST_USE_UNIT, - DOUBLE_MUST_USE, - MUST_USE_CANDIDATE, - RESULT_UNIT_ERR, - RESULT_LARGE_ERR, - MISNAMED_GETTERS, - IMPL_TRAIT_IN_PARAMS, - RENAMED_FUNCTION_PARAMS, - REF_OPTION, ]); impl<'tcx> LateLintPass<'tcx> for Functions { diff --git a/clippy_lints/src/ifs/mod.rs b/clippy_lints/src/ifs/mod.rs index 739f2fc91729..fa17685c1698 100644 --- a/clippy_lints/src/ifs/mod.rs +++ b/clippy_lints/src/ifs/mod.rs @@ -160,10 +160,10 @@ pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf) -> Self { } impl_lint_pass!(CopyAndPaste<'_> => [ + BRANCHES_SHARING_CODE, IFS_SAME_COND, - SAME_FUNCTIONS_IN_IF_CONDITION, IF_SAME_THEN_ELSE, - BRANCHES_SHARING_CODE + SAME_FUNCTIONS_IN_IF_CONDITION, ]); impl<'tcx> LateLintPass<'tcx> for CopyAndPaste<'tcx> { diff --git a/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs b/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs index f73182d3af0d..dec08d94e89d 100644 --- a/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs +++ b/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs @@ -69,7 +69,9 @@ "ensures that the semantics of `Borrow` for `Hash` are satisfied when `Borrow` and `Borrow<[u8]>` are implemented" } -declare_lint_pass!(ImplHashWithBorrowStrBytes => [IMPL_HASH_BORROW_WITH_STR_AND_BYTES]); +declare_lint_pass!(ImplHashWithBorrowStrBytes => [ + IMPL_HASH_BORROW_WITH_STR_AND_BYTES, +]); impl LateLintPass<'_> for ImplHashWithBorrowStrBytes { /// We are emitting this lint at the Hash impl of a type that implements all diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 516f9e3aa60c..a7ee6474242b 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -83,7 +83,10 @@ pub struct ImplicitSaturatingSub { msrv: Msrv, } -impl_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB, INVERTED_SATURATING_SUB]); +impl_lint_pass!(ImplicitSaturatingSub => [ + IMPLICIT_SATURATING_SUB, + INVERTED_SATURATING_SUB, +]); impl ImplicitSaturatingSub { pub fn new(conf: &'static Conf) -> Self { diff --git a/clippy_lints/src/inconsistent_struct_constructor.rs b/clippy_lints/src/inconsistent_struct_constructor.rs index e6129757e560..60cc1da3eee2 100644 --- a/clippy_lints/src/inconsistent_struct_constructor.rs +++ b/clippy_lints/src/inconsistent_struct_constructor.rs @@ -76,7 +76,9 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(InconsistentStructConstructor => [INCONSISTENT_STRUCT_CONSTRUCTOR]); +impl_lint_pass!(InconsistentStructConstructor => [ + INCONSISTENT_STRUCT_CONSTRUCTOR, +]); impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs index e569a5c7b612..22082646eb31 100644 --- a/clippy_lints/src/inherent_to_string.rs +++ b/clippy_lints/src/inherent_to_string.rs @@ -88,7 +88,10 @@ "type implements inherent method `to_string()`, which gets shadowed by the implementation of the `Display` trait" } -declare_lint_pass!(InherentToString => [INHERENT_TO_STRING, INHERENT_TO_STRING_SHADOW_DISPLAY]); +declare_lint_pass!(InherentToString => [ + INHERENT_TO_STRING, + INHERENT_TO_STRING_SHADOW_DISPLAY, +]); impl<'tcx> LateLintPass<'tcx> for InherentToString { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index 22767901614e..1727b5934a6a 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -197,9 +197,9 @@ fn is_allowed_prefix(&self, prefix: &str) -> bool { impl_lint_pass!(ItemNameRepetitions => [ ENUM_VARIANT_NAMES, - STRUCT_FIELD_NAMES, + MODULE_INCEPTION, MODULE_NAME_REPETITIONS, - MODULE_INCEPTION + STRUCT_FIELD_NAMES, ]); #[must_use] diff --git a/clippy_lints/src/iter_without_into_iter.rs b/clippy_lints/src/iter_without_into_iter.rs index 645e0f981f27..89f8ede06bb3 100644 --- a/clippy_lints/src/iter_without_into_iter.rs +++ b/clippy_lints/src/iter_without_into_iter.rs @@ -105,7 +105,10 @@ "implementing `IntoIterator for (&|&mut) Type` without an inherent `iter(_mut)` method" } -declare_lint_pass!(IterWithoutIntoIter => [ITER_WITHOUT_INTO_ITER, INTO_ITER_WITHOUT_ITER]); +declare_lint_pass!(IterWithoutIntoIter => [ + INTO_ITER_WITHOUT_ITER, + ITER_WITHOUT_INTO_ITER, +]); /// Checks if a given type is nameable in a trait (impl). /// RPIT is stable, but impl Trait in traits is not (yet), so when we have diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 2e576da38b89..9c954fe1b07d 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -93,7 +93,7 @@ pub struct LenZero { msrv: Msrv, } -impl_lint_pass!(LenZero => [LEN_ZERO, COMPARISON_TO_EMPTY]); +impl_lint_pass!(LenZero => [COMPARISON_TO_EMPTY, LEN_ZERO]); impl LenZero { pub fn new(conf: &'static Conf) -> Self { diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs index b72e14246db7..ff6ba3ea1623 100644 --- a/clippy_lints/src/let_underscore.rs +++ b/clippy_lints/src/let_underscore.rs @@ -127,7 +127,12 @@ "non-binding `let` without a type annotation" } -declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE, LET_UNDERSCORE_UNTYPED]); +declare_lint_pass!(LetUnderscore => [ + LET_UNDERSCORE_FUTURE, + LET_UNDERSCORE_LOCK, + LET_UNDERSCORE_MUST_USE, + LET_UNDERSCORE_UNTYPED, +]); impl<'tcx> LateLintPass<'tcx> for LetUnderscore { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &LetStmt<'tcx>) { diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 679fb983d532..d9008eee25d2 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -135,9 +135,9 @@ pub fn new(conf: &'static Conf) -> Self { } impl_lint_pass!(Lifetimes => [ - NEEDLESS_LIFETIMES, ELIDABLE_LIFETIME_NAMES, EXTRA_UNUSED_LIFETIMES, + NEEDLESS_LIFETIMES, ]); impl<'tcx> LateLintPass<'tcx> for Lifetimes { diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 7cbfa2d097ae..1dd3a042e3bf 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -196,10 +196,10 @@ pub struct LiteralDigitGrouping { } impl_lint_pass!(LiteralDigitGrouping => [ - UNREADABLE_LITERAL, INCONSISTENT_DIGIT_GROUPING, LARGE_DIGIT_GROUPS, MISTYPED_LITERAL_SUFFIXES, + UNREADABLE_LITERAL, UNUSUAL_BYTE_GROUPINGS, ]); diff --git a/clippy_lints/src/literal_string_with_formatting_args.rs b/clippy_lints/src/literal_string_with_formatting_args.rs index 244e7c95122e..2751a7edc1ae 100644 --- a/clippy_lints/src/literal_string_with_formatting_args.rs +++ b/clippy_lints/src/literal_string_with_formatting_args.rs @@ -36,7 +36,9 @@ "Checks if string literals have formatting arguments" } -declare_lint_pass!(LiteralStringWithFormattingArg => [LITERAL_STRING_WITH_FORMATTING_ARGS]); +declare_lint_pass!(LiteralStringWithFormattingArg => [ + LITERAL_STRING_WITH_FORMATTING_ARGS, +]); fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, spans: &[(Span, Option)]) { if !spans.is_empty() diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 83574cab6b67..0b69538c063f 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -799,30 +799,30 @@ pub fn new(conf: &'static Conf) -> Self { } impl_lint_pass!(Loops => [ - MANUAL_MEMCPY, - MANUAL_FLATTEN, - NEEDLESS_RANGE_LOOP, - EXPLICIT_ITER_LOOP, - EXPLICIT_INTO_ITER_LOOP, - ITER_NEXT_LOOP, - WHILE_LET_LOOP, - EXPLICIT_COUNTER_LOOP, + CHAR_INDICES_AS_BYTE_INDICES, EMPTY_LOOP, - WHILE_LET_ON_ITERATOR, + EXPLICIT_COUNTER_LOOP, + EXPLICIT_INTO_ITER_LOOP, + EXPLICIT_ITER_LOOP, FOR_KV_MAP, - NEVER_LOOP, + INFINITE_LOOP, + ITER_NEXT_LOOP, + MANUAL_FIND, + MANUAL_FLATTEN, + MANUAL_MEMCPY, + MANUAL_SLICE_FILL, + MANUAL_WHILE_LET_SOME, + MISSING_SPIN_LOOP, MUT_RANGE_BOUND, - WHILE_IMMUTABLE_CONDITION, - WHILE_FLOAT, + NEEDLESS_RANGE_LOOP, + NEVER_LOOP, SAME_ITEM_PUSH, SINGLE_ELEMENT_LOOP, - MISSING_SPIN_LOOP, - MANUAL_FIND, - MANUAL_WHILE_LET_SOME, UNUSED_ENUMERATE_INDEX, - INFINITE_LOOP, - MANUAL_SLICE_FILL, - CHAR_INDICES_AS_BYTE_INDICES, + WHILE_FLOAT, + WHILE_IMMUTABLE_CONDITION, + WHILE_LET_LOOP, + WHILE_LET_ON_ITERATOR, ]); impl<'tcx> LateLintPass<'tcx> for Loops { diff --git a/clippy_lints/src/manual_float_methods.rs b/clippy_lints/src/manual_float_methods.rs index a81c4dc6a793..6914c88323ac 100644 --- a/clippy_lints/src/manual_float_methods.rs +++ b/clippy_lints/src/manual_float_methods.rs @@ -61,7 +61,7 @@ style, "use dedicated method to check if a float is finite" } -impl_lint_pass!(ManualFloatMethods => [MANUAL_IS_INFINITE, MANUAL_IS_FINITE]); +impl_lint_pass!(ManualFloatMethods => [MANUAL_IS_FINITE, MANUAL_IS_INFINITE]); #[derive(Clone, Copy)] enum Variant { diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 6f49c5524118..aeffbb26722f 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -1021,33 +1021,33 @@ pub fn new(conf: &'static Conf) -> Self { } impl_lint_pass!(Matches => [ - SINGLE_MATCH, - MATCH_REF_PATS, - MATCH_BOOL, - SINGLE_MATCH_ELSE, - MATCH_OVERLAPPING_ARM, - MATCH_WILD_ERR_ARM, - MATCH_AS_REF, - WILDCARD_ENUM_MATCH_ARM, - MATCH_WILDCARD_FOR_SINGLE_VARIANTS, - WILDCARD_IN_OR_PATTERNS, - MATCH_SINGLE_BINDING, - INFALLIBLE_DESTRUCTURING_MATCH, - REST_PAT_IN_FULLY_BOUND_STRUCTS, - REDUNDANT_PATTERN_MATCHING, - MATCH_LIKE_MATCHES_MACRO, - MATCH_SAME_ARMS, - NEEDLESS_MATCH, COLLAPSIBLE_MATCH, + INFALLIBLE_DESTRUCTURING_MATCH, + MANUAL_FILTER, + MANUAL_MAP, + MANUAL_OK_ERR, MANUAL_UNWRAP_OR, MANUAL_UNWRAP_OR_DEFAULT, + MATCH_AS_REF, + MATCH_BOOL, + MATCH_LIKE_MATCHES_MACRO, + MATCH_OVERLAPPING_ARM, + MATCH_REF_PATS, + MATCH_SAME_ARMS, + MATCH_SINGLE_BINDING, MATCH_STR_CASE_MISMATCH, - SIGNIFICANT_DROP_IN_SCRUTINEE, - TRY_ERR, - MANUAL_MAP, - MANUAL_FILTER, + MATCH_WILDCARD_FOR_SINGLE_VARIANTS, + MATCH_WILD_ERR_ARM, + NEEDLESS_MATCH, REDUNDANT_GUARDS, - MANUAL_OK_ERR, + REDUNDANT_PATTERN_MATCHING, + REST_PAT_IN_FULLY_BOUND_STRUCTS, + SIGNIFICANT_DROP_IN_SCRUTINEE, + SINGLE_MATCH, + SINGLE_MATCH_ELSE, + TRY_ERR, + WILDCARD_ENUM_MATCH_ARM, + WILDCARD_IN_OR_PATTERNS, ]); impl<'tcx> LateLintPass<'tcx> for Matches { diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 0f32f89666a0..806b1553cc79 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -125,8 +125,12 @@ "replacing a value of type `T` with `T::default()` instead of using `std::mem::take`" } -impl_lint_pass!(MemReplace => - [MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_OPTION_WITH_SOME, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]); +impl_lint_pass!(MemReplace => [ + MEM_REPLACE_OPTION_WITH_NONE, + MEM_REPLACE_OPTION_WITH_SOME, + MEM_REPLACE_WITH_DEFAULT, + MEM_REPLACE_WITH_UNINIT, +]); fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) -> bool { if is_none_expr(cx, src) { diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 74db7ae03ba0..a8d912d5520c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4783,159 +4783,159 @@ pub fn new(conf: &'static Conf, format_args: FormatArgsStorage) -> Self { } impl_lint_pass!(Methods => [ - UNWRAP_USED, - EXPECT_USED, - SHOULD_IMPLEMENT_TRAIT, - WRONG_SELF_CONVENTION, - OK_EXPECT, - UNWRAP_OR_DEFAULT, - MAP_UNWRAP_OR, - RESULT_MAP_OR_INTO_OPTION, - OPTION_MAP_OR_NONE, BIND_INSTEAD_OF_MAP, - OR_FUN_CALL, - OR_THEN_UNWRAP, - EXPECT_FUN_CALL, - CHARS_NEXT_CMP, + BYTES_COUNT_TO_LEN, + BYTES_NTH, + CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS, CHARS_LAST_CMP, + CHARS_NEXT_CMP, + CLEAR_WITH_DRAIN, + CLONED_INSTEAD_OF_COPIED, CLONE_ON_COPY, CLONE_ON_REF_PTR, COLLAPSIBLE_STR_REPLACE, CONST_IS_EMPTY, - ITER_OVEREAGER_CLONED, - CLONED_INSTEAD_OF_COPIED, - FLAT_MAP_OPTION, - INEFFICIENT_TO_STRING, - NEW_RET_NO_SELF, - SINGLE_CHAR_ADD_STR, - SEARCH_IS_SOME, - FILTER_NEXT, - SKIP_WHILE_NEXT, + DOUBLE_ENDED_ITERATOR_LAST, + DRAIN_COLLECT, + ERR_EXPECT, + EXPECT_FUN_CALL, + EXPECT_USED, + EXTEND_WITH_DRAIN, + FILETYPE_IS_FILE, + FILTER_MAP_BOOL_THEN, FILTER_MAP_IDENTITY, - MAP_IDENTITY, - MANUAL_FILTER_MAP, - MANUAL_FIND_MAP, - OPTION_FILTER_MAP, FILTER_MAP_NEXT, + FILTER_NEXT, FLAT_MAP_IDENTITY, - MAP_FLATTEN, + FLAT_MAP_OPTION, + FORMAT_COLLECT, + FROM_ITER_INSTEAD_OF_COLLECT, + GET_FIRST, + GET_LAST_WITH_LEN, + GET_UNWRAP, + IMPLICIT_CLONE, + INEFFICIENT_TO_STRING, + INSPECT_FOR_EACH, + INTO_ITER_ON_REF, + IO_OTHER_ERROR, + IP_CONSTANT, + IS_DIGIT_ASCII_RADIX, ITERATOR_STEP_BY_ZERO, - ITER_NEXT_SLICE, + ITER_CLONED_COLLECT, ITER_COUNT, + ITER_FILTER_IS_OK, + ITER_FILTER_IS_SOME, + ITER_KV_MAP, + ITER_NEXT_SLICE, ITER_NTH, ITER_NTH_ZERO, - BYTES_NTH, + ITER_ON_EMPTY_COLLECTIONS, + ITER_ON_SINGLE_ITEMS, + ITER_OUT_OF_BOUNDS, + ITER_OVEREAGER_CLONED, ITER_SKIP_NEXT, - GET_UNWRAP, - GET_LAST_WITH_LEN, - STRING_EXTEND_CHARS, - ITER_CLONED_COLLECT, + ITER_SKIP_ZERO, ITER_WITH_DRAIN, - TYPE_ID_ON_BOX, - USELESS_ASREF, - UNNECESSARY_FOLD, - UNNECESSARY_FILTER_MAP, - UNNECESSARY_FIND_MAP, - INTO_ITER_ON_REF, - SUSPICIOUS_MAP, - UNINIT_ASSUMED_INIT, + JOIN_ABSOLUTE_PATHS, + LINES_FILTER_MAP_OK, + MANUAL_CONTAINS, + MANUAL_C_STR_LITERALS, + MANUAL_FILTER_MAP, + MANUAL_FIND_MAP, + MANUAL_INSPECT, + MANUAL_IS_VARIANT_AND, + MANUAL_NEXT_BACK, + MANUAL_OK_OR, + MANUAL_REPEAT_N, MANUAL_SATURATING_ARITHMETIC, - ZST_OFFSET, - PTR_OFFSET_BY_LITERAL, - PTR_OFFSET_WITH_CAST, - FILETYPE_IS_FILE, - OPTION_AS_REF_DEREF, - UNNECESSARY_LAZY_EVALUATIONS, - MAP_COLLECT_RESULT_UNIT, - FROM_ITER_INSTEAD_OF_COLLECT, - INSPECT_FOR_EACH, - IMPLICIT_CLONE, - SUSPICIOUS_TO_OWNED, - SUSPICIOUS_SPLITN, - MANUAL_STR_REPEAT, - EXTEND_WITH_DRAIN, MANUAL_SPLIT_ONCE, - NEEDLESS_SPLITN, - UNNECESSARY_TO_OWNED, - UNNECESSARY_JOIN, - ERR_EXPECT, + MANUAL_STR_REPEAT, + MANUAL_TRY_FOLD, + MAP_ALL_ANY_IDENTITY, + MAP_CLONE, + MAP_COLLECT_RESULT_UNIT, + MAP_ERR_IGNORE, + MAP_FLATTEN, + MAP_IDENTITY, + MAP_UNWRAP_OR, + MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES, + MUT_MUTEX_LOCK, + NAIVE_BYTECOUNT, + NEEDLESS_AS_BYTES, + NEEDLESS_CHARACTER_ITERATION, + NEEDLESS_COLLECT, NEEDLESS_OPTION_AS_DEREF, - IS_DIGIT_ASCII_RADIX, NEEDLESS_OPTION_TAKE, + NEEDLESS_SPLITN, + NEW_RET_NO_SELF, + NONSENSICAL_OPEN_OPTIONS, NO_EFFECT_REPLACE, OBFUSCATED_IF_ELSE, - ITER_ON_SINGLE_ITEMS, - ITER_ON_EMPTY_COLLECTIONS, - NAIVE_BYTECOUNT, - BYTES_COUNT_TO_LEN, - CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS, - GET_FIRST, - MANUAL_OK_OR, - MAP_CLONE, - MAP_ERR_IGNORE, - MUT_MUTEX_LOCK, - NONSENSICAL_OPEN_OPTIONS, - SUSPICIOUS_OPEN_OPTIONS, + OK_EXPECT, + OPTION_AS_REF_CLONED, + OPTION_AS_REF_DEREF, + OPTION_FILTER_MAP, + OPTION_MAP_OR_NONE, + OR_FUN_CALL, + OR_THEN_UNWRAP, PATH_BUF_PUSH_OVERWRITE, + PATH_ENDS_WITH_EXT, + PTR_OFFSET_BY_LITERAL, + PTR_OFFSET_WITH_CAST, RANGE_ZIP_WITH_LEN, - REPEAT_ONCE, - STABLE_SORT_PRIMITIVE, - UNIT_HASH, + READONLY_WRITE_LOCK, READ_LINE_WITHOUT_TRIM, - UNNECESSARY_SORT_BY, - VEC_RESIZE_TO_ZERO, - VERBOSE_FILE_READS, - ITER_KV_MAP, + REDUNDANT_AS_STR, + REDUNDANT_ITER_CLONED, + REPEAT_ONCE, + RESULT_FILTER_MAP, + RESULT_MAP_OR_INTO_OPTION, + RETURN_AND_THEN, + SEARCH_IS_SOME, SEEK_FROM_CURRENT, SEEK_TO_START_INSTEAD_OF_REWIND, - NEEDLESS_COLLECT, - SUSPICIOUS_COMMAND_ARG_SPACE, - CLEAR_WITH_DRAIN, - MANUAL_NEXT_BACK, - UNNECESSARY_LITERAL_UNWRAP, - DRAIN_COLLECT, - MANUAL_TRY_FOLD, - FORMAT_COLLECT, - STRING_LIT_CHARS_ANY, - ITER_SKIP_ZERO, - FILTER_MAP_BOOL_THEN, - READONLY_WRITE_LOCK, - ITER_OUT_OF_BOUNDS, - PATH_ENDS_WITH_EXT, - REDUNDANT_AS_STR, - WAKER_CLONE_WAKE, - UNNECESSARY_FALLIBLE_CONVERSIONS, - JOIN_ABSOLUTE_PATHS, - RESULT_FILTER_MAP, - ITER_FILTER_IS_SOME, - ITER_FILTER_IS_OK, - MANUAL_IS_VARIANT_AND, - STR_SPLIT_AT_NEWLINE, - OPTION_AS_REF_CLONED, - UNNECESSARY_RESULT_MAP_OR_ELSE, - MANUAL_C_STR_LITERALS, - UNNECESSARY_GET_THEN_CHECK, - UNNECESSARY_FIRST_THEN_CHECK, - NEEDLESS_CHARACTER_ITERATION, - MANUAL_INSPECT, - UNNECESSARY_MIN_OR_MAX, - NEEDLESS_AS_BYTES, - MAP_ALL_ANY_IDENTITY, - MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES, - UNNECESSARY_MAP_OR, - DOUBLE_ENDED_ITERATOR_LAST, - USELESS_NONZERO_NEW_UNCHECKED, - MANUAL_REPEAT_N, + SHOULD_IMPLEMENT_TRAIT, + SINGLE_CHAR_ADD_STR, + SKIP_WHILE_NEXT, SLICED_STRING_AS_BYTES, - RETURN_AND_THEN, - UNBUFFERED_BYTES, - MANUAL_CONTAINS, - IO_OTHER_ERROR, + STABLE_SORT_PRIMITIVE, + STRING_EXTEND_CHARS, + STRING_LIT_CHARS_ANY, + STR_SPLIT_AT_NEWLINE, + SUSPICIOUS_COMMAND_ARG_SPACE, + SUSPICIOUS_MAP, + SUSPICIOUS_OPEN_OPTIONS, + SUSPICIOUS_SPLITN, + SUSPICIOUS_TO_OWNED, SWAP_WITH_TEMPORARY, - IP_CONSTANT, - REDUNDANT_ITER_CLONED, + TYPE_ID_ON_BOX, + UNBUFFERED_BYTES, + UNINIT_ASSUMED_INIT, + UNIT_HASH, + UNNECESSARY_FALLIBLE_CONVERSIONS, + UNNECESSARY_FILTER_MAP, + UNNECESSARY_FIND_MAP, + UNNECESSARY_FIRST_THEN_CHECK, + UNNECESSARY_FOLD, + UNNECESSARY_GET_THEN_CHECK, + UNNECESSARY_JOIN, + UNNECESSARY_LAZY_EVALUATIONS, + UNNECESSARY_LITERAL_UNWRAP, + UNNECESSARY_MAP_OR, + UNNECESSARY_MIN_OR_MAX, UNNECESSARY_OPTION_MAP_OR_ELSE, - LINES_FILTER_MAP_OK, + UNNECESSARY_RESULT_MAP_OR_ELSE, + UNNECESSARY_SORT_BY, + UNNECESSARY_TO_OWNED, + UNWRAP_OR_DEFAULT, + UNWRAP_USED, + USELESS_ASREF, + USELESS_NONZERO_NEW_UNCHECKED, + VEC_RESIZE_TO_ZERO, + VERBOSE_FILE_READS, + WAKER_CLONE_WAKE, + WRONG_SELF_CONVENTION, + ZST_OFFSET, ]); /// Extracts a method call name, args, and `Span` of the method name. diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 19e9910dfe9d..0f04d90b70cf 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -94,9 +94,9 @@ } declare_lint_pass!(LintPass => [ + SHORT_CIRCUIT_STATEMENT, USED_UNDERSCORE_BINDING, USED_UNDERSCORE_ITEMS, - SHORT_CIRCUIT_STATEMENT, ]); impl<'tcx> LateLintPass<'tcx> for LintPass { diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index f988323a8c13..e4a2befef77c 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -303,15 +303,15 @@ } declare_lint_pass!(MiscEarlyLints => [ - UNNEEDED_FIELD_PATTERN, - MIXED_CASE_HEX_LITERALS, - UNSEPARATED_LITERAL_SUFFIX, - SEPARATED_LITERAL_SUFFIX, - ZERO_PREFIXED_LITERAL, BUILTIN_TYPE_SHADOW, - REDUNDANT_PATTERN, - UNNEEDED_WILDCARD_PATTERN, + MIXED_CASE_HEX_LITERALS, REDUNDANT_AT_REST_PATTERN, + REDUNDANT_PATTERN, + SEPARATED_LITERAL_SUFFIX, + UNNEEDED_FIELD_PATTERN, + UNNEEDED_WILDCARD_PATTERN, + UNSEPARATED_LITERAL_SUFFIX, + ZERO_PREFIXED_LITERAL, ]); impl EarlyLintPass for MiscEarlyLints { diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index 53f97abe0b44..d749a8017557 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -79,7 +79,10 @@ "whether an expression contains a diverging sub expression" } -declare_lint_pass!(EvalOrderDependence => [MIXED_READ_WRITE_IN_EXPRESSION, DIVERGING_SUB_EXPRESSION]); +declare_lint_pass!(EvalOrderDependence => [ + DIVERGING_SUB_EXPRESSION, + MIXED_READ_WRITE_IN_EXPRESSION, +]); impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs index 98a9a98d281a..e4e898362b51 100644 --- a/clippy_lints/src/mut_key.rs +++ b/clippy_lints/src/mut_key.rs @@ -72,7 +72,7 @@ pub struct MutableKeyType<'tcx> { interior_mut: InteriorMut<'tcx>, } -impl_lint_pass!(MutableKeyType<'_> => [ MUTABLE_KEY_TYPE ]); +impl_lint_pass!(MutableKeyType<'_> => [MUTABLE_KEY_TYPE]); impl<'tcx> LateLintPass<'tcx> for MutableKeyType<'tcx> { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index 25fcc7ee568e..0f82eb80ba77 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -66,7 +66,9 @@ pub struct NeedlessBorrowsForGenericArgs<'tcx> { // `IntoIterator` for arrays requires Rust 1.53. msrv: Msrv, } -impl_lint_pass!(NeedlessBorrowsForGenericArgs<'_> => [NEEDLESS_BORROWS_FOR_GENERIC_ARGS]); +impl_lint_pass!(NeedlessBorrowsForGenericArgs<'_> => [ + NEEDLESS_BORROWS_FOR_GENERIC_ARGS, +]); impl NeedlessBorrowsForGenericArgs<'_> { pub fn new(conf: &'static Conf) -> Self { diff --git a/clippy_lints/src/needless_parens_on_range_literals.rs b/clippy_lints/src/needless_parens_on_range_literals.rs index f270ba7277cb..0c23bd6b1f96 100644 --- a/clippy_lints/src/needless_parens_on_range_literals.rs +++ b/clippy_lints/src/needless_parens_on_range_literals.rs @@ -38,7 +38,9 @@ "needless parenthesis on range literals can be removed" } -declare_lint_pass!(NeedlessParensOnRangeLiterals => [NEEDLESS_PARENS_ON_RANGE_LITERALS]); +declare_lint_pass!(NeedlessParensOnRangeLiterals => [ + NEEDLESS_PARENS_ON_RANGE_LITERALS, +]); fn snippet_enclosed_in_parenthesis(snippet: &str) -> bool { snippet.starts_with('(') && snippet.ends_with(')') diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index fdb8e1b475c1..8739c7546e58 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -79,7 +79,11 @@ pub struct NoEffect { local_bindings: Vec>, } -impl_lint_pass!(NoEffect => [NO_EFFECT, UNNECESSARY_OPERATION, NO_EFFECT_UNDERSCORE_BINDING]); +impl_lint_pass!(NoEffect => [ + NO_EFFECT, + NO_EFFECT_UNDERSCORE_BINDING, + UNNECESSARY_OPERATION, +]); impl<'tcx> LateLintPass<'tcx> for NoEffect { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { diff --git a/clippy_lints/src/non_canonical_impls.rs b/clippy_lints/src/non_canonical_impls.rs index e66c088617cb..f87860ec164c 100644 --- a/clippy_lints/src/non_canonical_impls.rs +++ b/clippy_lints/src/non_canonical_impls.rs @@ -108,7 +108,10 @@ suspicious, "non-canonical implementation of `PartialOrd` on an `Ord` type" } -impl_lint_pass!(NonCanonicalImpls => [NON_CANONICAL_CLONE_IMPL, NON_CANONICAL_PARTIAL_ORD_IMPL]); +impl_lint_pass!(NonCanonicalImpls => [ + NON_CANONICAL_CLONE_IMPL, + NON_CANONICAL_PARTIAL_ORD_IMPL, +]); #[expect( clippy::struct_field_names, diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index e09fc0a76366..396d57f21612 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -257,7 +257,10 @@ pub struct NonCopyConst<'tcx> { freeze_tys: FxHashMap, IsFreeze>, } -impl_lint_pass!(NonCopyConst<'_> => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST]); +impl_lint_pass!(NonCopyConst<'_> => [ + BORROW_INTERIOR_MUTABLE_CONST, + DECLARE_INTERIOR_MUTABLE_CONST, +]); impl<'tcx> NonCopyConst<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf) -> Self { diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 1961ac1516da..4d43a9b6f5ee 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -77,7 +77,11 @@ pub struct NonExpressiveNames { pub single_char_binding_names_threshold: u64, } -impl_lint_pass!(NonExpressiveNames => [SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES, JUST_UNDERSCORES_AND_DIGITS]); +impl_lint_pass!(NonExpressiveNames => [ + JUST_UNDERSCORES_AND_DIGITS, + MANY_SINGLE_CHAR_NAMES, + SIMILAR_NAMES, +]); impl NonExpressiveNames { pub fn new(conf: &'static Conf) -> Self { diff --git a/clippy_lints/src/only_used_in_recursion.rs b/clippy_lints/src/only_used_in_recursion.rs index f756f94d97b3..ae1c229711f0 100644 --- a/clippy_lints/src/only_used_in_recursion.rs +++ b/clippy_lints/src/only_used_in_recursion.rs @@ -164,7 +164,10 @@ pedantic, "self receiver only used to recursively call method can be removed" } -impl_lint_pass!(OnlyUsedInRecursion => [ONLY_USED_IN_RECURSION, SELF_ONLY_USED_IN_RECURSION]); +impl_lint_pass!(OnlyUsedInRecursion => [ + ONLY_USED_IN_RECURSION, + SELF_ONLY_USED_IN_RECURSION, +]); #[derive(Clone, Copy)] enum FnKind { diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index 5b00f1b0bd13..9b70c9b17abb 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -979,35 +979,35 @@ pub fn new(conf: &'static Conf) -> Self { impl_lint_pass!(Operators => [ ABSURD_EXTREME_COMPARISONS, ARITHMETIC_SIDE_EFFECTS, - FLOAT_ARITHMETIC, ASSIGN_OP_PATTERN, - MISREFACTORED_ASSIGN_OP, BAD_BIT_MASK, - INEFFECTIVE_BIT_MASK, - VERBOSE_BIT_MASK, + CMP_OWNED, + DECIMAL_BITWISE_OPERANDS, DOUBLE_COMPARISONS, - IMPOSSIBLE_COMPARISONS, - REDUNDANT_COMPARISONS, DURATION_SUBSEC, EQ_OP, - OP_REF, ERASING_OP, - FLOAT_EQUALITY_WITHOUT_ABS, - IDENTITY_OP, - INTEGER_DIVISION, - INTEGER_DIVISION_REMAINDER_USED, - CMP_OWNED, + FLOAT_ARITHMETIC, FLOAT_CMP, FLOAT_CMP_CONST, - MODULO_ONE, - MODULO_ARITHMETIC, - NEEDLESS_BITWISE_BOOL, - SELF_ASSIGNMENT, - MANUAL_MIDPOINT, - MANUAL_IS_MULTIPLE_OF, - MANUAL_DIV_CEIL, + FLOAT_EQUALITY_WITHOUT_ABS, + IDENTITY_OP, + IMPOSSIBLE_COMPARISONS, + INEFFECTIVE_BIT_MASK, + INTEGER_DIVISION, + INTEGER_DIVISION_REMAINDER_USED, INVALID_UPCAST_COMPARISONS, - DECIMAL_BITWISE_OPERANDS + MANUAL_DIV_CEIL, + MANUAL_IS_MULTIPLE_OF, + MANUAL_MIDPOINT, + MISREFACTORED_ASSIGN_OP, + MODULO_ARITHMETIC, + MODULO_ONE, + NEEDLESS_BITWISE_BOOL, + OP_REF, + REDUNDANT_COMPARISONS, + SELF_ASSIGNMENT, + VERBOSE_BIT_MASK, ]); impl<'tcx> LateLintPass<'tcx> for Operators { diff --git a/clippy_lints/src/panic_in_result_fn.rs b/clippy_lints/src/panic_in_result_fn.rs index 57127e9d2298..cc147a4a84bd 100644 --- a/clippy_lints/src/panic_in_result_fn.rs +++ b/clippy_lints/src/panic_in_result_fn.rs @@ -40,7 +40,7 @@ "functions of type `Result<..>` that contain `panic!()` or assertion" } -declare_lint_pass!(PanicInResultFn => [PANIC_IN_RESULT_FN]); +declare_lint_pass!(PanicInResultFn => [PANIC_IN_RESULT_FN]); impl<'tcx> LateLintPass<'tcx> for PanicInResultFn { fn check_fn( diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 43db0085f2e3..4c318f4a7a0e 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -93,7 +93,7 @@ pub fn new(conf: &'static Conf) -> Self { "usage of the `unreachable!` macro" } -impl_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]); +impl_lint_pass!(PanicUnimplemented => [PANIC, TODO, UNIMPLEMENTED, UNREACHABLE]); impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 6e9142b22e0e..5d31c8687efc 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -237,7 +237,10 @@ fn check_poly_fn(&self, cx: &LateContext<'_>, def_id: LocalDefId, decl: &FnDecl< } } -impl_lint_pass!(PassByRefOrValue => [TRIVIALLY_COPY_PASS_BY_REF, LARGE_TYPES_PASSED_BY_VALUE]); +impl_lint_pass!(PassByRefOrValue => [ + LARGE_TYPES_PASSED_BY_VALUE, + TRIVIALLY_COPY_PASS_BY_REF, +]); impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { diff --git a/clippy_lints/src/permissions_set_readonly_false.rs b/clippy_lints/src/permissions_set_readonly_false.rs index 68a34d459e0d..fab167667b93 100644 --- a/clippy_lints/src/permissions_set_readonly_false.rs +++ b/clippy_lints/src/permissions_set_readonly_false.rs @@ -26,7 +26,9 @@ suspicious, "Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`" } -declare_lint_pass!(PermissionsSetReadonlyFalse => [PERMISSIONS_SET_READONLY_FALSE]); +declare_lint_pass!(PermissionsSetReadonlyFalse => [ + PERMISSIONS_SET_READONLY_FALSE, +]); impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { diff --git a/clippy_lints/src/ptr/mod.rs b/clippy_lints/src/ptr/mod.rs index c4f40a7ffcaa..ba1ae5c1e0e0 100644 --- a/clippy_lints/src/ptr/mod.rs +++ b/clippy_lints/src/ptr/mod.rs @@ -135,7 +135,7 @@ "use `std::ptr::eq` when comparing raw pointers" } -declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, PTR_EQ]); +declare_lint_pass!(Ptr => [CMP_NULL, MUT_FROM_REF, PTR_ARG, PTR_EQ]); impl<'tcx> LateLintPass<'tcx> for Ptr { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 719f364357d3..6e286d16ef36 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -65,7 +65,7 @@ pub struct QuestionMark { inferred_ret_closure_stack: u16, } -impl_lint_pass!(QuestionMark => [QUESTION_MARK, MANUAL_LET_ELSE]); +impl_lint_pass!(QuestionMark => [MANUAL_LET_ELSE, QUESTION_MARK]); impl QuestionMark { pub fn new(conf: &'static Conf) -> Self { diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index ca0d41fca524..73fad7951ca4 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -175,10 +175,10 @@ pub fn new(conf: &'static Conf) -> Self { } impl_lint_pass!(Ranges => [ - RANGE_PLUS_ONE, - RANGE_MINUS_ONE, - REVERSED_EMPTY_RANGES, MANUAL_RANGE_CONTAINS, + RANGE_MINUS_ONE, + RANGE_PLUS_ONE, + REVERSED_EMPTY_RANGES, ]); impl<'tcx> LateLintPass<'tcx> for Ranges { diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs index f2cf809d6012..03ed3a4076b9 100644 --- a/clippy_lints/src/redundant_slicing.rs +++ b/clippy_lints/src/redundant_slicing.rs @@ -66,7 +66,7 @@ "slicing instead of dereferencing" } -declare_lint_pass!(RedundantSlicing => [REDUNDANT_SLICING, DEREF_BY_SLICING]); +declare_lint_pass!(RedundantSlicing => [DEREF_BY_SLICING, REDUNDANT_SLICING]); static REDUNDANT_SLICING_LINT: (&Lint, &str) = (REDUNDANT_SLICING, "redundant slicing of the whole range"); static DEREF_BY_SLICING_LINT: (&Lint, &str) = (DEREF_BY_SLICING, "slicing when dereferencing would work"); diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index d1fc228f4b35..c7d200089701 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -119,7 +119,7 @@ pub struct Regex { loop_stack: Vec<(OwnerId, Span)>, } -impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX, REGEX_CREATION_IN_LOOPS]); +impl_lint_pass!(Regex => [INVALID_REGEX, REGEX_CREATION_IN_LOOPS, TRIVIAL_REGEX]); impl<'tcx> LateLintPass<'tcx> for Regex { fn check_crate(&mut self, cx: &LateContext<'tcx>) { diff --git a/clippy_lints/src/returns/mod.rs b/clippy_lints/src/returns/mod.rs index 47c6332b9b81..eb84582593a4 100644 --- a/clippy_lints/src/returns/mod.rs +++ b/clippy_lints/src/returns/mod.rs @@ -115,7 +115,11 @@ "using a return statement like `return Err(expr)?;` where removing it would suffice" } -declare_lint_pass!(Return => [LET_AND_RETURN, NEEDLESS_RETURN, NEEDLESS_RETURN_WITH_QUESTION_MARK]); +declare_lint_pass!(Return => [ + LET_AND_RETURN, + NEEDLESS_RETURN, + NEEDLESS_RETURN_WITH_QUESTION_MARK, +]); impl<'tcx> LateLintPass<'tcx> for Return { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index f6083394fea5..3a45e7bd2bc8 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -111,7 +111,7 @@ pub(crate) struct Shadow { bindings: Vec<(FxHashMap>, LocalDefId)>, } -impl_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]); +impl_lint_pass!(Shadow => [SHADOW_REUSE, SHADOW_SAME, SHADOW_UNRELATED]); impl<'tcx> LateLintPass<'tcx> for Shadow { fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index 143be5137038..4766057098de 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -109,7 +109,11 @@ fn lint_if_finish(&mut self, cx: &LateContext<'_>, krate: Span, lint_point: Lint } } -impl_lint_pass!(StdReexports => [STD_INSTEAD_OF_CORE, STD_INSTEAD_OF_ALLOC, ALLOC_INSTEAD_OF_CORE]); +impl_lint_pass!(StdReexports => [ + ALLOC_INSTEAD_OF_CORE, + STD_INSTEAD_OF_ALLOC, + STD_INSTEAD_OF_CORE, +]); #[derive(Debug)] enum LintPoint { diff --git a/clippy_lints/src/string_patterns.rs b/clippy_lints/src/string_patterns.rs index e5347bf3e8f0..4c640c2ed541 100644 --- a/clippy_lints/src/string_patterns.rs +++ b/clippy_lints/src/string_patterns.rs @@ -82,7 +82,10 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(StringPatterns => [MANUAL_PATTERN_CHAR_COMPARISON, SINGLE_CHAR_PATTERN]); +impl_lint_pass!(StringPatterns => [ + MANUAL_PATTERN_CHAR_COMPARISON, + SINGLE_CHAR_PATTERN, +]); const PATTERN_METHODS: [(Symbol, usize); 22] = [ (sym::contains, 0), diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 9d3e4a6b1d92..4b237e0907a9 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -243,7 +243,10 @@ fn is_add(cx: &LateContext<'_>, src: &Expr<'_>, target: &Expr<'_>) -> bool { // Max length a b"foo" string can take const MAX_LENGTH_BYTE_STRING_LIT: usize = 32; -declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES, STRING_FROM_UTF8_AS_BYTES]); +declare_lint_pass!(StringLitAsBytes => [ + STRING_FROM_UTF8_AS_BYTES, + STRING_LIT_AS_BYTES, +]); impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs index af5e3ccb674a..9fa4d2c142b5 100644 --- a/clippy_lints/src/suspicious_operation_groupings.rs +++ b/clippy_lints/src/suspicious_operation_groupings.rs @@ -64,7 +64,9 @@ "groupings of binary operations that look suspiciously like typos" } -declare_lint_pass!(SuspiciousOperationGroupings => [SUSPICIOUS_OPERATION_GROUPINGS]); +declare_lint_pass!(SuspiciousOperationGroupings => [ + SUSPICIOUS_OPERATION_GROUPINGS, +]); impl EarlyLintPass for SuspiciousOperationGroupings { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index edb7600b7c06..694f1896a4d2 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -53,7 +53,10 @@ "suspicious use of operators in impl of OpAssign trait" } -declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ASSIGN_IMPL]); +declare_lint_pass!(SuspiciousImpl => [ + SUSPICIOUS_ARITHMETIC_IMPL, + SUSPICIOUS_OP_ASSIGN_IMPL, +]); impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index c3cb2c09752f..66fdda46d060 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -75,7 +75,7 @@ "`foo = bar; bar = foo` sequence" } -declare_lint_pass!(Swap => [MANUAL_SWAP, ALMOST_SWAPPED]); +declare_lint_pass!(Swap => [ALMOST_SWAPPED, MANUAL_SWAP]); impl<'tcx> LateLintPass<'tcx> for Swap { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { diff --git a/clippy_lints/src/time_subtraction.rs b/clippy_lints/src/time_subtraction.rs index 457a8f48f7e2..aca8664ba10e 100644 --- a/clippy_lints/src/time_subtraction.rs +++ b/clippy_lints/src/time_subtraction.rs @@ -83,7 +83,10 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(UncheckedTimeSubtraction => [MANUAL_INSTANT_ELAPSED, UNCHECKED_TIME_SUBTRACTION]); +impl_lint_pass!(UncheckedTimeSubtraction => [ + MANUAL_INSTANT_ELAPSED, + UNCHECKED_TIME_SUBTRACTION, +]); impl LateLintPass<'_> for UncheckedTimeSubtraction { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 352b8526b021..0a6b999775f4 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -100,7 +100,10 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS, TRAIT_DUPLICATION_IN_BOUNDS]); +impl_lint_pass!(TraitBounds => [ + TRAIT_DUPLICATION_IN_BOUNDS, + TYPE_REPETITION_IN_BOUNDS, +]); impl<'tcx> LateLintPass<'tcx> for TraitBounds { fn check_generics(&mut self, cx: &LateContext<'tcx>, generics: &'tcx Generics<'_>) { diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 435cd7bcba4e..ad94dc92da1b 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -474,20 +474,20 @@ pub struct Transmute { } impl_lint_pass!(Transmute => [ CROSSPOINTER_TRANSMUTE, - TRANSMUTE_PTR_TO_REF, - TRANSMUTE_PTR_TO_PTR, - USELESS_TRANSMUTE, - WRONG_TRANSMUTE, + EAGER_TRANSMUTE, + MISSING_TRANSMUTE_ANNOTATIONS, + TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, TRANSMUTE_BYTES_TO_STR, TRANSMUTE_INT_TO_BOOL, TRANSMUTE_INT_TO_NON_ZERO, - UNSOUND_COLLECTION_TRANSMUTE, - TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, + TRANSMUTE_NULL_TO_FN, + TRANSMUTE_PTR_TO_PTR, + TRANSMUTE_PTR_TO_REF, TRANSMUTE_UNDEFINED_REPR, TRANSMUTING_NULL, - TRANSMUTE_NULL_TO_FN, - EAGER_TRANSMUTE, - MISSING_TRANSMUTE_ANNOTATIONS, + UNSOUND_COLLECTION_TRANSMUTE, + USELESS_TRANSMUTE, + WRONG_TRANSMUTE, ]); impl Transmute { pub fn new(conf: &'static Conf) -> Self { diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index 7d97ce97f487..4ae2e6a9b1e3 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -398,16 +398,16 @@ pub struct Types { } impl_lint_pass!(Types => [ - BOX_COLLECTION, - VEC_BOX, - OPTION_OPTION, - LINKEDLIST, BORROWED_BOX, - REDUNDANT_ALLOCATION, + BOX_COLLECTION, + LINKEDLIST, + OPTION_OPTION, + OWNED_COW, RC_BUFFER, RC_MUTEX, + REDUNDANT_ALLOCATION, TYPE_COMPLEXITY, - OWNED_COW + VEC_BOX, ]); impl<'tcx> LateLintPass<'tcx> for Types { diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 1b26b1b32b80..1ed78a53d640 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -106,7 +106,10 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]); +impl_lint_pass!(UndocumentedUnsafeBlocks => [ + UNDOCUMENTED_UNSAFE_BLOCKS, + UNNECESSARY_SAFETY_COMMENT, +]); impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 79571b0409d2..bef8b8fb4ee0 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -72,7 +72,11 @@ "using a Unicode literal not in NFC normal form (see [Unicode tr15](http://www.unicode.org/reports/tr15/) for further information)" } -declare_lint_pass!(Unicode => [INVISIBLE_CHARACTERS, NON_ASCII_LITERAL, UNICODE_NOT_NFC]); +declare_lint_pass!(Unicode => [ + INVISIBLE_CHARACTERS, + NON_ASCII_LITERAL, + UNICODE_NOT_NFC, +]); impl LateLintPass<'_> for Unicode { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { diff --git a/clippy_lints/src/unit_types/mod.rs b/clippy_lints/src/unit_types/mod.rs index 4ffcc247acf6..13dd9d7b72c0 100644 --- a/clippy_lints/src/unit_types/mod.rs +++ b/clippy_lints/src/unit_types/mod.rs @@ -101,7 +101,7 @@ pub struct UnitTypes { format_args: FormatArgsStorage, } -impl_lint_pass!(UnitTypes => [LET_UNIT_VALUE, UNIT_CMP, UNIT_ARG]); +impl_lint_pass!(UnitTypes => [LET_UNIT_VALUE, UNIT_ARG, UNIT_CMP]); impl UnitTypes { pub fn new(format_args: FormatArgsStorage) -> Self { diff --git a/clippy_lints/src/unnecessary_map_on_constructor.rs b/clippy_lints/src/unnecessary_map_on_constructor.rs index fba530d0dfca..f221044584a5 100644 --- a/clippy_lints/src/unnecessary_map_on_constructor.rs +++ b/clippy_lints/src/unnecessary_map_on_constructor.rs @@ -31,7 +31,9 @@ complexity, "using `map`/`map_err` on `Option` or `Result` constructors" } -declare_lint_pass!(UnnecessaryMapOnConstructor => [UNNECESSARY_MAP_ON_CONSTRUCTOR]); +declare_lint_pass!(UnnecessaryMapOnConstructor => [ + UNNECESSARY_MAP_ON_CONSTRUCTOR, +]); impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { diff --git a/clippy_lints/src/unnecessary_owned_empty_strings.rs b/clippy_lints/src/unnecessary_owned_empty_strings.rs index 0388450c9f7e..bcc10cbe7d7a 100644 --- a/clippy_lints/src/unnecessary_owned_empty_strings.rs +++ b/clippy_lints/src/unnecessary_owned_empty_strings.rs @@ -30,7 +30,9 @@ style, "detects cases of references to owned empty strings being passed as an argument to a function expecting `&str`" } -declare_lint_pass!(UnnecessaryOwnedEmptyStrings => [UNNECESSARY_OWNED_EMPTY_STRINGS]); +declare_lint_pass!(UnnecessaryOwnedEmptyStrings => [ + UNNECESSARY_OWNED_EMPTY_STRINGS, +]); impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { diff --git a/clippy_lints/src/unwrap_in_result.rs b/clippy_lints/src/unwrap_in_result.rs index f26647fa3485..aafd1153f933 100644 --- a/clippy_lints/src/unwrap_in_result.rs +++ b/clippy_lints/src/unwrap_in_result.rs @@ -56,7 +56,7 @@ "functions of type `Result<..>` or `Option`<...> that contain `expect()` or `unwrap()`" } -impl_lint_pass!(UnwrapInResult=> [UNWRAP_IN_RESULT]); +impl_lint_pass!(UnwrapInResult => [UNWRAP_IN_RESULT]); #[derive(Clone, Copy, Eq, PartialEq)] enum OptionOrResult { diff --git a/clippy_lints/src/visibility.rs b/clippy_lints/src/visibility.rs index d17b3df99216..429228912462 100644 --- a/clippy_lints/src/visibility.rs +++ b/clippy_lints/src/visibility.rs @@ -74,7 +74,11 @@ restriction, "disallows usage of `pub(in )` with `in`" } -declare_lint_pass!(Visibility => [NEEDLESS_PUB_SELF, PUB_WITH_SHORTHAND, PUB_WITHOUT_SHORTHAND]); +declare_lint_pass!(Visibility => [ + NEEDLESS_PUB_SELF, + PUB_WITHOUT_SHORTHAND, + PUB_WITH_SHORTHAND, +]); impl EarlyLintPass for Visibility { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { diff --git a/clippy_lints/src/write/mod.rs b/clippy_lints/src/write/mod.rs index c42c047745bb..5f80adbab2bf 100644 --- a/clippy_lints/src/write/mod.rs +++ b/clippy_lints/src/write/mod.rs @@ -257,15 +257,15 @@ fn in_debug_impl(&self) -> bool { } impl_lint_pass!(Write => [ - PRINT_WITH_NEWLINE, PRINTLN_EMPTY_STRING, - PRINT_STDOUT, - PRINT_STDERR, - USE_DEBUG, PRINT_LITERAL, - WRITE_WITH_NEWLINE, + PRINT_STDERR, + PRINT_STDOUT, + PRINT_WITH_NEWLINE, + USE_DEBUG, WRITELN_EMPTY_STRING, WRITE_LITERAL, + WRITE_WITH_NEWLINE, ]); impl<'tcx> LateLintPass<'tcx> for Write { From e16c8384396e481236cbc845ec570be18bf131d8 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Tue, 28 Oct 2025 08:47:38 -0400 Subject: [PATCH 32/38] `clippy_dev`: Sort all lint and lint pass declarations. --- clippy_dev/src/fmt.rs | 33 +- clippy_dev/src/generate.rs | 60 +- clippy_dev/src/parse.rs | 26 +- clippy_dev/src/utils.rs | 21 +- clippy_lints/src/absolute_paths.rs | 1 + clippy_lints/src/almost_complete_range.rs | 1 + clippy_lints/src/approx_const.rs | 4 +- clippy_lints/src/arc_with_non_send_sync.rs | 1 + clippy_lints/src/asm_syntax.rs | 96 +- clippy_lints/src/assertions_on_constants.rs | 1 + clippy_lints/src/assigning_clones.rs | 4 +- clippy_lints/src/attrs/mod.rs | 620 +- clippy_lints/src/await_holding_invalid.rs | 74 +- clippy_lints/src/bool_to_int_with_if.rs | 1 + clippy_lints/src/booleans.rs | 4 +- clippy_lints/src/byte_char_slices.rs | 1 + clippy_lints/src/cargo/mod.rs | 246 +- clippy_lints/src/casts/mod.rs | 974 +-- clippy_lints/src/checked_conversions.rs | 4 +- clippy_lints/src/cloned_ref_to_slice_refs.rs | 4 +- clippy_lints/src/coerce_container_to_any.rs | 1 + clippy_lints/src/cognitive_complexity.rs | 4 +- clippy_lints/src/collapsible_if.rs | 68 +- clippy_lints/src/collection_is_never_read.rs | 1 + clippy_lints/src/crate_in_macro_def.rs | 1 + clippy_lints/src/dbg_macro.rs | 4 +- clippy_lints/src/default.rs | 4 +- .../src/default_constructed_unit_structs.rs | 1 + .../src/default_instead_of_iter_empty.rs | 1 + .../src/default_union_representation.rs | 1 + clippy_lints/src/dereference.rs | 46 +- clippy_lints/src/derivable_impls.rs | 4 +- clippy_lints/src/derive/mod.rs | 124 +- clippy_lints/src/disallowed_fields.rs | 4 +- clippy_lints/src/disallowed_macros.rs | 4 +- clippy_lints/src/disallowed_methods.rs | 4 +- clippy_lints/src/disallowed_names.rs | 4 +- clippy_lints/src/disallowed_script_idents.rs | 4 +- clippy_lints/src/disallowed_types.rs | 4 +- clippy_lints/src/doc/mod.rs | 814 +- clippy_lints/src/drop_forget_ref.rs | 4 +- clippy_lints/src/duplicate_mod.rs | 4 +- clippy_lints/src/empty_drop.rs | 1 + clippy_lints/src/empty_line_after.rs | 80 +- clippy_lints/src/empty_with_brackets.rs | 66 +- clippy_lints/src/endian_bytes.rs | 36 +- clippy_lints/src/error_impl_error.rs | 1 + clippy_lints/src/escape.rs | 4 +- clippy_lints/src/excessive_bools.rs | 84 +- clippy_lints/src/excessive_nesting.rs | 1 + clippy_lints/src/explicit_write.rs | 4 +- .../src/extra_unused_type_parameters.rs | 4 +- clippy_lints/src/float_literal.rs | 4 +- clippy_lints/src/format.rs | 4 +- clippy_lints/src/format_args.rs | 132 +- clippy_lints/src/format_impl.rs | 82 +- clippy_lints/src/format_push_string.rs | 1 + clippy_lints/src/formatting.rs | 130 +- clippy_lints/src/four_forward_slashes.rs | 1 + clippy_lints/src/from_over_into.rs | 4 +- clippy_lints/src/from_raw_with_void_ptr.rs | 1 + clippy_lints/src/functions/mod.rs | 552 +- clippy_lints/src/if_then_some_else_none.rs | 4 +- clippy_lints/src/ifs/mod.rs | 124 +- clippy_lints/src/ignored_unit_patterns.rs | 1 + clippy_lints/src/implicit_saturating_add.rs | 1 + clippy_lints/src/implicit_saturating_sub.rs | 8 +- clippy_lints/src/implied_bounds_in_impls.rs | 1 + clippy_lints/src/incompatible_msrv.rs | 4 +- .../src/inconsistent_struct_constructor.rs | 8 +- clippy_lints/src/index_refutable_slice.rs | 4 +- clippy_lints/src/indexing_slicing.rs | 60 +- clippy_lints/src/infallible_try_from.rs | 1 + clippy_lints/src/item_name_repetitions.rs | 75 +- clippy_lints/src/iter_without_into_iter.rs | 88 +- clippy_lints/src/large_const_arrays.rs | 4 +- clippy_lints/src/large_enum_variant.rs | 4 +- clippy_lints/src/large_futures.rs | 4 +- clippy_lints/src/large_include_file.rs | 4 +- clippy_lints/src/large_stack_arrays.rs | 4 +- clippy_lints/src/large_stack_frames.rs | 4 +- clippy_lints/src/legacy_numeric_constants.rs | 5 +- clippy_lints/src/len_zero.rs | 74 +- clippy_lints/src/let_underscore.rs | 66 +- clippy_lints/src/let_with_type_underscore.rs | 1 + clippy_lints/src/lifetimes.rs | 82 +- clippy_lints/src/literal_representation.rs | 160 +- clippy_lints/src/loops/mod.rs | 970 +-- clippy_lints/src/macro_metavars_in_unsafe.rs | 1 + clippy_lints/src/macro_use.rs | 4 +- clippy_lints/src/main_recursion.rs | 4 +- clippy_lints/src/manual_bits.rs | 4 +- clippy_lints/src/manual_checked_ops.rs | 1 + clippy_lints/src/manual_clamp.rs | 1 + clippy_lints/src/manual_float_methods.rs | 48 +- clippy_lints/src/manual_hash_one.rs | 4 +- clippy_lints/src/manual_ilog2.rs | 4 +- clippy_lints/src/manual_is_ascii_check.rs | 1 + clippy_lints/src/manual_is_power_of_two.rs | 4 +- clippy_lints/src/manual_main_separator_str.rs | 4 +- clippy_lints/src/manual_non_exhaustive.rs | 4 +- clippy_lints/src/manual_option_as_slice.rs | 4 +- clippy_lints/src/manual_range_patterns.rs | 1 + clippy_lints/src/manual_rem_euclid.rs | 4 +- clippy_lints/src/manual_retain.rs | 4 +- .../src/manual_slice_size_calculation.rs | 1 + clippy_lints/src/manual_string_new.rs | 1 + clippy_lints/src/manual_strip.rs | 4 +- clippy_lints/src/manual_take.rs | 5 +- clippy_lints/src/matches/mod.rs | 1652 ++-- clippy_lints/src/mem_replace.rs | 50 +- clippy_lints/src/methods/mod.rs | 6902 ++++++++--------- clippy_lints/src/min_ident_chars.rs | 1 + clippy_lints/src/misc.rs | 42 +- clippy_lints/src/misc_early/mod.rs | 390 +- .../src/mismatching_type_param_order.rs | 1 + .../src/missing_asserts_for_indexing.rs | 1 + .../src/missing_const_for_thread_local.rs | 4 +- clippy_lints/src/missing_doc.rs | 4 +- .../src/missing_enforced_import_rename.rs | 4 +- clippy_lints/src/missing_fields_in_debug.rs | 1 + clippy_lints/src/missing_inline.rs | 4 +- clippy_lints/src/missing_trait_methods.rs | 1 + .../src/mixed_read_write_in_expression.rs | 56 +- .../src/multiple_unsafe_ops_per_block.rs | 1 + clippy_lints/src/mut_key.rs | 4 +- clippy_lints/src/needless_bool.rs | 1 + .../src/needless_borrows_for_generic_args.rs | 8 +- clippy_lints/src/needless_else.rs | 1 + clippy_lints/src/needless_ifs.rs | 1 + clippy_lints/src/needless_late_init.rs | 1 + clippy_lints/src/needless_maybe_sized.rs | 1 + clippy_lints/src/needless_pass_by_ref_mut.rs | 4 +- clippy_lints/src/new_without_default.rs | 4 +- clippy_lints/src/no_effect.rs | 12 +- clippy_lints/src/no_mangle_with_rust_abi.rs | 1 + clippy_lints/src/non_canonical_impls.rs | 2 + clippy_lints/src/non_copy_const.rs | 120 +- clippy_lints/src/non_expressive_names.rs | 88 +- .../src/non_send_fields_in_send_ty.rs | 4 +- clippy_lints/src/non_std_lazy_statics.rs | 4 +- clippy_lints/src/nonstandard_macro_braces.rs | 4 +- clippy_lints/src/only_used_in_recursion.rs | 1 + clippy_lints/src/operators/mod.rs | 810 +- clippy_lints/src/panic_unimplemented.rs | 34 +- clippy_lints/src/partial_pub_fields.rs | 1 + clippy_lints/src/partialeq_to_none.rs | 1 + clippy_lints/src/pass_by_ref_or_value.rs | 74 +- .../src/permissions_set_readonly_false.rs | 1 + clippy_lints/src/ptr/mod.rs | 72 +- clippy_lints/src/pub_underscore_fields.rs | 4 +- clippy_lints/src/pub_use.rs | 1 + clippy_lints/src/question_mark.rs | 4 +- clippy_lints/src/ranges.rs | 142 +- clippy_lints/src/raw_strings.rs | 44 +- clippy_lints/src/rc_clone_in_vec_init.rs | 1 + clippy_lints/src/read_zero_byte_vec.rs | 1 + clippy_lints/src/redundant_async_block.rs | 1 + clippy_lints/src/redundant_field_names.rs | 4 +- clippy_lints/src/redundant_locals.rs | 1 + clippy_lints/src/redundant_pub_crate.rs | 4 +- clippy_lints/src/redundant_slicing.rs | 48 +- .../src/redundant_static_lifetimes.rs | 4 +- .../src/redundant_type_annotations.rs | 1 + clippy_lints/src/ref_patterns.rs | 1 + clippy_lints/src/regex.rs | 64 +- clippy_lints/src/replace_box.rs | 4 +- .../src/reserve_after_initialization.rs | 1 + clippy_lints/src/same_length_and_capacity.rs | 1 + clippy_lints/src/semicolon_block.rs | 2 + clippy_lints/src/shadow.rs | 58 +- clippy_lints/src/single_call_fn.rs | 1 + .../src/single_component_path_imports.rs | 4 +- clippy_lints/src/single_range_in_vec_init.rs | 1 + clippy_lints/src/size_of_ref.rs | 1 + clippy_lints/src/std_instead_of_core.rs | 106 +- clippy_lints/src/string_patterns.rs | 10 +- clippy_lints/src/strings.rs | 177 +- clippy_lints/src/strlen_on_c_strings.rs | 4 +- .../src/suspicious_xor_used_as_pow.rs | 1 + clippy_lints/src/swap.rs | 52 +- clippy_lints/src/swap_ptr_to_ref.rs | 1 + clippy_lints/src/temporary_assignment.rs | 4 +- clippy_lints/src/time_subtraction.rs | 10 +- clippy_lints/src/trailing_empty_array.rs | 1 + clippy_lints/src/trait_bounds.rs | 56 +- clippy_lints/src/transmute/mod.rs | 638 +- clippy_lints/src/tuple_array_conversions.rs | 1 + clippy_lints/src/types/mod.rs | 316 +- clippy_lints/src/unconditional_recursion.rs | 4 +- .../src/undocumented_unsafe_blocks.rs | 11 +- clippy_lints/src/unit_types/mod.rs | 44 +- clippy_lints/src/unnecessary_box_returns.rs | 4 +- .../src/unnecessary_map_on_constructor.rs | 1 + .../src/unnecessary_owned_empty_strings.rs | 1 + clippy_lints/src/unnecessary_semicolon.rs | 4 +- .../src/unnecessary_struct_initialization.rs | 1 + clippy_lints/src/unnecessary_wraps.rs | 4 +- clippy_lints/src/unnested_or_patterns.rs | 4 +- clippy_lints/src/unused_async.rs | 4 +- clippy_lints/src/unused_result_ok.rs | 1 + clippy_lints/src/unused_rounding.rs | 1 + clippy_lints/src/unused_self.rs | 4 +- clippy_lints/src/unused_trait_names.rs | 4 +- clippy_lints/src/unwrap.rs | 56 +- clippy_lints/src/upper_case_acronyms.rs | 4 +- clippy_lints/src/use_self.rs | 4 +- clippy_lints/src/useless_conversion.rs | 4 +- clippy_lints/src/visibility.rs | 3 + clippy_lints/src/volatile_composites.rs | 1 + clippy_lints/src/wildcard_imports.rs | 4 +- clippy_lints/src/write/mod.rs | 182 +- clippy_lints/src/zombie_processes.rs | 1 + 213 files changed, 9508 insertions(+), 9329 deletions(-) diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index f4ee600dde04..d13f966b19c3 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -1,7 +1,9 @@ +use crate::generate::gen_sorted_lints_file; use crate::new_parse_cx; +use crate::parse::VecBuf; use crate::utils::{ - ErrAction, FileUpdater, UpdateMode, UpdateStatus, expect_action, run_with_output, slice_groups, - split_args_for_threads, walk_dir_no_dot_or_target, + ErrAction, FileUpdater, UpdateMode, UpdateStatus, expect_action, run_with_output, split_args_for_threads, + walk_dir_no_dot_or_target, }; use itertools::Itertools; use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize}; @@ -334,19 +336,24 @@ pub fn run(update_mode: UpdateMode) { } new_parse_cx(|cx| { - let data = cx.parse_lint_decls(); + let mut data = cx.parse_lint_decls(); + let (mut lints, passes) = data.split_by_lint_file(); let mut updater = FileUpdater::default(); + let mut ranges = VecBuf::with_capacity(256); - for passes in slice_groups(&data.lint_passes, |head, tail| { - tail.iter().take_while(|&x| x.path == head.path).count() - }) { - updater.update_file_checked("cargo dev fmt", update_mode, &passes[0].path, &mut |_, src, dst| { - let pos = passes.iter().fold(0u32, |start, pass| { - dst.push_str(&src[start as usize..pass.decl_range.start as usize]); - pass.gen_mac(dst); - pass.decl_range.end - }); - dst.push_str(&src[pos as usize..]); + for passes in passes { + let path = passes[0].path.clone(); + let mut lints = lints.remove(&*path); + let lints = lints.as_deref_mut().unwrap_or_default(); + updater.update_file_checked("cargo dev fmt", update_mode, &path, &mut |_, src, dst| { + gen_sorted_lints_file(src, dst, lints, passes, &mut ranges); + UpdateStatus::from_changed(src != dst) + }); + } + + for (&path, lints) in &mut lints { + updater.update_file_checked("cargo dev fmt", update_mode, path, &mut |_, src, dst| { + gen_sorted_lints_file(src, dst, lints, &mut [], &mut ranges); UpdateStatus::from_changed(src != dst) }); } diff --git a/clippy_dev/src/generate.rs b/clippy_dev/src/generate.rs index 0d86c0179cde..24e4218716ab 100644 --- a/clippy_dev/src/generate.rs +++ b/clippy_dev/src/generate.rs @@ -1,6 +1,7 @@ use crate::parse::cursor::Cursor; -use crate::parse::{Lint, LintData, LintPass}; +use crate::parse::{Lint, LintData, LintPass, VecBuf}; use crate::utils::{FileUpdater, UpdateMode, UpdateStatus, update_text_region_fn}; +use core::range::Range; use itertools::Itertools; use std::collections::HashSet; use std::fmt::Write; @@ -256,3 +257,60 @@ fn write_list<'a>( ListFmt::SingleLine } } + +/// Generates the contents of a lint's source file with all the lint and lint pass +/// declarations sorted. +pub fn gen_sorted_lints_file( + src: &str, + dst: &mut String, + lints: &mut [(&str, Range)], + passes: &mut [LintPass<'_>], + ranges: &mut VecBuf>, +) { + ranges.with(|ranges| { + ranges.extend(lints.iter().map(|&(_, x)| x)); + ranges.extend(passes.iter().map(|x| x.decl_range)); + ranges.sort_unstable_by_key(|x| x.start); + + lints.sort_unstable_by_key(|&(x, _)| x); + passes.sort_by_key(|x| x.name); + + let mut ranges = ranges.iter(); + let pos = if let Some(range) = ranges.next() { + dst.push_str(&src[..range.start as usize]); + for &(_, range) in &*lints { + dst.push_str(&src[range.start as usize..range.end as usize]); + dst.push_str("\n\n"); + } + for pass in passes { + pass.gen_mac(dst); + dst.push_str("\n\n"); + } + range.end + } else { + dst.push_str(src); + return; + }; + + let pos = ranges.fold(pos, |start, range| { + let s = &src[start as usize..range.start as usize]; + dst.push_str(if s.trim_start().is_empty() { + // Only whitespace between this and the previous item. No need to keep that. + "" + } else if src[..pos as usize].ends_with("\n\n") + && let Some(s) = s.strip_prefix("\n\n") + { + // Empty line before and after. Remove one of them. + s + } else { + // Remove only full lines unless something is in the way. + s.strip_prefix('\n').unwrap_or(s) + }); + range.end + }); + + // Since we always generate an empty line at the end, make sure to always skip it. + let s = &src[pos as usize..]; + dst.push_str(s.strip_prefix('\n').map_or(s, |s| s.strip_prefix('\n').unwrap_or(s))); + }); +} diff --git a/clippy_dev/src/parse.rs b/clippy_dev/src/parse.rs index 30eed05a4f8b..d51fb25552f9 100644 --- a/clippy_dev/src/parse.rs +++ b/clippy_dev/src/parse.rs @@ -1,7 +1,7 @@ pub mod cursor; use self::cursor::{Capture, Cursor}; -use crate::utils::{ErrAction, File, Scoped, expect_action, walk_dir_no_dot_or_target}; +use crate::utils::{ErrAction, File, Scoped, expect_action, slice_groups_mut, walk_dir_no_dot_or_target}; use core::fmt::{self, Display, Write as _}; use core::range::Range; use rustc_arena::DroplessArena; @@ -193,6 +193,30 @@ pub struct LintData<'cx> { pub lints: FxHashMap<&'cx str, Lint<'cx>>, pub lint_passes: Vec>, } +impl<'cx> LintData<'cx> { + #[expect(clippy::type_complexity)] + pub fn split_by_lint_file<'s>( + &'s mut self, + ) -> ( + FxHashMap<&'s Path, Vec<(&'s str, Range)>>, + impl Iterator]>, + ) { + #[expect(clippy::default_trait_access)] + let mut lints = FxHashMap::with_capacity_and_hasher(500, Default::default()); + for (&name, lint) in &self.lints { + if let Lint::Active(lint) = lint { + lints + .entry(&*lint.path) + .or_insert_with(|| Vec::with_capacity(8)) + .push((name, lint.declaration_range)); + } + } + let passes = slice_groups_mut(&mut self.lint_passes, |head, tail| { + tail.iter().take_while(|&x| x.path == head.path).count() + }); + (lints, passes) + } +} impl<'cx> ParseCxImpl<'cx> { /// Finds and parses all lint declarations. diff --git a/clippy_dev/src/utils.rs b/clippy_dev/src/utils.rs index 98a3458d6c2a..1f931140467e 100644 --- a/clippy_dev/src/utils.rs +++ b/clippy_dev/src/utils.rs @@ -1,5 +1,6 @@ use core::fmt::{self, Display}; use core::marker::PhantomData; +use core::mem; use core::num::NonZero; use core::ops::{Deref, DerefMut}; use core::range::Range; @@ -601,23 +602,25 @@ pub fn walk_dir_no_dot_or_target(p: impl AsRef) -> impl Iterator( - slice: &'a [T], - split_idx: impl FnMut(&'a T, &'a [T]) -> usize, -) -> impl Iterator { +pub fn slice_groups_mut( + slice: &mut [T], + split_idx: impl FnMut(&T, &[T]) -> usize, +) -> impl Iterator { struct I<'a, T, F> { - slice: &'a [T], + slice: &'a mut [T], split_idx: F, } - impl<'a, T, F: FnMut(&'a T, &'a [T]) -> usize> Iterator for I<'a, T, F> { - type Item = &'a [T]; + impl<'a, T, F: FnMut(&T, &[T]) -> usize> Iterator for I<'a, T, F> { + type Item = &'a mut [T]; fn next(&mut self) -> Option { let (head, tail) = self.slice.split_first()?; - if let Some((head, tail)) = self.slice.split_at_checked((self.split_idx)(head, tail) + 1) { + let idx = (self.split_idx)(head, tail) + 1; + // `mem::take` makes it so `self.slice` isn't reborrowed. + if let Some((head, tail)) = mem::take(&mut self.slice).split_at_mut_checked(idx) { self.slice = tail; Some(head) } else { - self.slice = &[]; + self.slice = &mut []; None } } diff --git a/clippy_lints/src/absolute_paths.rs b/clippy_lints/src/absolute_paths.rs index 1af6d448a93c..fd515939dfb8 100644 --- a/clippy_lints/src/absolute_paths.rs +++ b/clippy_lints/src/absolute_paths.rs @@ -52,6 +52,7 @@ restriction, "checks for usage of an item without a `use` statement" } + impl_lint_pass!(AbsolutePaths => [ABSOLUTE_PATHS]); pub struct AbsolutePaths { diff --git a/clippy_lints/src/almost_complete_range.rs b/clippy_lints/src/almost_complete_range.rs index 4f55968d5625..258970393023 100644 --- a/clippy_lints/src/almost_complete_range.rs +++ b/clippy_lints/src/almost_complete_range.rs @@ -28,6 +28,7 @@ suspicious, "almost complete range" } + impl_lint_pass!(AlmostCompleteRange => [ALMOST_COMPLETE_RANGE]); pub struct AlmostCompleteRange { diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index a3710ca51655..2ea921e5d461 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -39,6 +39,8 @@ "the approximate of a known float constant (in `std::fXX::consts`)" } +impl_lint_pass!(ApproxConstant => [APPROX_CONSTANT]); + // Tuples are of the form (constant, name, min_digits, msrv) const KNOWN_CONSTS: [(f64, &str, usize, Option); 19] = [ (f64::E, "E", 4, None), @@ -111,8 +113,6 @@ fn check_known_consts(&self, cx: &LateContext<'_>, span: Span, s: symbol::Symbol } } -impl_lint_pass!(ApproxConstant => [APPROX_CONSTANT]); - fn count_digits_after_dot(input: &str) -> usize { input .char_indices() diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index acfdfa65baed..e449b06199d3 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -39,6 +39,7 @@ suspicious, "using `Arc` with a type that does not implement `Send` and `Sync`" } + declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]); impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync { diff --git a/clippy_lints/src/asm_syntax.rs b/clippy_lints/src/asm_syntax.rs index 69a8eb7d94e7..3c5cf74d5a17 100644 --- a/clippy_lints/src/asm_syntax.rs +++ b/clippy_lints/src/asm_syntax.rs @@ -57,54 +57,6 @@ fn check_asm_syntax( } } -declare_clippy_lint! { - /// ### What it does - /// Checks for usage of Intel x86 assembly syntax. - /// - /// ### Why restrict this? - /// To enforce consistent use of AT&T x86 assembly syntax. - /// - /// ### Example - /// - /// ```rust,no_run - /// # #![feature(asm)] - /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - /// # unsafe { let ptr = "".as_ptr(); - /// # use std::arch::asm; - /// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr); - /// # } - /// ``` - /// Use instead: - /// ```rust,no_run - /// # #![feature(asm)] - /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - /// # unsafe { let ptr = "".as_ptr(); - /// # use std::arch::asm; - /// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax)); - /// # } - /// ``` - #[clippy::version = "1.49.0"] - pub INLINE_ASM_X86_INTEL_SYNTAX, - restriction, - "prefer AT&T x86 assembly syntax" -} - -declare_lint_pass!(InlineAsmX86IntelSyntax => [INLINE_ASM_X86_INTEL_SYNTAX]); - -impl EarlyLintPass for InlineAsmX86IntelSyntax { - fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if let ExprKind::InlineAsm(inline_asm) = &expr.kind { - check_asm_syntax(INLINE_ASM_X86_INTEL_SYNTAX, cx, inline_asm, expr.span, AsmStyle::Intel); - } - } - - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::GlobalAsm(inline_asm) = &item.kind { - check_asm_syntax(INLINE_ASM_X86_INTEL_SYNTAX, cx, inline_asm, item.span, AsmStyle::Intel); - } - } -} - declare_clippy_lint! { /// ### What it does /// Checks for usage of AT&T x86 assembly syntax. @@ -137,8 +89,56 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { "prefer Intel x86 assembly syntax" } +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of Intel x86 assembly syntax. + /// + /// ### Why restrict this? + /// To enforce consistent use of AT&T x86 assembly syntax. + /// + /// ### Example + /// + /// ```rust,no_run + /// # #![feature(asm)] + /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + /// # unsafe { let ptr = "".as_ptr(); + /// # use std::arch::asm; + /// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr); + /// # } + /// ``` + /// Use instead: + /// ```rust,no_run + /// # #![feature(asm)] + /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + /// # unsafe { let ptr = "".as_ptr(); + /// # use std::arch::asm; + /// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax)); + /// # } + /// ``` + #[clippy::version = "1.49.0"] + pub INLINE_ASM_X86_INTEL_SYNTAX, + restriction, + "prefer AT&T x86 assembly syntax" +} + declare_lint_pass!(InlineAsmX86AttSyntax => [INLINE_ASM_X86_ATT_SYNTAX]); +declare_lint_pass!(InlineAsmX86IntelSyntax => [INLINE_ASM_X86_INTEL_SYNTAX]); + +impl EarlyLintPass for InlineAsmX86IntelSyntax { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if let ExprKind::InlineAsm(inline_asm) = &expr.kind { + check_asm_syntax(INLINE_ASM_X86_INTEL_SYNTAX, cx, inline_asm, expr.span, AsmStyle::Intel); + } + } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if let ItemKind::GlobalAsm(inline_asm) = &item.kind { + check_asm_syntax(INLINE_ASM_X86_INTEL_SYNTAX, cx, inline_asm, item.span, AsmStyle::Intel); + } + } +} + impl EarlyLintPass for InlineAsmX86AttSyntax { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if let ExprKind::InlineAsm(inline_asm) = &expr.kind { diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index 4aa55e53445c..6e57d0608bed 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -33,6 +33,7 @@ } impl_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]); + pub struct AssertionsOnConstants { msrv: Msrv, } diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index efce23d13a38..60bc9b2b5b85 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -53,6 +53,8 @@ "assigning the result of cloning may be inefficient" } +impl_lint_pass!(AssigningClones => [ASSIGNING_CLONES]); + pub struct AssigningClones { msrv: Msrv, } @@ -63,8 +65,6 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(AssigningClones => [ASSIGNING_CLONES]); - impl<'tcx> LateLintPass<'tcx> for AssigningClones { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Assign(lhs, rhs, _) = e.kind diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 694b6625ffaf..c15a378053e3 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -25,106 +25,60 @@ declare_clippy_lint! { /// ### What it does - /// Checks for items annotated with `#[inline(always)]`, - /// unless the annotated function is empty or simply panics. + /// Checks for usage of the `#[allow]` attribute and suggests replacing it with + /// the `#[expect]` attribute (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html)) + /// + /// This lint only warns outer attributes (`#[allow]`), as inner attributes + /// (`#![allow]`) are usually used to enable or disable lints on a global scale. /// /// ### Why is this bad? - /// While there are valid uses of this annotation (and once - /// you know when to use it, by all means `allow` this lint), it's a common - /// newbie-mistake to pepper one's code with it. - /// - /// As a rule of thumb, before slapping `#[inline(always)]` on a function, - /// measure if that additional function call really affects your runtime profile - /// sufficiently to make up for the increase in compile time. - /// - /// ### Known problems - /// False positives, big time. This lint is meant to be - /// deactivated by everyone doing serious performance work. This means having - /// done the measurement. + /// `#[expect]` attributes suppress the lint emission, but emit a warning, if + /// the expectation is unfulfilled. This can be useful to be notified when the + /// lint is no longer triggered. /// /// ### Example - /// ```ignore - /// #[inline(always)] - /// fn not_quite_hot_code(..) { ... } + /// ```rust,ignore + /// #[allow(unused_mut)] + /// fn foo() -> usize { + /// let mut a = Vec::new(); + /// a.len() + /// } /// ``` - #[clippy::version = "pre 1.29.0"] - pub INLINE_ALWAYS, - pedantic, - "use of `#[inline(always)]`" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `extern crate` and `use` items annotated with - /// lint attributes. - /// - /// This lint permits lint attributes for lints emitted on the items themself. - /// For `use` items these lints are: - /// * ambiguous_glob_reexports - /// * dead_code - /// * deprecated - /// * hidden_glob_reexports - /// * unreachable_pub - /// * unused - /// * unused_braces - /// * unused_import_braces - /// * clippy::disallowed_types - /// * clippy::enum_glob_use - /// * clippy::macro_use_imports - /// * clippy::module_name_repetitions - /// * clippy::redundant_pub_crate - /// * clippy::single_component_path_imports - /// * clippy::unsafe_removed_from_name - /// * clippy::wildcard_imports - /// - /// For `extern crate` items these lints are: - /// * `unused_imports` on items with `#[macro_use]` - /// - /// ### Why is this bad? - /// Lint attributes have no effect on crate imports. Most - /// likely a `!` was forgotten. - /// - /// ### Example - /// ```ignore - /// #[deny(dead_code)] - /// extern crate foo; - /// #[forbid(dead_code)] - /// use foo::bar; - /// ``` - /// /// Use instead: /// ```rust,ignore - /// #[allow(unused_imports)] - /// use foo::baz; - /// #[allow(unused_imports)] - /// #[macro_use] - /// extern crate baz; + /// #[expect(unused_mut)] + /// fn foo() -> usize { + /// let mut a = Vec::new(); + /// a.len() + /// } /// ``` - #[clippy::version = "pre 1.29.0"] - pub USELESS_ATTRIBUTE, - correctness, - "use of lint attributes on `extern crate` items" + #[clippy::version = "1.70.0"] + pub ALLOW_ATTRIBUTES, + restriction, + "`#[allow]` will not trigger if a warning isn't found. `#[expect]` triggers if there are no warnings." } declare_clippy_lint! { /// ### What it does - /// Checks for `#[deprecated]` annotations with a `since` - /// field that is not a valid semantic version. Also allows "TBD" to signal - /// future deprecation. + /// Checks for attributes that allow lints without a reason. /// - /// ### Why is this bad? - /// For checking the version of the deprecation, it must be - /// a valid semver. Failing that, the contained information is useless. + /// ### Why restrict this? + /// Justifying each `allow` helps readers understand the reasoning, + /// and may allow removing `allow` attributes if their purpose is obsolete. /// /// ### Example /// ```no_run - /// #[deprecated(since = "forever")] - /// fn something_else() { /* ... */ } + /// #![allow(clippy::some_lint)] /// ``` - #[clippy::version = "pre 1.29.0"] - pub DEPRECATED_SEMVER, - correctness, - "use of `#[deprecated(since = \"x\")]` where x is not semver" + /// + /// Use instead: + /// ```no_run + /// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")] + /// ``` + #[clippy::version = "1.61.0"] + pub ALLOW_ATTRIBUTES_WITHOUT_REASON, + restriction, + "ensures that all `allow` and `expect` attributes have a reason" } declare_clippy_lint! { @@ -181,161 +135,6 @@ "usage of `cfg_attr(rustfmt)` instead of tool attributes" } -declare_clippy_lint! { - /// ### What it does - /// Checks for attributes that allow lints without a reason. - /// - /// ### Why restrict this? - /// Justifying each `allow` helps readers understand the reasoning, - /// and may allow removing `allow` attributes if their purpose is obsolete. - /// - /// ### Example - /// ```no_run - /// #![allow(clippy::some_lint)] - /// ``` - /// - /// Use instead: - /// ```no_run - /// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")] - /// ``` - #[clippy::version = "1.61.0"] - pub ALLOW_ATTRIBUTES_WITHOUT_REASON, - restriction, - "ensures that all `allow` and `expect` attributes have a reason" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for usage of the `#[allow]` attribute and suggests replacing it with - /// the `#[expect]` attribute (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html)) - /// - /// This lint only warns outer attributes (`#[allow]`), as inner attributes - /// (`#![allow]`) are usually used to enable or disable lints on a global scale. - /// - /// ### Why is this bad? - /// `#[expect]` attributes suppress the lint emission, but emit a warning, if - /// the expectation is unfulfilled. This can be useful to be notified when the - /// lint is no longer triggered. - /// - /// ### Example - /// ```rust,ignore - /// #[allow(unused_mut)] - /// fn foo() -> usize { - /// let mut a = Vec::new(); - /// a.len() - /// } - /// ``` - /// Use instead: - /// ```rust,ignore - /// #[expect(unused_mut)] - /// fn foo() -> usize { - /// let mut a = Vec::new(); - /// a.len() - /// } - /// ``` - #[clippy::version = "1.70.0"] - pub ALLOW_ATTRIBUTES, - restriction, - "`#[allow]` will not trigger if a warning isn't found. `#[expect]` triggers if there are no warnings." -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `#[should_panic]` attributes without specifying the expected panic message. - /// - /// ### Why is this bad? - /// The expected panic message should be specified to ensure that the test is actually - /// panicking with the expected message, and not another unrelated panic. - /// - /// ### Example - /// ```no_run - /// fn random() -> i32 { 0 } - /// - /// #[should_panic] - /// #[test] - /// fn my_test() { - /// let _ = 1 / random(); - /// } - /// ``` - /// - /// Use instead: - /// ```no_run - /// fn random() -> i32 { 0 } - /// - /// #[should_panic = "attempt to divide by zero"] - /// #[test] - /// fn my_test() { - /// let _ = 1 / random(); - /// } - /// ``` - #[clippy::version = "1.74.0"] - pub SHOULD_PANIC_WITHOUT_EXPECT, - pedantic, - "ensures that all `should_panic` attributes specify its expected panic message" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for items with `#[repr(packed)]`-attribute without ABI qualification - /// - /// ### Why is this bad? - /// Without qualification, `repr(packed)` implies `repr(Rust)`. The Rust-ABI is inherently unstable. - /// While this is fine as long as the type is accessed correctly within Rust-code, most uses - /// of `#[repr(packed)]` involve FFI and/or data structures specified by network-protocols or - /// other external specifications. In such situations, the unstable Rust-ABI implied in - /// `#[repr(packed)]` may lead to future bugs should the Rust-ABI change. - /// - /// In case you are relying on a well defined and stable memory layout, qualify the type's - /// representation using the `C`-ABI. Otherwise, if the type in question is only ever - /// accessed from Rust-code according to Rust's rules, use the `Rust`-ABI explicitly. - /// - /// ### Example - /// ```no_run - /// #[repr(packed)] - /// struct NetworkPacketHeader { - /// header_length: u8, - /// header_version: u16 - /// } - /// ``` - /// - /// Use instead: - /// ```no_run - /// #[repr(C, packed)] - /// struct NetworkPacketHeader { - /// header_length: u8, - /// header_version: u16 - /// } - /// ``` - #[clippy::version = "1.85.0"] - pub REPR_PACKED_WITHOUT_ABI, - suspicious, - "ensures that `repr(packed)` always comes with a qualified ABI" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `any` and `all` combinators in `cfg` with only one condition. - /// - /// ### Why is this bad? - /// If there is only one condition, no need to wrap it into `any` or `all` combinators. - /// - /// ### Example - /// ```no_run - /// #[cfg(any(unix))] - /// pub struct Bar; - /// ``` - /// - /// Use instead: - /// ```no_run - /// #[cfg(unix)] - /// pub struct Bar; - /// ``` - #[clippy::version = "1.71.0"] - pub NON_MINIMAL_CFG, - style, - "ensure that all `cfg(any())` and `cfg(all())` have more than one condition" -} - declare_clippy_lint! { /// ### What it does /// Checks for `#[cfg_attr(feature = "cargo-clippy", ...)]` and for @@ -364,63 +163,23 @@ declare_clippy_lint! { /// ### What it does - /// Checks for `#[cfg_attr(clippy, allow(clippy::lint))]` - /// and suggests to replace it with `#[allow(clippy::lint)]`. + /// Checks for `#[deprecated]` annotations with a `since` + /// field that is not a valid semantic version. Also allows "TBD" to signal + /// future deprecation. /// /// ### Why is this bad? - /// There is no reason to put clippy attributes behind a clippy `cfg` as they are not - /// run by anything else than clippy. + /// For checking the version of the deprecation, it must be + /// a valid semver. Failing that, the contained information is useless. /// /// ### Example /// ```no_run - /// #![cfg_attr(clippy, allow(clippy::deprecated_cfg_attr))] + /// #[deprecated(since = "forever")] + /// fn something_else() { /* ... */ } /// ``` - /// - /// Use instead: - /// ```no_run - /// #![allow(clippy::deprecated_cfg_attr)] - /// ``` - #[clippy::version = "1.78.0"] - pub UNNECESSARY_CLIPPY_CFG, - suspicious, - "usage of `cfg_attr(clippy, allow(clippy::lint))` instead of `allow(clippy::lint)`" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for items that have the same kind of attributes with mixed styles (inner/outer). - /// - /// ### Why is this bad? - /// Having both style of said attributes makes it more complicated to read code. - /// - /// ### Known problems - /// This lint currently has false-negatives when mixing same attributes - /// but they have different path symbols, for example: - /// ```ignore - /// #[custom_attribute] - /// pub fn foo() { - /// #![my_crate::custom_attribute] - /// } - /// ``` - /// - /// ### Example - /// ```no_run - /// #[cfg(linux)] - /// pub fn foo() { - /// #![cfg(windows)] - /// } - /// ``` - /// Use instead: - /// ```no_run - /// #[cfg(linux)] - /// #[cfg(windows)] - /// pub fn foo() { - /// } - /// ``` - #[clippy::version = "1.78.0"] - pub MIXED_ATTRIBUTES_STYLE, - style, - "item has both inner and outer attributes" + #[clippy::version = "pre 1.29.0"] + pub DEPRECATED_SEMVER, + correctness, + "use of `#[deprecated(since = \"x\")]` where x is not semver" } declare_clippy_lint! { @@ -478,12 +237,272 @@ "ignored tests without messages" } -pub struct Attributes { - msrv: Msrv, +declare_clippy_lint! { + /// ### What it does + /// Checks for items annotated with `#[inline(always)]`, + /// unless the annotated function is empty or simply panics. + /// + /// ### Why is this bad? + /// While there are valid uses of this annotation (and once + /// you know when to use it, by all means `allow` this lint), it's a common + /// newbie-mistake to pepper one's code with it. + /// + /// As a rule of thumb, before slapping `#[inline(always)]` on a function, + /// measure if that additional function call really affects your runtime profile + /// sufficiently to make up for the increase in compile time. + /// + /// ### Known problems + /// False positives, big time. This lint is meant to be + /// deactivated by everyone doing serious performance work. This means having + /// done the measurement. + /// + /// ### Example + /// ```ignore + /// #[inline(always)] + /// fn not_quite_hot_code(..) { ... } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub INLINE_ALWAYS, + pedantic, + "use of `#[inline(always)]`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for items that have the same kind of attributes with mixed styles (inner/outer). + /// + /// ### Why is this bad? + /// Having both style of said attributes makes it more complicated to read code. + /// + /// ### Known problems + /// This lint currently has false-negatives when mixing same attributes + /// but they have different path symbols, for example: + /// ```ignore + /// #[custom_attribute] + /// pub fn foo() { + /// #![my_crate::custom_attribute] + /// } + /// ``` + /// + /// ### Example + /// ```no_run + /// #[cfg(linux)] + /// pub fn foo() { + /// #![cfg(windows)] + /// } + /// ``` + /// Use instead: + /// ```no_run + /// #[cfg(linux)] + /// #[cfg(windows)] + /// pub fn foo() { + /// } + /// ``` + #[clippy::version = "1.78.0"] + pub MIXED_ATTRIBUTES_STYLE, + style, + "item has both inner and outer attributes" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `any` and `all` combinators in `cfg` with only one condition. + /// + /// ### Why is this bad? + /// If there is only one condition, no need to wrap it into `any` or `all` combinators. + /// + /// ### Example + /// ```no_run + /// #[cfg(any(unix))] + /// pub struct Bar; + /// ``` + /// + /// Use instead: + /// ```no_run + /// #[cfg(unix)] + /// pub struct Bar; + /// ``` + #[clippy::version = "1.71.0"] + pub NON_MINIMAL_CFG, + style, + "ensure that all `cfg(any())` and `cfg(all())` have more than one condition" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for items with `#[repr(packed)]`-attribute without ABI qualification + /// + /// ### Why is this bad? + /// Without qualification, `repr(packed)` implies `repr(Rust)`. The Rust-ABI is inherently unstable. + /// While this is fine as long as the type is accessed correctly within Rust-code, most uses + /// of `#[repr(packed)]` involve FFI and/or data structures specified by network-protocols or + /// other external specifications. In such situations, the unstable Rust-ABI implied in + /// `#[repr(packed)]` may lead to future bugs should the Rust-ABI change. + /// + /// In case you are relying on a well defined and stable memory layout, qualify the type's + /// representation using the `C`-ABI. Otherwise, if the type in question is only ever + /// accessed from Rust-code according to Rust's rules, use the `Rust`-ABI explicitly. + /// + /// ### Example + /// ```no_run + /// #[repr(packed)] + /// struct NetworkPacketHeader { + /// header_length: u8, + /// header_version: u16 + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// #[repr(C, packed)] + /// struct NetworkPacketHeader { + /// header_length: u8, + /// header_version: u16 + /// } + /// ``` + #[clippy::version = "1.85.0"] + pub REPR_PACKED_WITHOUT_ABI, + suspicious, + "ensures that `repr(packed)` always comes with a qualified ABI" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[should_panic]` attributes without specifying the expected panic message. + /// + /// ### Why is this bad? + /// The expected panic message should be specified to ensure that the test is actually + /// panicking with the expected message, and not another unrelated panic. + /// + /// ### Example + /// ```no_run + /// fn random() -> i32 { 0 } + /// + /// #[should_panic] + /// #[test] + /// fn my_test() { + /// let _ = 1 / random(); + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// fn random() -> i32 { 0 } + /// + /// #[should_panic = "attempt to divide by zero"] + /// #[test] + /// fn my_test() { + /// let _ = 1 / random(); + /// } + /// ``` + #[clippy::version = "1.74.0"] + pub SHOULD_PANIC_WITHOUT_EXPECT, + pedantic, + "ensures that all `should_panic` attributes specify its expected panic message" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[cfg_attr(clippy, allow(clippy::lint))]` + /// and suggests to replace it with `#[allow(clippy::lint)]`. + /// + /// ### Why is this bad? + /// There is no reason to put clippy attributes behind a clippy `cfg` as they are not + /// run by anything else than clippy. + /// + /// ### Example + /// ```no_run + /// #![cfg_attr(clippy, allow(clippy::deprecated_cfg_attr))] + /// ``` + /// + /// Use instead: + /// ```no_run + /// #![allow(clippy::deprecated_cfg_attr)] + /// ``` + #[clippy::version = "1.78.0"] + pub UNNECESSARY_CLIPPY_CFG, + suspicious, + "usage of `cfg_attr(clippy, allow(clippy::lint))` instead of `allow(clippy::lint)`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `extern crate` and `use` items annotated with + /// lint attributes. + /// + /// This lint permits lint attributes for lints emitted on the items themself. + /// For `use` items these lints are: + /// * ambiguous_glob_reexports + /// * dead_code + /// * deprecated + /// * hidden_glob_reexports + /// * unreachable_pub + /// * unused + /// * unused_braces + /// * unused_import_braces + /// * clippy::disallowed_types + /// * clippy::enum_glob_use + /// * clippy::macro_use_imports + /// * clippy::module_name_repetitions + /// * clippy::redundant_pub_crate + /// * clippy::single_component_path_imports + /// * clippy::unsafe_removed_from_name + /// * clippy::wildcard_imports + /// + /// For `extern crate` items these lints are: + /// * `unused_imports` on items with `#[macro_use]` + /// + /// ### Why is this bad? + /// Lint attributes have no effect on crate imports. Most + /// likely a `!` was forgotten. + /// + /// ### Example + /// ```ignore + /// #[deny(dead_code)] + /// extern crate foo; + /// #[forbid(dead_code)] + /// use foo::bar; + /// ``` + /// + /// Use instead: + /// ```rust,ignore + /// #[allow(unused_imports)] + /// use foo::baz; + /// #[allow(unused_imports)] + /// #[macro_use] + /// extern crate baz; + /// ``` + #[clippy::version = "pre 1.29.0"] + pub USELESS_ATTRIBUTE, + correctness, + "use of lint attributes on `extern crate` items" } impl_lint_pass!(Attributes => [INLINE_ALWAYS, REPR_PACKED_WITHOUT_ABI]); +impl_lint_pass!(EarlyAttributes => [ + DEPRECATED_CFG_ATTR, + DEPRECATED_CLIPPY_CFG_ATTR, + NON_MINIMAL_CFG, + UNNECESSARY_CLIPPY_CFG, +]); + +impl_lint_pass!(PostExpansionEarlyAttributes => [ + ALLOW_ATTRIBUTES, + ALLOW_ATTRIBUTES_WITHOUT_REASON, + BLANKET_CLIPPY_RESTRICTION_LINTS, + DEPRECATED_SEMVER, + DUPLICATED_ATTRIBUTES, + IGNORE_WITHOUT_REASON, + MIXED_ATTRIBUTES_STYLE, + SHOULD_PANIC_WITHOUT_EXPECT, + USELESS_ATTRIBUTE, +]); + +pub struct Attributes { + msrv: Msrv, +} + impl Attributes { pub fn new(conf: &'static Conf) -> Self { Self { msrv: conf.msrv } @@ -526,13 +545,6 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(EarlyAttributes => [ - DEPRECATED_CFG_ATTR, - DEPRECATED_CLIPPY_CFG_ATTR, - NON_MINIMAL_CFG, - UNNECESSARY_CLIPPY_CFG, -]); - impl EarlyLintPass for EarlyAttributes { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { deprecated_cfg_attr::check(cx, attr, &self.msrv); @@ -555,18 +567,6 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(PostExpansionEarlyAttributes => [ - ALLOW_ATTRIBUTES, - ALLOW_ATTRIBUTES_WITHOUT_REASON, - BLANKET_CLIPPY_RESTRICTION_LINTS, - DEPRECATED_SEMVER, - DUPLICATED_ATTRIBUTES, - IGNORE_WITHOUT_REASON, - MIXED_ATTRIBUTES_STYLE, - SHOULD_PANIC_WITHOUT_EXPECT, - USELESS_ATTRIBUTE, -]); - impl EarlyLintPass for PostExpansionEarlyAttributes { fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) { blanket_clippy_restriction_lints::check_command_line(cx); diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index 2d61c5e0b78a..dbd7dbdd1c6f 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -10,6 +10,43 @@ use rustc_session::impl_lint_pass; use rustc_span::{Span, sym}; +declare_clippy_lint! { + /// ### What it does + /// Allows users to configure types which should not be held across await + /// suspension points. + /// + /// ### Why is this bad? + /// There are some types which are perfectly safe to use concurrently from + /// a memory access perspective, but that will cause bugs at runtime if + /// they are held in such a way. + /// + /// ### Example + /// + /// ```toml + /// await-holding-invalid-types = [ + /// # You can specify a type name + /// "CustomLockType", + /// # You can (optionally) specify a reason + /// { path = "OtherCustomLockType", reason = "Relies on a thread local" } + /// ] + /// ``` + /// + /// ```no_run + /// # async fn baz() {} + /// struct CustomLockType; + /// struct OtherCustomLockType; + /// async fn foo() { + /// let _x = CustomLockType; + /// let _y = OtherCustomLockType; + /// baz().await; // Lint violation + /// } + /// ``` + #[clippy::version = "1.62.0"] + pub AWAIT_HOLDING_INVALID_TYPE, + suspicious, + "holding a type across an await point which is not allowed to be held as per the configuration" +} + declare_clippy_lint! { /// ### What it does /// Checks for calls to `await` while holding a non-async-aware @@ -134,43 +171,6 @@ "inside an async function, holding a `RefCell` ref while calling `await`" } -declare_clippy_lint! { - /// ### What it does - /// Allows users to configure types which should not be held across await - /// suspension points. - /// - /// ### Why is this bad? - /// There are some types which are perfectly safe to use concurrently from - /// a memory access perspective, but that will cause bugs at runtime if - /// they are held in such a way. - /// - /// ### Example - /// - /// ```toml - /// await-holding-invalid-types = [ - /// # You can specify a type name - /// "CustomLockType", - /// # You can (optionally) specify a reason - /// { path = "OtherCustomLockType", reason = "Relies on a thread local" } - /// ] - /// ``` - /// - /// ```no_run - /// # async fn baz() {} - /// struct CustomLockType; - /// struct OtherCustomLockType; - /// async fn foo() { - /// let _x = CustomLockType; - /// let _y = OtherCustomLockType; - /// baz().await; // Lint violation - /// } - /// ``` - #[clippy::version = "1.62.0"] - pub AWAIT_HOLDING_INVALID_TYPE, - suspicious, - "holding a type across an await point which is not allowed to be held as per the configuration" -} - impl_lint_pass!(AwaitHolding => [ AWAIT_HOLDING_INVALID_TYPE, AWAIT_HOLDING_LOCK, diff --git a/clippy_lints/src/bool_to_int_with_if.rs b/clippy_lints/src/bool_to_int_with_if.rs index 129e77478406..b98a20a90ccb 100644 --- a/clippy_lints/src/bool_to_int_with_if.rs +++ b/clippy_lints/src/bool_to_int_with_if.rs @@ -43,6 +43,7 @@ pedantic, "using if to convert bool to int" } + declare_lint_pass!(BoolToIntWithIf => [BOOL_TO_INT_WITH_IF]); impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf { diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 0bd459d8b021..8b7619d11a83 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -74,6 +74,8 @@ "boolean expressions that contain terminals which can be eliminated" } +impl_lint_pass!(NonminimalBool => [NONMINIMAL_BOOL, OVERLY_COMPLEX_BOOL_EXPR]); + // For each pairs, both orders are considered. const METHODS_WITH_NEGATION: [(Option, Symbol, Symbol); 3] = [ (None, sym::is_some, sym::is_none), @@ -91,8 +93,6 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(NonminimalBool => [NONMINIMAL_BOOL, OVERLY_COMPLEX_BOOL_EXPR]); - impl<'tcx> LateLintPass<'tcx> for NonminimalBool { fn check_fn( &mut self, diff --git a/clippy_lints/src/byte_char_slices.rs b/clippy_lints/src/byte_char_slices.rs index fc9931439e93..6c023189f69e 100644 --- a/clippy_lints/src/byte_char_slices.rs +++ b/clippy_lints/src/byte_char_slices.rs @@ -27,6 +27,7 @@ style, "hard to read byte char slice" } + declare_lint_pass!(ByteCharSlice => [BYTE_CHAR_SLICES]); impl EarlyLintPass for ByteCharSlice { diff --git a/clippy_lints/src/cargo/mod.rs b/clippy_lints/src/cargo/mod.rs index 2fb468aed618..0aa6e4c3e8e2 100644 --- a/clippy_lints/src/cargo/mod.rs +++ b/clippy_lints/src/cargo/mod.rs @@ -56,126 +56,6 @@ "common metadata is defined in `Cargo.toml`" } -declare_clippy_lint! { - /// ### What it does - /// Checks for feature names with prefix `use-`, `with-` or suffix `-support` - /// - /// ### Why is this bad? - /// These prefixes and suffixes have no significant meaning. - /// - /// ### Example - /// ```toml - /// # The `Cargo.toml` with feature name redundancy - /// [features] - /// default = ["use-abc", "with-def", "ghi-support"] - /// use-abc = [] // redundant - /// with-def = [] // redundant - /// ghi-support = [] // redundant - /// ``` - /// - /// Use instead: - /// ```toml - /// [features] - /// default = ["abc", "def", "ghi"] - /// abc = [] - /// def = [] - /// ghi = [] - /// ``` - /// - #[clippy::version = "1.57.0"] - pub REDUNDANT_FEATURE_NAMES, - cargo, - "usage of a redundant feature name" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for negative feature names with prefix `no-` or `not-` - /// - /// ### Why is this bad? - /// Features are supposed to be additive, and negatively-named features violate it. - /// - /// ### Example - /// ```toml - /// # The `Cargo.toml` with negative feature names - /// [features] - /// default = [] - /// no-abc = [] - /// not-def = [] - /// - /// ``` - /// Use instead: - /// ```toml - /// [features] - /// default = ["abc", "def"] - /// abc = [] - /// def = [] - /// - /// ``` - #[clippy::version = "1.57.0"] - pub NEGATIVE_FEATURE_NAMES, - cargo, - "usage of a negative feature name" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks to see if multiple versions of a crate are being - /// used. - /// - /// ### Why is this bad? - /// This bloats the size of targets, and can lead to - /// confusing error messages when structs or traits are used interchangeably - /// between different versions of a crate. - /// - /// ### Known problems - /// Because this can be caused purely by the dependencies - /// themselves, it's not always possible to fix this issue. - /// In those cases, you can allow that specific crate using - /// the `allowed-duplicate-crates` configuration option. - /// - /// ### Example - /// ```toml - /// # This will pull in both winapi v0.3.x and v0.2.x, triggering a warning. - /// [dependencies] - /// ctrlc = "=3.1.0" - /// ansi_term = "=0.11.0" - /// ``` - #[clippy::version = "pre 1.29.0"] - pub MULTIPLE_CRATE_VERSIONS, - cargo, - "multiple versions of the same crate being used" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for wildcard dependencies in the `Cargo.toml`. - /// - /// ### Why is this bad? - /// [As the edition guide says](https://rust-lang-nursery.github.io/edition-guide/rust-2018/cargo-and-crates-io/crates-io-disallows-wildcard-dependencies.html), - /// it is highly unlikely that you work with any possible version of your dependency, - /// and wildcard dependencies would cause unnecessary breakage in the ecosystem. - /// - /// ### Example - /// ```toml - /// [dependencies] - /// regex = "*" - /// ``` - /// Use instead: - /// ```toml - /// [dependencies] - /// # allow patch updates, but not minor or major version changes - /// some_crate_1 = "~1.2.3" - /// - /// # pin the version to a specific version - /// some_crate_2 = "=1.2.3" - /// ``` - #[clippy::version = "1.32.0"] - pub WILDCARD_DEPENDENCIES, - cargo, - "wildcard dependencies being used" -} - declare_clippy_lint! { /// ### What it does /// Checks for lint groups with the same priority as lints in the `Cargo.toml` @@ -213,9 +93,124 @@ "a lint group in `Cargo.toml` at the same priority as a lint" } -pub struct Cargo { - allowed_duplicate_crates: FxHashSet, - ignore_publish: bool, +declare_clippy_lint! { + /// ### What it does + /// Checks to see if multiple versions of a crate are being + /// used. + /// + /// ### Why is this bad? + /// This bloats the size of targets, and can lead to + /// confusing error messages when structs or traits are used interchangeably + /// between different versions of a crate. + /// + /// ### Known problems + /// Because this can be caused purely by the dependencies + /// themselves, it's not always possible to fix this issue. + /// In those cases, you can allow that specific crate using + /// the `allowed-duplicate-crates` configuration option. + /// + /// ### Example + /// ```toml + /// # This will pull in both winapi v0.3.x and v0.2.x, triggering a warning. + /// [dependencies] + /// ctrlc = "=3.1.0" + /// ansi_term = "=0.11.0" + /// ``` + #[clippy::version = "pre 1.29.0"] + pub MULTIPLE_CRATE_VERSIONS, + cargo, + "multiple versions of the same crate being used" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for negative feature names with prefix `no-` or `not-` + /// + /// ### Why is this bad? + /// Features are supposed to be additive, and negatively-named features violate it. + /// + /// ### Example + /// ```toml + /// # The `Cargo.toml` with negative feature names + /// [features] + /// default = [] + /// no-abc = [] + /// not-def = [] + /// + /// ``` + /// Use instead: + /// ```toml + /// [features] + /// default = ["abc", "def"] + /// abc = [] + /// def = [] + /// + /// ``` + #[clippy::version = "1.57.0"] + pub NEGATIVE_FEATURE_NAMES, + cargo, + "usage of a negative feature name" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for feature names with prefix `use-`, `with-` or suffix `-support` + /// + /// ### Why is this bad? + /// These prefixes and suffixes have no significant meaning. + /// + /// ### Example + /// ```toml + /// # The `Cargo.toml` with feature name redundancy + /// [features] + /// default = ["use-abc", "with-def", "ghi-support"] + /// use-abc = [] // redundant + /// with-def = [] // redundant + /// ghi-support = [] // redundant + /// ``` + /// + /// Use instead: + /// ```toml + /// [features] + /// default = ["abc", "def", "ghi"] + /// abc = [] + /// def = [] + /// ghi = [] + /// ``` + /// + #[clippy::version = "1.57.0"] + pub REDUNDANT_FEATURE_NAMES, + cargo, + "usage of a redundant feature name" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for wildcard dependencies in the `Cargo.toml`. + /// + /// ### Why is this bad? + /// [As the edition guide says](https://rust-lang-nursery.github.io/edition-guide/rust-2018/cargo-and-crates-io/crates-io-disallows-wildcard-dependencies.html), + /// it is highly unlikely that you work with any possible version of your dependency, + /// and wildcard dependencies would cause unnecessary breakage in the ecosystem. + /// + /// ### Example + /// ```toml + /// [dependencies] + /// regex = "*" + /// ``` + /// Use instead: + /// ```toml + /// [dependencies] + /// # allow patch updates, but not minor or major version changes + /// some_crate_1 = "~1.2.3" + /// + /// # pin the version to a specific version + /// some_crate_2 = "=1.2.3" + /// ``` + #[clippy::version = "1.32.0"] + pub WILDCARD_DEPENDENCIES, + cargo, + "wildcard dependencies being used" } impl_lint_pass!(Cargo => [ @@ -227,6 +222,11 @@ pub struct Cargo { WILDCARD_DEPENDENCIES, ]); +pub struct Cargo { + allowed_duplicate_crates: FxHashSet, + ignore_publish: bool, +} + impl Cargo { pub fn new(conf: &'static Conf) -> Self { Self { diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 2e5e5dd252a4..75761de4ae73 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -36,50 +36,231 @@ declare_clippy_lint! { /// ### What it does - /// Checks for casts from any numeric type to a float type where - /// the receiving type cannot store all values from the original type without - /// rounding errors. This possible rounding is to be expected, so this lint is - /// `Allow` by default. + /// Checks for the usage of `as *const _` or `as *mut _` conversion using inferred type. /// - /// Basically, this warns on casting any integer with 32 or more bits to `f32` - /// or any 64-bit integer to `f64`. - /// - /// ### Why is this bad? - /// It's not bad at all. But in some applications it can be - /// helpful to know where precision loss can take place. This lint can help find - /// those places in the code. + /// ### Why restrict this? + /// The conversion might include a dangerous cast that might go undetected due to the type being inferred. /// /// ### Example /// ```no_run - /// let x = u64::MAX; - /// x as f64; + /// fn as_usize(t: &T) -> usize { + /// // BUG: `t` is already a reference, so we will here + /// // return a dangling pointer to a temporary value instead + /// &t as *const _ as usize + /// } /// ``` - #[clippy::version = "pre 1.29.0"] - pub CAST_PRECISION_LOSS, - pedantic, - "casts that cause loss of precision, e.g., `x as f32` where `x: u64`" + /// Use instead: + /// ```no_run + /// fn as_usize(t: &T) -> usize { + /// t as *const T as usize + /// } + /// ``` + #[clippy::version = "1.85.0"] + pub AS_POINTER_UNDERSCORE, + restriction, + "detects `as *mut _` and `as *const _` conversion" } declare_clippy_lint! { /// ### What it does - /// Checks for casts from a signed to an unsigned numeric - /// type. In this case, negative values wrap around to large positive values, - /// which can be quite surprising in practice. However, since the cast works as - /// defined, this lint is `Allow` by default. + /// Checks for the result of a `&self`-taking `as_ptr` being cast to a mutable pointer. /// /// ### Why is this bad? - /// Possibly surprising results. You can activate this lint - /// as a one-time check to see where numeric wrapping can arise. + /// Since `as_ptr` takes a `&self`, the pointer won't have write permissions unless interior + /// mutability is used, making it unlikely that having it as a mutable pointer is correct. /// /// ### Example /// ```no_run - /// let y: i8 = -1; - /// y as u64; // will return 18446744073709551615 + /// let mut vec = Vec::::with_capacity(1); + /// let ptr = vec.as_ptr() as *mut u8; + /// unsafe { ptr.write(4) }; // UNDEFINED BEHAVIOUR + /// ``` + /// Use instead: + /// ```no_run + /// let mut vec = Vec::::with_capacity(1); + /// let ptr = vec.as_mut_ptr(); + /// unsafe { ptr.write(4) }; + /// ``` + #[clippy::version = "1.66.0"] + pub AS_PTR_CAST_MUT, + nursery, + "casting the result of the `&self`-taking `as_ptr` to a mutable pointer" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of `as _` conversion using inferred type. + /// + /// ### Why restrict this? + /// The conversion might include lossy conversion or a dangerous cast that might go + /// undetected due to the type being inferred. + /// + /// The lint is allowed by default as using `_` is less wordy than always specifying the type. + /// + /// ### Example + /// ```no_run + /// fn foo(n: usize) {} + /// let n: u16 = 256; + /// foo(n as _); + /// ``` + /// Use instead: + /// ```no_run + /// fn foo(n: usize) {} + /// let n: u16 = 256; + /// foo(n as usize); + /// ``` + #[clippy::version = "1.63.0"] + pub AS_UNDERSCORE, + restriction, + "detects `as _` conversion" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of `&expr as *const T` or + /// `&mut expr as *mut T`, and suggest using `&raw const` or + /// `&raw mut` instead. + /// + /// ### Why is this bad? + /// This would improve readability and avoid creating a reference + /// that points to an uninitialized value or unaligned place. + /// Read the `&raw` explanation in the Reference for more information. + /// + /// ### Example + /// ```no_run + /// let val = 1; + /// let p = &val as *const i32; + /// + /// let mut val_mut = 1; + /// let p_mut = &mut val_mut as *mut i32; + /// ``` + /// Use instead: + /// ```no_run + /// let val = 1; + /// let p = &raw const val; + /// + /// let mut val_mut = 1; + /// let p_mut = &raw mut val_mut; + /// ``` + #[clippy::version = "1.60.0"] + pub BORROW_AS_PTR, + pedantic, + "borrowing just to cast to a raw pointer" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of the `abs()` method that cast the result to unsigned. + /// + /// ### Why is this bad? + /// The `unsigned_abs()` method avoids panic when called on the MIN value. + /// + /// ### Example + /// ```no_run + /// let x: i32 = -42; + /// let y: u32 = x.abs() as u32; + /// ``` + /// Use instead: + /// ```no_run + /// let x: i32 = -42; + /// let y: u32 = x.unsigned_abs(); + /// ``` + #[clippy::version = "1.62.0"] + pub CAST_ABS_TO_UNSIGNED, + suspicious, + "casting the result of `abs()` to an unsigned integer can panic" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for casts from an enum tuple constructor to an integer. + /// + /// ### Why is this bad? + /// The cast is easily confused with casting a c-like enum value to an integer. + /// + /// ### Example + /// ```no_run + /// enum E { X(i32) }; + /// let _ = E::X as usize; + /// ``` + #[clippy::version = "1.61.0"] + pub CAST_ENUM_CONSTRUCTOR, + suspicious, + "casts from an enum tuple constructor to an integer" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for casts from an enum type to an integral type that will definitely truncate the + /// value. + /// + /// ### Why is this bad? + /// The resulting integral value will not match the value of the variant it came from. + /// + /// ### Example + /// ```no_run + /// enum E { X = 256 }; + /// let _ = E::X as u8; + /// ``` + #[clippy::version = "1.61.0"] + pub CAST_ENUM_TRUNCATION, + suspicious, + "casts from an enum type to an integral type that will truncate the value" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for casts between numeric types that can be replaced by safe + /// conversion functions. + /// + /// ### Why is this bad? + /// Rust's `as` keyword will perform many kinds of conversions, including + /// silently lossy conversions. Conversion functions such as `i32::from` + /// will only perform lossless conversions. Using the conversion functions + /// prevents conversions from becoming silently lossy if the input types + /// ever change, and makes it clear for people reading the code that the + /// conversion is lossless. + /// + /// ### Example + /// ```no_run + /// fn as_u64(x: u8) -> u64 { + /// x as u64 + /// } + /// ``` + /// + /// Using `::from` would look like this: + /// + /// ```no_run + /// fn as_u64(x: u8) -> u64 { + /// u64::from(x) + /// } /// ``` #[clippy::version = "pre 1.29.0"] - pub CAST_SIGN_LOSS, + pub CAST_LOSSLESS, pedantic, - "casts from signed types to unsigned types, e.g., `x as u32` where `x: i32`" + "casts using `as` that are known to be lossless, e.g., `x as u64` where `x: u8`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for a known NaN float being cast to an integer + /// + /// ### Why is this bad? + /// NaNs are cast into zero, so one could simply use this and make the + /// code more readable. The lint could also hint at a programmer error. + /// + /// ### Example + /// ```rust,ignore + /// let _ = (0.0_f32 / 0.0) as u64; + /// ``` + /// Use instead: + /// ```rust,ignore + /// let _ = 0_u64; + /// ``` + #[clippy::version = "1.66.0"] + pub CAST_NAN_TO_INT, + suspicious, + "casting a known floating-point NaN into an integer" } declare_clippy_lint! { @@ -159,71 +340,28 @@ declare_clippy_lint! { /// ### What it does - /// Checks for casts between numeric types that can be replaced by safe - /// conversion functions. + /// Checks for casts from any numeric type to a float type where + /// the receiving type cannot store all values from the original type without + /// rounding errors. This possible rounding is to be expected, so this lint is + /// `Allow` by default. + /// + /// Basically, this warns on casting any integer with 32 or more bits to `f32` + /// or any 64-bit integer to `f64`. /// /// ### Why is this bad? - /// Rust's `as` keyword will perform many kinds of conversions, including - /// silently lossy conversions. Conversion functions such as `i32::from` - /// will only perform lossless conversions. Using the conversion functions - /// prevents conversions from becoming silently lossy if the input types - /// ever change, and makes it clear for people reading the code that the - /// conversion is lossless. + /// It's not bad at all. But in some applications it can be + /// helpful to know where precision loss can take place. This lint can help find + /// those places in the code. /// /// ### Example /// ```no_run - /// fn as_u64(x: u8) -> u64 { - /// x as u64 - /// } - /// ``` - /// - /// Using `::from` would look like this: - /// - /// ```no_run - /// fn as_u64(x: u8) -> u64 { - /// u64::from(x) - /// } + /// let x = u64::MAX; + /// x as f64; /// ``` #[clippy::version = "pre 1.29.0"] - pub CAST_LOSSLESS, + pub CAST_PRECISION_LOSS, pedantic, - "casts using `as` that are known to be lossless, e.g., `x as u64` where `x: u8`" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for casts to the same type, casts of int literals to integer - /// types, casts of float literals to float types, and casts between raw - /// pointers that don't change type or constness. - /// - /// ### Why is this bad? - /// It's just unnecessary. - /// - /// ### Known problems - /// When the expression on the left is a function call, the lint considers - /// the return type to be a type alias if it's aliased through a `use` - /// statement (like `use std::io::Result as IoResult`). It will not lint - /// such cases. - /// - /// This check will only work on primitive types without any intermediate - /// references: raw pointers and trait objects may or may not work. - /// - /// ### Example - /// ```no_run - /// let _ = 2i32 as i32; - /// let _ = 0.5 as f32; - /// ``` - /// - /// Better: - /// - /// ```no_run - /// let _ = 2_i32; - /// let _ = 0.5_f32; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub UNNECESSARY_CAST, - complexity, - "cast to the same type, e.g., `x as i32` where `x: i32`" + "casts that cause loss of precision, e.g., `x as f32` where `x: u64`" } declare_clippy_lint! { @@ -254,6 +392,154 @@ "cast from a pointer to a more strictly aligned pointer" } +declare_clippy_lint! { + /// ### What it does + /// Checks for casts from a signed to an unsigned numeric + /// type. In this case, negative values wrap around to large positive values, + /// which can be quite surprising in practice. However, since the cast works as + /// defined, this lint is `Allow` by default. + /// + /// ### Why is this bad? + /// Possibly surprising results. You can activate this lint + /// as a one-time check to see where numeric wrapping can arise. + /// + /// ### Example + /// ```no_run + /// let y: i8 = -1; + /// y as u64; // will return 18446744073709551615 + /// ``` + #[clippy::version = "pre 1.29.0"] + pub CAST_SIGN_LOSS, + pedantic, + "casts from signed types to unsigned types, e.g., `x as u32` where `x: i32`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `as` casts between raw pointers to slices with differently sized elements. + /// + /// ### Why is this bad? + /// The produced raw pointer to a slice does not update its length metadata. The produced + /// pointer will point to a different number of bytes than the original pointer because the + /// length metadata of a raw slice pointer is in elements rather than bytes. + /// Producing a slice reference from the raw pointer will either create a slice with + /// less data (which can be surprising) or create a slice with more data and cause Undefined Behavior. + /// + /// ### Example + /// // Missing data + /// ```no_run + /// let a = [1_i32, 2, 3, 4]; + /// let p = &a as *const [i32] as *const [u8]; + /// unsafe { + /// println!("{:?}", &*p); + /// } + /// ``` + /// // Undefined Behavior (note: also potential alignment issues) + /// ```no_run + /// let a = [1_u8, 2, 3, 4]; + /// let p = &a as *const [u8] as *const [u32]; + /// unsafe { + /// println!("{:?}", &*p); + /// } + /// ``` + /// Instead use `ptr::slice_from_raw_parts` to construct a slice from a data pointer and the correct length + /// ```no_run + /// let a = [1_i32, 2, 3, 4]; + /// let old_ptr = &a as *const [i32]; + /// // The data pointer is cast to a pointer to the target `u8` not `[u8]` + /// // The length comes from the known length of 4 i32s times the 4 bytes per i32 + /// let new_ptr = core::ptr::slice_from_raw_parts(old_ptr as *const u8, 16); + /// unsafe { + /// println!("{:?}", &*new_ptr); + /// } + /// ``` + #[clippy::version = "1.61.0"] + pub CAST_SLICE_DIFFERENT_SIZES, + correctness, + "casting using `as` between raw pointers to slices of types with different sizes" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for a raw slice being cast to a slice pointer + /// + /// ### Why is this bad? + /// This can result in multiple `&mut` references to the same location when only a pointer is + /// required. + /// `ptr::slice_from_raw_parts` is a safe alternative that doesn't require + /// the same [safety requirements] to be upheld. + /// + /// ### Example + /// ```rust,ignore + /// let _: *const [u8] = std::slice::from_raw_parts(ptr, len) as *const _; + /// let _: *mut [u8] = std::slice::from_raw_parts_mut(ptr, len) as *mut _; + /// ``` + /// Use instead: + /// ```rust,ignore + /// let _: *const [u8] = std::ptr::slice_from_raw_parts(ptr, len); + /// let _: *mut [u8] = std::ptr::slice_from_raw_parts_mut(ptr, len); + /// ``` + /// [safety requirements]: https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety + #[clippy::version = "1.65.0"] + pub CAST_SLICE_FROM_RAW_PARTS, + suspicious, + "casting a slice created from a pointer and length to a slice pointer" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for expressions where a character literal is cast + /// to `u8` and suggests using a byte literal instead. + /// + /// ### Why is this bad? + /// In general, casting values to smaller types is + /// error-prone and should be avoided where possible. In the particular case of + /// converting a character literal to `u8`, it is easy to avoid by just using a + /// byte literal instead. As an added bonus, `b'a'` is also slightly shorter + /// than `'a' as u8`. + /// + /// ### Example + /// ```rust,ignore + /// 'x' as u8 + /// ``` + /// + /// A better version, using the byte literal: + /// + /// ```rust,ignore + /// b'x' + /// ``` + #[clippy::version = "pre 1.29.0"] + pub CHAR_LIT_AS_U8, + complexity, + "casting a character literal to `u8` truncates" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for casts of a primitive method pointer like `max`/`min` to any integer type. + /// + /// ### Why restrict this? + /// Casting a function pointer to an integer can have surprising results and can occur + /// accidentally if parentheses are omitted from a function call. If you aren't doing anything + /// low-level with function pointers then you can opt out of casting functions to integers in + /// order to avoid mistakes. Alternatively, you can use this lint to audit all uses of function + /// pointer casts in your code. + /// + /// ### Example + /// ```no_run + /// let _ = u16::max as usize; + /// ``` + /// + /// Use instead: + /// ```no_run + /// let _ = u16::MAX as usize; + /// ``` + #[clippy::version = "1.89.0"] + pub CONFUSING_METHOD_TO_NUMERIC_CAST, + suspicious, + "casting a primitive method pointer to any integer type" +} + declare_clippy_lint! { /// ### What it does /// Checks for casts of function pointers to something other than `usize`. @@ -284,39 +570,6 @@ "casting a function pointer to a numeric type other than `usize`" } -declare_clippy_lint! { - /// ### What it does - /// Checks for casts of a function pointer to a numeric type not wide enough to - /// store an address. - /// - /// ### Why is this bad? - /// Such a cast discards some bits of the function's address. If this is intended, it would be more - /// clearly expressed by casting to `usize` first, then casting the `usize` to the intended type (with - /// a comment) to perform the truncation. - /// - /// ### Example - /// ```no_run - /// fn fn1() -> i16 { - /// 1 - /// }; - /// let _ = fn1 as i32; - /// ``` - /// - /// Use instead: - /// ```no_run - /// // Cast to usize first, then comment with the reason for the truncation - /// fn fn1() -> i16 { - /// 1 - /// }; - /// let fn_ptr = fn1 as usize; - /// let fn_ptr_truncated = fn_ptr as i32; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION, - style, - "casting a function pointer to a numeric type not wide enough to store the address" -} - declare_clippy_lint! { /// ### What it does /// Checks for casts of a function pointer to any integer type. @@ -361,30 +614,87 @@ declare_clippy_lint! { /// ### What it does - /// Checks for expressions where a character literal is cast - /// to `u8` and suggests using a byte literal instead. + /// Checks for casts of a function pointer to a numeric type not wide enough to + /// store an address. /// /// ### Why is this bad? - /// In general, casting values to smaller types is - /// error-prone and should be avoided where possible. In the particular case of - /// converting a character literal to `u8`, it is easy to avoid by just using a - /// byte literal instead. As an added bonus, `b'a'` is also slightly shorter - /// than `'a' as u8`. + /// Such a cast discards some bits of the function's address. If this is intended, it would be more + /// clearly expressed by casting to `usize` first, then casting the `usize` to the intended type (with + /// a comment) to perform the truncation. /// /// ### Example - /// ```rust,ignore - /// 'x' as u8 + /// ```no_run + /// fn fn1() -> i16 { + /// 1 + /// }; + /// let _ = fn1 as i32; /// ``` /// - /// A better version, using the byte literal: - /// - /// ```rust,ignore - /// b'x' + /// Use instead: + /// ```no_run + /// // Cast to usize first, then comment with the reason for the truncation + /// fn fn1() -> i16 { + /// 1 + /// }; + /// let fn_ptr = fn1 as usize; + /// let fn_ptr_truncated = fn_ptr as i32; /// ``` #[clippy::version = "pre 1.29.0"] - pub CHAR_LIT_AS_U8, - complexity, - "casting a character literal to `u8` truncates" + pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION, + style, + "casting a function pointer to a numeric type not wide enough to store the address" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for casts of small constant literals or `mem::align_of` results to raw pointers. + /// + /// ### Why is this bad? + /// This creates a dangling pointer and is better expressed as + /// {`std`, `core`}`::ptr::`{`dangling`, `dangling_mut`}. + /// + /// ### Example + /// ```no_run + /// let ptr = 4 as *const u32; + /// let aligned = std::mem::align_of::() as *const u32; + /// let mut_ptr: *mut i64 = 8 as *mut _; + /// ``` + /// Use instead: + /// ```no_run + /// let ptr = std::ptr::dangling::(); + /// let aligned = std::ptr::dangling::(); + /// let mut_ptr: *mut i64 = std::ptr::dangling_mut(); + /// ``` + #[clippy::version = "1.88.0"] + pub MANUAL_DANGLING_PTR, + style, + "casting small constant literals to pointers to create dangling pointers" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for bindings (constants, statics, or let bindings) that are defined + /// with one numeric type but are consistently cast to a different type in all usages. + /// + /// ### Why is this bad? + /// If a binding is always cast to a different type when used, it would be clearer + /// and more efficient to define it with the target type from the start. + /// + /// ### Example + /// ```no_run + /// const SIZE: u16 = 15; + /// let arr: [u8; SIZE as usize] = [0; SIZE as usize]; + /// ``` + /// + /// Use instead: + /// ```no_run + /// const SIZE: usize = 15; + /// let arr: [u8; SIZE] = [0; SIZE]; + /// ``` + #[clippy::version = "1.93.0"] + pub NEEDLESS_TYPE_CAST, + nursery, + "binding defined with one type but always cast to another" } declare_clippy_lint! { @@ -453,270 +763,6 @@ "casting using `as` on raw pointers to change constness when specialized methods apply" } -declare_clippy_lint! { - /// ### What it does - /// Checks for casts from an enum type to an integral type that will definitely truncate the - /// value. - /// - /// ### Why is this bad? - /// The resulting integral value will not match the value of the variant it came from. - /// - /// ### Example - /// ```no_run - /// enum E { X = 256 }; - /// let _ = E::X as u8; - /// ``` - #[clippy::version = "1.61.0"] - pub CAST_ENUM_TRUNCATION, - suspicious, - "casts from an enum type to an integral type that will truncate the value" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `as` casts between raw pointers to slices with differently sized elements. - /// - /// ### Why is this bad? - /// The produced raw pointer to a slice does not update its length metadata. The produced - /// pointer will point to a different number of bytes than the original pointer because the - /// length metadata of a raw slice pointer is in elements rather than bytes. - /// Producing a slice reference from the raw pointer will either create a slice with - /// less data (which can be surprising) or create a slice with more data and cause Undefined Behavior. - /// - /// ### Example - /// // Missing data - /// ```no_run - /// let a = [1_i32, 2, 3, 4]; - /// let p = &a as *const [i32] as *const [u8]; - /// unsafe { - /// println!("{:?}", &*p); - /// } - /// ``` - /// // Undefined Behavior (note: also potential alignment issues) - /// ```no_run - /// let a = [1_u8, 2, 3, 4]; - /// let p = &a as *const [u8] as *const [u32]; - /// unsafe { - /// println!("{:?}", &*p); - /// } - /// ``` - /// Instead use `ptr::slice_from_raw_parts` to construct a slice from a data pointer and the correct length - /// ```no_run - /// let a = [1_i32, 2, 3, 4]; - /// let old_ptr = &a as *const [i32]; - /// // The data pointer is cast to a pointer to the target `u8` not `[u8]` - /// // The length comes from the known length of 4 i32s times the 4 bytes per i32 - /// let new_ptr = core::ptr::slice_from_raw_parts(old_ptr as *const u8, 16); - /// unsafe { - /// println!("{:?}", &*new_ptr); - /// } - /// ``` - #[clippy::version = "1.61.0"] - pub CAST_SLICE_DIFFERENT_SIZES, - correctness, - "casting using `as` between raw pointers to slices of types with different sizes" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for casts from an enum tuple constructor to an integer. - /// - /// ### Why is this bad? - /// The cast is easily confused with casting a c-like enum value to an integer. - /// - /// ### Example - /// ```no_run - /// enum E { X(i32) }; - /// let _ = E::X as usize; - /// ``` - #[clippy::version = "1.61.0"] - pub CAST_ENUM_CONSTRUCTOR, - suspicious, - "casts from an enum tuple constructor to an integer" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for usage of the `abs()` method that cast the result to unsigned. - /// - /// ### Why is this bad? - /// The `unsigned_abs()` method avoids panic when called on the MIN value. - /// - /// ### Example - /// ```no_run - /// let x: i32 = -42; - /// let y: u32 = x.abs() as u32; - /// ``` - /// Use instead: - /// ```no_run - /// let x: i32 = -42; - /// let y: u32 = x.unsigned_abs(); - /// ``` - #[clippy::version = "1.62.0"] - pub CAST_ABS_TO_UNSIGNED, - suspicious, - "casting the result of `abs()` to an unsigned integer can panic" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for the usage of `as _` conversion using inferred type. - /// - /// ### Why restrict this? - /// The conversion might include lossy conversion or a dangerous cast that might go - /// undetected due to the type being inferred. - /// - /// The lint is allowed by default as using `_` is less wordy than always specifying the type. - /// - /// ### Example - /// ```no_run - /// fn foo(n: usize) {} - /// let n: u16 = 256; - /// foo(n as _); - /// ``` - /// Use instead: - /// ```no_run - /// fn foo(n: usize) {} - /// let n: u16 = 256; - /// foo(n as usize); - /// ``` - #[clippy::version = "1.63.0"] - pub AS_UNDERSCORE, - restriction, - "detects `as _` conversion" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for the usage of `&expr as *const T` or - /// `&mut expr as *mut T`, and suggest using `&raw const` or - /// `&raw mut` instead. - /// - /// ### Why is this bad? - /// This would improve readability and avoid creating a reference - /// that points to an uninitialized value or unaligned place. - /// Read the `&raw` explanation in the Reference for more information. - /// - /// ### Example - /// ```no_run - /// let val = 1; - /// let p = &val as *const i32; - /// - /// let mut val_mut = 1; - /// let p_mut = &mut val_mut as *mut i32; - /// ``` - /// Use instead: - /// ```no_run - /// let val = 1; - /// let p = &raw const val; - /// - /// let mut val_mut = 1; - /// let p_mut = &raw mut val_mut; - /// ``` - #[clippy::version = "1.60.0"] - pub BORROW_AS_PTR, - pedantic, - "borrowing just to cast to a raw pointer" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for a raw slice being cast to a slice pointer - /// - /// ### Why is this bad? - /// This can result in multiple `&mut` references to the same location when only a pointer is - /// required. - /// `ptr::slice_from_raw_parts` is a safe alternative that doesn't require - /// the same [safety requirements] to be upheld. - /// - /// ### Example - /// ```rust,ignore - /// let _: *const [u8] = std::slice::from_raw_parts(ptr, len) as *const _; - /// let _: *mut [u8] = std::slice::from_raw_parts_mut(ptr, len) as *mut _; - /// ``` - /// Use instead: - /// ```rust,ignore - /// let _: *const [u8] = std::ptr::slice_from_raw_parts(ptr, len); - /// let _: *mut [u8] = std::ptr::slice_from_raw_parts_mut(ptr, len); - /// ``` - /// [safety requirements]: https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety - #[clippy::version = "1.65.0"] - pub CAST_SLICE_FROM_RAW_PARTS, - suspicious, - "casting a slice created from a pointer and length to a slice pointer" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for the result of a `&self`-taking `as_ptr` being cast to a mutable pointer. - /// - /// ### Why is this bad? - /// Since `as_ptr` takes a `&self`, the pointer won't have write permissions unless interior - /// mutability is used, making it unlikely that having it as a mutable pointer is correct. - /// - /// ### Example - /// ```no_run - /// let mut vec = Vec::::with_capacity(1); - /// let ptr = vec.as_ptr() as *mut u8; - /// unsafe { ptr.write(4) }; // UNDEFINED BEHAVIOUR - /// ``` - /// Use instead: - /// ```no_run - /// let mut vec = Vec::::with_capacity(1); - /// let ptr = vec.as_mut_ptr(); - /// unsafe { ptr.write(4) }; - /// ``` - #[clippy::version = "1.66.0"] - pub AS_PTR_CAST_MUT, - nursery, - "casting the result of the `&self`-taking `as_ptr` to a mutable pointer" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for a known NaN float being cast to an integer - /// - /// ### Why is this bad? - /// NaNs are cast into zero, so one could simply use this and make the - /// code more readable. The lint could also hint at a programmer error. - /// - /// ### Example - /// ```rust,ignore - /// let _ = (0.0_f32 / 0.0) as u64; - /// ``` - /// Use instead: - /// ```rust,ignore - /// let _ = 0_u64; - /// ``` - #[clippy::version = "1.66.0"] - pub CAST_NAN_TO_INT, - suspicious, - "casting a known floating-point NaN into an integer" -} - -declare_clippy_lint! { - /// ### What it does - /// Catch casts from `0` to some pointer type - /// - /// ### Why is this bad? - /// This generally means `null` and is better expressed as - /// {`std`, `core`}`::ptr::`{`null`, `null_mut`}. - /// - /// ### Example - /// ```no_run - /// let a = 0 as *const u32; - /// ``` - /// - /// Use instead: - /// ```no_run - /// let a = std::ptr::null::(); - /// ``` - #[clippy::version = "pre 1.29.0"] - pub ZERO_PTR, - style, - "using `0 as *{const, mut} T`" -} - declare_clippy_lint! { /// ### What it does /// Checks for casts of references to pointer using `as` @@ -743,117 +789,61 @@ declare_clippy_lint! { /// ### What it does - /// Checks for the usage of `as *const _` or `as *mut _` conversion using inferred type. + /// Checks for casts to the same type, casts of int literals to integer + /// types, casts of float literals to float types, and casts between raw + /// pointers that don't change type or constness. /// - /// ### Why restrict this? - /// The conversion might include a dangerous cast that might go undetected due to the type being inferred. + /// ### Why is this bad? + /// It's just unnecessary. + /// + /// ### Known problems + /// When the expression on the left is a function call, the lint considers + /// the return type to be a type alias if it's aliased through a `use` + /// statement (like `use std::io::Result as IoResult`). It will not lint + /// such cases. + /// + /// This check will only work on primitive types without any intermediate + /// references: raw pointers and trait objects may or may not work. /// /// ### Example /// ```no_run - /// fn as_usize(t: &T) -> usize { - /// // BUG: `t` is already a reference, so we will here - /// // return a dangling pointer to a temporary value instead - /// &t as *const _ as usize - /// } + /// let _ = 2i32 as i32; + /// let _ = 0.5 as f32; /// ``` - /// Use instead: + /// + /// Better: + /// /// ```no_run - /// fn as_usize(t: &T) -> usize { - /// t as *const T as usize - /// } + /// let _ = 2_i32; + /// let _ = 0.5_f32; /// ``` - #[clippy::version = "1.85.0"] - pub AS_POINTER_UNDERSCORE, - restriction, - "detects `as *mut _` and `as *const _` conversion" + #[clippy::version = "pre 1.29.0"] + pub UNNECESSARY_CAST, + complexity, + "cast to the same type, e.g., `x as i32` where `x: i32`" } declare_clippy_lint! { /// ### What it does - /// Checks for casts of small constant literals or `mem::align_of` results to raw pointers. + /// Catch casts from `0` to some pointer type /// /// ### Why is this bad? - /// This creates a dangling pointer and is better expressed as - /// {`std`, `core`}`::ptr::`{`dangling`, `dangling_mut`}. + /// This generally means `null` and is better expressed as + /// {`std`, `core`}`::ptr::`{`null`, `null_mut`}. /// /// ### Example /// ```no_run - /// let ptr = 4 as *const u32; - /// let aligned = std::mem::align_of::() as *const u32; - /// let mut_ptr: *mut i64 = 8 as *mut _; + /// let a = 0 as *const u32; /// ``` + /// /// Use instead: /// ```no_run - /// let ptr = std::ptr::dangling::(); - /// let aligned = std::ptr::dangling::(); - /// let mut_ptr: *mut i64 = std::ptr::dangling_mut(); + /// let a = std::ptr::null::(); /// ``` - #[clippy::version = "1.88.0"] - pub MANUAL_DANGLING_PTR, + #[clippy::version = "pre 1.29.0"] + pub ZERO_PTR, style, - "casting small constant literals to pointers to create dangling pointers" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for casts of a primitive method pointer like `max`/`min` to any integer type. - /// - /// ### Why restrict this? - /// Casting a function pointer to an integer can have surprising results and can occur - /// accidentally if parentheses are omitted from a function call. If you aren't doing anything - /// low-level with function pointers then you can opt out of casting functions to integers in - /// order to avoid mistakes. Alternatively, you can use this lint to audit all uses of function - /// pointer casts in your code. - /// - /// ### Example - /// ```no_run - /// let _ = u16::max as usize; - /// ``` - /// - /// Use instead: - /// ```no_run - /// let _ = u16::MAX as usize; - /// ``` - #[clippy::version = "1.89.0"] - pub CONFUSING_METHOD_TO_NUMERIC_CAST, - suspicious, - "casting a primitive method pointer to any integer type" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for bindings (constants, statics, or let bindings) that are defined - /// with one numeric type but are consistently cast to a different type in all usages. - /// - /// ### Why is this bad? - /// If a binding is always cast to a different type when used, it would be clearer - /// and more efficient to define it with the target type from the start. - /// - /// ### Example - /// ```no_run - /// const SIZE: u16 = 15; - /// let arr: [u8; SIZE as usize] = [0; SIZE as usize]; - /// ``` - /// - /// Use instead: - /// ```no_run - /// const SIZE: usize = 15; - /// let arr: [u8; SIZE] = [0; SIZE]; - /// ``` - #[clippy::version = "1.93.0"] - pub NEEDLESS_TYPE_CAST, - nursery, - "binding defined with one type but always cast to another" -} - -pub struct Casts { - msrv: Msrv, -} - -impl Casts { - pub fn new(conf: &'static Conf) -> Self { - Self { msrv: conf.msrv } - } + "using `0 as *{const, mut} T`" } impl_lint_pass!(Casts => [ @@ -887,6 +877,16 @@ pub fn new(conf: &'static Conf) -> Self { ZERO_PTR, ]); +pub struct Casts { + msrv: Msrv, +} + +impl Casts { + pub fn new(conf: &'static Conf) -> Self { + Self { msrv: conf.msrv } + } +} + impl<'tcx> LateLintPass<'tcx> for Casts { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if expr.span.in_external_macro(cx.sess().source_map()) { diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index 8303897d1294..5e9009c67197 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -34,6 +34,8 @@ "`try_from` could replace manual bounds checking when casting" } +impl_lint_pass!(CheckedConversions => [CHECKED_CONVERSIONS]); + pub struct CheckedConversions { msrv: Msrv, } @@ -44,8 +46,6 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(CheckedConversions => [CHECKED_CONVERSIONS]); - impl LateLintPass<'_> for CheckedConversions { fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) { if let ExprKind::Binary(op, lhs, rhs) = item.kind diff --git a/clippy_lints/src/cloned_ref_to_slice_refs.rs b/clippy_lints/src/cloned_ref_to_slice_refs.rs index 35b799aefb04..c5eabe4c2b88 100644 --- a/clippy_lints/src/cloned_ref_to_slice_refs.rs +++ b/clippy_lints/src/cloned_ref_to_slice_refs.rs @@ -44,6 +44,8 @@ "cloning a reference for slice references" } +impl_lint_pass!(ClonedRefToSliceRefs<'_> => [CLONED_REF_TO_SLICE_REFS]); + pub struct ClonedRefToSliceRefs<'a> { msrv: &'a Msrv, } @@ -53,8 +55,6 @@ pub fn new(conf: &'a Conf) -> Self { } } -impl_lint_pass!(ClonedRefToSliceRefs<'_> => [CLONED_REF_TO_SLICE_REFS]); - impl<'tcx> LateLintPass<'tcx> for ClonedRefToSliceRefs<'_> { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { if self.msrv.meets(cx, { diff --git a/clippy_lints/src/coerce_container_to_any.rs b/clippy_lints/src/coerce_container_to_any.rs index 2e3acb7748e2..1a7e20b98271 100644 --- a/clippy_lints/src/coerce_container_to_any.rs +++ b/clippy_lints/src/coerce_container_to_any.rs @@ -46,6 +46,7 @@ nursery, "coercing to `&dyn Any` when dereferencing could produce a `dyn Any` without coercion is usually not intended" } + declare_lint_pass!(CoerceContainerToAny => [COERCE_CONTAINER_TO_ANY]); impl<'tcx> LateLintPass<'tcx> for CoerceContainerToAny { diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index 950ac863d755..eaad18d25436 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -40,6 +40,8 @@ @eval_always = true } +impl_lint_pass!(CognitiveComplexity => [COGNITIVE_COMPLEXITY]); + pub struct CognitiveComplexity { limit: LimitStack, } @@ -52,8 +54,6 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(CognitiveComplexity => [COGNITIVE_COMPLEXITY]); - impl CognitiveComplexity { fn check<'tcx>( &self, diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 0f3ef054b865..a76027caebc8 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -12,38 +12,6 @@ use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, Span, Symbol}; -declare_clippy_lint! { - /// ### What it does - /// Checks for nested `if` statements which can be collapsed - /// by `&&`-combining their conditions. - /// - /// ### Why is this bad? - /// Each `if`-statement adds one level of nesting, which - /// makes code look more complex than it really is. - /// - /// ### Example - /// ```no_run - /// # let (x, y) = (true, true); - /// if x { - /// if y { - /// // … - /// } - /// } - /// ``` - /// - /// Use instead: - /// ```no_run - /// # let (x, y) = (true, true); - /// if x && y { - /// // … - /// } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub COLLAPSIBLE_IF, - style, - "nested `if`s that can be collapsed (e.g., `if x { if y { ... } }`" -} - declare_clippy_lint! { /// ### What it does /// Checks for collapsible `else { if ... }` expressions @@ -80,6 +48,40 @@ "nested `else`-`if` expressions that can be collapsed (e.g., `else { if x { ... } }`)" } +declare_clippy_lint! { + /// ### What it does + /// Checks for nested `if` statements which can be collapsed + /// by `&&`-combining their conditions. + /// + /// ### Why is this bad? + /// Each `if`-statement adds one level of nesting, which + /// makes code look more complex than it really is. + /// + /// ### Example + /// ```no_run + /// # let (x, y) = (true, true); + /// if x { + /// if y { + /// // … + /// } + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// # let (x, y) = (true, true); + /// if x && y { + /// // … + /// } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub COLLAPSIBLE_IF, + style, + "nested `if`s that can be collapsed (e.g., `if x { if y { ... } }`" +} + +impl_lint_pass!(CollapsibleIf => [COLLAPSIBLE_ELSE_IF, COLLAPSIBLE_IF]); + pub struct CollapsibleIf { msrv: Msrv, lint_commented_code: bool, @@ -259,8 +261,6 @@ fn check_significant_tokens_and_expect_attrs( } } -impl_lint_pass!(CollapsibleIf => [COLLAPSIBLE_ELSE_IF, COLLAPSIBLE_IF]); - impl LateLintPass<'_> for CollapsibleIf { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if let ExprKind::If(cond, then, else_) = &expr.kind diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs index fd84ce70bd71..f9afdb0cabf9 100644 --- a/clippy_lints/src/collection_is_never_read.rs +++ b/clippy_lints/src/collection_is_never_read.rs @@ -41,6 +41,7 @@ nursery, "a collection is never queried" } + declare_lint_pass!(CollectionIsNeverRead => [COLLECTION_IS_NEVER_READ]); impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs index 19f62e8bf79c..509b345048c1 100644 --- a/clippy_lints/src/crate_in_macro_def.rs +++ b/clippy_lints/src/crate_in_macro_def.rs @@ -49,6 +49,7 @@ suspicious, "using `crate` in a macro definition" } + declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]); impl EarlyLintPass for CrateInMacroDef { diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 45de4035d992..525f3da3efb1 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -33,6 +33,8 @@ "`dbg!` macro is intended as a debugging tool" } +impl_lint_pass!(DbgMacro => [DBG_MACRO]); + pub struct DbgMacro { allow_dbg_in_tests: bool, /// Tracks the `dbg!` macro callsites that are already checked. @@ -41,8 +43,6 @@ pub struct DbgMacro { prev_ctxt: SyntaxContext, } -impl_lint_pass!(DbgMacro => [DBG_MACRO]); - impl DbgMacro { pub fn new(conf: &'static Conf) -> Self { DbgMacro { diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs index a48e4d2fbd57..2064d896861b 100644 --- a/clippy_lints/src/default.rs +++ b/clippy_lints/src/default.rs @@ -69,14 +69,14 @@ "binding initialized with Default should have its fields set in the initializer" } +impl_lint_pass!(Default => [DEFAULT_TRAIT_ACCESS, FIELD_REASSIGN_WITH_DEFAULT]); + #[derive(Default)] pub struct Default { // Spans linted by `field_reassign_with_default`. reassigned_linted: FxHashSet, } -impl_lint_pass!(Default => [DEFAULT_TRAIT_ACCESS, FIELD_REASSIGN_WITH_DEFAULT]); - impl<'tcx> LateLintPass<'tcx> for Default { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !expr.span.from_expansion() diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index 95f0afcc3d88..c831f96443c6 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -45,6 +45,7 @@ complexity, "unit structs can be constructed without calling `default`" } + declare_lint_pass!(DefaultConstructedUnitStructs => [ DEFAULT_CONSTRUCTED_UNIT_STRUCTS, ]); diff --git a/clippy_lints/src/default_instead_of_iter_empty.rs b/clippy_lints/src/default_instead_of_iter_empty.rs index 056e39c02af9..f041fc95fdd2 100644 --- a/clippy_lints/src/default_instead_of_iter_empty.rs +++ b/clippy_lints/src/default_instead_of_iter_empty.rs @@ -28,6 +28,7 @@ style, "check `std::iter::Empty::default()` and replace with `std::iter::empty()`" } + declare_lint_pass!(DefaultIterEmpty => [DEFAULT_INSTEAD_OF_ITER_EMPTY]); impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty { diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs index df6525ce040e..c04e07ee7f10 100644 --- a/clippy_lints/src/default_union_representation.rs +++ b/clippy_lints/src/default_union_representation.rs @@ -48,6 +48,7 @@ restriction, "unions without a `#[repr(C)]` attribute" } + declare_lint_pass!(DefaultUnionRepresentation => [DEFAULT_UNION_REPRESENTATION]); impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation { diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 8ad5d40b2dc7..920200bf8263 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -23,6 +23,29 @@ use rustc_span::{Span, Symbol}; use std::borrow::Cow; +declare_clippy_lint! { + /// ### What it does + /// Checks for dereferencing expressions which would be covered by auto-deref. + /// + /// ### Why is this bad? + /// This unnecessarily complicates the code. + /// + /// ### Example + /// ```no_run + /// let x = String::new(); + /// let y: &str = &*x; + /// ``` + /// Use instead: + /// ```no_run + /// let x = String::new(); + /// let y: &str = &x; + /// ``` + #[clippy::version = "1.64.0"] + pub EXPLICIT_AUTO_DEREF, + complexity, + "dereferencing when the compiler would automatically dereference" +} + declare_clippy_lint! { /// ### What it does /// Checks for explicit `deref()` or `deref_mut()` method calls. @@ -120,29 +143,6 @@ "`ref` binding to a reference" } -declare_clippy_lint! { - /// ### What it does - /// Checks for dereferencing expressions which would be covered by auto-deref. - /// - /// ### Why is this bad? - /// This unnecessarily complicates the code. - /// - /// ### Example - /// ```no_run - /// let x = String::new(); - /// let y: &str = &*x; - /// ``` - /// Use instead: - /// ```no_run - /// let x = String::new(); - /// let y: &str = &x; - /// ``` - #[clippy::version = "1.64.0"] - pub EXPLICIT_AUTO_DEREF, - complexity, - "dereferencing when the compiler would automatically dereference" -} - impl_lint_pass!(Dereferencing<'_> => [ EXPLICIT_AUTO_DEREF, EXPLICIT_DEREF_METHODS, diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 992ed320ce68..c04163b1c7a0 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -56,6 +56,8 @@ "manual implementation of the `Default` trait which is equal to a derive" } +impl_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]); + pub struct DerivableImpls { msrv: Msrv, } @@ -66,8 +68,6 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]); - fn is_path_self(e: &Expr<'_>) -> bool { if let ExprKind::Path(QPath::Resolved(_, p)) = e.kind { matches!(p.res, Res::SelfCtor(..) | Res::Def(DefKind::Ctor(..), _)) diff --git a/clippy_lints/src/derive/mod.rs b/clippy_lints/src/derive/mod.rs index a18c7533196e..fa1a7037154e 100644 --- a/clippy_lints/src/derive/mod.rs +++ b/clippy_lints/src/derive/mod.rs @@ -10,36 +10,6 @@ mod expl_impl_clone_on_copy; mod unsafe_derive_deserialize; -declare_clippy_lint! { - /// ### What it does - /// Lints against manual `PartialEq` implementations for types with a derived `Hash` - /// implementation. - /// - /// ### Why is this bad? - /// The implementation of these traits must agree (for - /// example for use with `HashMap`) so it’s probably a bad idea to use a - /// default-generated `Hash` implementation with an explicitly defined - /// `PartialEq`. In particular, the following must hold for any type: - /// - /// ```text - /// k1 == k2 ⇒ hash(k1) == hash(k2) - /// ``` - /// - /// ### Example - /// ```ignore - /// #[derive(Hash)] - /// struct Foo; - /// - /// impl PartialEq for Foo { - /// ... - /// } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub DERIVED_HASH_WITH_MANUAL_EQ, - correctness, - "deriving `Hash` but implementing `PartialEq` explicitly" -} - declare_clippy_lint! { /// ### What it does /// Lints against manual `PartialOrd` and `Ord` implementations for types with a derived `Ord` @@ -91,6 +61,68 @@ "deriving `Ord` but implementing `PartialOrd` explicitly" } +declare_clippy_lint! { + /// ### What it does + /// Checks for types that derive `PartialEq` and could implement `Eq`. + /// + /// ### Why is this bad? + /// If a type `T` derives `PartialEq` and all of its members implement `Eq`, + /// then `T` can always implement `Eq`. Implementing `Eq` allows `T` to be used + /// in APIs that require `Eq` types. It also allows structs containing `T` to derive + /// `Eq` themselves. + /// + /// ### Example + /// ```no_run + /// #[derive(PartialEq)] + /// struct Foo { + /// i_am_eq: i32, + /// i_am_eq_too: Vec, + /// } + /// ``` + /// Use instead: + /// ```no_run + /// #[derive(PartialEq, Eq)] + /// struct Foo { + /// i_am_eq: i32, + /// i_am_eq_too: Vec, + /// } + /// ``` + #[clippy::version = "1.63.0"] + pub DERIVE_PARTIAL_EQ_WITHOUT_EQ, + nursery, + "deriving `PartialEq` on a type that can implement `Eq`, without implementing `Eq`" +} + +declare_clippy_lint! { + /// ### What it does + /// Lints against manual `PartialEq` implementations for types with a derived `Hash` + /// implementation. + /// + /// ### Why is this bad? + /// The implementation of these traits must agree (for + /// example for use with `HashMap`) so it’s probably a bad idea to use a + /// default-generated `Hash` implementation with an explicitly defined + /// `PartialEq`. In particular, the following must hold for any type: + /// + /// ```text + /// k1 == k2 ⇒ hash(k1) == hash(k2) + /// ``` + /// + /// ### Example + /// ```ignore + /// #[derive(Hash)] + /// struct Foo; + /// + /// impl PartialEq for Foo { + /// ... + /// } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub DERIVED_HASH_WITH_MANUAL_EQ, + correctness, + "deriving `Hash` but implementing `PartialEq` explicitly" +} + declare_clippy_lint! { /// ### What it does /// Checks for explicit `Clone` implementations for `Copy` @@ -152,38 +184,6 @@ "deriving `serde::Deserialize` on a type that has methods using `unsafe`" } -declare_clippy_lint! { - /// ### What it does - /// Checks for types that derive `PartialEq` and could implement `Eq`. - /// - /// ### Why is this bad? - /// If a type `T` derives `PartialEq` and all of its members implement `Eq`, - /// then `T` can always implement `Eq`. Implementing `Eq` allows `T` to be used - /// in APIs that require `Eq` types. It also allows structs containing `T` to derive - /// `Eq` themselves. - /// - /// ### Example - /// ```no_run - /// #[derive(PartialEq)] - /// struct Foo { - /// i_am_eq: i32, - /// i_am_eq_too: Vec, - /// } - /// ``` - /// Use instead: - /// ```no_run - /// #[derive(PartialEq, Eq)] - /// struct Foo { - /// i_am_eq: i32, - /// i_am_eq_too: Vec, - /// } - /// ``` - #[clippy::version = "1.63.0"] - pub DERIVE_PARTIAL_EQ_WITHOUT_EQ, - nursery, - "deriving `PartialEq` on a type that can implement `Eq`, without implementing `Eq`" -} - declare_lint_pass!(Derive => [ DERIVED_HASH_WITH_MANUAL_EQ, DERIVE_ORD_XOR_PARTIAL_ORD, diff --git a/clippy_lints/src/disallowed_fields.rs b/clippy_lints/src/disallowed_fields.rs index f1136556e2ed..9873c32f427f 100644 --- a/clippy_lints/src/disallowed_fields.rs +++ b/clippy_lints/src/disallowed_fields.rs @@ -56,6 +56,8 @@ "declaration of a disallowed field use" } +impl_lint_pass!(DisallowedFields => [DISALLOWED_FIELDS]); + pub struct DisallowedFields { disallowed: DefIdMap<(&'static str, &'static DisallowedPath)>, } @@ -74,8 +76,6 @@ pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { } } -impl_lint_pass!(DisallowedFields => [DISALLOWED_FIELDS]); - impl<'tcx> LateLintPass<'tcx> for DisallowedFields { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let (id, span) = match &expr.kind { diff --git a/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs index 1c9c971730f6..7253b65e4337 100644 --- a/clippy_lints/src/disallowed_macros.rs +++ b/clippy_lints/src/disallowed_macros.rs @@ -63,6 +63,8 @@ "use of a disallowed macro" } +impl_lint_pass!(DisallowedMacros => [DISALLOWED_MACROS]); + pub struct DisallowedMacros { disallowed: DefIdMap<(&'static str, &'static DisallowedPath)>, seen: FxHashSet, @@ -125,8 +127,6 @@ fn check(&mut self, cx: &LateContext<'_>, span: Span, derive_src: Option [DISALLOWED_MACROS]); - impl LateLintPass<'_> for DisallowedMacros { fn check_crate(&mut self, cx: &LateContext<'_>) { // once we check a crate in the late pass we can emit the early pass lints diff --git a/clippy_lints/src/disallowed_methods.rs b/clippy_lints/src/disallowed_methods.rs index 58403ad19235..e2fd71b7d990 100644 --- a/clippy_lints/src/disallowed_methods.rs +++ b/clippy_lints/src/disallowed_methods.rs @@ -61,6 +61,8 @@ "use of a disallowed method call" } +impl_lint_pass!(DisallowedMethods => [DISALLOWED_METHODS]); + pub struct DisallowedMethods { disallowed: DefIdMap<(&'static str, &'static DisallowedPath)>, } @@ -84,8 +86,6 @@ pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { } } -impl_lint_pass!(DisallowedMethods => [DISALLOWED_METHODS]); - impl<'tcx> LateLintPass<'tcx> for DisallowedMethods { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if expr.span.desugaring_kind().is_some() { diff --git a/clippy_lints/src/disallowed_names.rs b/clippy_lints/src/disallowed_names.rs index 566aa12b08f5..1f658b2aa068 100644 --- a/clippy_lints/src/disallowed_names.rs +++ b/clippy_lints/src/disallowed_names.rs @@ -26,6 +26,8 @@ "usage of a disallowed/placeholder name" } +impl_lint_pass!(DisallowedNames => [DISALLOWED_NAMES]); + pub struct DisallowedNames { disallow: FxHashSet, } @@ -38,8 +40,6 @@ pub fn new(conf: &'static Conf) -> Self { } } -impl_lint_pass!(DisallowedNames => [DISALLOWED_NAMES]); - impl<'tcx> LateLintPass<'tcx> for DisallowedNames { fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { if let PatKind::Binding(.., ident, _) = pat.kind diff --git a/clippy_lints/src/disallowed_script_idents.rs b/clippy_lints/src/disallowed_script_idents.rs index 5b4fe2a6b803..4596d9457c0b 100644 --- a/clippy_lints/src/disallowed_script_idents.rs +++ b/clippy_lints/src/disallowed_script_idents.rs @@ -45,6 +45,8 @@ "usage of non-allowed Unicode scripts" } +impl_lint_pass!(DisallowedScriptIdents => [DISALLOWED_SCRIPT_IDENTS]); + pub struct DisallowedScriptIdents { whitelist: FxHashSet