From 691fbb4338031141dc3fdb144fa72a4ac146a2b0 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Mon, 20 Apr 2026 17:44:26 +0000 Subject: [PATCH 001/100] fix: `collapsible_match` suggests wrongly when match body has no braces --- clippy_lints/src/matches/collapsible_match.rs | 36 ++++++------- tests/ui/collapsible_match_fixable.fixed | 32 ++++++++++++ tests/ui/collapsible_match_fixable.rs | 32 ++++++++++++ tests/ui/collapsible_match_fixable.stderr | 50 ++++++++++++++++++- 4 files changed, 132 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs index d86b05e5c8824..5e82df4cb15e1 100644 --- a/clippy_lints/src/matches/collapsible_match.rs +++ b/clippy_lints/src/matches/collapsible_match.rs @@ -156,18 +156,6 @@ fn check_arm<'tcx>( 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 { @@ -175,11 +163,25 @@ fn check_arm<'tcx>( }; let (paren_start, inner_if_span, paren_end) = peel_parens(cx, 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()), - ]; + let mut sugg = vec![(inner.then.span.shrink_to_lo(), "=> ".to_string())]; + if matches!(outer_then_body.kind, ExprKind::Block(..)) { + 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() + }; + sugg.push((outer_arrow_end.to(outer_then_open_bracket), String::new())); + sugg.push((outer_then_closing_bracket, String::new())); + } else { + sugg.push((outer_arrow_end.until(inner_if), " ".to_string())); + } if let Some(outer_guard) = outer_guard { sugg.extend(parens_around(outer_guard)); diff --git a/tests/ui/collapsible_match_fixable.fixed b/tests/ui/collapsible_match_fixable.fixed index 8e5934d3693a3..03dbd35c5a48b 100644 --- a/tests/ui/collapsible_match_fixable.fixed +++ b/tests/ui/collapsible_match_fixable.fixed @@ -43,3 +43,35 @@ fn issue16875(a: Option<&str>, b: i32) -> i32 { } res } + +#[rustfmt::skip] +fn issue16716(n: u32) { + match n { + 0 | 1 if false => { println!("hello world"); }, + //~^ collapsible_match + _ => (), + } + + let opt = Some(1); + let _ = match opt { + Some(s) if s == 1 => { s } + //~^ collapsible_match + _ => 1, + }; +} + +#[rustfmt::skip] +fn issue16894() { + let a = 5_u8; + let b = a; + _ = match a { + 11 => 0, + 13 if a > b => { 1 }, _ => 0, + //~^ collapsible_match + }; + + _ = match a { + 11 => 0, 12 if a == b => { 1 }, _ => 0, + //~^ collapsible_match + }; +} diff --git a/tests/ui/collapsible_match_fixable.rs b/tests/ui/collapsible_match_fixable.rs index e2ccae4559612..a5d1bdee409a1 100644 --- a/tests/ui/collapsible_match_fixable.rs +++ b/tests/ui/collapsible_match_fixable.rs @@ -45,3 +45,35 @@ fn issue16875(a: Option<&str>, b: i32) -> i32 { } res } + +#[rustfmt::skip] +fn issue16716(n: u32) { + match n { + 0 | 1 => if false { println!("hello world"); }, + //~^ collapsible_match + _ => (), + } + + let opt = Some(1); + let _ = match opt { + Some(s) => if s == 1 { s } else { 1 } + //~^ collapsible_match + _ => 1, + }; +} + +#[rustfmt::skip] +fn issue16894() { + let a = 5_u8; + let b = a; + _ = match a { + 11 => 0, + 13 => if a > b { 1 } else { 0 }, _ => 0, + //~^ collapsible_match + }; + + _ = match a { + 11 => 0, 12 => if a == b { 1 } else { 0 }, _ => 0, + //~^ collapsible_match + }; +} diff --git a/tests/ui/collapsible_match_fixable.stderr b/tests/ui/collapsible_match_fixable.stderr index 0be47076fa472..ef078b2cb1fd9 100644 --- a/tests/ui/collapsible_match_fixable.stderr +++ b/tests/ui/collapsible_match_fixable.stderr @@ -64,5 +64,53 @@ LL | res = 1; LL ~ }, | -error: aborting due to 4 previous errors +error: this `if` can be collapsed into the outer `match` + --> tests/ui/collapsible_match_fixable.rs:52:18 + | +LL | 0 | 1 => if false { println!("hello world"); }, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: collapse nested if block + | +LL - 0 | 1 => if false { println!("hello world"); }, +LL + 0 | 1 if false => { println!("hello world"); }, + | + +error: this `if` can be collapsed into the outer `match` + --> tests/ui/collapsible_match_fixable.rs:59:20 + | +LL | Some(s) => if s == 1 { s } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: collapse nested if block + | +LL - Some(s) => if s == 1 { s } else { 1 } +LL + Some(s) if s == 1 => { s } + | + +error: this `if` can be collapsed into the outer `match` + --> tests/ui/collapsible_match_fixable.rs:71:15 + | +LL | 13 => if a > b { 1 } else { 0 }, _ => 0, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: collapse nested if block + | +LL - 13 => if a > b { 1 } else { 0 }, _ => 0, +LL + 13 if a > b => { 1 }, _ => 0, + | + +error: this `if` can be collapsed into the outer `match` + --> tests/ui/collapsible_match_fixable.rs:76:24 + | +LL | 11 => 0, 12 => if a == b { 1 } else { 0 }, _ => 0, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: collapse nested if block + | +LL - 11 => 0, 12 => if a == b { 1 } else { 0 }, _ => 0, +LL + 11 => 0, 12 if a == b => { 1 }, _ => 0, + | + +error: aborting due to 8 previous errors From 553132d0a8ff8aaa91d4e342a881939efe69a9e3 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Sun, 26 Apr 2026 20:35:42 +0000 Subject: [PATCH 002/100] `doc_markdown`: add common database engines to whitelist --- book/src/lint_configuration.md | 2 +- clippy_config/src/conf.rs | 1 + tests/ui/doc/doc-fixable.fixed | 1 + tests/ui/doc/doc-fixable.rs | 1 + tests/ui/doc/doc-fixable.stderr | 44 ++++++++++++++++----------------- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 64d0bf9b62f69..d4c3afa1d745e 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -609,7 +609,7 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "SQLite", "MySQL", "PostgreSQL", "MariaDB", "MongoDB", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 465e88a783ed8..8ed0a1f0334ce 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -38,6 +38,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", + "SQLite", "MySQL", "PostgreSQL", "MariaDB", "MongoDB", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index 570d8090f8e3e..3ab46106c8837 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -78,6 +78,7 @@ fn test_units() { /// PowerPC PowerShell WebAssembly /// NaN NaNs /// OAuth GraphQL +/// SQLite MySQL PostgreSQL MariaDB MongoDB /// OCaml /// OpenAL OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry /// OpenType diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index dd80bc4b25eeb..f4eac11cda47f 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -78,6 +78,7 @@ fn test_units() { /// PowerPC PowerShell WebAssembly /// NaN NaNs /// OAuth GraphQL +/// SQLite MySQL PostgreSQL MariaDB MongoDB /// OCaml /// OpenAL OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry /// OpenType diff --git a/tests/ui/doc/doc-fixable.stderr b/tests/ui/doc/doc-fixable.stderr index a04d06f6db1ab..d22a38a7a5f91 100644 --- a/tests/ui/doc/doc-fixable.stderr +++ b/tests/ui/doc/doc-fixable.stderr @@ -145,7 +145,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:91:5 + --> tests/ui/doc/doc-fixable.rs:92:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:109:5 + --> tests/ui/doc/doc-fixable.rs:110:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -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:114:8 + --> tests/ui/doc/doc-fixable.rs:115:8 | LL | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + /// ## `CamelCaseThing` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:118:7 + --> tests/ui/doc/doc-fixable.rs:119:7 | LL | /// # CamelCaseThing | ^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + /// # `CamelCaseThing` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:121:22 + --> tests/ui/doc/doc-fixable.rs:122: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:123:5 + --> tests/ui/doc/doc-fixable.rs:124: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:131:5 + --> tests/ui/doc/doc-fixable.rs:132: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:145:5 + --> tests/ui/doc/doc-fixable.rs:146: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:157:43 + --> tests/ui/doc/doc-fixable.rs:158: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:162:5 + --> tests/ui/doc/doc-fixable.rs:163: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:163:1 + --> tests/ui/doc/doc-fixable.rs:164: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:171:43 + --> tests/ui/doc/doc-fixable.rs:172: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:176:5 + --> tests/ui/doc/doc-fixable.rs:177: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:177:1 + --> tests/ui/doc/doc-fixable.rs:178: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:191:5 + --> tests/ui/doc/doc-fixable.rs:192: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:211:22 + --> tests/ui/doc/doc-fixable.rs:212: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:236:34 + --> tests/ui/doc/doc-fixable.rs:237: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:260:22 + --> tests/ui/doc/doc-fixable.rs:261: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:260:30 + --> tests/ui/doc/doc-fixable.rs:261: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:265:5 + --> tests/ui/doc/doc-fixable.rs:266:5 | LL | /// ABes | ^^^^ @@ -385,7 +385,7 @@ LL + /// `ABes` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:272:9 + --> tests/ui/doc/doc-fixable.rs:273: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:277:5 + --> tests/ui/doc/doc-fixable.rs:278:5 | LL | /// https://github.com/rust-lang/rust-clippy/pull/12836 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `` From 0e60608bd7e35f34d51141d429ef47ffb4083055 Mon Sep 17 00:00:00 2001 From: Aliaksei Semianiuk Date: Sat, 23 May 2026 23:45:39 +0500 Subject: [PATCH 003/100] Changelog for Clippy 1.96 --- CHANGELOG.md | 96 ++++++++++++++++++++++++++++++- clippy_lints/src/manual_pop_if.rs | 2 +- clippy_lints/src/methods/mod.rs | 2 +- 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f53143e564b6c..c71f092727856 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,101 @@ document. ## Unreleased / Beta / In Rust Nightly -[df995e...master](https://github.com/rust-lang/rust-clippy/compare/df995e...master) +[88f787...master](https://github.com/rust-lang/rust-clippy/compare/88f787...master) + +## Rust 1.96 + +Current stable, released 2026-05-28 + +[View all 48 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2026-02-24T12%3A30%3A17Z..2026-04-03T17%3A32%3A48Z+base%3Amaster) + +### New Lints + +* Added [`manual_noop_waker`] to `complexity` + [#16687](https://github.com/rust-lang/rust-clippy/pull/16687) +* Added [`manual_option_zip`] to `complexity` + [#16600](https://github.com/rust-lang/rust-clippy/pull/16600) +* Added [`manual_pop_if`] to `complexity` + [#16582](https://github.com/rust-lang/rust-clippy/pull/16582) + +### Enhancements + +* [`explicit_counter_loop`] suggest `(init..).take(n)` when loop variable is unused and range is + `0..n` + [#16658](https://github.com/rust-lang/rust-clippy/pull/16658) +* [`iter_kv_map`] handle identity map for `map` and `flat_map` + [#16743](https://github.com/rust-lang/rust-clippy/pull/16743) +* [`manual_noop_waker`] add an MSRV check + [#16850](https://github.com/rust-lang/rust-clippy/pull/16850) +* [`manual_pop_if`] in case the popped value is used, just emit the lint with no suggestion + [#16683](https://github.com/rust-lang/rust-clippy/pull/16683) +* [`manual_pop_if`] also cover `.pop().unwrap_unchecked()` + [#16683](https://github.com/rust-lang/rust-clippy/pull/16683) +* [`manual_pop_if`] detect manual implementations of `BinaryHeap::pop_if()` + [#16734](https://github.com/rust-lang/rust-clippy/pull/16734) +* [`unnecessary_option_map_or_else`] function definitions are no longer traversed when checking if + an expression is the identity + [#15889](https://github.com/rust-lang/rust-clippy/pull/15889) +* [`unnecessary_result_map_or_else`] function definitions are no longer traversed when checking if + an expression is the identity + [#15889](https://github.com/rust-lang/rust-clippy/pull/15889) +* [`question_mark`] fix suggestion-caused error caused by semicolon inference relying only on + parent-node shape + [#16656](https://github.com/rust-lang/rust-clippy/pull/16656) +* Format-related lints now handle `core::panic!` + [#16597](https://github.com/rust-lang/rust-clippy/pull/16597) +* [`explicit_counter_loop`] fix FN when the initializer is not integral + [#16647](https://github.com/rust-lang/rust-clippy/pull/16647) +* [`suboptimal_flops`] fix FN on add and sub assign + [#16625](https://github.com/rust-lang/rust-clippy/pull/16625) +* [`infinite_loop`] fix wrong suggestion to add `-> !` when the loop is inside a conditional branch + [#16619](https://github.com/rust-lang/rust-clippy/pull/16619) +* [`unnecessary_cast`] preserve parentheses in presence of cascaded casts + [#16483](https://github.com/rust-lang/rust-clippy/pull/16483) +* [`cmp_owned`] fix wrong suggestions on `PathBuf` + [#16628](https://github.com/rust-lang/rust-clippy/pull/16628) +* [`redundant_closure`] fix wrong suggestions when local is dereferenced to callable + [#16648](https://github.com/rust-lang/rust-clippy/pull/16648) + +### False Positive Fixes + +* [`collapsible_if`] fix FP when the inner if contains cfg + [#16757](https://github.com/rust-lang/rust-clippy/pull/16757) +* [`collapsible_match`] fix FP when the pat binding is moved or mutated + [#16708](https://github.com/rust-lang/rust-clippy/pull/16708) +* [`collapsible_match`] fix a case where a suggested transformation changes runtime behavior + [#16878](https://github.com/rust-lang/rust-clippy/pull/16878) +* [`match_same_arms`] fix FP with associated consts + [#16701](https://github.com/rust-lang/rust-clippy/pull/16701) +* [`semicolon_inside_block`] fix FP in `try` blocks where moving `;` changes the block's return + type and causes type errors + [#16697](https://github.com/rust-lang/rust-clippy/pull/16697) +* [`unnecessary_safety_comment`] fix FP on code blocks inside inner docs + [#16559](https://github.com/rust-lang/rust-clippy/pull/16559) +* [`doc_paragraphs_missing_punctuation`] no longer lints punctuated paragraphs with a trailing + emoji + [#16514](https://github.com/rust-lang/rust-clippy/pull/16514) + +### ICE Fixes + +* [`match_same_arms`] fix ICE in `match_same_arms` + [#16685](https://github.com/rust-lang/rust-clippy/pull/16685) +* [`nonminimal_bool`] fix ICE in `swap_binop()` by using the proper `TypeckResults` + [#16659](https://github.com/rust-lang/rust-clippy/pull/16659) +* Fix ICE when using the `min_generic_const_args` incomplete feature + [#16692](https://github.com/rust-lang/rust-clippy/pull/16692) + +### Documentation Improvements + +* [`similar_names`] changed the lint docs to reflect its actual behavior + [#16300](https://github.com/rust-lang/rust-clippy/pull/16300) + +### Performance Improvements + +* [`repeat_vec_with_capacity`] optimized by 96.876% (784M -> 24M instructions) + [#16756](https://github.com/rust-lang/rust-clippy/pull/16756) +* [`manual_is_ascii_check`] optimized by 97.125% (822M -> 23M instructions) + [#16755](https://github.com/rust-lang/rust-clippy/pull/16755) ## Rust 1.95 diff --git a/clippy_lints/src/manual_pop_if.rs b/clippy_lints/src/manual_pop_if.rs index f279f330a3c0b..f29403d1a9060 100644 --- a/clippy_lints/src/manual_pop_if.rs +++ b/clippy_lints/src/manual_pop_if.rs @@ -51,7 +51,7 @@ declare_clippy_lint! { /// deque.pop_back_if(|x| *x > 5); /// deque.pop_front_if(|x| *x > 5); /// ``` - #[clippy::version = "1.95.0"] + #[clippy::version = "1.96.0"] pub MANUAL_POP_IF, complexity, "manual implementation of `pop_if` methods" diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 9deda935028eb..3c6334d69453d 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2004,7 +2004,7 @@ declare_clippy_lint! { /// let b: Option = Some(2); /// let _ = a.zip(b); /// ``` - #[clippy::version = "1.95.0"] + #[clippy::version = "1.96.0"] pub MANUAL_OPTION_ZIP, complexity, "manual reimplementation of `Option::zip`" From 22833b477b5af79b2f10fb9aed3db48c19b2b8f2 Mon Sep 17 00:00:00 2001 From: relaxcn Date: Sun, 17 May 2026 02:00:03 +0800 Subject: [PATCH 004/100] Fix `explicit_counter_loop` FP when the counter is only modified inside the `else` block of `let...else` binding. --- clippy_lints/src/loops/utils.rs | 11 +++++++++++ tests/ui/explicit_counter_loop.rs | 21 +++++++++++++++++++++ tests/ui/explicit_counter_loop.stderr | 8 +++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/loops/utils.rs b/clippy_lints/src/loops/utils.rs index 86f4e606a176a..68694d21e3d8c 100644 --- a/clippy_lints/src/loops/utils.rs +++ b/clippy_lints/src/loops/utils.rs @@ -46,6 +46,17 @@ impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> { } impl<'tcx> Visitor<'tcx> for IncrementVisitor<'_, 'tcx> { + fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) { + if let Some(init) = l.init { + self.visit_expr(init); + if let Some(els) = l.els { + self.depth += 1; + self.visit_block(els); + self.depth -= 1; + } + } + } + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { // If node is a variable if let Some(def_id) = expr.res_local_id() { diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs index a8145d16c149b..730b67c3969ca 100644 --- a/tests/ui/explicit_counter_loop.rs +++ b/tests/ui/explicit_counter_loop.rs @@ -363,3 +363,24 @@ pub fn issue_16642() { base += 1; } } + +fn issue_17014(v: Vec) { + let mut count = 0; + for item in &v { + let Some(_) = Some(0) else { + count += 1; + continue; + }; + } + + let mut count = 0; + for item in &v { + //~^ explicit_counter_loop + let Some(_) = ({ + count += 1; + Some(0) + }) else { + continue; + }; + } +} diff --git a/tests/ui/explicit_counter_loop.stderr b/tests/ui/explicit_counter_loop.stderr index eb6be74c88055..d8a2e475da514 100644 --- a/tests/ui/explicit_counter_loop.stderr +++ b/tests/ui/explicit_counter_loop.stderr @@ -105,5 +105,11 @@ error: the variable `base` is used as a loop counter LL | for _ in 5..MAX { | ^^^^^^^^^^^^^^^ help: consider using: `for (base, _) in (100..).zip((5..MAX))` -error: aborting due to 17 previous errors +error: the variable `count` is used as a loop counter + --> tests/ui/explicit_counter_loop.rs:377:5 + | +LL | for item in &v { + | ^^^^^^^^^^^^^^ help: consider using: `for (count, item) in v.iter().enumerate()` + +error: aborting due to 18 previous errors From 42eae426550a23b2a505eac19b44530e35b05cd2 Mon Sep 17 00:00:00 2001 From: Gri-ffin Date: Mon, 25 May 2026 11:07:04 +0100 Subject: [PATCH 005/100] fix(result_large_err): trigger lint for async functions --- clippy_lints/src/functions/result.rs | 34 ++++++++++++++++++++-------- tests/ui/result_large_err.rs | 14 ++++++++++++ tests/ui/result_large_err.stderr | 18 ++++++++++++++- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/functions/result.rs b/clippy_lints/src/functions/result.rs index 829f054d8854e..ef5b5b9d334df 100644 --- a/clippy_lints/src/functions/result.rs +++ b/clippy_lints/src/functions/result.rs @@ -2,10 +2,12 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef; use rustc_errors::Diag; use rustc_hir as hir; +use rustc_infer::infer::TyCtxtInferExt as _; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::{self, Ty}; use rustc_span::def_id::DefIdSet; use rustc_span::{Span, sym}; +use rustc_trait_selection::error_reporting::InferCtxtErrorExt as _; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; use clippy_utils::ty::{AdtVariantInfo, approx_ty_size}; @@ -23,17 +25,31 @@ fn result_err_ty<'tcx>( ) -> Option<(&'tcx hir::Ty<'tcx>, Ty<'tcx>)> { if !item_span.in_external_macro(cx.sess().source_map()) && let hir::FnRetTy::Return(hir_ty) = decl.output - && let ty = cx - .tcx - .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(id).instantiate_identity().skip_norm_wip().output()) - && ty.is_diag_item(cx, sym::Result) - && let ty::Adt(_, args) = ty.kind() { - let err_ty = args.type_at(1); - Some((hir_ty, err_ty)) - } else { - None + let mut ty = cx + .tcx + .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(id).instantiate_identity().skip_norm_wip().output()); + + // for async functions, peel through `impl Future` to get `T` + if cx.tcx.ty_is_opaque_future(ty) + && let Some(future_output_ty) = cx + .tcx + .infer_ctxt() + .build(cx.typing_mode()) + .err_ctxt() + .get_impl_future_output_ty(ty) + { + ty = future_output_ty; + } + + if ty.is_diag_item(cx, sym::Result) + && let ty::Adt(_, args) = ty.kind() + { + let err_ty = args.type_at(1); + return Some((hir_ty, err_ty)); + } } + None } pub(super) fn check_item<'tcx>( diff --git a/tests/ui/result_large_err.rs b/tests/ui/result_large_err.rs index b4ad050df3b79..0056c54ff5d42 100644 --- a/tests/ui/result_large_err.rs +++ b/tests/ui/result_large_err.rs @@ -150,3 +150,17 @@ fn issue16249() { let closure = || Ok::<(), Large>(()); //~^ result_large_err } + +pub async fn async_large_err() -> Result<(), [u8; 512]> { + //~^ result_large_err + Ok(()) +} + +pub async fn async_small_err() -> Result<(), u128> { + Ok(()) +} + +pub async fn async_struct_error() -> Result<(), FullyDefinedLargeError> { + //~^ result_large_err + Ok(()) +} diff --git a/tests/ui/result_large_err.stderr b/tests/ui/result_large_err.stderr index fd39179c61cb5..653b7e354f431 100644 --- a/tests/ui/result_large_err.stderr +++ b/tests/ui/result_large_err.stderr @@ -120,5 +120,21 @@ LL | let closure = || Ok::<(), Large>(()); | = help: try reducing the size of `[u8; 1024]`, for example by boxing large elements or replacing it with `Box<[u8; 1024]>` -error: aborting due to 14 previous errors +error: the `Err`-variant returned from this function is very large + --> tests/ui/result_large_err.rs:154:35 + | +LL | pub async fn async_large_err() -> Result<(), [u8; 512]> { + | ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes + | + = help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>` + +error: the `Err`-variant returned from this function is very large + --> tests/ui/result_large_err.rs:163:38 + | +LL | pub async fn async_struct_error() -> Result<(), FullyDefinedLargeError> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 240 bytes + | + = help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box` + +error: aborting due to 16 previous errors From 87bfa9bc9da4e9a416d06ee7dd3c2c60cc130431 Mon Sep 17 00:00:00 2001 From: Gri-ffin Date: Mon, 25 May 2026 11:09:23 +0100 Subject: [PATCH 006/100] test(len_without_is_empty): expect result_unit_err on async Result<_, ()> --- tests/ui/len_without_is_empty.rs | 2 ++ tests/ui/len_without_is_empty.stderr | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/tests/ui/len_without_is_empty.rs b/tests/ui/len_without_is_empty.rs index 509348628dd67..979739e73a5ea 100644 --- a/tests/ui/len_without_is_empty.rs +++ b/tests/ui/len_without_is_empty.rs @@ -351,6 +351,7 @@ impl AsyncResultLenWithoutIsEmpty { pub async fn len(&self) -> Result { //~^ len_without_is_empty + //~| result_unit_err Err(()) } @@ -364,6 +365,7 @@ impl AsyncOptionLen { } pub async fn len(&self) -> Result { + //~^ result_unit_err Err(()) } diff --git a/tests/ui/len_without_is_empty.stderr b/tests/ui/len_without_is_empty.stderr index 748a55712f882..1f96d85fa59e4 100644 --- a/tests/ui/len_without_is_empty.stderr +++ b/tests/ui/len_without_is_empty.stderr @@ -143,11 +143,27 @@ error: struct `AsyncResultLenWithoutIsEmpty` has a public `len` method, but no ` LL | pub async fn len(&self) -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: this returns a `Result<_, ()>` + --> tests/ui/len_without_is_empty.rs:352:5 + | +LL | pub async fn len(&self) -> Result { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a custom `Error` type instead + +error: this returns a `Result<_, ()>` + --> tests/ui/len_without_is_empty.rs:367:5 + | +LL | pub async fn len(&self) -> Result { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a custom `Error` type instead + error: type `Alias2` has a public `len` method, but no `is_empty` method - --> tests/ui/len_without_is_empty.rs:469:5 + --> tests/ui/len_without_is_empty.rs:471:5 | LL | pub fn len(&self) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 16 previous errors +error: aborting due to 18 previous errors From d082244b672eb7daffaf4802184895d12a6db903 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Wed, 27 May 2026 16:40:54 -0700 Subject: [PATCH 007/100] Improve excessive bools docs Clarify the rationale for fn_params_excessive_bools, document the main replacement patterns, and note that max-fn-params-bools accepts 0 to lint any bool parameter. --- book/src/lint_configuration.md | 3 +- clippy_config/src/conf.rs | 3 +- clippy_lints/src/excessive_bools.rs | 48 +++++++++++++++++++---------- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 64d0bf9b62f69..be7046e399fe9 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -780,7 +780,8 @@ be filtering for common types. ## `max-fn-params-bools` -The maximum number of bool parameters a function can have +The maximum number of bool parameters a function can have. +Use `0` to lint on any function with a bool parameter. **Default Value:** `3` diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 465e88a783ed8..ac681fad7e716 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -713,7 +713,8 @@ define_Conf! { /// be filtering for common types. #[lints(manual_let_else)] matches_for_let_else: MatchLintBehaviour = MatchLintBehaviour::WellKnownTypes, - /// The maximum number of bool parameters a function can have + /// The maximum number of bool parameters a function can have. + /// Use `0` to lint on any function with a bool parameter. #[lints(fn_params_excessive_bools)] max_fn_params_bools: u64 = 3, /// The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs index 65d0ff9b543f8..b44497ded301e 100644 --- a/clippy_lints/src/excessive_bools.rs +++ b/clippy_lints/src/excessive_bools.rs @@ -11,35 +11,51 @@ use rustc_span::def_id::LocalDefId; declare_clippy_lint! { /// ### What it does - /// Checks for excessive use of - /// bools in function definitions. + /// Checks for excessive use of bools in function declarations. /// /// ### Why is this bad? - /// Calls to such functions - /// are confusing and error prone, because it's - /// hard to remember argument order and you have - /// no type system support to back you up. Using - /// two-variant enums instead of bools often makes - /// API easier to use. + /// Boolean parameters obscure meaning at the call site. The reader has to + /// remember what each `true` or `false` means and which position each flag + /// belongs in, with no help from the type system. + /// + /// The best replacement depends on what role the bool plays: + /// + /// - Use a two-variant enum when one parameter selects a mode. + /// - Split one function into two named operations when the choices are + /// distinct actions. + /// - Group multiple related flags into a struct or options type when they + /// travel together. + /// - Move the setting onto `self` or an existing config/context parameter + /// when it is really part of the surrounding state. + /// + /// This optimizes for readability of the calling code, which future readers + /// encounter more often than the function declaration. + /// + /// The `max-fn-params-bools` configuration accepts `0`, which lints on any + /// function with a bool parameter. /// /// ### Example /// ```rust,ignore - /// fn f(is_round: bool, is_hot: bool) { ... } + /// fn render_document(show_hidden: bool, is_draft: bool) { ... } /// ``` /// /// Use instead: /// ```rust,ignore - /// enum Shape { - /// Round, - /// Spiky, + /// enum Visibility { + /// ShowHidden, + /// HideHidden, /// } /// - /// enum Temperature { - /// Hot, - /// IceCold, + /// enum DocumentKind { + /// Draft, + /// Final, /// } /// - /// fn f(shape: Shape, temperature: Temperature) { ... } + /// fn render_document(visibility: Visibility, kind: DocumentKind) { ... } + /// + /// // or split the operation when the choices are distinct + /// fn render_draft() { ... } + /// fn render_final() { ... } /// ``` #[clippy::version = "1.43.0"] pub FN_PARAMS_EXCESSIVE_BOOLS, From e8fdfcc086ca51330b35ce8f8124884c2755ce13 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 28 May 2026 18:01:02 +0200 Subject: [PATCH 008/100] Merge commit '9fca3bc9fc2bc83c60bde26d18ed68f11564b228' into clippy-subtree-update --- CHANGELOG.md | 2 + CONTRIBUTING.md | 17 +- Cargo.toml | 2 +- book/src/configuration.md | 8 +- book/src/development/emitting_lints.md | 65 ++++++- clippy_config/Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/attrs/useless_attribute.rs | 2 +- clippy_lints/src/booleans.rs | 7 +- clippy_lints/src/collapsible_if.rs | 2 + clippy_lints/src/dbg_macro.rs | 92 +++++---- clippy_lints/src/declared_lints.rs | 2 + clippy_lints/src/doc/mod.rs | 19 +- clippy_lints/src/duplicate_mod.rs | 2 +- clippy_lints/src/duration_suboptimal_units.rs | 22 ++- clippy_lints/src/format.rs | 11 +- clippy_lints/src/format_args.rs | 24 ++- clippy_lints/src/loops/manual_memcpy.rs | 42 +++-- clippy_lints/src/macro_metavars_in_unsafe.rs | 3 +- clippy_lints/src/methods/map_flatten.rs | 2 +- clippy_lints/src/methods/map_or_identity.rs | 36 ++++ clippy_lints/src/methods/mod.rs | 54 +++++- .../src/methods/unnecessary_literal_unwrap.rs | 2 +- .../src/operators/arithmetic_side_effects.rs | 12 +- clippy_lints/src/operators/manual_midpoint.rs | 30 ++- clippy_lints/src/operators/mod.rs | 13 +- clippy_lints/src/ranges.rs | 13 +- .../needless_return_with_question_mark.rs | 2 +- clippy_lints/src/unit_types/unit_arg.rs | 2 +- clippy_lints/src/unused_async.rs | 158 +++++++++++++++- clippy_utils/Cargo.toml | 2 +- clippy_utils/README.md | 2 +- clippy_utils/src/ast_utils/mod.rs | 106 +++++------ clippy_utils/src/lib.rs | 2 +- clippy_utils/src/source.rs | 37 ++-- clippy_utils/src/ty/mod.rs | 4 +- declare_clippy_lint/Cargo.toml | 2 +- rust-toolchain.toml | 2 +- tests/ui-cargo/feature_name/fail/src/main.rs | 3 +- tests/ui-cargo/feature_name/pass/src/main.rs | 3 +- .../config_fail/src/main.rs | 1 - .../ordering_good.rs | 1 - .../ordering_good_var_1.rs | 1 - .../ordering_mixed.default.stderr | 60 +++--- .../ordering_mixed.default_exp.stderr | 60 +++--- .../ordering_mixed.ord_within.stderr | 84 ++++----- .../ordering_mixed.rs | 1 - .../ordering_mixed_var_1.rs | 1 - .../ordering_mixed_var_1.var_1.stderr | 32 ++-- .../ordering_only_enum.only_enum.stderr | 4 +- .../ordering_only_enum.rs | 1 - .../ordering_only_impl.only_impl.stderr | 12 +- .../ordering_only_impl.rs | 1 - .../ordering_only_trait.only_trait.stderr | 12 +- .../ordering_only_trait.rs | 1 - .../selective_ordering.default.stderr | 6 +- .../selective_ordering.ord_in_2.stderr | 12 +- .../selective_ordering.ord_in_3.stderr | 6 +- .../selective_ordering.ord_within.stderr | 20 +- .../selective_ordering.rs | 1 - .../array_size_threshold.rs | 1 - .../array_size_threshold.stderr | 4 +- tests/ui-toml/dbg_macro/dbg_macro.fixed | 2 +- tests/ui-toml/dbg_macro/dbg_macro.rs | 2 +- .../disallowed_macros/disallowed_macros.rs | 2 - .../disallowed_macros.stderr | 32 ++-- .../excessive_nesting/excessive_nesting.rs | 13 +- .../excessive_nesting.stderr | 74 ++++---- .../excessive_precision.fixed | 8 +- .../excessive_precision.rs | 8 +- .../excessive_precision.stderr | 8 +- tests/ui-toml/ifs_same_cond/ifs_same_cond.rs | 2 +- .../impl_trait_in_params.rs | 2 +- .../item_name_repetitions.rs | 1 - .../item_name_repetitions.stderr | 2 +- .../allowed_prefixes/item_name_repetitions.rs | 1 - .../item_name_repetitions.stderr | 2 +- .../item_name_repetitions.rs | 1 - .../item_name_repetitions.stderr | 2 +- .../min_ident_chars/auxiliary/extern_types.rs | 2 +- .../min_ident_chars/min_ident_chars.rs | 2 +- .../min_rust_version/min_rust_version.fixed | 4 +- .../min_rust_version/min_rust_version.rs | 4 +- .../needless_raw_string_hashes.fixed | 2 +- .../needless_raw_string_hashes.rs | 2 +- tests/ui-toml/print_macro/print_macro.rs | 3 +- tests/ui-toml/print_macro/print_macro.stderr | 4 +- tests/ui-toml/private-doc-errors/doc_lints.rs | 4 +- .../private-doc-errors/doc_lints.stderr | 10 +- tests/ui/arithmetic_side_effects.rs | 20 ++ tests/ui/assign_ops.fixed | 6 +- tests/ui/assign_ops.rs | 6 +- tests/ui/collapsible_else_if.fixed | 29 +++ tests/ui/collapsible_else_if.rs | 33 ++++ tests/ui/collapsible_else_if.stderr | 38 +++- tests/ui/derivable_impls.fixed | 4 +- tests/ui/derivable_impls.rs | 4 +- tests/ui/derivable_impls_derive_const.rs | 4 +- tests/ui/derivable_impls_derive_const.stderr | 4 +- tests/ui/derive.rs | 1 + tests/ui/derive.stderr | 11 +- tests/ui/doc_unsafe.rs | 42 +++++ tests/ui/doc_unsafe.stderr | 61 +++++- tests/ui/double_ended_iterator_last.fixed | 4 +- tests/ui/double_ended_iterator_last.rs | 4 +- tests/ui/duplicated_attributes.rs | 6 +- tests/ui/duration_suboptimal_units.fixed | 54 +++++- tests/ui/duration_suboptimal_units.rs | 60 ++++-- tests/ui/duration_suboptimal_units.stderr | 174 +++++++++++++----- ...duration_suboptimal_units_days_weeks.fixed | 10 +- .../duration_suboptimal_units_days_weeks.rs | 6 + ...uration_suboptimal_units_days_weeks.stderr | 36 ++-- .../empty_enum_variants_with_brackets.fixed | 2 +- tests/ui/empty_enum_variants_with_brackets.rs | 2 +- tests/ui/equatable_if_let_const_cmp.fixed | 2 +- tests/ui/equatable_if_let_const_cmp.rs | 2 +- tests/ui/format.fixed | 39 ++++ tests/ui/format.rs | 39 ++++ tests/ui/format.stderr | 56 ++++-- tests/ui/ignored_unit_patterns.fixed | 4 +- tests/ui/ignored_unit_patterns.rs | 4 +- tests/ui/manual_midpoint.fixed | 24 ++- tests/ui/manual_midpoint.rs | 24 ++- tests/ui/manual_midpoint.stderr | 38 +++- tests/ui/manual_ok_or.fixed | 10 +- tests/ui/manual_ok_or.rs | 10 +- tests/ui/map_or_identity.fixed | 64 +++++++ tests/ui/map_or_identity.rs | 64 +++++++ tests/ui/map_or_identity.stderr | 88 +++++++++ .../ui/missing_const_for_fn/const_trait.fixed | 2 +- tests/ui/missing_const_for_fn/const_trait.rs | 2 +- tests/ui/mixed_attributes_style.rs | 14 +- .../needless_return_with_question_mark.fixed | 10 + .../ui/needless_return_with_question_mark.rs | 10 + .../needless_return_with_question_mark.stderr | 8 +- tests/ui/option_if_let_else.fixed | 3 +- tests/ui/option_if_let_else.rs | 3 +- tests/ui/option_if_let_else.stderr | 58 +++--- tests/ui/or_fun_call.fixed | 1 + tests/ui/or_fun_call.rs | 1 + tests/ui/or_fun_call.stderr | 98 +++++----- tests/ui/range_contains.fixed | 23 ++- tests/ui/range_contains.rs | 23 ++- tests/ui/range_contains.stderr | 40 ++-- tests/ui/unused_async_trait_impl.fixed | 109 +++++++++++ tests/ui/unused_async_trait_impl.rs | 109 +++++++++++ tests/ui/unused_async_trait_impl.stderr | 94 ++++++++++ tests/ui/unused_async_trait_impl_no_std.fixed | 15 ++ tests/ui/unused_async_trait_impl_no_std.rs | 15 ++ .../ui/unused_async_trait_impl_no_std.stderr | 21 +++ tests/ui/unused_format_specs.1.fixed | 2 +- tests/ui/unused_format_specs.2.fixed | 2 +- tests/ui/unused_format_specs.rs | 2 +- tests/ui/unused_format_specs_width.rs | 36 ++-- tests/ui/useless_borrows_in_formatting.fixed | 5 +- tests/ui/useless_borrows_in_formatting.rs | 5 +- tests/ui/useless_borrows_in_formatting.stderr | 94 ++++++---- triagebot.toml | 4 +- 158 files changed, 2388 insertions(+), 844 deletions(-) create mode 100644 clippy_lints/src/methods/map_or_identity.rs create mode 100644 tests/ui/map_or_identity.fixed create mode 100644 tests/ui/map_or_identity.rs create mode 100644 tests/ui/map_or_identity.stderr create mode 100644 tests/ui/unused_async_trait_impl.fixed create mode 100644 tests/ui/unused_async_trait_impl.rs create mode 100644 tests/ui/unused_async_trait_impl.stderr create mode 100644 tests/ui/unused_async_trait_impl_no_std.fixed create mode 100644 tests/ui/unused_async_trait_impl_no_std.rs create mode 100644 tests/ui/unused_async_trait_impl_no_std.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index f53143e564b6c..682e0c7af6d0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6947,6 +6947,7 @@ Released 2018-09-13 [`map_err_ignore`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_err_ignore [`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten [`map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_identity +[`map_or_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_or_identity [`map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or [`map_with_unused_argument_over_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_with_unused_argument_over_ranges [`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref @@ -7375,6 +7376,7 @@ Released 2018-09-13 [`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice [`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice [`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async +[`unused_async_trait_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async_trait_impl [`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect [`unused_enumerate_index`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_enumerate_index [`unused_format_specs`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_format_specs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f7f0a1ce2499a..8aeba28494cb3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -93,20 +93,9 @@ an AST expression). ## Getting code-completion for rustc internals to work ### RustRover -Unfortunately, [`RustRover`][RustRover_homepage] does not (yet?) understand how Clippy uses compiler-internals -using `extern crate` and it also needs to be able to read the source files of the rustc-compiler which are not -available via a `rustup` component at the time of writing. -To work around this, you need to have a copy of the [rustc-repo][rustc_repo] available which can be obtained via -`git clone https://github.com/rust-lang/rust/`. -Then you can run a `cargo dev` command to automatically make Clippy use the rustc-repo via path-dependencies -which `RustRover` will be able to understand. -Run `cargo dev setup intellij --repo-path ` where `` is a path to the rustc repo -you just cloned. -The command will add path-dependencies pointing towards rustc-crates inside the rustc repo to -Clippy's `Cargo.toml`s and should allow `RustRover` to understand most of the types that Clippy uses. -Just make sure to remove the dependencies again before finally making a pull request! - -[rustc_repo]: https://github.com/rust-lang/rust/ +Since [`RustRover`][RustRover_homepage] 2026.1, no additional setup is required. +Just open the project in RustRover as usual. + [RustRover_homepage]: https://www.jetbrains.com/rust/ ### Rust Analyzer diff --git a/Cargo.toml b/Cargo.toml index ca80c3fadc226..b93a3f1cbe9c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.97" +version = "0.1.98" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/book/src/configuration.md b/book/src/configuration.md index 45faf039dd670..aff9222ea6066 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -123,7 +123,13 @@ fn main() { You can also omit the patch version when specifying the MSRV, so `msrv = 1.30` is equivalent to `msrv = 1.30.0`. -Note: `custom_inner_attributes` is an unstable feature, so it has to be enabled explicitly. +> **Note:** Some lints change their behavior depending on the configured MSRV. +> In some cases, Clippy may suppress a lint entirely to avoid suggesting APIs or +> syntax unavailable for the configured MSRV. +> In other cases, Clippy may emit the lint but choose an older compatible suggestion. + +> **Note:** `custom_inner_attributes` is an unstable feature, so it has to be +> enabled explicitly. Lints that recognize this configuration option can be found [here](https://rust-lang.github.io/rust-clippy/master/index.html#msrv) diff --git a/book/src/development/emitting_lints.md b/book/src/development/emitting_lints.md index d70f4fc17ebf0..9ce56f0fc9dcf 100644 --- a/book/src/development/emitting_lints.md +++ b/book/src/development/emitting_lints.md @@ -88,6 +88,8 @@ LL | for _ in 1..1 + 1 {} | ^^^^^^^^ help: use: `1..=1` ``` +### Applicability + **Not all suggestions are always right**, some of them require human supervision, that's why we have [Applicability][applicability]. @@ -105,14 +107,18 @@ impl<'tcx> LateLintPass<'tcx> for LintName { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // Imagine that `some_lint_expr_logic` checks for requirements for emitting the lint if some_lint_expr_logic(expr) { - span_lint_and_sugg( // < Note this change + span_lint_and_then( // < Note this change cx, LINT_NAME, - span, + expr.span, "message on why the lint is emitted", - "use", - format!("foo + {} * bar", snippet(cx, expr.span, "")), // < Suggestion - Applicability::MachineApplicable, + |diag| { + // v Build and emit the suggestion + let mut app = Applicability::MachineApplicable; + let expr_snippet = snippet_with_applicability(cx, expr.span, "_", &mut app); + let sugg = format!("foo + {expr_snippet} * bar"); + diag.span_suggestion(expr.span, "use", sugg, app); + } ); } } @@ -120,8 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for LintName { ``` Suggestions generally use the [`format!`][format_macro] macro to interpolate the -old values with the new ones. To get code snippets, use one of the `snippet*` -functions from `clippy_utils::source`. +old values with the new ones. For information on getting code snippets, see [Snippets](emitting_lints.md#snippets). ## How to choose between notes, help messages and suggestions @@ -183,13 +188,50 @@ error: This `.fold` can be more succinctly expressed as `.any` | ``` -### Snippets +## Snippets Snippets are pieces of the source code (as a string), they are extracted -generally using the [`snippet`][snippet_fn] function. +generally using the various `snippet_*` functions from [`clippy_utils::source`][]. + +If you're using the snippets _not_ to build a suggestion, it's usually +enough to use [`snippet`][snippet_fn] -- it accepts the span of the item, and +also a fallback string (see [Fallback string](emitting_lints.md#fallback-string)). For example, if you want to know how an item looks (and you know the item's -span), you could use `snippet(cx, span, "..")`. +span), you could use `snippet(cx, span, "_")`. + +If you do use the snippet for a suggestion, it's recommended to use +[`snippet_with_applicability`] instead. This is so that Clippy can reduce the +[applicability](emitting_lints.md#applicability) of the suggestion in case it couldn't extract +the snippet "cleanly" -- see the function's documentation for more information. + +It's often necessary to create multiple snippets to build a suggestion, in which +case you'll have the following pattern: + +```rust +// inside `span_lint_and_then` + +// 1. Create initial applicability. +let mut app = Applicability::MachineApplicable; + +// 2. Use it to create all the snippets +let foo_snippet = snippet_with_applicability(cx, foo.span, "_", &mut app); +let bar_snippet = snippet_with_applicability(cx, bar.span, "_", &mut app); +let sugg = format!("{foo_snippet} + {bar_snippet}"); // or whatever + +// 3. Use it to emit the final suggestion +diag.span_suggestion(span, msg, sugg, app); +``` + +### Fallback string +This is the string that is used for the snippet when the source code that the +span points to is unavailable. That mostly only happens when proc-macros +mishandle spans -- see [the section on proc-macros][proc-macro-spans]. + +Most of the time, the snippets in a suggestion come from a (span of a) single +expression, and so `"_"` is an appropriate fallback string. If you instead +find yourself suggesting to insert multiple statements, or a block--basically +anything "big"--then consider using `".."` instead. ## Final: Run UI Tests to Emit the Lint @@ -210,8 +252,11 @@ cover in the next chapters. [`span_lint_and_help`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_help.html [`span_lint_and_sugg`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_sugg.html [`span_lint_and_then`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_then.html +[`clippy_utils::source`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/index.html [range_plus_one]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one [inclusive_range]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html [applicability]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_errors/enum.Applicability.html [snippet_fn]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/source/fn.snippet.html +[`snippet_with_applicability`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/source/fn.snippet_with_applicability.html +[proc-macro-spans]: macro_expansions.html#the-is_from_proc_macro-function [format_macro]: https://doc.rust-lang.org/std/macro.format.html diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index 3d5b425ac530d..9154439defc1a 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.97" +version = "0.1.98" edition = "2024" publish = false diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 52b85103209b4..2e4191f25ce24 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.97" +version = "0.1.98" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_lints/src/attrs/useless_attribute.rs b/clippy_lints/src/attrs/useless_attribute.rs index c025b47dc787d..2d56086a96024 100644 --- a/clippy_lints/src/attrs/useless_attribute.rs +++ b/clippy_lints/src/attrs/useless_attribute.rs @@ -15,7 +15,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { return; } if let Some(lint_list) = &attr.meta_item_list() - && attr.name().is_some_and(|name| is_lint_level(name)) + && attr.name().is_some_and(is_lint_level) { for lint in lint_list { match item.kind { diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index ecce0c90aa68b..2f2382d9a50ed 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -612,7 +612,12 @@ impl<'tcx> NonminimalBoolVisitor<'_, 'tcx> { } } let nonminimal_bool_lint = |mut suggestions: Vec<_>| { - if !self.cx.tcx.lint_level_spec_at_node(NONMINIMAL_BOOL, e.hir_id).is_allow() { + if !self + .cx + .tcx + .lint_level_spec_at_node(NONMINIMAL_BOOL, e.hir_id) + .is_allow() + { suggestions.sort(); span_lint_hir_and_then( self.cx, diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 3b9e0171f587d..baa13b2133277 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -140,6 +140,8 @@ impl CollapsibleIf { // Prevent "elseif" // Check that the "else" is followed by whitespace + // Note: We intentionally use char::is_whitespace instead of rustc_lexer::is_whitespace here to + // avoid visual issues with zero-width spaces. See ui tests. let requires_space = snippet(cx, up_to_else, "..").ends_with(|c: char| !c.is_whitespace()); let mut applicability = Applicability::MachineApplicable; diag.span_suggestion( diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 29d0b47002679..adc1c0a6c577c 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -75,53 +75,51 @@ impl LateLintPass<'_> for DbgMacro { "the `dbg!` macro is intended as a debugging tool", |diag| { let mut applicability = Applicability::MachineApplicable; - let (sugg_span, suggestion) = match is_async_move_desugar(expr) - .unwrap_or(expr) - .peel_drop_temps() - .kind - { - // dbg!() - ExprKind::Block(..) => { - // If the `dbg!` macro is a "free" statement and not contained within other expressions, - // remove the whole statement. - if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id) - && let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span) - { - (macro_call.span.to(semi_span), String::new()) - } else { - (macro_call.span, String::from("()")) - } - }, - // dbg!(1) - ExprKind::Match(val, ..) => ( - macro_call.span, - snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability) - .to_string(), - ), - // dbg!(2, 3) - ExprKind::Tup( - [ - Expr { - kind: ExprKind::Match(first, ..), - .. - }, - .., - Expr { - kind: ExprKind::Match(last, ..), - .. - }, - ], - ) => { - let snippet = snippet_with_applicability( - cx, - first.span.source_callsite().to(last.span.source_callsite()), - "..", - &mut applicability, - ); - (macro_call.span, format!("({snippet})")) - }, - _ => unreachable!(), - }; + let (sugg_span, suggestion) = + match is_async_move_desugar(expr).unwrap_or(expr).peel_drop_temps().kind { + // dbg!() + ExprKind::Block(..) => { + // If the `dbg!` macro is a "free" statement and not contained within other expressions, + // remove the whole statement. + if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id) + && let Some(semi_span) = + cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span) + { + (macro_call.span.to(semi_span), String::new()) + } else { + (macro_call.span, String::from("()")) + } + }, + // dbg!(1) + ExprKind::Match(val, ..) => ( + macro_call.span, + snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability) + .to_string(), + ), + // dbg!(2, 3) + ExprKind::Tup( + [ + Expr { + kind: ExprKind::Match(first, ..), + .. + }, + .., + Expr { + kind: ExprKind::Match(last, ..), + .. + }, + ], + ) => { + let snippet = snippet_with_applicability( + cx, + first.span.source_callsite().to(last.span.source_callsite()), + "..", + &mut applicability, + ); + (macro_call.span, format!("({snippet})")) + }, + _ => unreachable!(), + }; diag.span_suggestion( sugg_span, diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 4218d1fdc2901..b5047c628d0f0 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -435,6 +435,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::methods::MAP_ERR_IGNORE_INFO, crate::methods::MAP_FLATTEN_INFO, crate::methods::MAP_IDENTITY_INFO, + crate::methods::MAP_OR_IDENTITY_INFO, crate::methods::MAP_UNWRAP_OR_INFO, crate::methods::MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES_INFO, crate::methods::MUT_MUTEX_LOCK_INFO, @@ -783,6 +784,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO, crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO, crate::unused_async::UNUSED_ASYNC_INFO, + crate::unused_async::UNUSED_ASYNC_TRAIT_IMPL_INFO, crate::unused_io_amount::UNUSED_IO_AMOUNT_INFO, crate::unused_peekable::UNUSED_PEEKABLE_INFO, crate::unused_result_ok::UNUSED_RESULT_OK_INFO, diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index e772c20abf94d..1da0a010668bb 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -6,7 +6,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_the use clippy_utils::{is_entrypoint_fn, is_trait_impl_item}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{Attribute, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; +use rustc_hir::{Attribute, FieldDef, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_resolve::rustdoc::pulldown_cmark::Event::{ Code, DisplayMath, End, FootnoteReference, HardBreak, Html, InlineHtml, InlineMath, Rule, SoftBreak, Start, @@ -754,6 +754,23 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { }; match cx.tcx.hir_node(cx.last_node_with_lint_attrs) { + Node::Field(FieldDef { span, safety, .. }) => match (headers.safety, safety) { + (false, Safety::Unsafe) => span_lint( + cx, + MISSING_SAFETY_DOC, + *span, + "docs for unsafe field missing `# Safety` section", + ), + (true, Safety::Safe) if cx.tcx.features().unsafe_fields() => span_lint_and_help( + cx, + UNNECESSARY_SAFETY_DOC, + *span, + "field with `# Safety` documentation is not marked unsafe", + None, + "if the field has safety invariants, mark it `unsafe`", + ), + _ => (), + }, Node::Item(item) => { too_long_first_doc_paragraph::check( cx, diff --git a/clippy_lints/src/duplicate_mod.rs b/clippy_lints/src/duplicate_mod.rs index f1837e776e824..4b7ffc09b820c 100644 --- a/clippy_lints/src/duplicate_mod.rs +++ b/clippy_lints/src/duplicate_mod.rs @@ -96,7 +96,7 @@ impl EarlyLintPass for DuplicateMod { .zip(lint_level_specs) .filter_map(|(span, level_spec)| { if let Some(id) = level_spec.lint_id() { - cx.fulfill_expectation(id.into()); + cx.fulfill_expectation(id); } (!matches!(level_spec.level(), Level::Allow | Level::Expect)).then_some(*span) diff --git a/clippy_lints/src/duration_suboptimal_units.rs b/clippy_lints/src/duration_suboptimal_units.rs index 6ad432c2659ac..ceb24709add30 100644 --- a/clippy_lints/src/duration_suboptimal_units.rs +++ b/clippy_lints/src/duration_suboptimal_units.rs @@ -19,6 +19,9 @@ declare_clippy_lint! { /// Checks for instances where a `std::time::Duration` is constructed using a smaller time unit /// when the value could be expressed more clearly using a larger unit. /// + /// For literal values that would convert to 10 or fewer of the larger unit, + /// this lint does not apply. + /// /// ### Why is this bad? /// /// Using a smaller unit for a duration that is evenly divisible by a larger unit reduces @@ -29,8 +32,8 @@ declare_clippy_lint! { /// ``` /// use std::time::Duration; /// - /// let dur = Duration::from_millis(5_000); - /// let dur = Duration::from_secs(180); + /// let dur = Duration::from_millis(50_000); + /// let dur = Duration::from_secs(1800); /// let dur = Duration::from_mins(10 * 60); /// ``` /// @@ -38,8 +41,8 @@ declare_clippy_lint! { /// ``` /// use std::time::Duration; /// - /// let dur = Duration::from_secs(5); - /// let dur = Duration::from_mins(3); + /// let dur = Duration::from_secs(50); + /// let dur = Duration::from_mins(30); /// let dur = Duration::from_hours(10); /// ``` #[clippy::version = "1.95.0"] @@ -80,13 +83,20 @@ impl LateLintPass<'_> for DurationSuboptimalUnits { // We intentionally don't want to evaluate referenced constants, as we don't want to // recommend a literal value over using constants: // - // let dur = Duration::from_secs(SIXTY); - // ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::from_mins(1)` + // let dur = Duration::from_millis(TWELVE_THOUSAND); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::from_secs(12)` && let Some(Constant::Int(value)) = ConstEvalCtxt::new(cx).eval_local(arg, expr.span.ctxt()) && let Ok(value) = u64::try_from(value) // Cannot fail // There is no need to promote e.g. 0 seconds to 0 hours && value != 0 && let Some((promoted_constructor, promoted_value)) = self.promote(cx, func_name.ident.name, value) + // For plain integer literals, only lint if the promoted value is large enough. + // Small promoted values (e.g. `from_millis(1_000)` -> `from_secs(1)`) are not + // necessarily more readable, and keeping the smaller unit makes quick adjustments + // easier (e.g. changing 1_000 to 1_200 without also changing the function name). + // For expressions (e.g. `10 * 60`), always lint since the expression already + // signals intent to compute a converted value. + && (!matches!(arg.kind, ExprKind::Lit(_)) || promoted_value > 10) { span_lint_and_then( cx, diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 486fdb8a2bb8e..2691fb4766397 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, root_macro_call_first_node}; +use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, first_node_in_macro, matching_root_macro_call}; use clippy_utils::source::{SpanRangeExt, snippet_with_context}; use clippy_utils::sugg::Sugg; use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait}; @@ -53,8 +53,13 @@ impl UselessFormat { impl<'tcx> LateLintPass<'tcx> for UselessFormat { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(macro_call) = root_macro_call_first_node(cx, expr) - && cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) + // Loosened from `root_macro_call_first_node` so the lint also fires when `format!` is + // the tail of a block emitted by another macro. The `!= macro_call.expn` check filters + // HIR nodes inside `format!`'s own expansion (its outer block's tail, its nested + // `format_args!`), which would otherwise also pass `first_node_in_macro` and cause the + // lint to fire multiple times per call. + if let Some(macro_call) = matching_root_macro_call(cx, expr.span, sym::format_macro) + && first_node_in_macro(cx, expr).is_some_and(|p_expn| p_expn != macro_call.expn) && let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn) { let mut applicability = Applicability::MachineApplicable; diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index c9b2c28344525..05145456071c0 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -17,7 +17,7 @@ use itertools::Itertools; use rustc_ast::FormatTrait::{Binary, Debug, Display, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex}; use rustc_ast::{ BorrowKind, FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, - FormatOptions, FormatPlaceholder, + FormatOptions, FormatPlaceholder, Mutability, }; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; @@ -451,6 +451,10 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { } fn check_useless_borrows_in_formatting(&self, placeholder: &FormatPlaceholder, arg_expr: &Expr<'tcx>) { + // Updated while peeling: + let mut only_mutable = true; + let mut has_mutable = false; + if !arg_expr.span.from_expansion() && !is_from_proc_macro(self.cx, arg_expr) && let Some(fmt_trait) = match placeholder.format_trait { @@ -461,11 +465,13 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { && let Some(sized_trait) = self.cx.tcx.lang_items().sized_trait() && let peeled_expr = peel_hir_expr_while(arg_expr, |e| { // Need to handle `&&&T` to `&T` when a single ref is still required - if let ExprKind::AddrOf(BorrowKind::Ref, _, e) = e.kind + if let ExprKind::AddrOf(BorrowKind::Ref, m, e) = e.kind && let ty = self.cx.typeck_results().expr_ty(e) && implements_trait(self.cx, ty, sized_trait, &[]) && implements_trait(self.cx, ty, fmt_trait, &[]) { + only_mutable = only_mutable && m == Mutability::Mut; + has_mutable = has_mutable || m == Mutability::Mut; Some(e) } else { None @@ -475,12 +481,19 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { && let Some(peeled_snippet) = snippet_opt(self.cx, peeled_expr.span) { let name = self.cx.tcx.item_name(self.macro_call.def_id); + let message = if only_mutable { + "remove the redundant `&mut`" + } else if has_mutable { + "remove the redundant `&`/`&mut`" + } else { + "remove the redundant `&`" + }; span_lint_and_sugg( self.cx, USELESS_BORROWS_IN_FORMATTING, arg_expr.span, format!("redundant reference in `{name}!` argument"), - "remove the redundant `&`", + message, peeled_snippet, Applicability::MachineApplicable, ); @@ -843,10 +856,7 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { }; let pointer_debug = derived_debug && adt.all_fields().any(|f| { - self.has_pointer_debug( - tcx.normalize_erasing_regions(typing_env, f.ty(tcx, args)), - depth, - ) + self.has_pointer_debug(tcx.normalize_erasing_regions(typing_env, f.ty(tcx, args)), depth) }); self.has_pointer_format.insert(ty, pointer_debug); pointer_debug diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index 3056be4e0d387..d8c55974fa926 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -230,6 +230,10 @@ impl<'a> MinifyingSugg<'a> { fn into_sugg(self) -> Sugg<'a> { self.0 } + + fn is_zero(&self) -> bool { + matches!(&self.0, Sugg::NonParen(s) | Sugg::MaybeParen(s) if s == "0") + } } impl<'a> From> for MinifyingSugg<'a> { @@ -241,9 +245,9 @@ impl<'a> From> for MinifyingSugg<'a> { impl std::ops::Add for &MinifyingSugg<'static> { type Output = MinifyingSugg<'static>; fn add(self, rhs: &MinifyingSugg<'static>) -> MinifyingSugg<'static> { - match (self.to_string().as_str(), rhs.to_string().as_str()) { - ("0", _) => rhs.clone(), - (_, "0") => self.clone(), + match (self.is_zero(), rhs.is_zero()) { + (true, _) => rhs.clone(), + (_, true) => self.clone(), (_, _) => (&self.0 + &rhs.0).into(), } } @@ -252,11 +256,14 @@ impl std::ops::Add for &MinifyingSugg<'static> { impl std::ops::Sub for &MinifyingSugg<'static> { type Output = MinifyingSugg<'static>; fn sub(self, rhs: &MinifyingSugg<'static>) -> MinifyingSugg<'static> { - match (self.to_string().as_str(), rhs.to_string().as_str()) { - (_, "0") => self.clone(), - ("0", _) => (-rhs.0.clone()).into(), - (x, y) if x == y => sugg::ZERO.into(), - (_, _) => (&self.0 - &rhs.0).into(), + if rhs.is_zero() { + self.clone() + } else if self.is_zero() { + (-rhs.0.clone()).into() + } else if self.to_string() == rhs.to_string() { + sugg::ZERO.into() + } else { + (&self.0 - &rhs.0).into() } } } @@ -264,9 +271,9 @@ impl std::ops::Sub for &MinifyingSugg<'static> { impl std::ops::Add<&MinifyingSugg<'static>> for MinifyingSugg<'static> { type Output = MinifyingSugg<'static>; fn add(self, rhs: &MinifyingSugg<'static>) -> MinifyingSugg<'static> { - match (self.to_string().as_str(), rhs.to_string().as_str()) { - ("0", _) => rhs.clone(), - (_, "0") => self, + match (self.is_zero(), rhs.is_zero()) { + (true, _) => rhs.clone(), + (_, true) => self, (_, _) => (self.0 + &rhs.0).into(), } } @@ -275,11 +282,14 @@ impl std::ops::Add<&MinifyingSugg<'static>> for MinifyingSugg<'static> { impl std::ops::Sub<&MinifyingSugg<'static>> for MinifyingSugg<'static> { type Output = MinifyingSugg<'static>; fn sub(self, rhs: &MinifyingSugg<'static>) -> MinifyingSugg<'static> { - match (self.to_string().as_str(), rhs.to_string().as_str()) { - (_, "0") => self, - ("0", _) => (-rhs.0.clone()).into(), - (x, y) if x == y => sugg::ZERO.into(), - (_, _) => (self.0 - &rhs.0).into(), + if rhs.is_zero() { + self + } else if self.is_zero() { + (-rhs.0.clone()).into() + } else if self.to_string() == rhs.to_string() { + sugg::ZERO.into() + } else { + (self.0 - &rhs.0).into() } } } diff --git a/clippy_lints/src/macro_metavars_in_unsafe.rs b/clippy_lints/src/macro_metavars_in_unsafe.rs index 5f086988c083b..8ff6de283557f 100644 --- a/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -251,8 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for ExprMetavarsInUnsafe { .flatten() .copied() .inspect(|&unsafe_block| { - let level_spec = - cx.tcx.lint_level_spec_at_node(MACRO_METAVARS_IN_UNSAFE, unsafe_block); + let level_spec = cx.tcx.lint_level_spec_at_node(MACRO_METAVARS_IN_UNSAFE, unsafe_block); if level_spec.is_expect() { // Since we're going to deduplicate expanded unsafe blocks by its enclosing macro definition soon, // which would lead to unfulfilled `#[expect()]`s in all other unsafe blocks that are filtered out diff --git a/clippy_lints/src/methods/map_flatten.rs b/clippy_lints/src/methods/map_flatten.rs index 09733953255ec..b654548cc2050 100644 --- a/clippy_lints/src/methods/map_flatten.rs +++ b/clippy_lints/src/methods/map_flatten.rs @@ -11,7 +11,7 @@ use rustc_span::symbol::sym; use super::MAP_FLATTEN; -/// lint use of `map().flatten()` for `Iterators` and 'Options' +/// lint use of `map().flatten()` for `Iterator`s, 'Option's, and `Result`s. pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, map_arg: &Expr<'_>, map_span: Span) { if let Some((caller_ty_name, method_to_use)) = try_get_caller_ty_name_and_method_name(cx, expr, recv, map_arg) { let mut applicability = Applicability::MachineApplicable; diff --git a/clippy_lints/src/methods/map_or_identity.rs b/clippy_lints/src/methods/map_or_identity.rs new file mode 100644 index 0000000000000..e4e5fa5420105 --- /dev/null +++ b/clippy_lints/src/methods/map_or_identity.rs @@ -0,0 +1,36 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_expr_identity_function; +use clippy_utils::res::MaybeDef; +use clippy_utils::source::snippet_with_context; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_span::Span; +use rustc_span::symbol::sym; + +use super::MAP_OR_IDENTITY; + +/// lint use of `_.map_or(err, |n| n)` for `Result`s and `Option`s. +pub(super) fn check( + cx: &LateContext<'_>, + expr: &Expr<'_>, + recv: &Expr<'_>, + call_span: Span, + def_arg: &Expr<'_>, + map_arg: &Expr<'_>, +) { + // lint if the caller of `map_or()` is a `Result` or an `Option` + // and if the mapping function is the identity function + if let Some(symbol @ (sym::Result | sym::Option)) = cx.typeck_results().expr_ty_adjusted(recv).opt_diag_name(cx) + && is_expr_identity_function(cx, map_arg) + { + let msg = format!("expression can be simplified using `{symbol}::unwrap_or()`"); + span_lint_and_then(cx, MAP_OR_IDENTITY, expr.span, msg, |diag| { + let mut applicability = Applicability::MachineApplicable; + let (err_snippet, _) = snippet_with_context(cx, def_arg.span, expr.span.ctxt(), "..", &mut applicability); + let sugg = format!("unwrap_or({err_snippet})"); + + diag.span_suggestion_verbose(call_span, "consider using `unwrap_or`", sugg, applicability); + }); + } +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index a8a2fc55c9019..d7fc44bab5386 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -75,6 +75,7 @@ mod map_collect_result_unit; mod map_err_ignore; mod map_flatten; mod map_identity; +mod map_or_identity; mod map_unwrap_or; mod map_unwrap_or_else; mod map_with_unused_argument_over_ranges; @@ -2327,27 +2328,34 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usage of `_.map(_).flatten(_)` on `Iterator` and `Option` + /// Checks for usage of `_.map(_).flatten(_)` on `Iterator`, `Option`, and `Result`. /// /// ### Why is this bad? - /// Readability, this can be written more concisely as - /// `_.flat_map(_)` for `Iterator` or `_.and_then(_)` for `Option` + /// Readability. This can be written more concisely with `Iterator::flat_map`, `Option::and_then`, and + /// `Result::and_then`. /// /// ### Example /// ```no_run /// let vec = vec![vec![1]]; - /// let opt = Some(5); - /// /// vec.iter().map(|x| x.iter()).flatten(); + /// + /// let opt = Some(5); /// opt.map(|x| Some(x * 2)).flatten(); + /// + /// let res: Result = Ok(5); + /// res.map(|x| Ok(x * 2)).flatten(); /// ``` /// /// Use instead: /// ```no_run - /// # let vec = vec![vec![1]]; - /// # let opt = Some(5); + /// let vec = vec![vec![1]]; /// vec.iter().flat_map(|x| x.iter()); + /// + /// let opt = Some(5); /// opt.and_then(|x| Some(x * 2)); + /// + /// let res: Result = Ok(5); + /// res.and_then(|x| Ok(x * 2)); /// ``` #[clippy::version = "1.31.0"] pub MAP_FLATTEN, @@ -2378,6 +2386,29 @@ declare_clippy_lint! { "using iterator.map(|x| x)" } +declare_clippy_lint! { + /// ### What it does + /// Checks the usage of `.map_or(...)` with an identity function for `Option` and `Result` types. + /// + /// ### Why is this bad? + /// This can be written more concisely by using `unwrap_or()`. + /// + /// ### Example + /// ```no_run + /// let opt = Some(1); + /// opt.map_or(42, |v| v); + /// ``` + /// Use instead: + /// ```no_run + /// let opt = Some(1); + /// opt.unwrap_or(42); + /// ``` + #[clippy::version = "1.97.0"] + pub MAP_OR_IDENTITY, + complexity, + "using an identity function when mapping with `.map_or(|err| ..., |x| x)`" +} + declare_clippy_lint! { /// ### What it does /// Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or @@ -4267,7 +4298,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.78.0"] pub UNNECESSARY_GET_THEN_CHECK, - suspicious, + complexity, "calling `.get().is_some()` or `.get().is_none()` instead of `.contains()` or `.contains_key()`" } @@ -4910,6 +4941,7 @@ impl_lint_pass!(Methods => [ MAP_ERR_IGNORE, MAP_FLATTEN, MAP_IDENTITY, + MAP_OR_IDENTITY, MAP_UNWRAP_OR, MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES, MUT_MUTEX_LOCK, @@ -5813,7 +5845,7 @@ impl Methods { } } // Handle method calls whose receiver and arguments may come from expansion - if let ExprKind::MethodCall(path, recv, args, _call_span) = expr.kind { + if let ExprKind::MethodCall(path, recv, args, call_span) = expr.kind { let method_span = path.ident.span; // Those methods do their own method name checking as they deal with multiple methods. @@ -5858,6 +5890,10 @@ impl Methods { (sym::into_iter, []) => { into_iter_on_ref::check(cx, expr, method_span, recv); }, + (sym::map_or, [def, map]) => { + map_or_identity::check(cx, expr, recv, call_span, def, map); + }, + (sym::to_string, []) => { inefficient_to_string::check(cx, expr, recv, self.msrv); }, diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index da6f03931e24b..fdd335c762013 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -92,7 +92,7 @@ pub(super) fn check( (sym::None, sym::unwrap_or_default, _) => { let ty = cx.typeck_results().expr_ty(expr); let default_ty_string = if let ty::Adt(def, ..) = ty.kind() { - with_forced_trimmed_paths!(format!("{}", cx.tcx.def_path_str(def.did()))) + with_forced_trimmed_paths!(cx.tcx.def_path_str(def.did())) } else { "Default".to_string() }; diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index 96e7f77853577..6891ecb0cf9d8 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -330,12 +330,12 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects { /// Detects a type-casting conversion and returns the type of the original expression. For /// example, `let foo = u64::from(bar)`. fn find_original_primitive_ty<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) -> Option> { - if let hir::ExprKind::Call(path, [arg]) = &expr.kind - && path.res(cx).opt_def_id().is_diag_item(&cx.tcx, sym::from_fn) - { - Some(cx.typeck_results().expr_ty(arg)) - } else { - None + match &expr.kind { + hir::ExprKind::Call(path, [arg]) if path.res(cx).opt_def_id().is_diag_item(&cx.tcx, sym::from_fn) => { + Some(cx.typeck_results().expr_ty(arg)) + }, + hir::ExprKind::Cast(arg, _) => Some(cx.typeck_results().expr_ty(arg)), + _ => None, } } diff --git a/clippy_lints/src/operators/manual_midpoint.rs b/clippy_lints/src/operators/manual_midpoint.rs index 81721a9f2af55..1ad58612c2fe4 100644 --- a/clippy_lints/src/operators/manual_midpoint.rs +++ b/clippy_lints/src/operators/manual_midpoint.rs @@ -18,22 +18,34 @@ pub(super) fn check<'tcx>( right: &'tcx Expr<'_>, msrv: Msrv, ) { + let (maybe_add_expr, require_uint) = + if op == BinOpKind::Div && (is_integer_literal(right, 2) || is_float_literal(right, 2.0)) { + (left, false) + } else if op == BinOpKind::Mul && is_float_literal(left, 0.5) { + (right, false) + } else if op == BinOpKind::Mul && is_float_literal(right, 0.5) { + (left, false) + } else if op == BinOpKind::Shr && is_integer_literal(right, 1) { + (left, true) + } else { + return; + }; + if !left.span.from_expansion() && !right.span.from_expansion() - && op == BinOpKind::Div - && (is_integer_literal(right, 2) || is_float_literal(right, 2.0)) - && let Some((ll_expr, lr_expr)) = add_operands(left) - && add_operands(ll_expr).is_none() && add_operands(lr_expr).is_none() - && let left_ty = cx.typeck_results().expr_ty_adjusted(ll_expr) - && let right_ty = cx.typeck_results().expr_ty_adjusted(lr_expr) + && let Some((add_l_expr, add_r_expr)) = add_operands(maybe_add_expr) + && add_operands(add_l_expr).is_none() && add_operands(add_r_expr).is_none() + && let left_ty = cx.typeck_results().expr_ty_adjusted(add_l_expr) + && let right_ty = cx.typeck_results().expr_ty_adjusted(add_r_expr) && left_ty == right_ty + && (!require_uint || matches!(left_ty.kind(), ty::Uint(_))) // Do not lint on `(_+1)/2` and `(1+_)/2`, it is likely a `div_ceil()` operation - && !is_integer_literal(ll_expr, 1) && !is_integer_literal(lr_expr, 1) + && !is_integer_literal(add_l_expr, 1) && !is_integer_literal(add_r_expr, 1) && is_midpoint_implemented(cx, left_ty, msrv) { let mut app = Applicability::MachineApplicable; - let left_sugg = Sugg::hir_with_context(cx, ll_expr, expr.span.ctxt(), "..", &mut app); - let right_sugg = Sugg::hir_with_context(cx, lr_expr, expr.span.ctxt(), "..", &mut app); + let left_sugg = Sugg::hir_with_context(cx, add_l_expr, expr.span.ctxt(), "..", &mut app); + let right_sugg = Sugg::hir_with_context(cx, add_r_expr, expr.span.ctxt(), "..", &mut app); let sugg = format!("{left_ty}::midpoint({left_sugg}, {right_sugg})"); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index b4519d654722a..0571cedca47e5 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -727,18 +727,27 @@ declare_clippy_lint! { /// Checks for manual implementation of `midpoint`. /// /// ### Why is this bad? - /// Using `(x + y) / 2` might cause an overflow on the intermediate - /// addition result. + /// Using `(x + y) / 2` or `(x + y) >> 1` on integer types might cause an overflow on the + /// intermediate addition result. The latter will only warn for unsigned integer types. + /// Similar for floating-point `(x + y) / 2.0` and `(x + y) * 0.5`. /// /// ### Example /// ```no_run /// # let a: u32 = 0; /// let c = (a + 10) / 2; + /// let d = (a + 10) >> 1; + /// let b: f32 = 0.0; + /// let e = (b + 10.0) / 2.0; + /// let f = (b + 10.0) * 0.5; /// ``` /// Use instead: /// ```no_run /// # let a: u32 = 0; /// let c = u32::midpoint(a, 10); + /// let d = u32::midpoint(a, 10); + /// let b: f32 = 0.0; + /// let e = f32::midpoint(b, 10.0); + /// let f = f32::midpoint(b, 10.0); /// ``` #[clippy::version = "1.87.0"] pub MANUAL_MIDPOINT, diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index aa840f400d42e..93f01594351c8 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -20,7 +20,7 @@ use std::cmp::Ordering; declare_clippy_lint! { /// ### What it does /// Checks for expressions like `x >= 3 && x < 8` that could - /// be more readably expressed as `(3..8).contains(x)`. + /// be more readably expressed as `(3..8).contains(&x)`. /// /// ### Why is this bad? /// `contains` expresses the intent better and has less @@ -38,6 +38,12 @@ declare_clippy_lint! { ///# let x = 6; /// assert!((3..8).contains(&x)); /// ``` + /// + /// ### Limitations + /// Out-of-range checks on floating-point types, such as `q < 0.0 || q > 1.0`, + /// are not linted. For `NaN`, that expression is `false`, but + /// `!(0.0..=1.0).contains(&q)` is `true`, so the suggested rewrite would + /// change control flow. #[clippy::version = "1.49.0"] pub MANUAL_RANGE_CONTAINS, style, @@ -250,6 +256,11 @@ fn check_possible_range_contains( applicability, ); } else if !combine_and && ord == Some(l.ord) { + // For floating-point types, `q < lo || q > hi` evaluates to `false` for NaN, + // but `!(lo..=hi).contains(&q)` evaluates to `true` for NaN, so not linting. + if matches!(cx.typeck_results().expr_ty(l.expr).kind(), ty::Float(_)) { + return; + } // `!_.contains(_)` // order lower bound and upper bound let (l_span, u_span, l_inc, u_inc) = if l.ord == Ordering::Less { diff --git a/clippy_lints/src/returns/needless_return_with_question_mark.rs b/clippy_lints/src/returns/needless_return_with_question_mark.rs index 7c55150db10d5..e37ea9800ed0e 100644 --- a/clippy_lints/src/returns/needless_return_with_question_mark.rs +++ b/clippy_lints/src/returns/needless_return_with_question_mark.rs @@ -27,7 +27,7 @@ pub(super) fn check_stmt<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { && let ExprKind::Block(block, _) = peel_async_body(block).kind && !is_inside_let_else(cx.tcx, expr) && let [.., final_stmt] = block.stmts - && final_stmt.hir_id != stmt.hir_id + && (block.expr.is_some() || final_stmt.hir_id != stmt.hir_id) && !is_from_proc_macro(cx, expr) && !stmt_needs_never_type(cx, stmt.hir_id) { diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs index c48ca652ffd11..6df3e7baa1bca 100644 --- a/clippy_lints/src/unit_types/unit_arg.rs +++ b/clippy_lints/src/unit_types/unit_arg.rs @@ -159,7 +159,7 @@ fn lint_unit_args<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, args_to_ fn is_expr_default_nested<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { is_expr_default(cx, expr) || matches!(expr.kind, ExprKind::Block(block, _) - if block.expr.is_some() && is_expr_default_nested(cx, block.expr.unwrap())) + if block.expr.is_some_and(|e| is_expr_default_nested(cx, e))) } enum MaybeTypeUncertain<'tcx> { diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs index f5e903426d578..456b98e6459d4 100644 --- a/clippy_lints/src/unused_async.rs +++ b/clippy_lints/src/unused_async.rs @@ -1,11 +1,13 @@ -use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::is_def_id_trait_method; +use clippy_utils::source::{HasSession, snippet_with_applicability, walk_span_to_context}; use clippy_utils::usage::is_todo_unimplemented_stub; +use rustc_errors::Applicability; use rustc_hir::def::DefKind; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn}; use rustc_hir::{ - Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, Defaultness, Expr, ExprKind, FnDecl, HirId, Node, - TraitItem, YieldSource, + Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, Defaultness, Expr, ExprKind, FnDecl, HirId, + ImplItem, ImplItemKind, IsAsync, Node, TraitItem, YieldSource, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; @@ -43,7 +45,52 @@ declare_clippy_lint! { "finds async functions with no await statements" } -impl_lint_pass!(UnusedAsync => [UNUSED_ASYNC]); +declare_clippy_lint! { + /// ### What it does + /// Checks for trait method implementations that are declared `async` but have no `.await`s inside of them. + /// + /// ### Why is this bad? + /// Async functions with no async code create computational overhead. + /// Even though the trait requires the method to return a future, + /// returning a `core::future::ready` with the result is more efficient + /// as it reduces the number of states in the Future state machine by at least one. + /// + /// Note that the behaviour is slightly different when using `core::future::ready`, + /// as the value is computed immediately and stored in a future for later retrieval at the first (and only valid) call to `poll`. + /// An `async` block generates code that completely defers the computation of this value until the Future is polled. + /// + /// ### Example + /// ```no_run + /// trait AsyncTrait { + /// async fn get_random_number() -> i64; + /// } + /// + /// impl AsyncTrait for () { + /// async fn get_random_number() -> i64 { + /// 4 // Chosen by fair dice roll. Guaranteed to be random. + /// } + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// trait AsyncTrait { + /// async fn get_random_number() -> i64; + /// } + /// + /// impl AsyncTrait for () { + /// fn get_random_number() -> impl Future { + /// core::future::ready(4) // Chosen by fair dice roll. Guaranteed to be random. + /// } + /// } + /// ``` + #[clippy::version = "1.98.0"] + pub UNUSED_ASYNC_TRAIT_IMPL, + pedantic, + "finds async trait impl functions with no await statements" +} + +impl_lint_pass!(UnusedAsync => [UNUSED_ASYNC, UNUSED_ASYNC_TRAIT_IMPL]); #[derive(Default)] pub struct UnusedAsync { @@ -194,6 +241,72 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { ); } } + + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { + if let ImplItemKind::Fn(ref sig, body_id) = impl_item.kind + && let IsAsync::Async(async_span) = sig.header.asyncness + && let body = cx.tcx.hir_body(body_id) + && !async_fn_contains_todo_unimplemented_macro(cx, body) + { + let mut visitor = AsyncFnVisitor { + cx, + found_await: false, + await_in_async_block: None, + async_depth: 0, + }; + visitor.visit_nested_body(body_id); + + if !visitor.found_await + && let Some(builtin_crate) = clippy_utils::std_or_core(cx) + && let Some(inner) = unpack_async_fn_body(cx, body) + // Find the tail expression contained in the async fn (if any), + // which will be wrapped in std::future::ready. + && let ExprKind::Block(block, _) = inner.kind + && let Some(tail_expr) = block.expr + { + span_lint_and_then( + cx, + UNUSED_ASYNC_TRAIT_IMPL, + impl_item.span, + "unused `async` for async trait impl function with no `.await` statements", + |diag| { + diag.note(format!( + "`{builtin_crate}::future::ready` creates a `Future` which returns the value immediately when `poll`ed" + )); + + let ctxt = impl_item.span.ctxt(); + if let Some(signature_span) = walk_span_to_context(sig.decl.output.span(), ctxt) + && let Some(tail_span) = walk_span_to_context(tail_expr.span, ctxt) + { + // The suggestion might be incorrect. The future changes from awaiting for the first poll to + // evaluate the expression, to immediately evaluate the expression. + let mut app = Applicability::MaybeIncorrect; + + let async_span = cx.sess().source_map().span_extend_while_whitespace(async_span); + + let signature_snippet = snippet_with_applicability(cx, signature_span, "_", &mut app); + let tail_snippet = snippet_with_applicability(cx, tail_span, "_", &mut app).to_string(); + + let sugg = vec![ + (async_span, String::new()), + (signature_span, format!("impl Future")), + (tail_span, format!("{builtin_crate}::future::ready({tail_snippet})")), + ]; + + diag.multipart_suggestion( + format!( + "consider removing the `async` from this function \ + and returning `impl Future` instead" + ), + sugg, + app, + ); + } + }, + ); + } + } + } } fn is_default_trait_impl(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { @@ -206,7 +319,34 @@ fn is_default_trait_impl(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { ) } -fn async_fn_contains_todo_unimplemented_macro(cx: &LateContext<'_>, body: &Body<'_>) -> bool { +/// Get the inner expression of the body of an async function. +/// +/// If it is not an async function, returns `None`. +/// +/// An async function like +/// ```rs +/// async fn get_random_number() -> i64 { +/// do_something(); +/// 4 +/// } +/// ``` +/// (roughly) desugars to +/// ```rs +/// fn get_random_number() -> impl Future { +/// async move { +/// do_something(); +/// 4 +/// } +/// } +/// ``` +/// +/// We first get to the `async move {}` block, +/// which is the one and only expression in the body of the function. +/// This block is a coroutine wrapped in a closure. +/// The expression in this block is contained in a terminating scope. +/// +/// This function returns that expression in `Some(...)` if this body indeed is an async function. +fn unpack_async_fn_body<'hir>(cx: &LateContext<'hir>, body: &Body<'hir>) -> Option<&'hir Expr<'hir>> { if let ExprKind::Closure(closure) = body.value.kind && let ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) = closure.kind && let body = cx.tcx.hir_body(closure.body) @@ -214,8 +354,12 @@ fn async_fn_contains_todo_unimplemented_macro(cx: &LateContext<'_>, body: &Body< && let Some(expr) = block.expr && let ExprKind::DropTemps(inner) = expr.kind { - return is_todo_unimplemented_stub(cx, inner); + Some(inner) + } else { + None } +} - false +fn async_fn_contains_todo_unimplemented_macro<'hir>(cx: &LateContext<'hir>, body: &Body<'hir>) -> bool { + unpack_async_fn_body(cx, body).is_some_and(|inner| is_todo_unimplemented_stub(cx, inner)) } diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index 3d87129e8953c..0dcb116988bb8 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.97" +version = "0.1.98" edition = "2024" description = "Helpful tools for writing lints, provided as they are used in Clippy" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/clippy_utils/README.md b/clippy_utils/README.md index 716b13a5e8f0b..1778500d4902a 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-05-13 +nightly-2026-05-28 ``` diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index c41ffad8431ba..e0a182523f673 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -65,7 +65,7 @@ pub fn eq_pat(l: &Pat, r: &Pat) -> bool { } } -pub fn eq_range_end(l: RangeEnd, r: RangeEnd) -> bool { +fn eq_range_end(l: RangeEnd, r: RangeEnd) -> bool { match (l, r) { (RangeEnd::Excluded, RangeEnd::Excluded) => true, (RangeEnd::Included(l), RangeEnd::Included(r)) => { @@ -82,7 +82,7 @@ pub fn eq_field_pat(l: &PatField, r: &PatField) -> bool { && over(&l.attrs, &r.attrs, eq_attr) } -pub fn eq_qself(l: &QSelf, r: &QSelf) -> bool { +fn eq_qself(l: &QSelf, r: &QSelf) -> bool { l.position == r.position && eq_ty(&l.ty, &r.ty) } @@ -98,11 +98,11 @@ pub fn eq_path(l: &Path, r: &Path) -> bool { over(&l.segments, &r.segments, eq_path_seg) } -pub fn eq_path_seg(l: &PathSegment, r: &PathSegment) -> bool { +fn eq_path_seg(l: &PathSegment, r: &PathSegment) -> bool { eq_id(l.ident, r.ident) && both(l.args.as_ref(), r.args.as_ref(), |l, r| eq_generic_args(l, r)) } -pub fn eq_generic_args(l: &GenericArgs, r: &GenericArgs) -> bool { +fn eq_generic_args(l: &GenericArgs, r: &GenericArgs) -> bool { match (l, r) { (AngleBracketed(l), AngleBracketed(r)) => over(&l.args, &r.args, eq_angle_arg), (Parenthesized(l), Parenthesized(r)) => { @@ -112,7 +112,7 @@ pub fn eq_generic_args(l: &GenericArgs, r: &GenericArgs) -> bool { } } -pub fn eq_angle_arg(l: &AngleBracketedArg, r: &AngleBracketedArg) -> bool { +fn eq_angle_arg(l: &AngleBracketedArg, r: &AngleBracketedArg) -> bool { match (l, r) { (AngleBracketedArg::Arg(l), AngleBracketedArg::Arg(r)) => eq_generic_arg(l, r), (AngleBracketedArg::Constraint(l), AngleBracketedArg::Constraint(r)) => eq_assoc_item_constraint(l, r), @@ -120,7 +120,7 @@ pub fn eq_angle_arg(l: &AngleBracketedArg, r: &AngleBracketedArg) -> bool { } } -pub fn eq_generic_arg(l: &GenericArg, r: &GenericArg) -> bool { +fn eq_generic_arg(l: &GenericArg, r: &GenericArg) -> bool { match (l, r) { (GenericArg::Lifetime(l), GenericArg::Lifetime(r)) => eq_id(l.ident, r.ident), (GenericArg::Type(l), GenericArg::Type(r)) => eq_ty(l, r), @@ -129,11 +129,11 @@ pub fn eq_generic_arg(l: &GenericArg, r: &GenericArg) -> bool { } } -pub fn eq_expr_opt(l: Option<&Expr>, r: Option<&Expr>) -> bool { +fn eq_expr_opt(l: Option<&Expr>, r: Option<&Expr>) -> bool { both(l, r, eq_expr) } -pub fn eq_struct_rest(l: &StructRest, r: &StructRest) -> bool { +fn eq_struct_rest(l: &StructRest, r: &StructRest) -> bool { match (l, r) { (StructRest::Base(lb), StructRest::Base(rb)) => eq_expr(lb, rb), (StructRest::Rest(_), StructRest::Rest(_)) | (StructRest::None, StructRest::None) => true, @@ -142,7 +142,7 @@ pub fn eq_struct_rest(l: &StructRest, r: &StructRest) -> bool { } #[expect(clippy::too_many_lines, reason = "big match statement")] -pub fn eq_expr(l: &Expr, r: &Expr) -> bool { +fn eq_expr(l: &Expr, r: &Expr) -> bool { use ExprKind::*; if !over(&l.attrs, &r.attrs, eq_attr) { return false; @@ -270,14 +270,14 @@ fn eq_coroutine_kind(a: Option, b: Option) -> bool ) } -pub fn eq_field(l: &ExprField, r: &ExprField) -> bool { +fn eq_field(l: &ExprField, r: &ExprField) -> bool { l.is_placeholder == r.is_placeholder && eq_id(l.ident, r.ident) && eq_expr(&l.expr, &r.expr) && over(&l.attrs, &r.attrs, eq_attr) } -pub fn eq_arm(l: &Arm, r: &Arm) -> bool { +fn eq_arm(l: &Arm, r: &Arm) -> bool { l.is_placeholder == r.is_placeholder && eq_pat(&l.pat, &r.pat) && eq_expr_opt(l.body.as_deref(), r.body.as_deref()) @@ -285,15 +285,15 @@ pub fn eq_arm(l: &Arm, r: &Arm) -> bool { && over(&l.attrs, &r.attrs, eq_attr) } -pub fn eq_label(l: Option<&Label>, r: Option<&Label>) -> bool { +fn eq_label(l: Option<&Label>, r: Option<&Label>) -> bool { both(l, r, |l, r| eq_id(l.ident, r.ident)) } -pub fn eq_block(l: &Block, r: &Block) -> bool { +fn eq_block(l: &Block, r: &Block) -> bool { l.rules == r.rules && over(&l.stmts, &r.stmts, eq_stmt) } -pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool { +fn eq_stmt(l: &Stmt, r: &Stmt) -> bool { use StmtKind::*; match (&l.kind, &r.kind) { (Let(l), Let(r)) => { @@ -312,7 +312,7 @@ pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool { } } -pub fn eq_local_kind(l: &LocalKind, r: &LocalKind) -> bool { +fn eq_local_kind(l: &LocalKind, r: &LocalKind) -> bool { use LocalKind::*; match (l, r) { (Decl, Decl) => true, @@ -322,12 +322,12 @@ pub fn eq_local_kind(l: &LocalKind, r: &LocalKind) -> bool { } } -pub fn eq_item(l: &Item, r: &Item, mut eq_kind: impl FnMut(&K, &K) -> bool) -> bool { +fn eq_item(l: &Item, r: &Item, mut eq_kind: impl FnMut(&K, &K) -> bool) -> bool { over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind) } #[expect(clippy::too_many_lines, reason = "big match statement")] -pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { +fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { use ItemKind::*; match (l, r) { (ExternCrate(ls, li), ExternCrate(rs, ri)) => ls == rs && eq_id(*li, *ri), @@ -532,7 +532,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { } } -pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { +fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { use ForeignItemKind::*; match (l, r) { ( @@ -614,7 +614,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { } } -pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { +fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { use AssocItemKind::*; match (l, r) { ( @@ -700,7 +700,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { } } -pub fn eq_variant(l: &Variant, r: &Variant) -> bool { +fn eq_variant(l: &Variant, r: &Variant) -> bool { l.is_placeholder == r.is_placeholder && over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) @@ -711,7 +711,7 @@ pub fn eq_variant(l: &Variant, r: &Variant) -> bool { }) } -pub fn eq_variant_data(l: &VariantData, r: &VariantData) -> bool { +fn eq_variant_data(l: &VariantData, r: &VariantData) -> bool { use VariantData::*; match (l, r) { (Unit(_), Unit(_)) => true, @@ -722,7 +722,7 @@ pub fn eq_variant_data(l: &VariantData, r: &VariantData) -> bool { } } -pub fn eq_struct_field(l: &FieldDef, r: &FieldDef) -> bool { +fn eq_struct_field(l: &FieldDef, r: &FieldDef) -> bool { l.is_placeholder == r.is_placeholder && over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) @@ -731,7 +731,7 @@ pub fn eq_struct_field(l: &FieldDef, r: &FieldDef) -> bool { && eq_ty(&l.ty, &r.ty) } -pub fn eq_fn_sig(l: &FnSig, r: &FnSig) -> bool { +fn eq_fn_sig(l: &FnSig, r: &FnSig) -> bool { eq_fn_decl(&l.decl, &r.decl) && eq_fn_header(&l.header, &r.header) } @@ -748,7 +748,7 @@ fn eq_opt_coroutine_kind(l: Option, r: Option) -> ) } -pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool { +fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool { matches!(l.safety, Safety::Default) == matches!(r.safety, Safety::Default) && eq_opt_coroutine_kind(l.coroutine_kind, r.coroutine_kind) && matches!(l.constness, Const::No) == matches!(r.constness, Const::No) @@ -756,7 +756,7 @@ pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool { } #[expect(clippy::ref_option, reason = "This is the type how it is stored in the AST")] -pub fn eq_opt_fn_contract(l: &Option>, r: &Option>) -> bool { +fn eq_opt_fn_contract(l: &Option>, r: &Option>) -> bool { match (l, r) { (Some(l), Some(r)) => { eq_expr_opt(l.requires.as_deref(), r.requires.as_deref()) @@ -767,14 +767,14 @@ pub fn eq_opt_fn_contract(l: &Option>, r: &Option bool { +fn eq_generics(l: &Generics, r: &Generics) -> bool { over(&l.params, &r.params, eq_generic_param) && over(&l.where_clause.predicates, &r.where_clause.predicates, |l, r| { eq_where_predicate(l, r) }) } -pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { +fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { use WherePredicateKind::*; over(&l.attrs, &r.attrs, eq_attr) && match (&l.kind, &r.kind) { @@ -792,15 +792,15 @@ pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { } } -pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool { +fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool { eq_path(&l.prefix, &r.prefix) && eq_use_tree_kind(&l.kind, &r.kind) } -pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool { +fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool { eq_expr(&l.value, &r.value) } -pub fn eq_const_item_rhs(l: &ConstItemRhsKind, r: &ConstItemRhsKind) -> bool { +fn eq_const_item_rhs(l: &ConstItemRhsKind, r: &ConstItemRhsKind) -> bool { use ConstItemRhsKind::*; match (l, r) { (TypeConst { rhs: Some(l) }, TypeConst { rhs: Some(r) }) => eq_anon_const(l, r), @@ -815,7 +815,7 @@ pub fn eq_const_item_rhs(l: &ConstItemRhsKind, r: &ConstItemRhsKind) -> bool { } } -pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool { +fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool { use UseTreeKind::*; match (l, r) { (Glob(_), Glob(_)) => true, @@ -825,7 +825,7 @@ pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool { } } -pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool { +fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool { matches!( (l, r), (Defaultness::Implicit, Defaultness::Implicit) @@ -834,7 +834,7 @@ pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool { ) } -pub fn eq_vis(l: &Visibility, r: &Visibility) -> bool { +fn eq_vis(l: &Visibility, r: &Visibility) -> bool { use VisibilityKind::*; match (&l.kind, &r.kind) { (Public, Public) | (Inherited, Inherited) => true, @@ -843,7 +843,7 @@ pub fn eq_vis(l: &Visibility, r: &Visibility) -> bool { } } -pub fn eq_impl_restriction(l: &ImplRestriction, r: &ImplRestriction) -> bool { +fn eq_impl_restriction(l: &ImplRestriction, r: &ImplRestriction) -> bool { eq_restriction_kind(&l.kind, &r.kind) } @@ -870,7 +870,7 @@ fn eq_restriction_kind(l: &RestrictionKind, r: &RestrictionKind) -> bool { } } -pub fn eq_fn_decl(l: &FnDecl, r: &FnDecl) -> bool { +fn eq_fn_decl(l: &FnDecl, r: &FnDecl) -> bool { eq_fn_ret_ty(&l.output, &r.output) && over(&l.inputs, &r.inputs, |l, r| { l.is_placeholder == r.is_placeholder @@ -880,7 +880,7 @@ pub fn eq_fn_decl(l: &FnDecl, r: &FnDecl) -> bool { }) } -pub fn eq_closure_binder(l: &ClosureBinder, r: &ClosureBinder) -> bool { +fn eq_closure_binder(l: &ClosureBinder, r: &ClosureBinder) -> bool { match (l, r) { (ClosureBinder::NotPresent, ClosureBinder::NotPresent) => true, (ClosureBinder::For { generic_params: lp, .. }, ClosureBinder::For { generic_params: rp, .. }) => { @@ -890,7 +890,7 @@ pub fn eq_closure_binder(l: &ClosureBinder, r: &ClosureBinder) -> bool { } } -pub fn eq_fn_ret_ty(l: &FnRetTy, r: &FnRetTy) -> bool { +fn eq_fn_ret_ty(l: &FnRetTy, r: &FnRetTy) -> bool { match (l, r) { (FnRetTy::Default(_), FnRetTy::Default(_)) => true, (FnRetTy::Ty(l), FnRetTy::Ty(r)) => eq_ty(l, r), @@ -898,7 +898,7 @@ pub fn eq_fn_ret_ty(l: &FnRetTy, r: &FnRetTy) -> bool { } } -pub fn eq_ty(l: &Ty, r: &Ty) -> bool { +fn eq_ty(l: &Ty, r: &Ty) -> bool { use TyKind::*; match (&l.kind, &r.kind) { (Paren(l), _) => eq_ty(l, r), @@ -930,7 +930,7 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool { } } -pub fn eq_ext(l: &Extern, r: &Extern) -> bool { +fn eq_ext(l: &Extern, r: &Extern) -> bool { use Extern::*; match (l, r) { (None, None) | (Implicit(_), Implicit(_)) => true, @@ -939,11 +939,11 @@ pub fn eq_ext(l: &Extern, r: &Extern) -> bool { } } -pub fn eq_str_lit(l: &StrLit, r: &StrLit) -> bool { +fn eq_str_lit(l: &StrLit, r: &StrLit) -> bool { l.style == r.style && l.symbol == r.symbol && l.suffix == r.suffix } -pub fn eq_poly_ref_trait(l: &PolyTraitRef, r: &PolyTraitRef) -> bool { +fn eq_poly_ref_trait(l: &PolyTraitRef, r: &PolyTraitRef) -> bool { l.modifiers == r.modifiers && eq_path(&l.trait_ref.path, &r.trait_ref.path) && over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { @@ -951,7 +951,7 @@ pub fn eq_poly_ref_trait(l: &PolyTraitRef, r: &PolyTraitRef) -> bool { }) } -pub fn eq_generic_param(l: &GenericParam, r: &GenericParam) -> bool { +fn eq_generic_param(l: &GenericParam, r: &GenericParam) -> bool { use GenericParamKind::*; l.is_placeholder == r.is_placeholder && eq_id(l.ident, r.ident) @@ -976,7 +976,7 @@ pub fn eq_generic_param(l: &GenericParam, r: &GenericParam) -> bool { && over(&l.attrs, &r.attrs, eq_attr) } -pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { +fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { use GenericBound::*; match (l, r) { (Trait(ptr1), Trait(ptr2)) => eq_poly_ref_trait(ptr1, ptr2), @@ -985,14 +985,6 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { } } -pub fn eq_precise_capture(l: &PreciseCapturingArg, r: &PreciseCapturingArg) -> bool { - match (l, r) { - (PreciseCapturingArg::Lifetime(l), PreciseCapturingArg::Lifetime(r)) => l.ident == r.ident, - (PreciseCapturingArg::Arg(l, _), PreciseCapturingArg::Arg(r, _)) => l.segments[0].ident == r.segments[0].ident, - _ => false, - } -} - fn eq_term(l: &Term, r: &Term) -> bool { match (l, r) { (Term::Ty(l), Term::Ty(r)) => eq_ty(l, r), @@ -1001,7 +993,7 @@ fn eq_term(l: &Term, r: &Term) -> bool { } } -pub fn eq_assoc_item_constraint(l: &AssocItemConstraint, r: &AssocItemConstraint) -> bool { +fn eq_assoc_item_constraint(l: &AssocItemConstraint, r: &AssocItemConstraint) -> bool { use AssocItemConstraintKind::*; eq_id(l.ident, r.ident) && match (&l.kind, &r.kind) { @@ -1011,11 +1003,11 @@ pub fn eq_assoc_item_constraint(l: &AssocItemConstraint, r: &AssocItemConstraint } } -pub fn eq_mac_call(l: &MacCall, r: &MacCall) -> bool { +fn eq_mac_call(l: &MacCall, r: &MacCall) -> bool { eq_path(&l.path, &r.path) && eq_delim_args(&l.args, &r.args) } -pub fn eq_attr(l: &Attribute, r: &Attribute) -> bool { +fn eq_attr(l: &Attribute, r: &Attribute) -> bool { use AttrKind::*; l.style == r.style && match (&l.kind, &r.kind) { @@ -1027,7 +1019,7 @@ pub fn eq_attr(l: &Attribute, r: &Attribute) -> bool { } } -pub fn eq_attr_item_kind(l: &AttrItemKind, r: &AttrItemKind) -> bool { +fn eq_attr_item_kind(l: &AttrItemKind, r: &AttrItemKind) -> bool { match (l, r) { (AttrItemKind::Unparsed(l), AttrItemKind::Unparsed(r)) => eq_attr_args(l, r), (AttrItemKind::Parsed(_l), AttrItemKind::Parsed(_r)) => todo!(), @@ -1035,7 +1027,7 @@ pub fn eq_attr_item_kind(l: &AttrItemKind, r: &AttrItemKind) -> bool { } } -pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool { +fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool { use AttrArgs::*; match (l, r) { (Empty, Empty) => true, @@ -1045,7 +1037,7 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool { } } -pub fn eq_delim_args(l: &DelimArgs, r: &DelimArgs) -> bool { +fn eq_delim_args(l: &DelimArgs, r: &DelimArgs) -> bool { l.delim == r.delim && l.tokens.len() == r.tokens.len() && l.tokens.iter().zip(r.tokens.iter()).all(|(a, b)| a.eq_unspanned(b)) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 52b3a4700c482..1ad12da6e62cb 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1030,7 +1030,7 @@ pub fn method_calls<'tcx>(expr: &'tcx Expr<'tcx>, max_depth: usize) -> (Vec(expr: &'a Expr<'_>, methods: &[Symbol]) -> Option, &'a [Expr<'a>])>> { diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index f30f26f3a70b8..02d502f8b67f8 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -352,7 +352,7 @@ impl SourceFileRange { } } -/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block` with no label. +/// Like [`snippet_block`], but add braces if the expr is not an `ExprKind::Block` with no label. pub fn expr_block( sess: &impl HasSession, expr: &Expr<'_>, @@ -518,8 +518,10 @@ fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option, /// Converts a span to a code snippet if available, otherwise returns the default. /// /// This is useful if you want to provide suggestions for your lint or more generally, if you want -/// to convert a given `Span` to a `str`. To create suggestions consider using -/// [`snippet_with_applicability`] to ensure that the applicability stays correct. +/// to convert a given `Span` to a `str`. +/// +/// To create suggestions consider using [`snippet_with_applicability`] to ensure that the +/// applicability stays correct. /// /// # Example /// ```rust,ignore @@ -528,7 +530,7 @@ fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option, /// // ^^^^^ ^^^^^^^^^^ /// // span1 span2 /// -/// // The snipped call would return the corresponding code snippet +/// // The snippet call would return the corresponding code snippet /// snippet(cx, span1, "..") // -> "value" /// snippet(cx, span2, "..") // -> "Vec::new()" /// ``` @@ -542,6 +544,9 @@ pub fn snippet<'a>(sess: &impl HasSession, span: Span, default: &'a str) -> Cow< /// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`. /// - If the default value is used and the applicability level is `MachineApplicable`, change it to /// `HasPlaceholders` +/// +/// If the span might realistically contain a macro call (e.g. `vec![]`), consider using +/// [`snippet_with_context`] instead. pub fn snippet_with_applicability<'a>( sess: &impl HasSession, span: Span, @@ -560,15 +565,14 @@ fn snippet_with_applicability_sess<'a>( if *applicability != Applicability::Unspecified && span.from_expansion() { *applicability = Applicability::MaybeIncorrect; } - snippet_opt(sess, span).map_or_else( - || { - if *applicability == Applicability::MachineApplicable { - *applicability = Applicability::HasPlaceholders; - } - Cow::Borrowed(default) - }, - From::from, - ) + if let Some(t) = snippet_opt(sess, span) { + Cow::Owned(t) + } else { + if *applicability == Applicability::MachineApplicable { + *applicability = Applicability::HasPlaceholders; + } + Cow::Borrowed(default) + } } /// Converts a span to a code snippet. Returns `None` if not available. @@ -616,8 +620,8 @@ pub fn snippet_block(sess: &impl HasSession, span: Span, default: &str, indent_r reindent_multiline(&snip, true, indent) } -/// Same as `snippet_block`, but adapts the applicability level by the rules of -/// `snippet_with_applicability`. +/// Same as [`snippet_block`], but adapts the applicability level by the rules of +/// [`snippet_with_applicability`]. pub fn snippet_block_with_applicability( sess: &impl HasSession, span: Span, @@ -630,6 +634,7 @@ pub fn snippet_block_with_applicability( reindent_multiline(&snip, true, indent) } +/// Combination of [`snippet_block`] and [`snippet_with_context`]. pub fn snippet_block_with_context( sess: &impl HasSession, span: Span, @@ -643,7 +648,7 @@ pub fn snippet_block_with_context( (reindent_multiline(&snip, true, indent), from_macro) } -/// Same as `snippet_with_applicability`, but first walks the span up to the given context. +/// Same as [`snippet_with_applicability`], but first walks the span up to the given context. /// /// This will result in the macro call, rather than the expansion, if the span is from a child /// context. If the span is not from a child context, it will be used directly instead. diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index b384d58a02f83..056eb818c1ac3 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -65,7 +65,9 @@ pub fn can_partially_move_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool } match ty.kind() { ty::Param(_) => false, - ty::Adt(def, subs) => def.all_fields().any(|f| !is_copy(cx, f.ty(cx.tcx, subs).skip_norm_wip())), + ty::Adt(def, subs) => def + .all_fields() + .any(|f| !is_copy(cx, f.ty(cx.tcx, subs).skip_norm_wip())), _ => true, } } diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index d350af46d97a2..93def90352ada 100644 --- a/declare_clippy_lint/Cargo.toml +++ b/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.97" +version = "0.1.98" edition = "2024" repository = "https://github.com/rust-lang/rust-clippy" license = "MIT OR Apache-2.0" diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 397173e05f8ff..ddf1c5b9333b6 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2026-05-13" +channel = "nightly-2026-05-28" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/tests/ui-cargo/feature_name/fail/src/main.rs b/tests/ui-cargo/feature_name/fail/src/main.rs index 74e40c09ebc83..25a48ea541d1c 100644 --- a/tests/ui-cargo/feature_name/fail/src/main.rs +++ b/tests/ui-cargo/feature_name/fail/src/main.rs @@ -1,5 +1,4 @@ -#![warn(clippy::redundant_feature_names)] -#![warn(clippy::negative_feature_names)] +#![warn(clippy::negative_feature_names, clippy::redundant_feature_names)] fn main() { // test code goes here diff --git a/tests/ui-cargo/feature_name/pass/src/main.rs b/tests/ui-cargo/feature_name/pass/src/main.rs index 74e40c09ebc83..25a48ea541d1c 100644 --- a/tests/ui-cargo/feature_name/pass/src/main.rs +++ b/tests/ui-cargo/feature_name/pass/src/main.rs @@ -1,5 +1,4 @@ -#![warn(clippy::redundant_feature_names)] -#![warn(clippy::negative_feature_names)] +#![warn(clippy::negative_feature_names, clippy::redundant_feature_names)] fn main() { // test code goes here diff --git a/tests/ui-cargo/multiple_inherent_impl/config_fail/src/main.rs b/tests/ui-cargo/multiple_inherent_impl/config_fail/src/main.rs index 7d5e783022480..c3bf642635d4e 100644 --- a/tests/ui-cargo/multiple_inherent_impl/config_fail/src/main.rs +++ b/tests/ui-cargo/multiple_inherent_impl/config_fail/src/main.rs @@ -1,3 +1,2 @@ -#![allow(dead_code)] #![deny(clippy::multiple_inherent_impl)] fn main() {} diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs index 694ef45c75b08..cff001ea7ac70 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs @@ -18,7 +18,6 @@ //@[bad_conf_6] error-in-other-file: //@compile-flags: --test -#![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] /// This module gets linted before clippy gives up. diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs index fb2d2e64bceaf..2b287e62da0b6 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs @@ -3,7 +3,6 @@ //@[var_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/var_1 //@check-pass -#![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] /// This module gets linted before clippy gives up. diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr index 87e4b0c5c7d0a..55f8c0dcbecc9 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr @@ -1,11 +1,11 @@ error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:26:14 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:25:14 | LL | use std::rc::Weak; | ^^^^ | note: should be placed before `SNAKE_CASE` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:22:7 | LL | const SNAKE_CASE: &str = "zzzzzzzz"; | ^^^^^^^^^^ @@ -13,169 +13,169 @@ LL | const SNAKE_CASE: &str = "zzzzzzzz"; = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:165:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:164:7 | LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `TraitUnorderedItemKinds` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:152:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:151:7 | LL | trait TraitUnorderedItemKinds { | ^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:204:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:203:5 | LL | mod this_is_in_the_wrong_position { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `main` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:199:4 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:198:4 | LL | fn main() { | ^^^^ error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:214:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:213:7 | LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `ZisShouldBeBeforeZeMainFn` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:212:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:211:8 | LL | struct ZisShouldBeBeforeZeMainFn; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:44:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 | LL | B, | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:42:5 | LL | C, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:57:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:56:5 | LL | g: u8, | ^ | note: should be placed before `r` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:56:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:55:5 | LL | r: u8, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:59:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:58:5 | LL | b: u8, | ^ | note: should be placed before `g` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:57:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:56:5 | LL | g: u8, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:112:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:111:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:111:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:110:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:121:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:119:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:141:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:140:11 | LL | const B: bool; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:140:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:139:11 | LL | const C: bool; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:148:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:147:8 | LL | fn b(); | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:147:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:146:8 | LL | fn c(); | ^ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:5 | LL | const A: bool; | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:153:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:152:5 | LL | type SomeType; | ^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:170:11 | LL | const B: bool = false; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:170:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:169:11 | LL | const C: bool = false; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:178:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:177:8 | LL | fn b() {} | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:177:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:176:8 | LL | fn c() {} | ^ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:189:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:188:5 | LL | const A: bool = false; | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:187:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:186:5 | LL | type SomeType = (); | ^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr index 87e4b0c5c7d0a..55f8c0dcbecc9 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr @@ -1,11 +1,11 @@ error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:26:14 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:25:14 | LL | use std::rc::Weak; | ^^^^ | note: should be placed before `SNAKE_CASE` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:22:7 | LL | const SNAKE_CASE: &str = "zzzzzzzz"; | ^^^^^^^^^^ @@ -13,169 +13,169 @@ LL | const SNAKE_CASE: &str = "zzzzzzzz"; = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:165:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:164:7 | LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `TraitUnorderedItemKinds` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:152:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:151:7 | LL | trait TraitUnorderedItemKinds { | ^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:204:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:203:5 | LL | mod this_is_in_the_wrong_position { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `main` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:199:4 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:198:4 | LL | fn main() { | ^^^^ error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:214:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:213:7 | LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `ZisShouldBeBeforeZeMainFn` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:212:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:211:8 | LL | struct ZisShouldBeBeforeZeMainFn; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:44:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 | LL | B, | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:42:5 | LL | C, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:57:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:56:5 | LL | g: u8, | ^ | note: should be placed before `r` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:56:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:55:5 | LL | r: u8, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:59:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:58:5 | LL | b: u8, | ^ | note: should be placed before `g` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:57:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:56:5 | LL | g: u8, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:112:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:111:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:111:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:110:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:121:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:119:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:141:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:140:11 | LL | const B: bool; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:140:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:139:11 | LL | const C: bool; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:148:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:147:8 | LL | fn b(); | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:147:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:146:8 | LL | fn c(); | ^ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:5 | LL | const A: bool; | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:153:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:152:5 | LL | type SomeType; | ^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:170:11 | LL | const B: bool = false; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:170:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:169:11 | LL | const C: bool = false; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:178:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:177:8 | LL | fn b() {} | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:177:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:176:8 | LL | fn c() {} | ^ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:189:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:188:5 | LL | const A: bool = false; | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:187:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:186:5 | LL | type SomeType = (); | ^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr index 40505e2a1c452..e668f5543bd49 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr @@ -1,11 +1,11 @@ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:22:7 | LL | const SNAKE_CASE: &str = "zzzzzzzz"; | ^^^^^^^^^^ | note: should be placed before `ZNAKE_CASE` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:22:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:21:7 | LL | const ZNAKE_CASE: &str = "123"; | ^^^^^^^^^^ @@ -13,31 +13,31 @@ LL | const ZNAKE_CASE: &str = "123"; = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:26:14 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:25:14 | LL | use std::rc::Weak; | ^^^^ | note: should be placed before `SNAKE_CASE` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:22:7 | LL | const SNAKE_CASE: &str = "zzzzzzzz"; | ^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:64:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:63:8 | LL | struct EnumWithExternButAtWrongPosition { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `EnumWithoutExtern` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:55:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:54:8 | LL | struct EnumWithoutExtern { | ^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:87:1 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:86:1 | LL | / impl CloneSelf for StructOrdered { LL | | @@ -48,7 +48,7 @@ LL | | } | |_^ | note: should be placed before the following item - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:77:1 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:76:1 | LL | / impl Default for StructOrdered { LL | | fn default() -> Self { @@ -59,25 +59,25 @@ LL | | } | |_^ error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:165:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:164:7 | LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `TraitUnorderedItemKinds` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:152:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:151:7 | LL | trait TraitUnorderedItemKinds { | ^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:183:1 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:182:1 | LL | impl BasicEmptyTrait for StructOrdered {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before the following item - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:168:1 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:167:1 | LL | / impl TraitUnordered for StructUnordered { LL | | const A: bool = false; @@ -88,181 +88,181 @@ LL | | } | |_^ error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:204:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:203:5 | LL | mod this_is_in_the_wrong_position { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `main` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:199:4 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:198:4 | LL | fn main() { | ^^^^ error: incorrect ordering of items (module item groupings specify another order) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:214:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:213:7 | LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `ZisShouldBeBeforeZeMainFn` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:212:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:211:8 | LL | struct ZisShouldBeBeforeZeMainFn; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:14:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:13:11 | LL | const AFTER: i8 = 0; | ^^^^^ | note: should be placed before `BEFORE` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:12:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:11:11 | LL | const BEFORE: i8 = 0; | ^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:44:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 | LL | B, | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:42:5 | LL | C, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:57:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:56:5 | LL | g: u8, | ^ | note: should be placed before `r` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:56:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:55:5 | LL | r: u8, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:59:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:58:5 | LL | b: u8, | ^ | note: should be placed before `g` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:57:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:56:5 | LL | g: u8, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:112:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:111:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:111:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:110:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:121:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:119:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:141:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:140:11 | LL | const B: bool; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:140:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:139:11 | LL | const C: bool; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:148:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:147:8 | LL | fn b(); | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:147:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:146:8 | LL | fn c(); | ^ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:5 | LL | const A: bool; | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:153:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:152:5 | LL | type SomeType; | ^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:170:11 | LL | const B: bool = false; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:170:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:169:11 | LL | const C: bool = false; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:178:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:177:8 | LL | fn b() {} | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:177:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:176:8 | LL | fn c() {} | ^ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:189:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:188:5 | LL | const A: bool = false; | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:187:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:186:5 | LL | type SomeType = (); | ^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:207:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:206:11 | LL | const A: i8 = 1; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:206:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:205:11 | LL | const C: i8 = 0; | ^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs index 1cfed9790c120..4dc8ad8028098 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs @@ -4,7 +4,6 @@ //@[default_exp] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default_exp //@[ord_within] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_within -#![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] /// This module gets linted before clippy gives up. diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs index 96b2fb16f8f52..1de8f46128822 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs @@ -2,7 +2,6 @@ //@revisions: var_1 //@[var_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/var_1 -#![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] /// This module gets linted before clippy gives up. diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr index d8db2243d4171..09b273015029b 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr @@ -1,11 +1,11 @@ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:105:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:104:8 | LL | fn b() {} | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:104:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:103:8 | LL | fn c() {} | ^ @@ -13,85 +13,85 @@ LL | fn c() {} = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:112:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:111:11 | LL | const B: bool = false; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:111:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:110:11 | LL | const C: bool = false; | ^ error: incorrect ordering of impl items (defined order: [Fn, Type, Const]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:119:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:118:5 | LL | type SomeType = (); | ^^^^^^^^^^^^^ | note: should be placed before `A` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:116:5 | LL | const A: bool = false; | ^^^^^^^^^^^^^ error: incorrect ordering of impl items (defined order: [Fn, Type, Const]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:122:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:121:5 | LL | fn a() {} | ^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:119:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:118:5 | LL | type SomeType = (); | ^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:149:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:148:8 | LL | fn b(); | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:148:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:147:8 | LL | fn c(); | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:156:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:155:11 | LL | const B: bool; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:155:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:154:11 | LL | const C: bool; | ^ error: incorrect ordering of trait items (defined order: [Fn, Type, Const]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:163:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:162:5 | LL | type SomeType; | ^^^^^^^^^^^^^ | note: should be placed before `A` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:161:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:160:5 | LL | const A: bool; | ^^^^^^^^^^^^^ error: incorrect ordering of trait items (defined order: [Fn, Type, Const]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:166:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:165:5 | LL | fn a(); | ^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:163:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:162:5 | LL | type SomeType; | ^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr index 57069fd8feed7..3b0d066e45590 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr @@ -1,11 +1,11 @@ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs:22:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs:21:5 | LL | A, | ^ | note: should be placed before `B` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs:21:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs:20:5 | LL | B, | ^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs index 4e8ed5e550a33..f593e1d66fd8c 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs @@ -2,7 +2,6 @@ //@revisions: only_enum //@[only_enum] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_enum -#![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] fn main() {} diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr index 7f6bddf8005fe..700ad90921026 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr @@ -1,11 +1,11 @@ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:43:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:42:8 | LL | fn a() {} | ^ | note: should be placed before `b` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:42:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:41:8 | LL | fn b() {} | ^ @@ -13,25 +13,25 @@ LL | fn b() {} = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:46:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:45:5 | LL | type SomeType = i8; | ^^^^^^^^^^^^^ | note: should be placed before `a` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:43:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:42:5 | LL | fn a() {} | ^^^^^^ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:49:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:48:5 | LL | const A: bool = true; | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:46:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:45:5 | LL | type SomeType = i8; | ^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs index 56e2e188be6aa..51ed8cac5b522 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs @@ -2,7 +2,6 @@ //@revisions: only_impl //@[only_impl] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_impl -#![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] fn main() {} diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr index a7cff238b785b..a511b0e0995d2 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr @@ -1,11 +1,11 @@ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:32:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:31:11 | LL | const A: bool; | ^ | note: should be placed before `B` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:31:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:30:11 | LL | const B: bool; | ^ @@ -13,25 +13,25 @@ LL | const B: bool; = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:38:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:37:8 | LL | fn a(); | ^ | note: should be placed before `b` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:37:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:36:8 | LL | fn b(); | ^ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:45:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:44:5 | LL | const A: bool; | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:43:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:42:5 | LL | type SomeType; | ^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs index d885a20ca50ab..6f7eaef0c891a 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs @@ -2,7 +2,6 @@ //@revisions: only_trait //@[only_trait] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_trait -#![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] fn main() {} diff --git a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr index fcd7864c6677d..7fc216b30d508 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr @@ -1,16 +1,16 @@ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:36:5 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 | LL | a: bool, | ^ | note: should be placed before `b` - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5 | LL | b: bool, | ^ note: the lint level is defined here - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:33:8 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8 | LL | #[deny(clippy::arbitrary_source_item_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr index 81c35ff778b7f..1f75f5099ecc1 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr @@ -1,33 +1,33 @@ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:25:8 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8 | LL | struct OrderedChecked { | ^^^^^^^^^^^^^^ | note: should be placed before `Unordered` - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:19:8 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8 | LL | struct Unordered { | ^^^^^^^^^ note: the lint level is defined here - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:10:9 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9 | LL | #![deny(clippy::arbitrary_source_item_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:36:5 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 | LL | a: bool, | ^ | note: should be placed before `b` - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5 | LL | b: bool, | ^ note: the lint level is defined here - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:33:8 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8 | LL | #[deny(clippy::arbitrary_source_item_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr index 09ede57f295e8..8027f55add673 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr @@ -1,16 +1,16 @@ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:25:8 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8 | LL | struct OrderedChecked { | ^^^^^^^^^^^^^^ | note: should be placed before `Unordered` - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:19:8 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8 | LL | struct Unordered { | ^^^^^^^^^ note: the lint level is defined here - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:10:9 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9 | LL | #![deny(clippy::arbitrary_source_item_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr index 7c515f050c127..f9b56b4bd5142 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr @@ -1,57 +1,57 @@ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:25:8 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8 | LL | struct OrderedChecked { | ^^^^^^^^^^^^^^ | note: should be placed before `Unordered` - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:19:8 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8 | LL | struct Unordered { | ^^^^^^^^^ note: the lint level is defined here - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:10:9 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9 | LL | #![deny(clippy::arbitrary_source_item_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:46:4 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:45:4 | LL | fn before_main() {} | ^^^^^^^^^^^ | note: should be placed before `main` - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:42:4 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:41:4 | LL | fn main() { | ^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:36:5 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 | LL | a: bool, | ^ | note: should be placed before `b` - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5 | LL | b: bool, | ^ note: the lint level is defined here - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:33:8 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8 | LL | #[deny(clippy::arbitrary_source_item_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:52:11 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:51:11 | LL | const A: i8 = 0; | ^ | note: should be placed before `B` - --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:51:11 + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:50:11 | LL | const B: i8 = 1; | ^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs index cb6d0170b8f97..d7bc398451cb0 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs @@ -6,7 +6,6 @@ //@[ord_in_3] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_in_3 //@compile-flags: --test -#![allow(dead_code)] #![deny(clippy::arbitrary_source_item_ordering)] #[allow(clippy::arbitrary_source_item_ordering)] diff --git a/tests/ui-toml/array_size_threshold/array_size_threshold.rs b/tests/ui-toml/array_size_threshold/array_size_threshold.rs index b8652137378e6..07779e7926425 100644 --- a/tests/ui-toml/array_size_threshold/array_size_threshold.rs +++ b/tests/ui-toml/array_size_threshold/array_size_threshold.rs @@ -1,4 +1,3 @@ -#![allow(unused)] #![warn(clippy::large_const_arrays, clippy::large_stack_arrays)] //@no-rustfix const ABOVE: [u8; 11] = [0; 11]; diff --git a/tests/ui-toml/array_size_threshold/array_size_threshold.stderr b/tests/ui-toml/array_size_threshold/array_size_threshold.stderr index c962e80940763..fbfd38de5809d 100644 --- a/tests/ui-toml/array_size_threshold/array_size_threshold.stderr +++ b/tests/ui-toml/array_size_threshold/array_size_threshold.stderr @@ -1,5 +1,5 @@ error: large array defined as const - --> tests/ui-toml/array_size_threshold/array_size_threshold.rs:4:1 + --> tests/ui-toml/array_size_threshold/array_size_threshold.rs:3:1 | LL | const ABOVE: [u8; 11] = [0; 11]; | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | const ABOVE: [u8; 11] = [0; 11]; = help: to override `-D warnings` add `#[allow(clippy::large_const_arrays)]` error: allocating a local array larger than 10 bytes - --> tests/ui-toml/array_size_threshold/array_size_threshold.rs:9:17 + --> tests/ui-toml/array_size_threshold/array_size_threshold.rs:8:17 | LL | let above = [0u8; 11]; | ^^^^^^^^^ diff --git a/tests/ui-toml/dbg_macro/dbg_macro.fixed b/tests/ui-toml/dbg_macro/dbg_macro.fixed index a914145593248..08a8437e10504 100644 --- a/tests/ui-toml/dbg_macro/dbg_macro.fixed +++ b/tests/ui-toml/dbg_macro/dbg_macro.fixed @@ -1,6 +1,6 @@ //@compile-flags: --test #![warn(clippy::dbg_macro)] -#![allow(clippy::unnecessary_operation, clippy::no_effect)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] fn foo(n: u32) -> u32 { if let Some(n) = n.checked_sub(4) { n } else { n } diff --git a/tests/ui-toml/dbg_macro/dbg_macro.rs b/tests/ui-toml/dbg_macro/dbg_macro.rs index 6565f2e3cf7c6..1286f696fcd09 100644 --- a/tests/ui-toml/dbg_macro/dbg_macro.rs +++ b/tests/ui-toml/dbg_macro/dbg_macro.rs @@ -1,6 +1,6 @@ //@compile-flags: --test #![warn(clippy::dbg_macro)] -#![allow(clippy::unnecessary_operation, clippy::no_effect)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } diff --git a/tests/ui-toml/disallowed_macros/disallowed_macros.rs b/tests/ui-toml/disallowed_macros/disallowed_macros.rs index cfe19606ef4a8..4cdc89ef190d4 100644 --- a/tests/ui-toml/disallowed_macros/disallowed_macros.rs +++ b/tests/ui-toml/disallowed_macros/disallowed_macros.rs @@ -1,8 +1,6 @@ //@aux-build:macros.rs //@aux-build:proc_macros.rs -#![allow(unused)] - extern crate macros; extern crate proc_macros; diff --git a/tests/ui-toml/disallowed_macros/disallowed_macros.stderr b/tests/ui-toml/disallowed_macros/disallowed_macros.stderr index 589995fa87d91..8e375a418bf8f 100644 --- a/tests/ui-toml/disallowed_macros/disallowed_macros.stderr +++ b/tests/ui-toml/disallowed_macros/disallowed_macros.stderr @@ -1,5 +1,5 @@ error: use of a disallowed macro `serde::Serialize` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:22:14 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:20:14 | LL | #[derive(Serialize)] | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | #[derive(Serialize)] = help: to override `-D warnings` add `#[allow(clippy::disallowed_macros)]` error: use of a disallowed macro `macros::attr` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:42:1 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:40:1 | LL | / macros::attr! { LL | | @@ -18,85 +18,85 @@ LL | | } | |_^ error: use of a disallowed macro `proc_macros::Derive` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:62:10 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:60:10 | LL | #[derive(Derive)] | ^^^^^^ error: use of a disallowed macro `std::println` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:13:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:11:5 | LL | println!("one"); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `std::println` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:15:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:13:5 | LL | println!("two"); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `std::cfg` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:17:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:15:5 | LL | cfg!(unix); | ^^^^^^^^^^ error: use of a disallowed macro `std::vec` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:19:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:17:5 | LL | vec![1, 2, 3]; | ^^^^^^^^^^^^^ error: use of a disallowed macro `macros::expr` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:26:13 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:24:13 | LL | let _ = macros::expr!(); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::stmt` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:28:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:26:5 | LL | macros::stmt!(); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::pat` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:30:9 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:28:9 | LL | let macros::pat!() = 1; | ^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::ty` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:32:12 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:30:12 | LL | let _: macros::ty!() = ""; | ^^^^^^^^^^^^^ error: use of a disallowed macro `macros::item` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:34:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:32:5 | LL | macros::item!(); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::binop` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:36:13 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:34:13 | LL | let _ = macros::binop!(1); | ^^^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::item` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:48:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:46:5 | LL | macros::item!(); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::item` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:53:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:51:5 | LL | macros::item!(); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::item` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:58:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:56:5 | LL | macros::item!(); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index 001a6ceb1b17d..24be4b69d2704 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -3,16 +3,15 @@ #![feature(custom_inner_attributes)] #![warn(clippy::excessive_nesting)] #![allow( - unused, + clippy::blocks_in_conditions, + clippy::collapsible_if, clippy::let_and_return, - clippy::redundant_closure_call, - clippy::no_effect, - clippy::unnecessary_operation, - clippy::never_loop, clippy::needless_ifs, - clippy::collapsible_if, - clippy::blocks_in_conditions, + clippy::never_loop, + clippy::no_effect, + clippy::redundant_closure_call, clippy::single_match, + clippy::unnecessary_operation, )] #[macro_use] diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr index bc2c4b8612ecd..a6fe677a8a71e 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr @@ -1,5 +1,5 @@ error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:25:25 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:24:25 | LL | let w = { 3 }; | ^^^^^ @@ -9,7 +9,7 @@ LL | let w = { 3 }; = help: to override `-D warnings` add `#[allow(clippy::excessive_nesting)]` error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:72:17 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:71:17 | LL | / impl C { LL | | @@ -20,7 +20,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:87:25 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:86:25 | LL | let x = { 1 }; // not a warning, but cc is | ^^^^^ @@ -28,7 +28,7 @@ LL | let x = { 1 }; // not a warning, but cc is = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:105:17 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:104:17 | LL | / pub mod e { LL | | @@ -39,7 +39,7 @@ LL | | } // not here = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:119:18 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:118:18 | LL | a_but_not({{{{{{{{0}}}}}}}}); | ^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | a_but_not({{{{{{{{0}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:121:12 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:120:12 | LL | a.a({{{{{{{{{0}}}}}}}}}); | ^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | a.a({{{{{{{{{0}}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:123:12 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:122:12 | LL | (0, {{{{{{{1}}}}}}}); | ^^^^^^^^^ @@ -63,7 +63,7 @@ LL | (0, {{{{{{{1}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:129:25 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:128:25 | LL | if true { | _________________________^ @@ -76,7 +76,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:142:29 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:141:29 | LL | let z = (|| { | _____________________________^ @@ -89,7 +89,7 @@ LL | | })(); = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:162:13 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:161:13 | LL | y += {{{{{5}}}}}; | ^^^^^ @@ -97,7 +97,7 @@ LL | y += {{{{{5}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:164:20 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:163:20 | LL | let z = y + {{{{{{{{{5}}}}}}}}}; | ^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | let z = y + {{{{{{{{{5}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:166:12 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:165:12 | LL | [0, {{{{{{{{{{0}}}}}}}}}}]; | ^^^^^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | [0, {{{{{{{{{{0}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:168:25 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:167:25 | LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; | ^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:170:11 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:169:11 | LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:172:13 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:171:13 | LL | &mut {{{{{{{{{{y}}}}}}}}}}; | ^^^^^^^^^^^^^^^ @@ -137,7 +137,7 @@ LL | &mut {{{{{{{{{{y}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:175:17 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:174:17 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^ @@ -145,7 +145,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:175:28 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:174:28 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^^^^^ @@ -153,7 +153,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:179:28 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:178:28 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^^^^ @@ -161,7 +161,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:179:48 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:178:48 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^ @@ -169,7 +169,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:183:14 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:182:14 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:183:35 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:182:35 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:187:23 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:186:23 | LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:190:8 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:189:8 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^ @@ -201,7 +201,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:190:20 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:189:20 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^^^^ @@ -209,7 +209,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:193:8 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:192:8 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^ @@ -217,7 +217,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:193:21 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:192:21 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:196:10 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:195:10 | LL | ..{{{{{{{5}}}}}}}; | ^^^^^^^^^ @@ -233,7 +233,7 @@ LL | ..{{{{{{{5}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:198:11 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:197:11 | LL | ..={{{{{3}}}}}; | ^^^^^ @@ -241,7 +241,7 @@ LL | ..={{{{{3}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:200:8 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:199:8 | LL | {{{{{1;}}}}}..; | ^^^^^^ @@ -249,7 +249,7 @@ LL | {{{{{1;}}}}}..; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:203:20 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:202:20 | LL | loop { break {{{{1}}}} }; | ^^^^^ @@ -257,7 +257,7 @@ LL | loop { break {{{{1}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:205:13 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:204:13 | LL | loop {{{{{{}}}}}} | ^^^^^^ @@ -265,7 +265,7 @@ LL | loop {{{{{{}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:208:14 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:207:14 | LL | match {{{{{{true}}}}}} { | ^^^^^^^^^^ @@ -273,7 +273,7 @@ LL | match {{{{{{true}}}}}} { = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:210:20 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:209:20 | LL | true => {{{{}}}}, | ^^ @@ -281,7 +281,7 @@ LL | true => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:212:21 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:211:21 | LL | false => {{{{}}}}, | ^^ @@ -289,7 +289,7 @@ LL | false => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:219:17 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:218:17 | LL | / { LL | | @@ -300,7 +300,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:229:28 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:228:28 | LL | async fn c() -> u32 {{{{{{{0}}}}}}} | ^^^^^^^^^ @@ -308,7 +308,7 @@ LL | async fn c() -> u32 {{{{{{{0}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:236:8 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:235:8 | LL | {{{{b().await}}}}; | ^^^^^^^^^^^ diff --git a/tests/ui-toml/excessive_precision/excessive_precision.fixed b/tests/ui-toml/excessive_precision/excessive_precision.fixed index 577bbff2957fb..13a4b47ae262c 100644 --- a/tests/ui-toml/excessive_precision/excessive_precision.fixed +++ b/tests/ui-toml/excessive_precision/excessive_precision.fixed @@ -1,11 +1,5 @@ #![warn(clippy::excessive_precision)] -#![allow( - dead_code, - overflowing_literals, - unused_variables, - clippy::print_literal, - clippy::useless_vec -)] +#![allow(overflowing_literals, clippy::print_literal, clippy::useless_vec)] fn main() { // Overly specified constants diff --git a/tests/ui-toml/excessive_precision/excessive_precision.rs b/tests/ui-toml/excessive_precision/excessive_precision.rs index 121448ed540dc..7ebcb2d24c4e7 100644 --- a/tests/ui-toml/excessive_precision/excessive_precision.rs +++ b/tests/ui-toml/excessive_precision/excessive_precision.rs @@ -1,11 +1,5 @@ #![warn(clippy::excessive_precision)] -#![allow( - dead_code, - overflowing_literals, - unused_variables, - clippy::print_literal, - clippy::useless_vec -)] +#![allow(overflowing_literals, clippy::print_literal, clippy::useless_vec)] fn main() { // Overly specified constants diff --git a/tests/ui-toml/excessive_precision/excessive_precision.stderr b/tests/ui-toml/excessive_precision/excessive_precision.stderr index 65d33eddef172..da98bd28c0e07 100644 --- a/tests/ui-toml/excessive_precision/excessive_precision.stderr +++ b/tests/ui-toml/excessive_precision/excessive_precision.stderr @@ -1,11 +1,11 @@ error: float has excessive precision - --> tests/ui-toml/excessive_precision/excessive_precision.rs:12:18 + --> tests/ui-toml/excessive_precision/excessive_precision.rs:6:18 | LL | let _: f32 = 1.012345678901234567890; | ^^^^^^^^^^^^^^^^^^^^^^^ | note: consider making it a `const` item - --> tests/ui-toml/excessive_precision/excessive_precision.rs:12:5 + --> tests/ui-toml/excessive_precision/excessive_precision.rs:6:5 | LL | let _: f32 = 1.012345678901234567890; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,13 +18,13 @@ LL + let _: f32 = 1.012_345_7; | error: float has excessive precision - --> tests/ui-toml/excessive_precision/excessive_precision.rs:14:18 + --> tests/ui-toml/excessive_precision/excessive_precision.rs:8:18 | LL | let _: f64 = 1.012345678901234567890; | ^^^^^^^^^^^^^^^^^^^^^^^ | note: consider making it a `const` item - --> tests/ui-toml/excessive_precision/excessive_precision.rs:14:5 + --> tests/ui-toml/excessive_precision/excessive_precision.rs:8:5 | LL | let _: f64 = 1.012345678901234567890; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs b/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs index 2a6097fb57953..63978c8b6e197 100644 --- a/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs +++ b/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs @@ -1,5 +1,5 @@ #![warn(clippy::ifs_same_cond)] -#![allow(clippy::if_same_then_else, clippy::comparison_chain, clippy::needless_else)] +#![allow(clippy::comparison_chain, clippy::if_same_then_else, clippy::needless_else)] fn main() {} diff --git a/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.rs b/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.rs index 08fc7edf1c861..1fb1d6bab3b01 100644 --- a/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.rs +++ b/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.rs @@ -11,6 +11,6 @@ trait Private { } pub trait Public { - fn t(_: impl Trait); //~ ERROR: `impl Trait` used as a function parameter + fn t(_: impl Trait); //~ impl_trait_in_params fn tt(_: T); } diff --git a/tests/ui-toml/item_name_repetitions/allow_exact_repetitions/item_name_repetitions.rs b/tests/ui-toml/item_name_repetitions/allow_exact_repetitions/item_name_repetitions.rs index 20603766624c7..ce5373e45a4af 100644 --- a/tests/ui-toml/item_name_repetitions/allow_exact_repetitions/item_name_repetitions.rs +++ b/tests/ui-toml/item_name_repetitions/allow_exact_repetitions/item_name_repetitions.rs @@ -1,5 +1,4 @@ #![warn(clippy::module_name_repetitions)] -#![allow(dead_code)] pub mod foo { // this line should produce a warning: diff --git a/tests/ui-toml/item_name_repetitions/allow_exact_repetitions/item_name_repetitions.stderr b/tests/ui-toml/item_name_repetitions/allow_exact_repetitions/item_name_repetitions.stderr index 8e6f726d02c01..3186a73cac9d9 100644 --- a/tests/ui-toml/item_name_repetitions/allow_exact_repetitions/item_name_repetitions.stderr +++ b/tests/ui-toml/item_name_repetitions/allow_exact_repetitions/item_name_repetitions.stderr @@ -1,5 +1,5 @@ error: item name is the same as its containing module's name - --> tests/ui-toml/item_name_repetitions/allow_exact_repetitions/item_name_repetitions.rs:6:12 + --> tests/ui-toml/item_name_repetitions/allow_exact_repetitions/item_name_repetitions.rs:5:12 | LL | pub fn foo() {} | ^^^ diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs index d6b0a30179208..e08a822d763ec 100644 --- a/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs +++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs @@ -1,5 +1,4 @@ #![warn(clippy::module_name_repetitions)] -#![allow(dead_code)] pub mod foo { // #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name. diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.stderr b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.stderr index 6cfe0eab47927..fd37833a4258b 100644 --- a/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.stderr +++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.stderr @@ -1,5 +1,5 @@ error: item name ends with its containing module's name - --> tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs:9:12 + --> tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs:8:12 | LL | pub fn to_foo() {} | ^^^^^^ diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs index 347430f3d2f97..323d14819fc49 100644 --- a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs +++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs @@ -1,5 +1,4 @@ #![warn(clippy::module_name_repetitions)] -#![allow(dead_code)] pub mod foo { // #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name. diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.stderr b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.stderr index f495ec4218411..d897cdb50073d 100644 --- a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.stderr +++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.stderr @@ -1,5 +1,5 @@ error: item name ends with its containing module's name - --> tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs:9:12 + --> tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs:8:12 | LL | pub fn something_foo() {} | ^^^^^^^^^^^^^ diff --git a/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs b/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs index 1f1f1c6f1a316..8e2abc7869498 100644 --- a/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs +++ b/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs @@ -1,4 +1,4 @@ -#![allow(nonstandard_style, unused)] +#![allow(nonstandard_style)] pub struct Aaa; pub struct Bbb; diff --git a/tests/ui-toml/min_ident_chars/min_ident_chars.rs b/tests/ui-toml/min_ident_chars/min_ident_chars.rs index 385e23d69bcd0..4b99924cc0462 100644 --- a/tests/ui-toml/min_ident_chars/min_ident_chars.rs +++ b/tests/ui-toml/min_ident_chars/min_ident_chars.rs @@ -1,5 +1,5 @@ //@aux-build:extern_types.rs -#![allow(nonstandard_style, unused)] +#![allow(nonstandard_style)] #![warn(clippy::min_ident_chars)] extern crate extern_types; 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 d73da96543d72..c77f6144f9c9b 100644 --- a/tests/ui-toml/min_rust_version/min_rust_version.fixed +++ b/tests/ui-toml/min_rust_version/min_rust_version.fixed @@ -1,5 +1,5 @@ -#![allow(clippy::redundant_clone, clippy::unnecessary_operation, clippy::incompatible_msrv)] -#![warn(clippy::manual_non_exhaustive, clippy::borrow_as_ptr, clippy::manual_bits)] +#![allow(clippy::incompatible_msrv, clippy::redundant_clone, clippy::unnecessary_operation)] +#![warn(clippy::borrow_as_ptr, clippy::manual_bits, clippy::manual_non_exhaustive)] use std::mem::{size_of, size_of_val}; use std::ops::Deref; 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 78cfba1189fbf..8e82e2c3d84a7 100644 --- a/tests/ui-toml/min_rust_version/min_rust_version.rs +++ b/tests/ui-toml/min_rust_version/min_rust_version.rs @@ -1,5 +1,5 @@ -#![allow(clippy::redundant_clone, clippy::unnecessary_operation, clippy::incompatible_msrv)] -#![warn(clippy::manual_non_exhaustive, clippy::borrow_as_ptr, clippy::manual_bits)] +#![allow(clippy::incompatible_msrv, clippy::redundant_clone, clippy::unnecessary_operation)] +#![warn(clippy::borrow_as_ptr, clippy::manual_bits, clippy::manual_non_exhaustive)] use std::mem::{size_of, size_of_val}; use std::ops::Deref; diff --git a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed index 6b386046efa7c..b83c102582cd8 100644 --- a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed +++ b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed @@ -1,4 +1,4 @@ -#![allow(clippy::no_effect, unused)] +#![allow(clippy::no_effect)] #![warn(clippy::needless_raw_string_hashes)] fn main() { diff --git a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs index f928e590d45c7..f043510356df3 100644 --- a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs +++ b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs @@ -1,4 +1,4 @@ -#![allow(clippy::no_effect, unused)] +#![allow(clippy::no_effect)] #![warn(clippy::needless_raw_string_hashes)] fn main() { diff --git a/tests/ui-toml/print_macro/print_macro.rs b/tests/ui-toml/print_macro/print_macro.rs index 74f3ba7e7fa90..2ee8719d1c602 100644 --- a/tests/ui-toml/print_macro/print_macro.rs +++ b/tests/ui-toml/print_macro/print_macro.rs @@ -1,6 +1,5 @@ //@compile-flags: --test -#![warn(clippy::print_stdout)] -#![warn(clippy::print_stderr)] +#![warn(clippy::print_stderr, clippy::print_stdout)] fn foo(n: u32) { print!("{n}"); diff --git a/tests/ui-toml/print_macro/print_macro.stderr b/tests/ui-toml/print_macro/print_macro.stderr index 835af7ef8c72a..e2a284cb7ec86 100644 --- a/tests/ui-toml/print_macro/print_macro.stderr +++ b/tests/ui-toml/print_macro/print_macro.stderr @@ -1,5 +1,5 @@ error: use of `print!` - --> tests/ui-toml/print_macro/print_macro.rs:6:5 + --> tests/ui-toml/print_macro/print_macro.rs:5:5 | LL | print!("{n}"); | ^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | print!("{n}"); = help: to override `-D warnings` add `#[allow(clippy::print_stdout)]` error: use of `eprint!` - --> tests/ui-toml/print_macro/print_macro.rs:8:5 + --> tests/ui-toml/print_macro/print_macro.rs:7:5 | LL | eprint!("{n}"); | ^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/private-doc-errors/doc_lints.rs b/tests/ui-toml/private-doc-errors/doc_lints.rs index c5d00c91b052f..4d354e22c6d2b 100644 --- a/tests/ui-toml/private-doc-errors/doc_lints.rs +++ b/tests/ui-toml/private-doc-errors/doc_lints.rs @@ -1,7 +1,7 @@ #![deny( - clippy::unnecessary_safety_doc, clippy::missing_errors_doc, - clippy::missing_panics_doc + clippy::missing_panics_doc, + clippy::unnecessary_safety_doc )] /// This is a private function, skip to match behavior with `missing_safety_doc`. diff --git a/tests/ui-toml/private-doc-errors/doc_lints.stderr b/tests/ui-toml/private-doc-errors/doc_lints.stderr index a8ee09b9df78f..d83e10ddb94ed 100644 --- a/tests/ui-toml/private-doc-errors/doc_lints.stderr +++ b/tests/ui-toml/private-doc-errors/doc_lints.stderr @@ -5,9 +5,9 @@ LL | fn you_dont_see_me() { | ^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> tests/ui-toml/private-doc-errors/doc_lints.rs:2:5 + --> tests/ui-toml/private-doc-errors/doc_lints.rs:4:5 | -LL | clippy::unnecessary_safety_doc, +LL | clippy::unnecessary_safety_doc | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: safe function's docs have unnecessary `# Safety` section @@ -23,7 +23,7 @@ LL | pub fn only_crate_wide_accessible() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> tests/ui-toml/private-doc-errors/doc_lints.rs:3:5 + --> tests/ui-toml/private-doc-errors/doc_lints.rs:2:5 | LL | clippy::missing_errors_doc, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,9 +46,9 @@ note: first possible panic found here LL | panic!(); | ^^^^^^^^ note: the lint level is defined here - --> tests/ui-toml/private-doc-errors/doc_lints.rs:4:5 + --> tests/ui-toml/private-doc-errors/doc_lints.rs:3:5 | -LL | clippy::missing_panics_doc +LL | clippy::missing_panics_doc, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe function's docs are missing a `# Safety` section diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs index 87397a549bf41..744ba27899100 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -742,4 +742,24 @@ pub fn type_conversion_does_not_escape_its_context() { //~^ arithmetic_side_effects } +pub fn issue_17005() { + fn id_u8() -> u8 { + 0 + } + fn id_u16() -> u16 { + 0 + } + fn id_u32() -> u32 { + 0 + } + + // cast from a smaller unsigned type, sum cannot overflow + let _ = 1u32 + id_u8() as u32; + let _ = 1u32 + id_u16() as u32; + let _ = 1u64 + id_u8() as u64; + let _ = 1u64 + id_u16() as u64; + let _ = 1u64 + id_u32() as u64; + let _ = 0xf301_0000u32 + id_u16() as u32; +} + fn main() {} diff --git a/tests/ui/assign_ops.fixed b/tests/ui/assign_ops.fixed index 2046d089d6a6c..cdae89a8a7f71 100644 --- a/tests/ui/assign_ops.fixed +++ b/tests/ui/assign_ops.fixed @@ -102,7 +102,7 @@ mod issue14871 { fn constant(value: usize) -> Self; } - impl const NumberConstants for T + const impl NumberConstants for T where T: Number + [const] std::ops::Add, { @@ -120,14 +120,14 @@ mod issue14871 { pub struct S; - impl const std::ops::Add for S { + const impl std::ops::Add for S { type Output = S; fn add(self, _rhs: S) -> S { S } } - impl const std::ops::AddAssign for S { + const impl std::ops::AddAssign for S { fn add_assign(&mut self, rhs: S) {} } diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index f83a40f554730..356522b4e91b4 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -102,7 +102,7 @@ mod issue14871 { fn constant(value: usize) -> Self; } - impl const NumberConstants for T + const impl NumberConstants for T where T: Number + [const] std::ops::Add, { @@ -120,14 +120,14 @@ mod issue14871 { pub struct S; - impl const std::ops::Add for S { + const impl std::ops::Add for S { type Output = S; fn add(self, _rhs: S) -> S { S } } - impl const std::ops::AddAssign for S { + const impl std::ops::AddAssign for S { fn add_assign(&mut self, rhs: S) {} } diff --git a/tests/ui/collapsible_else_if.fixed b/tests/ui/collapsible_else_if.fixed index cd2d9be9f4334..0943ab0e7bf80 100644 --- a/tests/ui/collapsible_else_if.fixed +++ b/tests/ui/collapsible_else_if.fixed @@ -161,3 +161,32 @@ fn in_brackets() { { if y == "world" { println!("world") } else { println!("!") } } } } + +#[rustfmt::skip] +fn ends_with_zero_width_whitespace() { + // Test out snippets ending with the 2 zero-width characters recognized as whitespaces by the lexer, + // but not by char::is_whitespace + // Behaviour shows a whitespace is inserted between else and if here which is desirable in this case + + let x = "hello"; + let y = "world"; + + + // LRM (U+200E) + if x == "hello" { + println!("hello LRM"); + } else‎ if y == "world" { + println!("LRM world"); + } + //~^^^^^ collapsible_else_if + + // RLM (U+200F) + if x == "hello" { + println!("hello RLM"); + } else‏ if y == "world" { + println!("RLM world"); + } + //~^^^^^ collapsible_else_if + + +} diff --git a/tests/ui/collapsible_else_if.rs b/tests/ui/collapsible_else_if.rs index 75f2043285388..21492923db442 100644 --- a/tests/ui/collapsible_else_if.rs +++ b/tests/ui/collapsible_else_if.rs @@ -181,3 +181,36 @@ fn in_brackets() { { if y == "world" { println!("world") } else { println!("!") } } } } + +#[rustfmt::skip] +fn ends_with_zero_width_whitespace() { + // Test out snippets ending with the 2 zero-width characters recognized as whitespaces by the lexer, + // but not by char::is_whitespace + // Behaviour shows a whitespace is inserted between else and if here which is desirable in this case + + let x = "hello"; + let y = "world"; + + + // LRM (U+200E) + if x == "hello" { + println!("hello LRM"); + } else‎{ + if y == "world" { + println!("LRM world"); + } + } + //~^^^^^ collapsible_else_if + + // RLM (U+200F) + if x == "hello" { + println!("hello RLM"); + } else‏{ + if y == "world" { + println!("RLM world"); + } + } + //~^^^^^ collapsible_else_if + + +} diff --git a/tests/ui/collapsible_else_if.stderr b/tests/ui/collapsible_else_if.stderr index ebd78d2b1ffe5..0f88374953e8b 100644 --- a/tests/ui/collapsible_else_if.stderr +++ b/tests/ui/collapsible_else_if.stderr @@ -177,5 +177,41 @@ LL | | (if y == "world" { println!("world") } else { println!("!") }) LL | | } | |_____^ help: collapse nested if block: `if y == "world" { println!("world") } else { println!("!") }` -error: aborting due to 10 previous errors +error: this `else { if .. }` block can be collapsed + --> tests/ui/collapsible_else_if.rs:198:12 + | +LL | } else‎{ + | ___________^ +LL | | if y == "world" { +LL | | println!("LRM world"); +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ } else‎ if y == "world" { +LL + println!("LRM world"); +LL + } + | + +error: this `else { if .. }` block can be collapsed + --> tests/ui/collapsible_else_if.rs:208:12 + | +LL | } else‏{ + | ___________^ +LL | | if y == "world" { +LL | | println!("RLM world"); +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ } else‏ if y == "world" { +LL + println!("RLM world"); +LL + } + | + +error: aborting due to 12 previous errors diff --git a/tests/ui/derivable_impls.fixed b/tests/ui/derivable_impls.fixed index 9f9e4e253c3c4..b5f261cbfcd18 100644 --- a/tests/ui/derivable_impls.fixed +++ b/tests/ui/derivable_impls.fixed @@ -333,7 +333,7 @@ mod issue15493 { #[repr(transparent)] struct Foo(u64); - impl const Default for Foo { + const impl Default for Foo { fn default() -> Self { Self(0) } @@ -345,7 +345,7 @@ mod issue15493 { B, } - impl const Default for Bar { + const impl Default for Bar { fn default() -> Self { Bar::A } diff --git a/tests/ui/derivable_impls.rs b/tests/ui/derivable_impls.rs index 74a793b9a70e6..520af40628a8e 100644 --- a/tests/ui/derivable_impls.rs +++ b/tests/ui/derivable_impls.rs @@ -403,7 +403,7 @@ mod issue15493 { #[repr(transparent)] struct Foo(u64); - impl const Default for Foo { + const impl Default for Foo { fn default() -> Self { Self(0) } @@ -415,7 +415,7 @@ mod issue15493 { B, } - impl const Default for Bar { + const impl Default for Bar { fn default() -> Self { Bar::A } diff --git a/tests/ui/derivable_impls_derive_const.rs b/tests/ui/derivable_impls_derive_const.rs index 7d70db1c097d4..7e4e52d161b69 100644 --- a/tests/ui/derivable_impls_derive_const.rs +++ b/tests/ui/derivable_impls_derive_const.rs @@ -8,7 +8,7 @@ mod issue15493 { #[repr(transparent)] struct Foo(u64); - impl const Default for Foo { + const impl Default for Foo { //~^ derivable_impls fn default() -> Self { Self(0) @@ -21,7 +21,7 @@ mod issue15493 { B, } - impl const Default for Bar { + const impl Default for Bar { //~^ derivable_impls fn default() -> Self { Bar::A diff --git a/tests/ui/derivable_impls_derive_const.stderr b/tests/ui/derivable_impls_derive_const.stderr index 196bac185ddaa..3e6ce13450cdc 100644 --- a/tests/ui/derivable_impls_derive_const.stderr +++ b/tests/ui/derivable_impls_derive_const.stderr @@ -1,7 +1,7 @@ error: this `impl` can be derived --> tests/ui/derivable_impls_derive_const.rs:11:5 | -LL | / impl const Default for Foo { +LL | / const impl Default for Foo { LL | | LL | | fn default() -> Self { LL | | Self(0) @@ -22,7 +22,7 @@ LL ~ error: this `impl` can be derived --> tests/ui/derivable_impls_derive_const.rs:24:5 | -LL | / impl const Default for Bar { +LL | / const impl Default for Bar { LL | | LL | | fn default() -> Self { LL | | Bar::A diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index 036f6c444b649..221d709db754c 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -117,6 +117,7 @@ impl Clone for Packed { fn issue14558() { pub struct Valid { pub unsafe actual: (), + //~^ missing_safety_doc } unsafe impl Copy for Valid {} diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index 2701680e788de..388b077146d36 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -65,5 +65,14 @@ LL | | } | = help: consider deriving `Clone` or removing `Copy` -error: aborting due to 5 previous errors +error: docs for unsafe field missing `# Safety` section + --> tests/ui/derive.rs:119:9 + | +LL | pub unsafe actual: (), + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::missing-safety-doc` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::missing_safety_doc)]` + +error: aborting due to 6 previous errors diff --git a/tests/ui/doc_unsafe.rs b/tests/ui/doc_unsafe.rs index 7146fd7941ab0..12aada4f6cc2c 100644 --- a/tests/ui/doc_unsafe.rs +++ b/tests/ui/doc_unsafe.rs @@ -1,6 +1,9 @@ //@aux-build:proc_macros.rs #![allow(clippy::let_unit_value, clippy::needless_pass_by_ref_mut)] +#![deny(clippy::unnecessary_safety_doc)] +#![expect(incomplete_features)] +#![feature(unsafe_fields)] extern crate proc_macros; use proc_macros::external; @@ -38,6 +41,45 @@ mod private_mod { pub use private_mod::republished; +struct UnsafeStruct { + // Unsafe fields are almost always private, so excluding according to + // `check-private-items` does not make sense (they are also not items). + unsafe field: u8, + //~^ missing_safety_doc +} + +enum UnsafeEnum { + Variant { + unsafe field: u8, + //~^ missing_safety_doc + }, +} + +union UnsafeUnion { + unsafe field: u8, + //~^ missing_safety_doc +} + +struct SafeStruct { + /// # Safety + field: u8, + //~^ unnecessary_safety_doc +} + +enum SafeEnum { + Variant { + /// # Safety + field: u8, + //~^ unnecessary_safety_doc + }, +} + +union SafeUnion { + /// # Safety + field: u8, + //~^ unnecessary_safety_doc +} + pub trait SafeTraitUnsafeMethods { unsafe fn woefully_underdocumented(self); //~^ missing_safety_doc diff --git a/tests/ui/doc_unsafe.stderr b/tests/ui/doc_unsafe.stderr index 6e128133d498e..7d8ff938fdacf 100644 --- a/tests/ui/doc_unsafe.stderr +++ b/tests/ui/doc_unsafe.stderr @@ -1,5 +1,5 @@ error: unsafe function's docs are missing a `# Safety` section - --> tests/ui/doc_unsafe.rs:9:1 + --> tests/ui/doc_unsafe.rs:12:1 | LL | pub unsafe fn destroy_the_planet() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,31 +8,78 @@ LL | pub unsafe fn destroy_the_planet() { = help: to override `-D warnings` add `#[allow(clippy::missing_safety_doc)]` error: unsafe function's docs are missing a `# Safety` section - --> tests/ui/doc_unsafe.rs:33:5 + --> tests/ui/doc_unsafe.rs:36:5 | LL | pub unsafe fn republished() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: docs for unsafe field missing `# Safety` section + --> tests/ui/doc_unsafe.rs:47:5 + | +LL | unsafe field: u8, + | ^^^^^^^^^^^^^^^^ + +error: docs for unsafe field missing `# Safety` section + --> tests/ui/doc_unsafe.rs:53:9 + | +LL | unsafe field: u8, + | ^^^^^^^^^^^^^^^^ + +error: docs for unsafe field missing `# Safety` section + --> tests/ui/doc_unsafe.rs:59:5 + | +LL | unsafe field: u8, + | ^^^^^^^^^^^^^^^^ + +error: field with `# Safety` documentation is not marked unsafe + --> tests/ui/doc_unsafe.rs:65:5 + | +LL | field: u8, + | ^^^^^^^^^ + | + = help: if the field has safety invariants, mark it `unsafe` +note: the lint level is defined here + --> tests/ui/doc_unsafe.rs:4:9 + | +LL | #![deny(clippy::unnecessary_safety_doc)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: field with `# Safety` documentation is not marked unsafe + --> tests/ui/doc_unsafe.rs:72:9 + | +LL | field: u8, + | ^^^^^^^^^ + | + = help: if the field has safety invariants, mark it `unsafe` + +error: field with `# Safety` documentation is not marked unsafe + --> tests/ui/doc_unsafe.rs:79:5 + | +LL | field: u8, + | ^^^^^^^^^ + | + = help: if the field has safety invariants, mark it `unsafe` + error: unsafe function's docs are missing a `# Safety` section - --> tests/ui/doc_unsafe.rs:42:5 + --> tests/ui/doc_unsafe.rs:84:5 | LL | unsafe fn woefully_underdocumented(self); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for unsafe trait missing `# Safety` section - --> tests/ui/doc_unsafe.rs:49:1 + --> tests/ui/doc_unsafe.rs:91:1 | LL | pub unsafe trait UnsafeTrait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe function's docs are missing a `# Safety` section - --> tests/ui/doc_unsafe.rs:80:5 + --> tests/ui/doc_unsafe.rs:122:5 | LL | pub unsafe fn more_undocumented_unsafe() -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe function's docs are missing a `# Safety` section - --> tests/ui/doc_unsafe.rs:97:9 + --> tests/ui/doc_unsafe.rs:139:9 | LL | pub unsafe fn whee() { | ^^^^^^^^^^^^^^^^^^^^ @@ -42,5 +89,5 @@ LL | very_unsafe!(); | = note: this error originates in the macro `very_unsafe` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error: aborting due to 12 previous errors diff --git a/tests/ui/double_ended_iterator_last.fixed b/tests/ui/double_ended_iterator_last.fixed index 180a513d0f8e6..be66483beac9c 100644 --- a/tests/ui/double_ended_iterator_last.fixed +++ b/tests/ui/double_ended_iterator_last.fixed @@ -2,7 +2,7 @@ // Typical case pub fn last_arg(s: &str) -> Option<&str> { - s.split(' ').next_back() //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + s.split(' ').next_back() //~ double_ended_iterator_last } fn main() { @@ -19,7 +19,7 @@ fn main() { Some(()) } } - let _ = DeIterator.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + let _ = DeIterator.next_back(); //~ double_ended_iterator_last // Should not apply to other methods of Iterator let _ = DeIterator.count(); diff --git a/tests/ui/double_ended_iterator_last.rs b/tests/ui/double_ended_iterator_last.rs index 3dd72cfeaac73..c99349cecd6d2 100644 --- a/tests/ui/double_ended_iterator_last.rs +++ b/tests/ui/double_ended_iterator_last.rs @@ -2,7 +2,7 @@ // Typical case pub fn last_arg(s: &str) -> Option<&str> { - s.split(' ').last() //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + s.split(' ').last() //~ double_ended_iterator_last } fn main() { @@ -19,7 +19,7 @@ fn main() { Some(()) } } - let _ = DeIterator.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + let _ = DeIterator.last(); //~ double_ended_iterator_last // Should not apply to other methods of Iterator let _ = DeIterator.count(); diff --git a/tests/ui/duplicated_attributes.rs b/tests/ui/duplicated_attributes.rs index 9a67149950595..47ce3e45a2fdd 100644 --- a/tests/ui/duplicated_attributes.rs +++ b/tests/ui/duplicated_attributes.rs @@ -1,9 +1,9 @@ //@aux-build:proc_macro_attr.rs -#![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)] //~ ERROR: duplicated attribute +#![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)] //~ duplicated_attributes #![feature(rustc_attrs)] #![cfg(any(unix, windows))] #![allow(dead_code)] -#![allow(dead_code)] //~ ERROR: duplicated attribute +#![allow(dead_code)] //~ duplicated_attributes #![cfg(any(unix, windows))] // Should not warn! #[macro_use] @@ -11,7 +11,7 @@ extern crate proc_macro_attr; #[cfg(any(unix, windows, target_os = "linux"))] #[allow(dead_code)] -#[allow(dead_code)] //~ ERROR: duplicated attribute +#[allow(dead_code)] //~ duplicated_attributes #[cfg(any(unix, windows, target_os = "linux"))] // Should not warn! fn foo() {} diff --git a/tests/ui/duration_suboptimal_units.fixed b/tests/ui/duration_suboptimal_units.fixed index a4eb981ebfa21..ebdae6f4a2259 100644 --- a/tests/ui/duration_suboptimal_units.fixed +++ b/tests/ui/duration_suboptimal_units.fixed @@ -6,8 +6,8 @@ use std::time::Duration; const SIXTY: u64 = 60; macro_rules! mac { - (slow_rythm) => { - 3600 + (slow_rhythm) => { + 60 * 60 }; (duration) => { Duration::from_mins(5) @@ -23,8 +23,6 @@ fn main() { let dur = Duration::from_secs(42); let dur = Duration::from_hours(3); - let dur = Duration::from_mins(1); - //~^ duration_suboptimal_units let dur = Duration::from_mins(3); //~^ duration_suboptimal_units let dur = Duration::from_mins(10); @@ -44,8 +42,16 @@ fn main() { const { let dur = Duration::from_secs(0); + let dur = Duration::from_millis(5_000); let dur = Duration::from_secs(5); //~^ duration_suboptimal_units + let dur = Duration::from_secs(11); + //~^ duration_suboptimal_units + + let dur = Duration::from_secs(180); + // 39600 secs = 11 hours + let dur = Duration::from_hours(11); + //~^ duration_suboptimal_units let dur = Duration::from_mins(3); //~^ duration_suboptimal_units let dur = Duration::from_hours(24); @@ -55,10 +61,11 @@ fn main() { } // Qualified Durations must be kept - std::time::Duration::from_mins(1); + std::time::Duration::from_mins(12); //~^ duration_suboptimal_units // We lint in normal macros + assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); assert_eq!(Duration::from_hours(1), Duration::from_mins(6)); //~^ duration_suboptimal_units @@ -66,13 +73,13 @@ fn main() { let dur = mac!(duration); // We don't lint in macros if duration comes from outside - let dur = mac!(arg => 3600); + let dur = mac!(arg => 60 * 60); // We don't lint in external macros - let dur = proc_macros::external! { Duration::from_secs(3_600) }; + let dur = proc_macros::external! { Duration::from_secs(60 * 60) }; // We don't lint values coming from macros - let dur = Duration::from_secs(mac!(slow_rythm)); + let dur = Duration::from_secs(mac!(slow_rhythm)); } mod my_duration { @@ -105,3 +112,34 @@ fn sufficient_msrv() { _ = Duration::from_hours(18824455811688); //~^ duration_suboptimal_units } + +fn issue16532() { + // Literals with small promoted values should not lint (issue #16532) + let dur = Duration::from_secs(60); + let dur = Duration::from_secs(180); + let dur = Duration::from_millis(5_000); + let dur = Duration::from_millis(1_000); + let dur = Duration::from_secs(3_600); + let dur = Duration::from_secs(600); + + // Literals with larger promoted values should lint + let dur = Duration::from_secs(20); + //~^ duration_suboptimal_units + let dur = Duration::from_hours(12); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(11); + //~^ duration_suboptimal_units + + // Expressions should always be promoted, as they show intent to use a larger unit + // 5 minutes + let dur = Duration::from_mins(5); + //~^ duration_suboptimal_units + + // 2 Hours + let dur = Duration::from_hours(2); + //~^ duration_suboptimal_units + + // Daily + let dur = Duration::from_hours(24); + //~^ duration_suboptimal_units +} diff --git a/tests/ui/duration_suboptimal_units.rs b/tests/ui/duration_suboptimal_units.rs index e31ca679b5a1a..6a778c9d7c942 100644 --- a/tests/ui/duration_suboptimal_units.rs +++ b/tests/ui/duration_suboptimal_units.rs @@ -6,11 +6,11 @@ use std::time::Duration; const SIXTY: u64 = 60; macro_rules! mac { - (slow_rythm) => { - 3600 + (slow_rhythm) => { + 60 * 60 }; (duration) => { - Duration::from_secs(300) + Duration::from_secs(60 * 5) //~^ duration_suboptimal_units }; (arg => $e:expr) => { @@ -23,15 +23,13 @@ fn main() { let dur = Duration::from_secs(42); let dur = Duration::from_hours(3); - let dur = Duration::from_secs(60); - //~^ duration_suboptimal_units - let dur = Duration::from_secs(180); + let dur = Duration::from_secs(60 * 3); //~^ duration_suboptimal_units let dur = Duration::from_secs(10 * 60); //~^ duration_suboptimal_units let dur = Duration::from_mins(24 * 60); //~^ duration_suboptimal_units - let dur = Duration::from_millis(5_000); + let dur = Duration::from_millis(5 * 1000); //~^ duration_suboptimal_units let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); //~^ duration_suboptimal_units @@ -45,8 +43,16 @@ fn main() { const { let dur = Duration::from_secs(0); let dur = Duration::from_millis(5_000); + let dur = Duration::from_millis(1000 * 5); + //~^ duration_suboptimal_units + let dur = Duration::from_millis(11000); //~^ duration_suboptimal_units + let dur = Duration::from_secs(180); + // 39600 secs = 11 hours + let dur = Duration::from_secs(39600); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(3 * 60); //~^ duration_suboptimal_units let dur = Duration::from_mins(24 * 60); //~^ duration_suboptimal_units @@ -55,24 +61,25 @@ fn main() { } // Qualified Durations must be kept - std::time::Duration::from_secs(60); + std::time::Duration::from_secs(12 * 60); //~^ duration_suboptimal_units // We lint in normal macros assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); + assert_eq!(Duration::from_secs(60 * 60), Duration::from_mins(6)); //~^ duration_suboptimal_units // We lint in normal macros (marker is in macro itself) let dur = mac!(duration); // We don't lint in macros if duration comes from outside - let dur = mac!(arg => 3600); + let dur = mac!(arg => 60 * 60); // We don't lint in external macros - let dur = proc_macros::external! { Duration::from_secs(3_600) }; + let dur = proc_macros::external! { Duration::from_secs(60 * 60) }; // We don't lint values coming from macros - let dur = Duration::from_secs(mac!(slow_rythm)); + let dur = Duration::from_secs(mac!(slow_rhythm)); } mod my_duration { @@ -105,3 +112,34 @@ fn sufficient_msrv() { _ = Duration::from_secs(67_768_040_922_076_800); //~^ duration_suboptimal_units } + +fn issue16532() { + // Literals with small promoted values should not lint (issue #16532) + let dur = Duration::from_secs(60); + let dur = Duration::from_secs(180); + let dur = Duration::from_millis(5_000); + let dur = Duration::from_millis(1_000); + let dur = Duration::from_secs(3_600); + let dur = Duration::from_secs(600); + + // Literals with larger promoted values should lint + let dur = Duration::from_millis(20_000); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(720); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(660); + //~^ duration_suboptimal_units + + // Expressions should always be promoted, as they show intent to use a larger unit + // 5 minutes + let dur = Duration::from_secs(60 * 5); + //~^ duration_suboptimal_units + + // 2 Hours + let dur = Duration::from_mins(60 * 2); + //~^ duration_suboptimal_units + + // Daily + let dur = Duration::from_mins(60 * 24); + //~^ duration_suboptimal_units +} diff --git a/tests/ui/duration_suboptimal_units.stderr b/tests/ui/duration_suboptimal_units.stderr index 97b26f6667eb8..f106005c2bbc5 100644 --- a/tests/ui/duration_suboptimal_units.stderr +++ b/tests/ui/duration_suboptimal_units.stderr @@ -1,31 +1,19 @@ error: constructing a `Duration` using a smaller unit when a larger unit would be more readable --> tests/ui/duration_suboptimal_units.rs:26:15 | -LL | let dur = Duration::from_secs(60); - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | let dur = Duration::from_secs(60 * 3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::duration-suboptimal-units` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::duration_suboptimal_units)]` help: try using from_mins | -LL - let dur = Duration::from_secs(60); -LL + let dur = Duration::from_mins(1); - | - -error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:28:15 - | -LL | let dur = Duration::from_secs(180); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try using from_mins - | -LL - let dur = Duration::from_secs(180); +LL - let dur = Duration::from_secs(60 * 3); LL + let dur = Duration::from_mins(3); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:30:15 + --> tests/ui/duration_suboptimal_units.rs:28:15 | LL | let dur = Duration::from_secs(10 * 60); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +25,7 @@ LL + let dur = Duration::from_mins(10); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:32:15 + --> tests/ui/duration_suboptimal_units.rs:30:15 | LL | let dur = Duration::from_mins(24 * 60); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,19 +37,19 @@ LL + let dur = Duration::from_hours(24); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:34:15 + --> tests/ui/duration_suboptimal_units.rs:32:15 | -LL | let dur = Duration::from_millis(5_000); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let dur = Duration::from_millis(5 * 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: try using from_secs | -LL - let dur = Duration::from_millis(5_000); +LL - let dur = Duration::from_millis(5 * 1000); LL + let dur = Duration::from_secs(5); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:36:15 + --> tests/ui/duration_suboptimal_units.rs:34:15 | LL | let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,31 +61,55 @@ LL + let dur = Duration::from_hours(13); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:47:19 + --> tests/ui/duration_suboptimal_units.rs:46:19 | -LL | let dur = Duration::from_millis(5_000); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let dur = Duration::from_millis(1000 * 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: try using from_secs | -LL - let dur = Duration::from_millis(5_000); +LL - let dur = Duration::from_millis(1000 * 5); LL + let dur = Duration::from_secs(5); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:49:19 + --> tests/ui/duration_suboptimal_units.rs:48:19 + | +LL | let dur = Duration::from_millis(11000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_secs + | +LL - let dur = Duration::from_millis(11000); +LL + let dur = Duration::from_secs(11); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:53:19 + | +LL | let dur = Duration::from_secs(39600); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_secs(39600); +LL + let dur = Duration::from_hours(11); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:55:19 | -LL | let dur = Duration::from_secs(180); - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let dur = Duration::from_secs(3 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: try using from_mins | -LL - let dur = Duration::from_secs(180); +LL - let dur = Duration::from_secs(3 * 60); LL + let dur = Duration::from_mins(3); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:51:19 + --> tests/ui/duration_suboptimal_units.rs:57:19 | LL | let dur = Duration::from_mins(24 * 60); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,34 +121,34 @@ LL + let dur = Duration::from_hours(24); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:58:5 + --> tests/ui/duration_suboptimal_units.rs:64:5 | -LL | std::time::Duration::from_secs(60); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | std::time::Duration::from_secs(12 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: try using from_mins | -LL - std::time::Duration::from_secs(60); -LL + std::time::Duration::from_mins(1); +LL - std::time::Duration::from_secs(12 * 60); +LL + std::time::Duration::from_mins(12); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:62:16 + --> tests/ui/duration_suboptimal_units.rs:69:16 | -LL | assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | assert_eq!(Duration::from_secs(60 * 60), Duration::from_mins(6)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: try using from_hours | -LL - assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); +LL - assert_eq!(Duration::from_secs(60 * 60), Duration::from_mins(6)); LL + assert_eq!(Duration::from_hours(1), Duration::from_mins(6)); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable --> tests/ui/duration_suboptimal_units.rs:13:9 | -LL | Duration::from_secs(300) - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Duration::from_secs(60 * 5) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | let dur = mac!(duration); | -------------- in this macro invocation @@ -144,12 +156,12 @@ LL | let dur = mac!(duration); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: try using from_mins | -LL - Duration::from_secs(300) +LL - Duration::from_secs(60 * 5) LL + Duration::from_mins(5) | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units.rs:105:9 + --> tests/ui/duration_suboptimal_units.rs:112:9 | LL | _ = Duration::from_secs(67_768_040_922_076_800); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,5 +172,77 @@ LL - _ = Duration::from_secs(67_768_040_922_076_800); LL + _ = Duration::from_hours(18824455811688); | -error: aborting due to 13 previous errors +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:126:15 + | +LL | let dur = Duration::from_millis(20_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_secs + | +LL - let dur = Duration::from_millis(20_000); +LL + let dur = Duration::from_secs(20); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:128:15 + | +LL | let dur = Duration::from_mins(720); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_mins(720); +LL + let dur = Duration::from_hours(12); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:130:15 + | +LL | let dur = Duration::from_secs(660); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(660); +LL + let dur = Duration::from_mins(11); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:135:15 + | +LL | let dur = Duration::from_secs(60 * 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(60 * 5); +LL + let dur = Duration::from_mins(5); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:139:15 + | +LL | let dur = Duration::from_mins(60 * 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_mins(60 * 2); +LL + let dur = Duration::from_hours(2); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:143:15 + | +LL | let dur = Duration::from_mins(60 * 24); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_mins(60 * 24); +LL + let dur = Duration::from_hours(24); + | + +error: aborting due to 20 previous errors diff --git a/tests/ui/duration_suboptimal_units_days_weeks.fixed b/tests/ui/duration_suboptimal_units_days_weeks.fixed index b0abcbb7bf034..f9d8852f512ad 100644 --- a/tests/ui/duration_suboptimal_units_days_weeks.fixed +++ b/tests/ui/duration_suboptimal_units_days_weeks.fixed @@ -6,12 +6,18 @@ use std::time::Duration; fn main() { - let dur = Duration::from_mins(1); + let dur = Duration::from_secs(60); + let dur = Duration::from_mins(100); //~^ duration_suboptimal_units - let dur = Duration::from_days(1); + let dur = Duration::from_hours(24); + let dur = Duration::from_days(1000); //~^ duration_suboptimal_units let dur = Duration::from_weeks(13); //~^ duration_suboptimal_units + + // Weekly + let dur = Duration::from_weeks(1); + //~^ duration_suboptimal_units } diff --git a/tests/ui/duration_suboptimal_units_days_weeks.rs b/tests/ui/duration_suboptimal_units_days_weeks.rs index 663476905c0f2..9d71071e768c8 100644 --- a/tests/ui/duration_suboptimal_units_days_weeks.rs +++ b/tests/ui/duration_suboptimal_units_days_weeks.rs @@ -7,11 +7,17 @@ use std::time::Duration; fn main() { let dur = Duration::from_secs(60); + let dur = Duration::from_secs(6000); //~^ duration_suboptimal_units let dur = Duration::from_hours(24); + let dur = Duration::from_hours(24000); //~^ duration_suboptimal_units let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); //~^ duration_suboptimal_units + + // Weekly + let dur = Duration::from_hours(24 * 7); + //~^ duration_suboptimal_units } diff --git a/tests/ui/duration_suboptimal_units_days_weeks.stderr b/tests/ui/duration_suboptimal_units_days_weeks.stderr index 98325358bfa6e..8e8dbfe13fc95 100644 --- a/tests/ui/duration_suboptimal_units_days_weeks.stderr +++ b/tests/ui/duration_suboptimal_units_days_weeks.stderr @@ -1,31 +1,31 @@ error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units_days_weeks.rs:9:15 + --> tests/ui/duration_suboptimal_units_days_weeks.rs:10:15 | -LL | let dur = Duration::from_secs(60); - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | let dur = Duration::from_secs(6000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::duration-suboptimal-units` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::duration_suboptimal_units)]` help: try using from_mins | -LL - let dur = Duration::from_secs(60); -LL + let dur = Duration::from_mins(1); +LL - let dur = Duration::from_secs(6000); +LL + let dur = Duration::from_mins(100); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units_days_weeks.rs:12:15 + --> tests/ui/duration_suboptimal_units_days_weeks.rs:14:15 | -LL | let dur = Duration::from_hours(24); - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let dur = Duration::from_hours(24000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: try using from_days | -LL - let dur = Duration::from_hours(24); -LL + let dur = Duration::from_days(1); +LL - let dur = Duration::from_hours(24000); +LL + let dur = Duration::from_days(1000); | error: constructing a `Duration` using a smaller unit when a larger unit would be more readable - --> tests/ui/duration_suboptimal_units_days_weeks.rs:15:15 + --> tests/ui/duration_suboptimal_units_days_weeks.rs:17:15 | LL | let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,5 +36,17 @@ LL - let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * LL + let dur = Duration::from_weeks(13); | -error: aborting due to 3 previous errors +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units_days_weeks.rs:21:15 + | +LL | let dur = Duration::from_hours(24 * 7); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_weeks + | +LL - let dur = Duration::from_hours(24 * 7); +LL + let dur = Duration::from_weeks(1); + | + +error: aborting due to 4 previous errors diff --git a/tests/ui/empty_enum_variants_with_brackets.fixed b/tests/ui/empty_enum_variants_with_brackets.fixed index caf34eaefab9a..54044f86e71f4 100644 --- a/tests/ui/empty_enum_variants_with_brackets.fixed +++ b/tests/ui/empty_enum_variants_with_brackets.fixed @@ -93,7 +93,7 @@ enum TestEnumWithFeatures { enum Foo { Variant1(i32), Variant2, - Variant3, //~ ERROR: enum variant has empty brackets + Variant3, //~ empty_enum_variants_with_brackets } #[derive(Clone)] diff --git a/tests/ui/empty_enum_variants_with_brackets.rs b/tests/ui/empty_enum_variants_with_brackets.rs index f7ab062edd1e0..9e555b89fc36e 100644 --- a/tests/ui/empty_enum_variants_with_brackets.rs +++ b/tests/ui/empty_enum_variants_with_brackets.rs @@ -93,7 +93,7 @@ enum TestEnumWithFeatures { enum Foo { Variant1(i32), Variant2, - Variant3(), //~ ERROR: enum variant has empty brackets + Variant3(), //~ empty_enum_variants_with_brackets } #[derive(Clone)] diff --git a/tests/ui/equatable_if_let_const_cmp.fixed b/tests/ui/equatable_if_let_const_cmp.fixed index 51dab25ed6d83..32d81688e7d3a 100644 --- a/tests/ui/equatable_if_let_const_cmp.fixed +++ b/tests/ui/equatable_if_let_const_cmp.fixed @@ -7,7 +7,7 @@ fn issue15376() { A, B, } - impl const PartialEq for ConstEq { + const impl PartialEq for ConstEq { fn eq(&self, _other: &Self) -> bool { true } diff --git a/tests/ui/equatable_if_let_const_cmp.rs b/tests/ui/equatable_if_let_const_cmp.rs index b402e05c53de9..336f169380f06 100644 --- a/tests/ui/equatable_if_let_const_cmp.rs +++ b/tests/ui/equatable_if_let_const_cmp.rs @@ -7,7 +7,7 @@ fn issue15376() { A, B, } - impl const PartialEq for ConstEq { + const impl PartialEq for ConstEq { fn eq(&self, _other: &Self) -> bool { true } diff --git a/tests/ui/format.fixed b/tests/ui/format.fixed index 16437c62094af..d461835a43d3d 100644 --- a/tests/ui/format.fixed +++ b/tests/ui/format.fixed @@ -1,3 +1,4 @@ +#![feature(decl_macro)] #![warn(clippy::useless_format)] #![allow( clippy::print_literal, @@ -103,3 +104,41 @@ fn main() { let _ = xx.to_string(); //~^ useless_format } + +// `format!` as the tail expression of a block emitted by another macro +// (e.g. rustc's `with_forced_trimmed_paths!`). The lint must still fire. +mod block_wrap { + macro_rules! plain_mr { + ($e:expr) => { + $e + }; + } + macro_rules! block_mr { + ($e:expr) => {{ + let _g: i32 = 0; + $e + }}; + } + pub macro plain_dm($e:expr) { + $e + } + pub macro block_dm($e:expr) {{ + let _g: i32 = 0; + $e + }} + + fn s() -> String { + String::from("x") + } + + pub fn check() { + let _ = plain_mr!(s().to_string()); + //~^ useless_format + let _ = block_mr!(s().to_string()); + //~^ useless_format + let _ = plain_dm!(s().to_string()); + //~^ useless_format + let _ = block_dm!(s().to_string()); + //~^ useless_format + } +} diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 06371378f27ed..79acf6f33874f 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -1,3 +1,4 @@ +#![feature(decl_macro)] #![warn(clippy::useless_format)] #![allow( clippy::print_literal, @@ -106,3 +107,41 @@ fn main() { let _ = format!("{xx}"); //~^ useless_format } + +// `format!` as the tail expression of a block emitted by another macro +// (e.g. rustc's `with_forced_trimmed_paths!`). The lint must still fire. +mod block_wrap { + macro_rules! plain_mr { + ($e:expr) => { + $e + }; + } + macro_rules! block_mr { + ($e:expr) => {{ + let _g: i32 = 0; + $e + }}; + } + pub macro plain_dm($e:expr) { + $e + } + pub macro block_dm($e:expr) {{ + let _g: i32 = 0; + $e + }} + + fn s() -> String { + String::from("x") + } + + pub fn check() { + let _ = plain_mr!(format!("{}", s())); + //~^ useless_format + let _ = block_mr!(format!("{}", s())); + //~^ useless_format + let _ = plain_dm!(format!("{}", s())); + //~^ useless_format + let _ = block_dm!(format!("{}", s())); + //~^ useless_format + } +} diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index da990d32cb80e..d238dabd6e61a 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -1,5 +1,5 @@ error: useless use of `format!` - --> tests/ui/format.rs:20:5 + --> tests/ui/format.rs:21:5 | LL | format!("foo"); | ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` @@ -8,19 +8,19 @@ LL | format!("foo"); = help: to override `-D warnings` add `#[allow(clippy::useless_format)]` error: useless use of `format!` - --> tests/ui/format.rs:22:5 + --> tests/ui/format.rs:23:5 | LL | format!("{{}}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{}".to_string()` error: useless use of `format!` - --> tests/ui/format.rs:24:5 + --> tests/ui/format.rs:25:5 | LL | format!("{{}} abc {{}}"); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{} abc {}".to_string()` error: useless use of `format!` - --> tests/ui/format.rs:26:5 + --> tests/ui/format.rs:27:5 | LL | / format!( LL | | @@ -36,70 +36,94 @@ LL ~ " bar"##.to_string(); | error: useless use of `format!` - --> tests/ui/format.rs:32:13 + --> tests/ui/format.rs:33:13 | LL | let _ = format!(""); | ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()` error: useless use of `format!` - --> tests/ui/format.rs:35:5 + --> tests/ui/format.rs:36:5 | LL | format!("{}", "foo"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` error: useless use of `format!` - --> tests/ui/format.rs:44:5 + --> tests/ui/format.rs:45:5 | LL | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:75:5 + --> tests/ui/format.rs:76:5 | LL | format!("{}", 42.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:78:5 + --> tests/ui/format.rs:79:5 | LL | format!("{}", x.display().to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()` error: useless use of `format!` - --> tests/ui/format.rs:83:18 + --> tests/ui/format.rs:84:18 | LL | let _ = Some(format!("{}", a + "bar")); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"` error: useless use of `format!` - --> tests/ui/format.rs:88:22 + --> tests/ui/format.rs:89:22 | LL | let _s: String = format!("{}", &*v.join("\n")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("\n")).to_string()` error: useless use of `format!` - --> tests/ui/format.rs:95:13 + --> tests/ui/format.rs:96:13 | LL | let _ = format!("{x}"); | ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:98:13 + --> tests/ui/format.rs:99:13 | LL | let _ = format!("{y}", y = x); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:103:13 + --> tests/ui/format.rs:104:13 | LL | let _ = format!("{abc}"); | ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:106:13 + --> tests/ui/format.rs:107:13 | LL | let _ = format!("{xx}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()` -error: aborting due to 15 previous errors +error: useless use of `format!` + --> tests/ui/format.rs:138:27 + | +LL | let _ = plain_mr!(format!("{}", s())); + | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `s().to_string()` + +error: useless use of `format!` + --> tests/ui/format.rs:140:27 + | +LL | let _ = block_mr!(format!("{}", s())); + | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `s().to_string()` + +error: useless use of `format!` + --> tests/ui/format.rs:142:27 + | +LL | let _ = plain_dm!(format!("{}", s())); + | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `s().to_string()` + +error: useless use of `format!` + --> tests/ui/format.rs:144:27 + | +LL | let _ = block_dm!(format!("{}", s())); + | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `s().to_string()` + +error: aborting due to 19 previous errors diff --git a/tests/ui/ignored_unit_patterns.fixed b/tests/ui/ignored_unit_patterns.fixed index 118f0b4889529..4ae649dd0fbbf 100644 --- a/tests/ui/ignored_unit_patterns.fixed +++ b/tests/ui/ignored_unit_patterns.fixed @@ -13,8 +13,8 @@ fn foo() -> Result<(), ()> { fn main() { match foo() { - Ok(()) => {}, //~ ERROR: matching over `()` is more explicit - Err(()) => {}, //~ ERROR: matching over `()` is more explicit + Ok(()) => {}, //~ ignored_unit_patterns + Err(()) => {}, //~ ignored_unit_patterns } if let Ok(()) = foo() {} //~^ ERROR: matching over `()` is more explicit diff --git a/tests/ui/ignored_unit_patterns.rs b/tests/ui/ignored_unit_patterns.rs index 92feb9e6c2814..e98446a3a1eac 100644 --- a/tests/ui/ignored_unit_patterns.rs +++ b/tests/ui/ignored_unit_patterns.rs @@ -13,8 +13,8 @@ fn foo() -> Result<(), ()> { fn main() { match foo() { - Ok(_) => {}, //~ ERROR: matching over `()` is more explicit - Err(_) => {}, //~ ERROR: matching over `()` is more explicit + Ok(_) => {}, //~ ignored_unit_patterns + Err(_) => {}, //~ ignored_unit_patterns } if let Ok(_) = foo() {} //~^ ERROR: matching over `()` is more explicit diff --git a/tests/ui/manual_midpoint.fixed b/tests/ui/manual_midpoint.fixed index 63116ced84384..f9e16d43956e8 100644 --- a/tests/ui/manual_midpoint.fixed +++ b/tests/ui/manual_midpoint.fixed @@ -27,16 +27,19 @@ fn older_msrv() { #[clippy::msrv = "1.85"] fn main() { let a: u32 = 10; - let _ = u32::midpoint(a, 5); //~ ERROR: manual implementation of `midpoint` + let _ = u32::midpoint(a, 5); //~ manual_midpoint + let _ = u32::midpoint(a, 5); //~ manual_midpoint let f: f32 = 10.0; - let _ = f32::midpoint(f, 5.0); //~ ERROR: manual implementation of `midpoint` + let _ = f32::midpoint(f, 5.0); //~ manual_midpoint + let _ = f32::midpoint(f, 10.0); //~ manual_midpoint + let _ = f32::midpoint(f, 10.0); //~ manual_midpoint - let _: u32 = 5 + u32::midpoint(8, 8) + 2; //~ ERROR: manual implementation of `midpoint` - let _: u32 = const { u32::midpoint(8, 8) }; //~ ERROR: manual implementation of `midpoint` - let _: f64 = const { f64::midpoint(8.0f64, 8.) }; //~ ERROR: manual implementation of `midpoint` - let _: u32 = u32::midpoint(u32::default(), u32::default()); //~ ERROR: manual implementation of `midpoint` - let _: u32 = u32::midpoint(two!(), two!()); //~ ERROR: manual implementation of `midpoint` + let _: u32 = 5 + u32::midpoint(8, 8) + 2; //~ manual_midpoint + let _: u32 = const { u32::midpoint(8, 8) }; //~ manual_midpoint + let _: f64 = const { f64::midpoint(8.0f64, 8.) }; //~ manual_midpoint + let _: u32 = u32::midpoint(u32::default(), u32::default()); //~ manual_midpoint + let _: u32 = u32::midpoint(two!(), two!()); //~ manual_midpoint // Do not lint in presence of an addition with more than 2 operands let _: u32 = (10 + 20 + 30) / 2; @@ -52,14 +55,15 @@ fn main() { // Do not lint on signed integer types let i: i32 = 10; let _ = (i + 5) / 2; + let _ = (i + 5) >> 1; // Do not lint on (x+1)/2 or (1+x)/2 as this looks more like a `div_ceil()` operation let _ = (i + 1) / 2; let _ = (1 + i) / 2; // But if we see (x+1.0)/2.0 or (x+1.0)/2.0, it is probably a midpoint operation - let _ = f32::midpoint(f, 1.0); //~ ERROR: manual implementation of `midpoint` - let _ = f32::midpoint(1.0, f); //~ ERROR: manual implementation of `midpoint` + let _ = f32::midpoint(f, 1.0); //~ manual_midpoint + let _ = f32::midpoint(1.0, f); //~ manual_midpoint } #[clippy::msrv = "1.86"] @@ -70,5 +74,5 @@ fn older_signed_midpoint(i: i32) { #[clippy::msrv = "1.87"] fn signed_midpoint(i: i32) { - let _ = i32::midpoint(i, 10); //~ ERROR: manual implementation of `midpoint` + let _ = i32::midpoint(i, 10); //~ manual_midpoint } diff --git a/tests/ui/manual_midpoint.rs b/tests/ui/manual_midpoint.rs index 47f1b88c78cd8..c3893ef2db12d 100644 --- a/tests/ui/manual_midpoint.rs +++ b/tests/ui/manual_midpoint.rs @@ -27,16 +27,19 @@ fn older_msrv() { #[clippy::msrv = "1.85"] fn main() { let a: u32 = 10; - let _ = (a + 5) / 2; //~ ERROR: manual implementation of `midpoint` + let _ = (a + 5) / 2; //~ manual_midpoint + let _ = (a + 5) >> 1; //~ manual_midpoint let f: f32 = 10.0; - let _ = (f + 5.0) / 2.0; //~ ERROR: manual implementation of `midpoint` + let _ = (f + 5.0) / 2.0; //~ manual_midpoint + let _ = (f + 10.0) * 0.5; //~ manual_midpoint + let _ = 0.5 * (f + 10.0); //~ manual_midpoint - let _: u32 = 5 + (8 + 8) / 2 + 2; //~ ERROR: manual implementation of `midpoint` - let _: u32 = const { (8 + 8) / 2 }; //~ ERROR: manual implementation of `midpoint` - let _: f64 = const { (8.0f64 + 8.) / 2. }; //~ ERROR: manual implementation of `midpoint` - let _: u32 = (u32::default() + u32::default()) / 2; //~ ERROR: manual implementation of `midpoint` - let _: u32 = (two!() + two!()) / 2; //~ ERROR: manual implementation of `midpoint` + let _: u32 = 5 + (8 + 8) / 2 + 2; //~ manual_midpoint + let _: u32 = const { (8 + 8) / 2 }; //~ manual_midpoint + let _: f64 = const { (8.0f64 + 8.) / 2. }; //~ manual_midpoint + let _: u32 = (u32::default() + u32::default()) / 2; //~ manual_midpoint + let _: u32 = (two!() + two!()) / 2; //~ manual_midpoint // Do not lint in presence of an addition with more than 2 operands let _: u32 = (10 + 20 + 30) / 2; @@ -52,14 +55,15 @@ fn main() { // Do not lint on signed integer types let i: i32 = 10; let _ = (i + 5) / 2; + let _ = (i + 5) >> 1; // Do not lint on (x+1)/2 or (1+x)/2 as this looks more like a `div_ceil()` operation let _ = (i + 1) / 2; let _ = (1 + i) / 2; // But if we see (x+1.0)/2.0 or (x+1.0)/2.0, it is probably a midpoint operation - let _ = (f + 1.0) / 2.0; //~ ERROR: manual implementation of `midpoint` - let _ = (1.0 + f) / 2.0; //~ ERROR: manual implementation of `midpoint` + let _ = (f + 1.0) / 2.0; //~ manual_midpoint + let _ = (1.0 + f) / 2.0; //~ manual_midpoint } #[clippy::msrv = "1.86"] @@ -70,5 +74,5 @@ fn older_signed_midpoint(i: i32) { #[clippy::msrv = "1.87"] fn signed_midpoint(i: i32) { - let _ = (i + 10) / 2; //~ ERROR: manual implementation of `midpoint` + let _ = (i + 10) / 2; //~ manual_midpoint } diff --git a/tests/ui/manual_midpoint.stderr b/tests/ui/manual_midpoint.stderr index 3d588e2114df3..1728aea08b04c 100644 --- a/tests/ui/manual_midpoint.stderr +++ b/tests/ui/manual_midpoint.stderr @@ -8,58 +8,76 @@ LL | let _ = (a + 5) / 2; = help: to override `-D warnings` add `#[allow(clippy::manual_midpoint)]` error: manual implementation of `midpoint` which can overflow - --> tests/ui/manual_midpoint.rs:33:13 + --> tests/ui/manual_midpoint.rs:31:13 + | +LL | let _ = (a + 5) >> 1; + | ^^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(a, 5)` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:34:13 | LL | let _ = (f + 5.0) / 2.0; | ^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(f, 5.0)` error: manual implementation of `midpoint` which can overflow - --> tests/ui/manual_midpoint.rs:35:22 + --> tests/ui/manual_midpoint.rs:35:13 + | +LL | let _ = (f + 10.0) * 0.5; + | ^^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(f, 10.0)` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:36:13 + | +LL | let _ = 0.5 * (f + 10.0); + | ^^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(f, 10.0)` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:38:22 | LL | let _: u32 = 5 + (8 + 8) / 2 + 2; | ^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(8, 8)` error: manual implementation of `midpoint` which can overflow - --> tests/ui/manual_midpoint.rs:36:26 + --> tests/ui/manual_midpoint.rs:39:26 | LL | let _: u32 = const { (8 + 8) / 2 }; | ^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(8, 8)` error: manual implementation of `midpoint` which can overflow - --> tests/ui/manual_midpoint.rs:37:26 + --> tests/ui/manual_midpoint.rs:40:26 | LL | let _: f64 = const { (8.0f64 + 8.) / 2. }; | ^^^^^^^^^^^^^^^^^^ help: use `f64::midpoint` instead: `f64::midpoint(8.0f64, 8.)` error: manual implementation of `midpoint` which can overflow - --> tests/ui/manual_midpoint.rs:38:18 + --> tests/ui/manual_midpoint.rs:41:18 | LL | let _: u32 = (u32::default() + u32::default()) / 2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(u32::default(), u32::default())` error: manual implementation of `midpoint` which can overflow - --> tests/ui/manual_midpoint.rs:39:18 + --> tests/ui/manual_midpoint.rs:42:18 | LL | let _: u32 = (two!() + two!()) / 2; | ^^^^^^^^^^^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(two!(), two!())` error: manual implementation of `midpoint` which can overflow - --> tests/ui/manual_midpoint.rs:61:13 + --> tests/ui/manual_midpoint.rs:65:13 | LL | let _ = (f + 1.0) / 2.0; | ^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(f, 1.0)` error: manual implementation of `midpoint` which can overflow - --> tests/ui/manual_midpoint.rs:62:13 + --> tests/ui/manual_midpoint.rs:66:13 | LL | let _ = (1.0 + f) / 2.0; | ^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(1.0, f)` error: manual implementation of `midpoint` which can overflow - --> tests/ui/manual_midpoint.rs:73:13 + --> tests/ui/manual_midpoint.rs:77:13 | LL | let _ = (i + 10) / 2; | ^^^^^^^^^^^^ help: use `i32::midpoint` instead: `i32::midpoint(i, 10)` -error: aborting due to 10 previous errors +error: aborting due to 13 previous errors diff --git a/tests/ui/manual_ok_or.fixed b/tests/ui/manual_ok_or.fixed index f326822149cd3..73987128951e4 100644 --- a/tests/ui/manual_ok_or.fixed +++ b/tests/ui/manual_ok_or.fixed @@ -32,7 +32,15 @@ fn main() { foo.map_or(Ok::(1), |v| Ok(v)); // not applicable, expr is not a `Result` value - foo.map_or(42, |v| v); + foo.map_or(42, |v| v + 1); + + // not applicable, closure isn't `Ok` wrapping + let bar: Option> = None; + #[allow(clippy::map_or_identity)] + bar.map_or(Err("error"), |v| v); + + // not applicable, closure isn't using value + foo.map_or(Err("error"), |_| Ok(42)); // TODO patterns not covered yet match foo { diff --git a/tests/ui/manual_ok_or.rs b/tests/ui/manual_ok_or.rs index 7d065eda0ea1e..f662883964bb4 100644 --- a/tests/ui/manual_ok_or.rs +++ b/tests/ui/manual_ok_or.rs @@ -37,7 +37,15 @@ fn main() { foo.map_or(Ok::(1), |v| Ok(v)); // not applicable, expr is not a `Result` value - foo.map_or(42, |v| v); + foo.map_or(42, |v| v + 1); + + // not applicable, closure isn't `Ok` wrapping + let bar: Option> = None; + #[allow(clippy::map_or_identity)] + bar.map_or(Err("error"), |v| v); + + // not applicable, closure isn't using value + foo.map_or(Err("error"), |_| Ok(42)); // TODO patterns not covered yet match foo { diff --git a/tests/ui/map_or_identity.fixed b/tests/ui/map_or_identity.fixed new file mode 100644 index 0000000000000..67af86195ac2b --- /dev/null +++ b/tests/ui/map_or_identity.fixed @@ -0,0 +1,64 @@ +#![warn(clippy::map_or_identity)] + +mod issue15801 { + + fn foo(opt: Option, default: i32) -> i32 { + opt.unwrap_or(default) + //~^ map_or_identity + } + + fn bar(res: Result, default: i32) -> i32 { + res.unwrap_or(default) + //~^ map_or_identity + } + + fn with_deref(opt: &Option, default: i32) -> i32 { + opt.unwrap_or(default) + //~^ map_or_identity + } +} + +mod macros { + macro_rules! mac { + ($e:expr) => {{ $e }}; + } + + fn option_with_macro(opt: Option) -> i32 { + opt.unwrap_or(mac!(42)) + //~^ map_or_identity + } + + fn result_with_macro(res: Result) -> i32 { + res.unwrap_or(mac!(42)) + //~^ map_or_identity + } + + fn option_with_macro_receiver(opt: Option) -> i32 { + mac!(opt).unwrap_or(42) + //~^ map_or_identity + } + + fn result_with_macro_receiver(res: Result) -> i32 { + mac!(res).unwrap_or(42) + //~^ map_or_identity + } + + // These should not lint because the method call comes from a macro expansion + macro_rules! map_or_mac { + ($e:expr, $d:expr, $f:expr) => { + $e.map_or($d, $f) + }; + } + + fn option_with_macro_call(opt: Option) -> i32 { + map_or_mac!(opt, 42, |x| x) + } + + fn result_with_macro_call(res: Result) -> i32 { + map_or_mac!(res, 42, |x| x) + } +} + +fn main() { + // test code goes here +} diff --git a/tests/ui/map_or_identity.rs b/tests/ui/map_or_identity.rs new file mode 100644 index 0000000000000..bcbb2f899537b --- /dev/null +++ b/tests/ui/map_or_identity.rs @@ -0,0 +1,64 @@ +#![warn(clippy::map_or_identity)] + +mod issue15801 { + + fn foo(opt: Option, default: i32) -> i32 { + opt.map_or(default, |o| o) + //~^ map_or_identity + } + + fn bar(res: Result, default: i32) -> i32 { + res.map_or(default, |o| o) + //~^ map_or_identity + } + + fn with_deref(opt: &Option, default: i32) -> i32 { + opt.map_or(default, |o| o) + //~^ map_or_identity + } +} + +mod macros { + macro_rules! mac { + ($e:expr) => {{ $e }}; + } + + fn option_with_macro(opt: Option) -> i32 { + opt.map_or(mac!(42), |x| x) + //~^ map_or_identity + } + + fn result_with_macro(res: Result) -> i32 { + res.map_or(mac!(42), |x| x) + //~^ map_or_identity + } + + fn option_with_macro_receiver(opt: Option) -> i32 { + mac!(opt).map_or(42, |x| x) + //~^ map_or_identity + } + + fn result_with_macro_receiver(res: Result) -> i32 { + mac!(res).map_or(42, |x| x) + //~^ map_or_identity + } + + // These should not lint because the method call comes from a macro expansion + macro_rules! map_or_mac { + ($e:expr, $d:expr, $f:expr) => { + $e.map_or($d, $f) + }; + } + + fn option_with_macro_call(opt: Option) -> i32 { + map_or_mac!(opt, 42, |x| x) + } + + fn result_with_macro_call(res: Result) -> i32 { + map_or_mac!(res, 42, |x| x) + } +} + +fn main() { + // test code goes here +} diff --git a/tests/ui/map_or_identity.stderr b/tests/ui/map_or_identity.stderr new file mode 100644 index 0000000000000..111ccaccd3abc --- /dev/null +++ b/tests/ui/map_or_identity.stderr @@ -0,0 +1,88 @@ +error: expression can be simplified using `Option::unwrap_or()` + --> tests/ui/map_or_identity.rs:6:9 + | +LL | opt.map_or(default, |o| o) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::map-or-identity` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::map_or_identity)]` +help: consider using `unwrap_or` + | +LL - opt.map_or(default, |o| o) +LL + opt.unwrap_or(default) + | + +error: expression can be simplified using `Result::unwrap_or()` + --> tests/ui/map_or_identity.rs:11:9 + | +LL | res.map_or(default, |o| o) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `unwrap_or` + | +LL - res.map_or(default, |o| o) +LL + res.unwrap_or(default) + | + +error: expression can be simplified using `Option::unwrap_or()` + --> tests/ui/map_or_identity.rs:16:9 + | +LL | opt.map_or(default, |o| o) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `unwrap_or` + | +LL - opt.map_or(default, |o| o) +LL + opt.unwrap_or(default) + | + +error: expression can be simplified using `Option::unwrap_or()` + --> tests/ui/map_or_identity.rs:27:9 + | +LL | opt.map_or(mac!(42), |x| x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `unwrap_or` + | +LL - opt.map_or(mac!(42), |x| x) +LL + opt.unwrap_or(mac!(42)) + | + +error: expression can be simplified using `Result::unwrap_or()` + --> tests/ui/map_or_identity.rs:32:9 + | +LL | res.map_or(mac!(42), |x| x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `unwrap_or` + | +LL - res.map_or(mac!(42), |x| x) +LL + res.unwrap_or(mac!(42)) + | + +error: expression can be simplified using `Option::unwrap_or()` + --> tests/ui/map_or_identity.rs:37:9 + | +LL | mac!(opt).map_or(42, |x| x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `unwrap_or` + | +LL - mac!(opt).map_or(42, |x| x) +LL + mac!(opt).unwrap_or(42) + | + +error: expression can be simplified using `Result::unwrap_or()` + --> tests/ui/map_or_identity.rs:42:9 + | +LL | mac!(res).map_or(42, |x| x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `unwrap_or` + | +LL - mac!(res).map_or(42, |x| x) +LL + mac!(res).unwrap_or(42) + | + +error: aborting due to 7 previous errors + diff --git a/tests/ui/missing_const_for_fn/const_trait.fixed b/tests/ui/missing_const_for_fn/const_trait.fixed index c113c1caaa651..2d0fa2cb38dcf 100644 --- a/tests/ui/missing_const_for_fn/const_trait.fixed +++ b/tests/ui/missing_const_for_fn/const_trait.fixed @@ -11,7 +11,7 @@ impl ConstTrait for u32 { fn method(self) {} } -impl const ConstTrait for u64 { +const impl ConstTrait for u64 { fn method(self) {} } diff --git a/tests/ui/missing_const_for_fn/const_trait.rs b/tests/ui/missing_const_for_fn/const_trait.rs index 69248bc52d5ce..6021469f2ae0c 100644 --- a/tests/ui/missing_const_for_fn/const_trait.rs +++ b/tests/ui/missing_const_for_fn/const_trait.rs @@ -11,7 +11,7 @@ impl ConstTrait for u32 { fn method(self) {} } -impl const ConstTrait for u64 { +const impl ConstTrait for u64 { fn method(self) {} } diff --git a/tests/ui/mixed_attributes_style.rs b/tests/ui/mixed_attributes_style.rs index 93ab9392cf8bd..18ca41b6c519e 100644 --- a/tests/ui/mixed_attributes_style.rs +++ b/tests/ui/mixed_attributes_style.rs @@ -7,7 +7,7 @@ #[macro_use] extern crate proc_macro_attr; -#[allow(unused)] //~ ERROR: item has both inner and outer attributes +#[allow(unused)] //~ mixed_attributes_style fn foo1() { #![allow(unused)] } @@ -22,7 +22,7 @@ fn foo3() { } /// linux -//~^ ERROR: item has both inner and outer attributes +//~^ mixed_attributes_style fn foo4() { //! windows } @@ -36,7 +36,7 @@ fn foo6() { //! windows } -#[allow(unused)] //~ ERROR: item has both inner and outer attributes +#[allow(unused)] //~ mixed_attributes_style mod bar { #![allow(unused)] } @@ -66,7 +66,7 @@ mod issue_12530 { mod tests { #![allow(clippy::unreadable_literal)] - #[allow(dead_code)] //~ ERROR: item has both inner and outer attributes + #[allow(dead_code)] //~ mixed_attributes_style mod inner_mod { #![allow(dead_code)] } @@ -77,18 +77,18 @@ mod issue_12530 { } /// Nested mod mod nested_mod { - #[allow(dead_code)] //~ ERROR: item has both inner and outer attributes + #[allow(dead_code)] //~ mixed_attributes_style mod inner_mod { #![allow(dead_code)] } } /// Nested mod - //~^ ERROR: item has both inner and outer attributes + //~^ mixed_attributes_style #[allow(unused)] mod nest_mod_2 { #![allow(unused)] - #[allow(dead_code)] //~ ERROR: item has both inner and outer attributes + #[allow(dead_code)] //~ mixed_attributes_style mod inner_mod { #![allow(dead_code)] } diff --git a/tests/ui/needless_return_with_question_mark.fixed b/tests/ui/needless_return_with_question_mark.fixed index 8658192a0468e..a8e9f09fa5ecf 100644 --- a/tests/ui/needless_return_with_question_mark.fixed +++ b/tests/ui/needless_return_with_question_mark.fixed @@ -154,3 +154,13 @@ async fn async_block_final_stmt() -> Result<(), ()> { } .await } + +fn last_stmt() -> Result<(), ()> { + return Err(())?; +} + +fn expr_after_stmt() -> Result<(), ()> { + Err(())?; + //~^ needless_return_with_question_mark + Ok(()) +} diff --git a/tests/ui/needless_return_with_question_mark.rs b/tests/ui/needless_return_with_question_mark.rs index 64c2d5f404d4d..aba7ffb273bce 100644 --- a/tests/ui/needless_return_with_question_mark.rs +++ b/tests/ui/needless_return_with_question_mark.rs @@ -154,3 +154,13 @@ async fn async_block_final_stmt() -> Result<(), ()> { } .await } + +fn last_stmt() -> Result<(), ()> { + return Err(())?; +} + +fn expr_after_stmt() -> Result<(), ()> { + return Err(())?; + //~^ needless_return_with_question_mark + Ok(()) +} diff --git a/tests/ui/needless_return_with_question_mark.stderr b/tests/ui/needless_return_with_question_mark.stderr index c4ca4003c3221..d73a0e3fdc896 100644 --- a/tests/ui/needless_return_with_question_mark.stderr +++ b/tests/ui/needless_return_with_question_mark.stderr @@ -25,5 +25,11 @@ error: unneeded `return` statement with `?` operator LL | return Err(())?; | ^^^^^^^ help: remove it -error: aborting due to 4 previous errors +error: unneeded `return` statement with `?` operator + --> tests/ui/needless_return_with_question_mark.rs:163:5 + | +LL | return Err(())?; + | ^^^^^^^ help: remove it + +error: aborting due to 5 previous errors diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index a2ecea773efe5..2c13ce5dae2a6 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -7,7 +7,8 @@ clippy::manual_midpoint, clippy::manual_unwrap_or_default, clippy::manual_unwrap_or, - clippy::unnecessary_option_map_or_else + clippy::unnecessary_option_map_or_else, + clippy::map_or_identity )] fn bad1(string: Option<&str>) -> (bool, &str) { diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 3adbc785237f6..c41394a1e35e8 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -7,7 +7,8 @@ clippy::manual_midpoint, clippy::manual_unwrap_or_default, clippy::manual_unwrap_or, - clippy::unnecessary_option_map_or_else + clippy::unnecessary_option_map_or_else, + clippy::map_or_identity )] fn bad1(string: Option<&str>) -> (bool, &str) { diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index f5578f63c946b..7e5df7c531105 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -1,5 +1,5 @@ error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:14:5 + --> tests/ui/option_if_let_else.rs:15:5 | LL | / if let Some(x) = string { LL | | @@ -13,19 +13,19 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::option_if_let_else)]` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:33:13 + --> tests/ui/option_if_let_else.rs:34:13 | LL | let _ = if let Some(s) = *string { s.len() } else { 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:35:13 + --> tests/ui/option_if_let_else.rs:36:13 | LL | let _ = if let Some(s) = &num { s } else { &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:37:13 + --> tests/ui/option_if_let_else.rs:38:13 | LL | let _ = if let Some(s) = &mut num { | _____________^ @@ -47,13 +47,13 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:44:13 + --> tests/ui/option_if_let_else.rs:45:13 | LL | let _ = if let Some(ref s) = num { s } else { &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:46:13 + --> tests/ui/option_if_let_else.rs:47:13 | LL | let _ = if let Some(mut s) = num { | _____________^ @@ -75,7 +75,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:53:13 + --> tests/ui/option_if_let_else.rs:54:13 | LL | let _ = if let Some(ref mut s) = num { | _____________^ @@ -97,7 +97,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:63:5 + --> tests/ui/option_if_let_else.rs:64:5 | LL | / if let Some(x) = arg { LL | | @@ -118,7 +118,7 @@ LL + }) | error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:77:13 + --> tests/ui/option_if_let_else.rs:78:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -131,7 +131,7 @@ LL | | }; | |_____^ help: try: `arg.map_or_else(side_effect, |x| x)` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:87:13 + --> tests/ui/option_if_let_else.rs:88:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -154,7 +154,7 @@ LL ~ }, |x| x * x * x * x); | error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:121:13 + --> tests/ui/option_if_let_else.rs:122:13 | LL | / if let Some(idx) = s.find('.') { LL | | @@ -165,7 +165,7 @@ LL | | } | |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:133:5 + --> tests/ui/option_if_let_else.rs:134:5 | LL | / if let Ok(binding) = variable { LL | | @@ -189,7 +189,7 @@ LL + }) | error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:158:5 + --> tests/ui/option_if_let_else.rs:159:5 | LL | / match r { LL | | @@ -199,7 +199,7 @@ LL | | } | |_____^ help: try: `r.map_or_else(|_| Vec::new(), |s| s.to_owned())` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:167:5 + --> tests/ui/option_if_let_else.rs:168:5 | LL | / if let Ok(s) = r { s.to_owned() } LL | | @@ -207,13 +207,13 @@ LL | | else { Vec::new() } | |_______________________^ help: try: `r.map_or_else(|_| Vec::new(), |s| s.to_owned())` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:174:13 + --> tests/ui/option_if_let_else.rs:175:13 | LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:185:13 + --> tests/ui/option_if_let_else.rs:186:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ @@ -235,13 +235,13 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:214:13 + --> tests/ui/option_if_let_else.rs:215:13 | LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:219:13 + --> tests/ui/option_if_let_else.rs:220:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ @@ -263,7 +263,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:259:13 + --> tests/ui/option_if_let_else.rs:260:13 | LL | let _ = match s { | _____________^ @@ -274,7 +274,7 @@ LL | | }; | |_____^ help: try: `s.map_or(1, |string| string.len())` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:264:13 + --> tests/ui/option_if_let_else.rs:265:13 | LL | let _ = match Some(10) { | _____________^ @@ -285,7 +285,7 @@ LL | | }; | |_____^ help: try: `Some(10).map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:271:13 + --> tests/ui/option_if_let_else.rs:272:13 | LL | let _ = match res { | _____________^ @@ -296,7 +296,7 @@ LL | | }; | |_____^ help: try: `res.map_or(1, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:276:13 + --> tests/ui/option_if_let_else.rs:277:13 | LL | let _ = match res { | _____________^ @@ -307,13 +307,13 @@ LL | | }; | |_____^ help: try: `res.map_or(1, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:281:13 + --> tests/ui/option_if_let_else.rs:282:13 | LL | let _ = if let Ok(a) = res { a + 1 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:299:17 + --> tests/ui/option_if_let_else.rs:300:17 | LL | let _ = match initial { | _________________^ @@ -324,7 +324,7 @@ LL | | }; | |_________^ help: try: `initial.as_ref().map_or(42, |value| do_something(value))` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:307:17 + --> tests/ui/option_if_let_else.rs:308:17 | LL | let _ = match initial { | _________________^ @@ -335,7 +335,7 @@ LL | | }; | |_________^ help: try: `initial.as_mut().map_or(42, |value| do_something2(value))` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:331:24 + --> tests/ui/option_if_let_else.rs:332:24 | LL | let mut _hashmap = if let Some(hm) = &opt { | ________________________^ @@ -347,19 +347,19 @@ LL | | }; | |_____^ help: try: `opt.as_ref().map_or_else(HashMap::new, |hm| hm.clone())` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:338:19 + --> tests/ui/option_if_let_else.rs:339:19 | LL | let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone())` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:389:22 + --> tests/ui/option_if_let_else.rs:390:22 | LL | let _ = unsafe { if let Some(o) = *opt_raw_ptr { o } else { 1 } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*opt_raw_ptr).map_or(1, |o| o)` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:395:13 + --> tests/ui/option_if_let_else.rs:396:13 | LL | let _ = match res { | _____________^ diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index 0d6f2aefa8a8b..1633161c4264e 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -6,6 +6,7 @@ clippy::unnecessary_literal_unwrap, clippy::unnecessary_result_map_or_else, clippy::unnecessary_option_map_or_else, + clippy::map_or_identity, clippy::useless_vec )] diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index e1946847698be..55339348e2bc1 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -6,6 +6,7 @@ clippy::unnecessary_literal_unwrap, clippy::unnecessary_result_map_or_else, clippy::unnecessary_option_map_or_else, + clippy::map_or_identity, clippy::useless_vec )] diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index 3d55f2cd1f9fc..934af4656ea34 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -1,5 +1,5 @@ error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:53:22 + --> tests/ui/or_fun_call.rs:54:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(make)` @@ -8,7 +8,7 @@ LL | with_constructor.unwrap_or(make()); = help: to override `-D warnings` add `#[allow(clippy::or_fun_call)]` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:57:14 + --> tests/ui/or_fun_call.rs:58:14 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` @@ -17,205 +17,205 @@ LL | with_new.unwrap_or(Vec::new()); = help: to override `-D warnings` add `#[allow(clippy::unwrap_or_default)]` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:61:21 + --> tests/ui/or_fun_call.rs:62:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Vec::with_capacity(12))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:65:14 + --> tests/ui/or_fun_call.rs:66:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| make())` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:69:19 + --> tests/ui/or_fun_call.rs:70:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:73:24 + --> tests/ui/or_fun_call.rs:74:24 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:77:23 + --> tests/ui/or_fun_call.rs:78:23 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:97:18 + --> tests/ui/or_fun_call.rs:98:18 | LL | self_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(::default)` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:101:18 + --> tests/ui/or_fun_call.rs:102:18 | LL | real_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:105:14 + --> tests/ui/or_fun_call.rs:106:14 | LL | with_vec.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:109:21 + --> tests/ui/or_fun_call.rs:110:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(Foo::new)` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:113:19 + --> tests/ui/or_fun_call.rs:114:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:117:23 + --> tests/ui/or_fun_call.rs:118:23 | LL | map_vec.entry(42).or_insert(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:121:21 + --> tests/ui/or_fun_call.rs:122:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:125:25 + --> tests/ui/or_fun_call.rs:126:25 | LL | btree_vec.entry(42).or_insert(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:129:21 + --> tests/ui/or_fun_call.rs:130:21 | LL | let _ = stringy.unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `ok_or` - --> tests/ui/or_fun_call.rs:134:17 + --> tests/ui/or_fun_call.rs:135:17 | LL | let _ = opt.ok_or(format!("{} world.", hello)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ok_or_else(|| format!("{} world.", hello))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:139:21 + --> tests/ui/or_fun_call.rs:140:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:142:21 + --> tests/ui/or_fun_call.rs:143:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])` error: function call inside of `or` - --> tests/ui/or_fun_call.rs:167:35 + --> tests/ui/or_fun_call.rs:168:35 | LL | let _ = Some("a".to_string()).or(Some("b".to_string())); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_else(|| Some("b".to_string()))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:210:18 + --> tests/ui/or_fun_call.rs:211:18 | LL | None.unwrap_or(ptr_to_ref(s)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| ptr_to_ref(s))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:218:14 + --> tests/ui/or_fun_call.rs:219:14 | LL | None.unwrap_or(unsafe { ptr_to_ref(s) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:221:14 + --> tests/ui/or_fun_call.rs:222:14 | LL | None.unwrap_or( unsafe { ptr_to_ref(s) } ); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:297:25 + --> tests/ui/or_fun_call.rs:298:25 | LL | let _ = Some(4).map_or(g(), |v| v); | ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(g, |v| v)` error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:299:25 + --> tests/ui/or_fun_call.rs:300:25 | LL | let _ = Some(4).map_or(g(), f); | ^^^^^^^^^^^^^^ help: try: `map_or_else(g, f)` error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:302:25 + --> tests/ui/or_fun_call.rs:303:25 | LL | let _ = Some(4).map_or("asd".to_string().len() as i32, f); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| "asd".to_string().len() as i32, f)` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:333:18 + --> tests/ui/or_fun_call.rs:334:18 | LL | with_new.unwrap_or_else(Vec::new); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:337:28 + --> tests/ui/or_fun_call.rs:338:28 | LL | with_default_trait.unwrap_or_else(Default::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:341:27 + --> tests/ui/or_fun_call.rs:342:27 | LL | with_default_type.unwrap_or_else(u64::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:345:22 + --> tests/ui/or_fun_call.rs:346:22 | LL | real_default.unwrap_or_else(::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `or_insert_with` to construct default value - --> tests/ui/or_fun_call.rs:349:23 + --> tests/ui/or_fun_call.rs:350:23 | LL | map.entry(42).or_insert_with(String::new); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert_with` to construct default value - --> tests/ui/or_fun_call.rs:353:25 + --> tests/ui/or_fun_call.rs:354:25 | LL | btree.entry(42).or_insert_with(String::new); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:357:25 + --> tests/ui/or_fun_call.rs:358:25 | LL | let _ = stringy.unwrap_or_else(String::new); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:399:17 + --> tests/ui/or_fun_call.rs:400:17 | LL | let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)` | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(f)` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:404:17 + --> tests/ui/or_fun_call.rs:405:17 | LL | let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)` | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| f() + 1)` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:409:17 + --> tests/ui/or_fun_call.rs:410:17 | LL | let _ = opt.unwrap_or({ | _________________^ @@ -235,79 +235,79 @@ LL ~ }); | error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:415:17 + --> tests/ui/or_fun_call.rs:416:17 | LL | let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| f() + 1, |v| v)` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:420:17 + --> tests/ui/or_fun_call.rs:421:17 | LL | let _ = opt.unwrap_or({ i32::default() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:427:21 + --> tests/ui/or_fun_call.rs:428:21 | LL | let _ = opt_foo.unwrap_or(Foo { val: String::default() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Foo { val: String::default() })` error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:442:19 + --> tests/ui/or_fun_call.rs:443:19 | LL | let _ = x.map_or(g(), |v| v); | ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|_| g(), |v| v)` error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:444:19 + --> tests/ui/or_fun_call.rs:445:19 | LL | let _ = x.map_or(g(), f); | ^^^^^^^^^^^^^^ help: try: `map_or_else(|_| g(), f)` error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:447:19 + --> tests/ui/or_fun_call.rs:448:19 | LL | let _ = x.map_or("asd".to_string().len() as i32, f); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|_| "asd".to_string().len() as i32, f)` error: function call inside of `get_or_insert` - --> tests/ui/or_fun_call.rs:458:15 + --> tests/ui/or_fun_call.rs:459:15 | LL | let _ = x.get_or_insert(g()); | ^^^^^^^^^^^^^^^^^^ help: try: `get_or_insert_with(g)` error: function call inside of `and` - --> tests/ui/or_fun_call.rs:468:15 + --> tests/ui/or_fun_call.rs:469:15 | LL | let _ = x.and(g()); | ^^^^^^^^ help: try: `and_then(|_| g())` error: function call inside of `and` - --> tests/ui/or_fun_call.rs:478:15 + --> tests/ui/or_fun_call.rs:479:15 | LL | let _ = x.and(g()); | ^^^^^^^^ help: try: `and_then(|_| g())` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:484:17 + --> tests/ui/or_fun_call.rs:485:17 | LL | let _ = opt.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:486:17 + --> tests/ui/or_fun_call.rs:487:17 | LL | let _ = res.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| Default::default())` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:492:17 + --> tests/ui/or_fun_call.rs:493:17 | LL | let _ = opt.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:494:17 + --> tests/ui/or_fun_call.rs:495:17 | LL | let _ = res.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` diff --git a/tests/ui/range_contains.fixed b/tests/ui/range_contains.fixed index 19d6165e9820c..859f12d79d486 100644 --- a/tests/ui/range_contains.fixed +++ b/tests/ui/range_contains.fixed @@ -56,8 +56,7 @@ fn main() { let y = 3.; (0. ..1.).contains(&y); //~^ manual_range_contains - !(0. ..=1.).contains(&y); - //~^ manual_range_contains + y < 0. || y > 1.; // no lint: float `||` differs in NaN handling (fix #16706) // handle negatives #8721 (-10..=10).contains(&x); @@ -96,3 +95,23 @@ fn msrv_1_35() { (8..35).contains(&x); //~^ manual_range_contains } + +// Fix #16706 +fn float_nan_no_lint() { + let q = 0.5_f64; + // these still lint — float && (in-range) is fine, NaN semantics match + (0.0..1.0).contains(&q); + //~^ manual_range_contains + (0.0..=1.0).contains(&q); + //~^ manual_range_contains + + // these do NOT lint — float || (out-of-range) NaN semantics differ + q < 0.0 || q > 1.0; // no lint + q < 0.0 || q >= 1.0; // no lint + + let r = 0.5_f32; + (0.0..1.0).contains(&r); + //~^ manual_range_contains + + r < 0.0 || r > 1.0; // no lint +} diff --git a/tests/ui/range_contains.rs b/tests/ui/range_contains.rs index 80bf40806697e..b39767a85034b 100644 --- a/tests/ui/range_contains.rs +++ b/tests/ui/range_contains.rs @@ -56,8 +56,7 @@ fn main() { let y = 3.; y >= 0. && y < 1.; //~^ manual_range_contains - y < 0. || y > 1.; - //~^ manual_range_contains + y < 0. || y > 1.; // no lint: float `||` differs in NaN handling (fix #16706) // handle negatives #8721 x >= -10 && x <= 10; @@ -96,3 +95,23 @@ fn msrv_1_35() { x >= 8 && x < 35; //~^ manual_range_contains } + +// Fix #16706 +fn float_nan_no_lint() { + let q = 0.5_f64; + // these still lint — float && (in-range) is fine, NaN semantics match + q >= 0.0 && q < 1.0; + //~^ manual_range_contains + q >= 0.0 && q <= 1.0; + //~^ manual_range_contains + + // these do NOT lint — float || (out-of-range) NaN semantics differ + q < 0.0 || q > 1.0; // no lint + q < 0.0 || q >= 1.0; // no lint + + let r = 0.5_f32; + r >= 0.0 && r < 1.0; + //~^ manual_range_contains + + r < 0.0 || r > 1.0; // no lint +} diff --git a/tests/ui/range_contains.stderr b/tests/ui/range_contains.stderr index 67bd5aad093dc..814199d49e537 100644 --- a/tests/ui/range_contains.stderr +++ b/tests/ui/range_contains.stderr @@ -79,53 +79,65 @@ error: manual `Range::contains` implementation LL | y >= 0. && y < 1.; | ^^^^^^^^^^^^^^^^^ help: use: `(0. ..1.).contains(&y)` -error: manual `!RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:59:5 - | -LL | y < 0. || y > 1.; - | ^^^^^^^^^^^^^^^^ help: use: `!(0. ..=1.).contains(&y)` - error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:63:5 + --> tests/ui/range_contains.rs:62:5 | LL | x >= -10 && x <= 10; | ^^^^^^^^^^^^^^^^^^^ help: use: `(-10..=10).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:66:5 + --> tests/ui/range_contains.rs:65:5 | LL | y >= -3. && y <= 3.; | ^^^^^^^^^^^^^^^^^^^ help: use: `(-3. ..=3.).contains(&y)` error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:72:30 + --> tests/ui/range_contains.rs:71:30 | LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&z)` error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:72:5 + --> tests/ui/range_contains.rs:71:5 | LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&x)` error: manual `!Range::contains` implementation - --> tests/ui/range_contains.rs:75:29 + --> tests/ui/range_contains.rs:74:29 | LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10); | ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&z)` error: manual `!Range::contains` implementation - --> tests/ui/range_contains.rs:75:5 + --> tests/ui/range_contains.rs:74:5 | LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10); | ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&x)` error: manual `Range::contains` implementation - --> tests/ui/range_contains.rs:96:5 + --> tests/ui/range_contains.rs:95:5 | LL | x >= 8 && x < 35; | ^^^^^^^^^^^^^^^^ help: use: `(8..35).contains(&x)` -error: aborting due to 21 previous errors +error: manual `Range::contains` implementation + --> tests/ui/range_contains.rs:103:5 + | +LL | q >= 0.0 && q < 1.0; + | ^^^^^^^^^^^^^^^^^^^ help: use: `(0.0..1.0).contains(&q)` + +error: manual `RangeInclusive::contains` implementation + --> tests/ui/range_contains.rs:105:5 + | +LL | q >= 0.0 && q <= 1.0; + | ^^^^^^^^^^^^^^^^^^^^ help: use: `(0.0..=1.0).contains(&q)` + +error: manual `Range::contains` implementation + --> tests/ui/range_contains.rs:113:5 + | +LL | r >= 0.0 && r < 1.0; + | ^^^^^^^^^^^^^^^^^^^ help: use: `(0.0..1.0).contains(&r)` + +error: aborting due to 23 previous errors diff --git a/tests/ui/unused_async_trait_impl.fixed b/tests/ui/unused_async_trait_impl.fixed new file mode 100644 index 0000000000000..384bb3449f90b --- /dev/null +++ b/tests/ui/unused_async_trait_impl.fixed @@ -0,0 +1,109 @@ +#![warn(clippy::unused_async_trait_impl)] + +trait HasAsyncMethod { + async fn do_something() -> u32; +} + +struct Stub; + +mod typical { + struct Inefficient; + struct Efficient; + + use crate::Stub; + + impl crate::HasAsyncMethod for Inefficient { + fn do_something() -> impl Future { + //~^ unused_async_trait_impl + std::future::ready(1) + } + } + + impl crate::HasAsyncMethod for Efficient { + fn do_something() -> impl Future { + std::future::ready(1) + } + } + + impl crate::HasAsyncMethod for crate::Stub { + async fn do_something() -> u32 { + todo!() // Do not emit the lint in this case. + } + } +} + +// Test to check if the identation of the various snippets goes as intended. +mod indented { + struct Indented; + + impl crate::HasAsyncMethod for Indented { + fn do_something() -> impl Future { + //~^ unused_async_trait_impl + let mut x = 0; + for y in 0..64 { + x = (x + 1) * y; + } + + let fake_fut = async { + if x == 0 { + panic!("Fake example"); + } + }; + + std::future::ready(x) + } + } + + struct Complex(std::marker::PhantomData); + + impl crate::HasAsyncMethod for Complex + where + T: Sized, + { + fn do_something() -> impl Future { + //~^ unused_async_trait_impl + std::future::ready(5) + } + } +} + +mod default_unchanged { + trait HasDefaultAsyncMethod { + // The lint should not suggest a change for trait fn's as changing that decl + // implies a less restrictive Future type. + async fn do_something() -> u32 { + 0 + } + } + + impl HasDefaultAsyncMethod for crate::Stub { + // Nothing! + } +} + +mod macros { + trait HasAsyncMethodVec { + async fn do_something() -> Vec; + } + + struct MacroInType; + struct MacroInExpr; + + macro_rules! vec_ty { + ($t:ty) => { Vec<$t> } + } + + impl HasAsyncMethodVec for MacroInType { + fn do_something() -> impl Future { + //~^ unused_async_trait_impl + std::future::ready(Vec::new()) + } + } + + impl HasAsyncMethodVec for MacroInExpr { + fn do_something() -> impl Future> { + //~^ unused_async_trait_impl + std::future::ready(vec![]) + } + } +} diff --git a/tests/ui/unused_async_trait_impl.rs b/tests/ui/unused_async_trait_impl.rs new file mode 100644 index 0000000000000..0a93635c264f5 --- /dev/null +++ b/tests/ui/unused_async_trait_impl.rs @@ -0,0 +1,109 @@ +#![warn(clippy::unused_async_trait_impl)] + +trait HasAsyncMethod { + async fn do_something() -> u32; +} + +struct Stub; + +mod typical { + struct Inefficient; + struct Efficient; + + use crate::Stub; + + impl crate::HasAsyncMethod for Inefficient { + async fn do_something() -> u32 { + //~^ unused_async_trait_impl + 1 + } + } + + impl crate::HasAsyncMethod for Efficient { + fn do_something() -> impl Future { + std::future::ready(1) + } + } + + impl crate::HasAsyncMethod for crate::Stub { + async fn do_something() -> u32 { + todo!() // Do not emit the lint in this case. + } + } +} + +// Test to check if the identation of the various snippets goes as intended. +mod indented { + struct Indented; + + impl crate::HasAsyncMethod for Indented { + async fn do_something() -> u32 { + //~^ unused_async_trait_impl + let mut x = 0; + for y in 0..64 { + x = (x + 1) * y; + } + + let fake_fut = async { + if x == 0 { + panic!("Fake example"); + } + }; + + x + } + } + + struct Complex(std::marker::PhantomData); + + impl crate::HasAsyncMethod for Complex + where + T: Sized, + { + async fn do_something() -> u32 { + //~^ unused_async_trait_impl + 5 + } + } +} + +mod default_unchanged { + trait HasDefaultAsyncMethod { + // The lint should not suggest a change for trait fn's as changing that decl + // implies a less restrictive Future type. + async fn do_something() -> u32 { + 0 + } + } + + impl HasDefaultAsyncMethod for crate::Stub { + // Nothing! + } +} + +mod macros { + trait HasAsyncMethodVec { + async fn do_something() -> Vec; + } + + struct MacroInType; + struct MacroInExpr; + + macro_rules! vec_ty { + ($t:ty) => { Vec<$t> } + } + + impl HasAsyncMethodVec for MacroInType { + async fn do_something() -> vec_ty!(u32) { + //~^ unused_async_trait_impl + Vec::new() + } + } + + impl HasAsyncMethodVec for MacroInExpr { + async fn do_something() -> Vec { + //~^ unused_async_trait_impl + vec![] + } + } +} diff --git a/tests/ui/unused_async_trait_impl.stderr b/tests/ui/unused_async_trait_impl.stderr new file mode 100644 index 0000000000000..7265dc2dd0595 --- /dev/null +++ b/tests/ui/unused_async_trait_impl.stderr @@ -0,0 +1,94 @@ +error: unused `async` for async trait impl function with no `.await` statements + --> tests/ui/unused_async_trait_impl.rs:16:9 + | +LL | / async fn do_something() -> u32 { +LL | | +LL | | 1 +LL | | } + | |_________^ + | + = note: `std::future::ready` creates a `Future` which returns the value immediately when `poll`ed + = note: `-D clippy::unused-async-trait-impl` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unused_async_trait_impl)]` +help: consider removing the `async` from this function and returning `impl Future` instead + | +LL ~ fn do_something() -> impl Future { +LL | +LL ~ std::future::ready(1) + | + +error: unused `async` for async trait impl function with no `.await` statements + --> tests/ui/unused_async_trait_impl.rs:40:9 + | +LL | / async fn do_something() -> u32 { +LL | | +LL | | let mut x = 0; +LL | | for y in 0..64 { +... | +LL | | x +LL | | } + | |_________^ + | + = note: `std::future::ready` creates a `Future` which returns the value immediately when `poll`ed +help: consider removing the `async` from this function and returning `impl Future` instead + | +LL ~ fn do_something() -> impl Future { +LL | +... +LL | +LL ~ std::future::ready(x) + | + +error: unused `async` for async trait impl function with no `.await` statements + --> tests/ui/unused_async_trait_impl.rs:63:9 + | +LL | / async fn do_something() -> u32 { +LL | | +LL | | 5 +LL | | } + | |_________^ + | + = note: `std::future::ready` creates a `Future` which returns the value immediately when `poll`ed +help: consider removing the `async` from this function and returning `impl Future` instead + | +LL ~ fn do_something() -> impl Future { +LL | +LL ~ std::future::ready(5) + | + +error: unused `async` for async trait impl function with no `.await` statements + --> tests/ui/unused_async_trait_impl.rs:97:9 + | +LL | / async fn do_something() -> vec_ty!(u32) { +LL | | +LL | | Vec::new() +LL | | } + | |_________^ + | + = note: `std::future::ready` creates a `Future` which returns the value immediately when `poll`ed +help: consider removing the `async` from this function and returning `impl Future` instead + | +LL ~ fn do_something() -> impl Future { +LL | +LL ~ std::future::ready(Vec::new()) + | + +error: unused `async` for async trait impl function with no `.await` statements + --> tests/ui/unused_async_trait_impl.rs:104:9 + | +LL | / async fn do_something() -> Vec { +LL | | +LL | | vec![] +LL | | } + | |_________^ + | + = note: `std::future::ready` creates a `Future` which returns the value immediately when `poll`ed +help: consider removing the `async` from this function and returning `impl Future>` instead + | +LL ~ fn do_something() -> impl Future> { +LL | +LL ~ std::future::ready(vec![]) + | + +error: aborting due to 5 previous errors + diff --git a/tests/ui/unused_async_trait_impl_no_std.fixed b/tests/ui/unused_async_trait_impl_no_std.fixed new file mode 100644 index 0000000000000..0b4451f8934ee --- /dev/null +++ b/tests/ui/unused_async_trait_impl_no_std.fixed @@ -0,0 +1,15 @@ +#![no_std] +#![warn(clippy::unused_async_trait_impl)] + +trait HasAsyncMethod { + async fn do_something() -> u32; +} + +struct Inefficient; + +impl HasAsyncMethod for Inefficient { + fn do_something() -> impl Future { + //~^ unused_async_trait_impl + core::future::ready(1) + } +} diff --git a/tests/ui/unused_async_trait_impl_no_std.rs b/tests/ui/unused_async_trait_impl_no_std.rs new file mode 100644 index 0000000000000..ab6f1f3716a77 --- /dev/null +++ b/tests/ui/unused_async_trait_impl_no_std.rs @@ -0,0 +1,15 @@ +#![no_std] +#![warn(clippy::unused_async_trait_impl)] + +trait HasAsyncMethod { + async fn do_something() -> u32; +} + +struct Inefficient; + +impl HasAsyncMethod for Inefficient { + async fn do_something() -> u32 { + //~^ unused_async_trait_impl + 1 + } +} diff --git a/tests/ui/unused_async_trait_impl_no_std.stderr b/tests/ui/unused_async_trait_impl_no_std.stderr new file mode 100644 index 0000000000000..4cd02b005a2a6 --- /dev/null +++ b/tests/ui/unused_async_trait_impl_no_std.stderr @@ -0,0 +1,21 @@ +error: unused `async` for async trait impl function with no `.await` statements + --> tests/ui/unused_async_trait_impl_no_std.rs:11:5 + | +LL | / async fn do_something() -> u32 { +LL | | +LL | | 1 +LL | | } + | |_____^ + | + = note: `core::future::ready` creates a `Future` which returns the value immediately when `poll`ed + = note: `-D clippy::unused-async-trait-impl` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unused_async_trait_impl)]` +help: consider removing the `async` from this function and returning `impl Future` instead + | +LL ~ fn do_something() -> impl Future { +LL | +LL ~ core::future::ready(1) + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/unused_format_specs.1.fixed b/tests/ui/unused_format_specs.1.fixed index 05bd1df9a5236..96509c80a4adf 100644 --- a/tests/ui/unused_format_specs.1.fixed +++ b/tests/ui/unused_format_specs.1.fixed @@ -1,5 +1,5 @@ #![warn(clippy::unused_format_specs)] -#![allow(unused)] +#![allow(clippy::useless_format)] macro_rules! format_args_from_macro { () => { diff --git a/tests/ui/unused_format_specs.2.fixed b/tests/ui/unused_format_specs.2.fixed index c1f3d4fa20c6f..c947d88f77db1 100644 --- a/tests/ui/unused_format_specs.2.fixed +++ b/tests/ui/unused_format_specs.2.fixed @@ -1,5 +1,5 @@ #![warn(clippy::unused_format_specs)] -#![allow(unused)] +#![allow(clippy::useless_format)] macro_rules! format_args_from_macro { () => { diff --git a/tests/ui/unused_format_specs.rs b/tests/ui/unused_format_specs.rs index b47047ba34e5f..10202c6d6053d 100644 --- a/tests/ui/unused_format_specs.rs +++ b/tests/ui/unused_format_specs.rs @@ -1,5 +1,5 @@ #![warn(clippy::unused_format_specs)] -#![allow(unused)] +#![allow(clippy::useless_format)] macro_rules! format_args_from_macro { () => { diff --git a/tests/ui/unused_format_specs_width.rs b/tests/ui/unused_format_specs_width.rs index e894ea76fc186..3f0bfc0963a87 100644 --- a/tests/ui/unused_format_specs_width.rs +++ b/tests/ui/unused_format_specs_width.rs @@ -6,32 +6,32 @@ fn main() { // Integer formats with # (alternate): 0x/0o/0b prefix makes min width 4 - println!("{:#02X}", 1u8); //~ ERROR: format width has no effect on the output - println!("{:#2X}", 1u8); //~ ERROR: format width has no effect on the output - println!("{:#02x}", 1u8); //~ ERROR: format width has no effect on the output - println!("{:#02o}", 1u8); //~ ERROR: format width has no effect on the output - println!("{:#02b}", 1u8); //~ ERROR: format width has no effect on the output + println!("{:#02X}", 1u8); //~ unused_format_specs + println!("{:#2X}", 1u8); //~ unused_format_specs + println!("{:#02x}", 1u8); //~ unused_format_specs + println!("{:#02o}", 1u8); //~ unused_format_specs + println!("{:#02b}", 1u8); //~ unused_format_specs // Exponent formats: min width 4 (e.g. 1e0) - println!("{:02e}", 1u8); //~ ERROR: format width has no effect on the output - println!("{:02E}", 1u8); //~ ERROR: format width has no effect on the output - println!("{:2e}", 1.0); //~ ERROR: format width has no effect on the output - println!("{:2E}", 1.0); //~ ERROR: format width has no effect on the output - println!("{:2e}", 0.1); //~ ERROR: format width has no effect on the output - println!("{:2E}", 0.1); //~ ERROR: format width has no effect on the output + println!("{:02e}", 1u8); //~ unused_format_specs + println!("{:02E}", 1u8); //~ unused_format_specs + println!("{:2e}", 1.0); //~ unused_format_specs + println!("{:2E}", 1.0); //~ unused_format_specs + println!("{:2e}", 0.1); //~ unused_format_specs + println!("{:2E}", 0.1); //~ unused_format_specs // Pointer: min width 4 (0x1) - println!("{:2p}", 0 as *const usize); //~ ERROR: format width has no effect on the output - println!("{:02p}", 1 as *const usize); //~ ERROR: format width has no effect on the output + println!("{:2p}", 0 as *const usize); //~ unused_format_specs + println!("{:02p}", 1 as *const usize); //~ unused_format_specs // Width 2 still too small for exponent; precision+width - println!("{:2.2e}", 1.0); //~ ERROR: format width has no effect on the output - println!("{:2.2E}", 1.0); //~ ERROR: format width has no effect on the output - println!("{:2.2e}", 0.1); //~ ERROR: format width has no effect on the output - println!("{:2.2E}", 0.1); //~ ERROR: format width has no effect on the output + println!("{:2.2e}", 1.0); //~ unused_format_specs + println!("{:2.2E}", 1.0); //~ unused_format_specs + println!("{:2.2e}", 0.1); //~ unused_format_specs + println!("{:2.2E}", 0.1); //~ unused_format_specs // Width 3 is exactly the minimum for alternate hex, still warn - println!("{:#03X}", 1u8); //~ ERROR: format width has no effect on the output + println!("{:#03X}", 1u8); //~ unused_format_specs // Not linted: width more than 3, or no # for x/o/b println!("{:#04X}", 1u8); diff --git a/tests/ui/useless_borrows_in_formatting.fixed b/tests/ui/useless_borrows_in_formatting.fixed index 82319252b4688..f1a4635ee7268 100644 --- a/tests/ui/useless_borrows_in_formatting.fixed +++ b/tests/ui/useless_borrows_in_formatting.fixed @@ -5,10 +5,13 @@ #![allow(unused, clippy::useless_format)] fn main() { - let s: &str = "hello"; + let mut s: &str = "hello"; println!("{}", s); //~ useless_borrows_in_formatting println!("{:?}", s); //~ useless_borrows_in_formatting println!("{}", s); //~ useless_borrows_in_formatting + println!("{}", s); //~ useless_borrows_in_formatting + println!("{}", s); //~ useless_borrows_in_formatting + println!("{}", s); //~ useless_borrows_in_formatting let string = String::from("world"); println!("{}", string); //~ useless_borrows_in_formatting diff --git a/tests/ui/useless_borrows_in_formatting.rs b/tests/ui/useless_borrows_in_formatting.rs index 6d23c9c8e7bbc..12ad80cc8dd52 100644 --- a/tests/ui/useless_borrows_in_formatting.rs +++ b/tests/ui/useless_borrows_in_formatting.rs @@ -5,10 +5,13 @@ #![allow(unused, clippy::useless_format)] fn main() { - let s: &str = "hello"; + let mut s: &str = "hello"; println!("{}", &s); //~ useless_borrows_in_formatting println!("{:?}", &s); //~ useless_borrows_in_formatting println!("{}", &&s); //~ useless_borrows_in_formatting + println!("{}", &&mut s); //~ useless_borrows_in_formatting + println!("{}", &mut &s); //~ useless_borrows_in_formatting + println!("{}", &mut s); //~ useless_borrows_in_formatting let string = String::from("world"); println!("{}", &string); //~ useless_borrows_in_formatting diff --git a/tests/ui/useless_borrows_in_formatting.stderr b/tests/ui/useless_borrows_in_formatting.stderr index e9e028c81ac43..683d9dfdf946e 100644 --- a/tests/ui/useless_borrows_in_formatting.stderr +++ b/tests/ui/useless_borrows_in_formatting.stderr @@ -19,74 +19,92 @@ error: redundant reference in `println!` argument LL | println!("{}", &&s); | ^^^ help: remove the redundant `&`: `s` +error: redundant reference in `println!` argument + --> tests/ui/useless_borrows_in_formatting.rs:12:20 + | +LL | println!("{}", &&mut s); + | ^^^^^^^ help: remove the redundant `&`/`&mut`: `s` + +error: redundant reference in `println!` argument + --> tests/ui/useless_borrows_in_formatting.rs:13:20 + | +LL | println!("{}", &mut &s); + | ^^^^^^^ help: remove the redundant `&`/`&mut`: `s` + error: redundant reference in `println!` argument --> tests/ui/useless_borrows_in_formatting.rs:14:20 | +LL | println!("{}", &mut s); + | ^^^^^^ help: remove the redundant `&mut`: `s` + +error: redundant reference in `println!` argument + --> tests/ui/useless_borrows_in_formatting.rs:17:20 + | LL | println!("{}", &string); | ^^^^^^^ help: remove the redundant `&`: `string` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:15:22 + --> tests/ui/useless_borrows_in_formatting.rs:18:22 | LL | println!("{:?}", &string); | ^^^^^^^ help: remove the redundant `&`: `string` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:16:20 + --> tests/ui/useless_borrows_in_formatting.rs:19:20 | LL | println!("{}", &&string); | ^^^^^^^^ help: remove the redundant `&`: `string` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:17:20 + --> tests/ui/useless_borrows_in_formatting.rs:20:20 | LL | println!("{}", &&string[..2]); | ^^^^^^^^^^^^^ help: remove the redundant `&`: `&string[..2]` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:18:22 + --> tests/ui/useless_borrows_in_formatting.rs:21:22 | LL | println!("{:?}", &&string[..2]); | ^^^^^^^^^^^^^ help: remove the redundant `&`: `&string[..2]` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:24:20 + --> tests/ui/useless_borrows_in_formatting.rs:27:20 | LL | println!("{}", &n); | ^^ help: remove the redundant `&`: `n` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:25:22 + --> tests/ui/useless_borrows_in_formatting.rs:28:22 | LL | println!("{:?}", &n); | ^^ help: remove the redundant `&`: `n` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:26:20 + --> tests/ui/useless_borrows_in_formatting.rs:29:20 | LL | println!("{}", &&n); | ^^^ help: remove the redundant `&`: `n` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:30:20 + --> tests/ui/useless_borrows_in_formatting.rs:33:20 | LL | println!("{}", &slice[0]); | ^^^^^^^^^ help: remove the redundant `&`: `slice[0]` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:31:22 + --> tests/ui/useless_borrows_in_formatting.rs:34:22 | LL | println!("{:?}", &slice[0]); | ^^^^^^^^^ help: remove the redundant `&`: `slice[0]` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:32:20 + --> tests/ui/useless_borrows_in_formatting.rs:35:20 | LL | println!("{}", &&slice[0]); | ^^^^^^^^^^ help: remove the redundant `&`: `slice[0]` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:37:9 + --> tests/ui/useless_borrows_in_formatting.rs:40:9 | LL | / &[ LL | | @@ -107,160 +125,160 @@ LL + ] | error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:45:22 + --> tests/ui/useless_borrows_in_formatting.rs:48:22 | LL | println!("{:?}", &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the redundant `&`: `[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:49:26 + --> tests/ui/useless_borrows_in_formatting.rs:52:26 | LL | println!("{:016x?}", &[a[0], a[1], a[0], a[1]]); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the redundant `&`: `[a[0], a[1], a[0], a[1]]` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:53:22 + --> tests/ui/useless_borrows_in_formatting.rs:56:22 | LL | println!("{:?}", &&slice[0..1]); | ^^^^^^^^^^^^^ help: remove the redundant `&`: `&slice[0..1]` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:62:20 + --> tests/ui/useless_borrows_in_formatting.rs:65:20 | LL | println!("{}", &w.0); | ^^^^ help: remove the redundant `&`: `w.0` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:63:22 + --> tests/ui/useless_borrows_in_formatting.rs:66:22 | LL | println!("{:?}", &w.0); | ^^^^ help: remove the redundant `&`: `w.0` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:64:20 + --> tests/ui/useless_borrows_in_formatting.rs:67:20 | LL | println!("{}", &&w.0); | ^^^^^ help: remove the redundant `&`: `w.0` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:69:20 + --> tests/ui/useless_borrows_in_formatting.rs:72:20 | LL | println!("{}", &w.0); | ^^^^ help: remove the redundant `&`: `w.0` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:70:22 + --> tests/ui/useless_borrows_in_formatting.rs:73:22 | LL | println!("{:?}", &w.0); | ^^^^ help: remove the redundant `&`: `w.0` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:71:20 + --> tests/ui/useless_borrows_in_formatting.rs:74:20 | LL | println!("{}", &&w.0); | ^^^^^ help: remove the redundant `&`: `w.0` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:74:20 + --> tests/ui/useless_borrows_in_formatting.rs:77:20 | LL | println!("{}", &*a); | ^^^ help: remove the redundant `&`: `*a` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:75:22 + --> tests/ui/useless_borrows_in_formatting.rs:78:22 | LL | println!("{:?}", &*a); | ^^^ help: remove the redundant `&`: `*a` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:79:20 + --> tests/ui/useless_borrows_in_formatting.rs:82:20 | LL | println!("{}", &(n)); | ^^^^ help: remove the redundant `&`: `(n)` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:80:22 + --> tests/ui/useless_borrows_in_formatting.rs:83:22 | LL | println!("{:?}", &(n + 1)); | ^^^^^^^^ help: remove the redundant `&`: `(n + 1)` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:81:20 + --> tests/ui/useless_borrows_in_formatting.rs:84:20 | LL | println!("{}", &(String::from("paren"))); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the redundant `&`: `(String::from("paren"))` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:84:20 + --> tests/ui/useless_borrows_in_formatting.rs:87:20 | LL | println!("{}", &{ n }); | ^^^^^^ help: remove the redundant `&`: `{ n }` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:85:22 + --> tests/ui/useless_borrows_in_formatting.rs:88:22 | LL | println!("{:?}", &{ n + 1 }); | ^^^^^^^^^^ help: remove the redundant `&`: `{ n + 1 }` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:86:20 + --> tests/ui/useless_borrows_in_formatting.rs:89:20 | LL | println!("{}", &{ String::from("block") }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the redundant `&`: `{ String::from("block") }` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:91:27 + --> tests/ui/useless_borrows_in_formatting.rs:94:27 | LL | println!("{0:1$.2$}", &v1, &v2, &v3); | ^^^ help: remove the redundant `&`: `v1` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:91:32 + --> tests/ui/useless_borrows_in_formatting.rs:94:32 | LL | println!("{0:1$.2$}", &v1, &v2, &v3); | ^^^ help: remove the redundant `&`: `v2` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:91:37 + --> tests/ui/useless_borrows_in_formatting.rs:94:37 | LL | println!("{0:1$.2$}", &v1, &v2, &v3); | ^^^ help: remove the redundant `&`: `v3` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:95:28 + --> tests/ui/useless_borrows_in_formatting.rs:98:28 | LL | println!("{0:1$.2$?}", &v1, &v2, &v3); | ^^^ help: remove the redundant `&`: `v1` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:95:33 + --> tests/ui/useless_borrows_in_formatting.rs:98:33 | LL | println!("{0:1$.2$?}", &v1, &v2, &v3); | ^^^ help: remove the redundant `&`: `v2` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:95:38 + --> tests/ui/useless_borrows_in_formatting.rs:98:38 | LL | println!("{0:1$.2$?}", &v1, &v2, &v3); | ^^^ help: remove the redundant `&`: `v3` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:99:27 + --> tests/ui/useless_borrows_in_formatting.rs:102:27 | LL | println!("{0:1$.2$}", &v1, v2, v3); | ^^^ help: remove the redundant `&`: `v1` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:100:31 + --> tests/ui/useless_borrows_in_formatting.rs:103:31 | LL | println!("{0:1$.2$}", v1, &v2, v3); | ^^^ help: remove the redundant `&`: `v2` error: redundant reference in `println!` argument - --> tests/ui/useless_borrows_in_formatting.rs:101:35 + --> tests/ui/useless_borrows_in_formatting.rs:104:35 | LL | println!("{0:1$.2$}", v1, v2, &v3); | ^^^ help: remove the redundant `&`: `v3` -error: aborting due to 41 previous errors +error: aborting due to 44 previous errors diff --git a/triagebot.toml b/triagebot.toml index 3ed0463f8937e..e357c528ed65f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -94,13 +94,12 @@ users_on_vacation = [ "Alexendoo", "y21", "blyxyas", - "dswij", ] [assign.owners] "/.github" = ["@flip1995"] "/triagebot.toml" = ["@flip1995"] -"/book" = ["@flip1995"] +"/book" = ["@ada4a", "@samueltardieu"] "*" = [ "@Manishearth", "@llogiq", @@ -109,4 +108,5 @@ users_on_vacation = [ "@Jarcho", "@y21", "@samueltardieu", + "@ada4a", ] From b8953cbd7399e7012689db37bd6a3074a8801d74 Mon Sep 17 00:00:00 2001 From: Arun Singh Date: Tue, 19 May 2026 19:24:01 +0530 Subject: [PATCH 009/100] Add manual_isolate_lowest_one lint --- CHANGELOG.md | 1 + book/src/lint_configuration.md | 1 + clippy_config/src/conf.rs | 1 + clippy_lints/src/declared_lints.rs | 1 + .../operators/manual_isolate_lowest_one.rs | 167 ++++++++++++++++++ clippy_lints/src/operators/mod.rs | 27 +++ clippy_utils/src/msrvs.rs | 1 + clippy_utils/src/sym.rs | 1 + tests/ui/manual_isolate_lowest_one.fixed | 92 ++++++++++ tests/ui/manual_isolate_lowest_one.rs | 92 ++++++++++ tests/ui/manual_isolate_lowest_one.stderr | 59 +++++++ 11 files changed, 443 insertions(+) create mode 100644 clippy_lints/src/operators/manual_isolate_lowest_one.rs create mode 100644 tests/ui/manual_isolate_lowest_one.fixed create mode 100644 tests/ui/manual_isolate_lowest_one.rs create mode 100644 tests/ui/manual_isolate_lowest_one.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index f53143e564b6c..df0fb10ba434a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6906,6 +6906,7 @@ Released 2018-09-13 [`manual_is_multiple_of`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_multiple_of [`manual_is_power_of_two`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two [`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and +[`manual_isolate_lowest_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_isolate_lowest_one [`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else [`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str [`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 64d0bf9b62f69..e940cadd5758d 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -925,6 +925,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one) * [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) * [`manual_is_power_of_two`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two) +* [`manual_isolate_lowest_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_isolate_lowest_one) * [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) * [`manual_midpoint`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_midpoint) * [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 465e88a783ed8..b9cd07a7c1aa3 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -786,6 +786,7 @@ define_Conf! { manual_hash_one, manual_is_ascii_check, manual_is_power_of_two, + manual_isolate_lowest_one, manual_let_else, manual_midpoint, manual_non_exhaustive, diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 4218d1fdc2901..eec025699e003 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -612,6 +612,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::operators::INVALID_UPCAST_COMPARISONS_INFO, crate::operators::MANUAL_DIV_CEIL_INFO, crate::operators::MANUAL_IS_MULTIPLE_OF_INFO, + crate::operators::MANUAL_ISOLATE_LOWEST_ONE_INFO, crate::operators::MANUAL_MIDPOINT_INFO, crate::operators::MISREFACTORED_ASSIGN_OP_INFO, crate::operators::MODULO_ARITHMETIC_INFO, diff --git a/clippy_lints/src/operators/manual_isolate_lowest_one.rs b/clippy_lints/src/operators/manual_isolate_lowest_one.rs new file mode 100644 index 0000000000000..f62514ce99a63 --- /dev/null +++ b/clippy_lints/src/operators/manual_isolate_lowest_one.rs @@ -0,0 +1,167 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::res::MaybeResPath; +use clippy_utils::sugg::Sugg; +use clippy_utils::sym; +use rustc_ast::BinOpKind; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, UnOp}; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_span::Span; + +use super::MANUAL_ISOLATE_LOWEST_ONE; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + op: BinOpKind, + lhs: &'tcx Expr<'tcx>, + rhs: &'tcx Expr<'tcx>, + msrv: Msrv, +) { + if op != BinOpKind::BitAnd || expr.span.from_expansion() || lhs.span.from_expansion() || rhs.span.from_expansion() { + return; + } + + // x & x.wrapping_neg() + if let Some(base) = matching_wrapping_neg(lhs, rhs) + // x.wrapping_neg() & x + .or_else(|| matching_wrapping_neg(rhs, lhs)) + && is_primitive_int(cx, base) + { + maybe_emit_lint(cx, expr.span, base, msrv, false); + } else if let Some(base) = matching_neg(lhs, rhs) + // x & -x or -x & x + .or_else(|| matching_neg(rhs, lhs)) + && is_signed_int(cx, base) + { + maybe_emit_lint(cx, expr.span, base, msrv, false); + } else if let Some(base) = matching_nonzero_wrapping_neg(lhs, rhs) + // nz.get() & nz.get().wrapping_neg() or reversed + .or_else(|| matching_nonzero_wrapping_neg(rhs, lhs)) + && is_nonzero_int(cx, base) + { + maybe_emit_lint(cx, expr.span, base, msrv, true); + } else if let Some(base) = matching_nonzero_neg(lhs, rhs) + // nz.get() & -nz.get() or reversed + .or_else(|| matching_nonzero_neg(rhs, lhs)) + && is_nonzero_signed_int(cx, base) + { + maybe_emit_lint(cx, expr.span, base, msrv, true); + } +} + +fn maybe_emit_lint(cx: &LateContext<'_>, span: Span, base: &Expr<'_>, msrv: Msrv, add_get: bool) { + if !msrv.meets(cx, msrvs::ISOLATE_LOWEST_ONE) { + return; + } + + let mut applicability = Applicability::MachineApplicable; + let snippet = Sugg::hir_with_applicability(cx, base, "_", &mut applicability); + let get = if add_get { ".get()" } else { "" }; + + span_lint_and_sugg( + cx, + MANUAL_ISOLATE_LOWEST_ONE, + span, + "manual implementation of `isolate_lowest_one`", + "consider using `.isolate_lowest_one()`", + format!("{}.isolate_lowest_one(){get}", snippet.maybe_paren()), + applicability, + ); +} + +fn matching_wrapping_neg<'tcx>(base: &'tcx Expr<'tcx>, negated: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + let receiver = wrapping_neg_receiver(negated)?; + is_same_local_path(base, receiver).then_some(base) +} + +fn matching_neg<'tcx>(base: &'tcx Expr<'tcx>, negated: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + if let ExprKind::Unary(UnOp::Neg, inner) = negated.kind + && is_same_local_path(base, inner) + { + Some(base) + } else { + None + } +} + +fn matching_nonzero_wrapping_neg<'tcx>(base_get: &'tcx Expr<'tcx>, negated: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + let base = get_receiver(base_get)?; + let receiver = wrapping_neg_receiver(negated)?; + let negated_base = get_receiver(receiver)?; + is_same_local_path(base, negated_base).then_some(base) +} + +fn matching_nonzero_neg<'tcx>(base_get: &'tcx Expr<'tcx>, negated: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + let base = get_receiver(base_get)?; + if let ExprKind::Unary(UnOp::Neg, inner) = negated.kind { + let negated_base = get_receiver(inner)?; + is_same_local_path(base, negated_base).then_some(base) + } else { + None + } +} + +fn wrapping_neg_receiver<'tcx>(expr: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + if let ExprKind::MethodCall(method_name, receiver, [], _) = expr.kind + && method_name.ident.name == sym::wrapping_neg + { + Some(receiver) + } else { + None + } +} + +fn get_receiver<'tcx>(expr: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + if let ExprKind::MethodCall(method_name, receiver, [], _) = expr.kind + && method_name.ident.name == sym::get + && is_local_path(receiver) + { + Some(receiver) + } else { + None + } +} + +fn is_same_local_path(left: &Expr<'_>, right: &Expr<'_>) -> bool { + !left.span.from_expansion() + && !right.span.from_expansion() + && matches!((left.res_local_id(), right.res_local_id()), (Some(left), Some(right)) if left == right) +} + +fn is_local_path(expr: &Expr<'_>) -> bool { + expr.res_local_id().is_some() +} + +fn is_primitive_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + matches!( + cx.typeck_results().expr_ty_adjusted(expr).kind(), + ty::Int(_) | ty::Uint(_) + ) +} + +fn is_signed_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + matches!(cx.typeck_results().expr_ty_adjusted(expr).kind(), ty::Int(_)) +} + +fn is_nonzero_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let ty::Adt(adt, args) = cx.typeck_results().expr_ty_adjusted(expr).kind() + && cx.tcx.is_diagnostic_item(sym::NonZero, adt.did()) + { + matches!(args.type_at(0).kind(), ty::Int(_) | ty::Uint(_)) + } else { + false + } +} + +fn is_nonzero_signed_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let ty::Adt(adt, args) = cx.typeck_results().expr_ty_adjusted(expr).kind() + && cx.tcx.is_diagnostic_item(sym::NonZero, adt.did()) + { + matches!(args.type_at(0).kind(), ty::Int(_)) + } else { + false + } +} diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index b4519d654722a..0265feeb1fc75 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -16,6 +16,7 @@ mod integer_division_remainder_used; mod invalid_upcast_comparisons; mod manual_div_ceil; mod manual_is_multiple_of; +mod manual_isolate_lowest_one; mod manual_midpoint; mod misrefactored_assign_op; mod modulo_arithmetic; @@ -722,6 +723,30 @@ declare_clippy_lint! { "manual implementation of `.is_multiple_of()`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for manual implementations of isolating the lowest set bit. + /// + /// ### Why is this bad? + /// The manual bit-twiddling forms are harder to read than the standard library method. + /// Using `-x` can also overflow for signed minimum values. + /// + /// ### Example + /// ```no_run + /// let x: u32 = 5; + /// let lsb = x & x.wrapping_neg(); + /// ``` + /// Use instead: + /// ```no_run + /// let x: u32 = 5; + /// let lsb = x.isolate_lowest_one(); + /// ``` + #[clippy::version = "1.98.0"] + pub MANUAL_ISOLATE_LOWEST_ONE, + complexity, + "manual implementation of `isolate_lowest_one`" +} + declare_clippy_lint! { /// ### What it does /// Checks for manual implementation of `midpoint`. @@ -980,6 +1005,7 @@ impl_lint_pass!(Operators => [ INTEGER_DIVISION_REMAINDER_USED, INVALID_UPCAST_COMPARISONS, MANUAL_DIV_CEIL, + MANUAL_ISOLATE_LOWEST_ONE, MANUAL_IS_MULTIPLE_OF, MANUAL_MIDPOINT, MISREFACTORED_ASSIGN_OP, @@ -1027,6 +1053,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators { needless_bitwise_bool::check(cx, e, op.node, lhs, rhs); manual_midpoint::check(cx, e, op.node, lhs, rhs, self.msrv); manual_is_multiple_of::check(cx, e, op.node, lhs, rhs, self.msrv); + manual_isolate_lowest_one::check(cx, e, op.node, lhs, rhs, self.msrv); decimal_bitwise_operands::check(cx, op.node, lhs, rhs); } self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs); diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index a56e729c70bbb..5151351ed2ade 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -23,6 +23,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,97,0 { ISOLATE_LOWEST_ONE } 1,93,0 { VEC_DEQUE_POP_BACK_IF, VEC_DEQUE_POP_FRONT_IF } 1,91,0 { DURATION_FROM_MINUTES_HOURS } 1,88,0 { LET_CHAINS } diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index 6a7637fb18585..eab1b5db8ce2c 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -648,6 +648,7 @@ generate! { warnings, wildcard_imports, with_capacity, + wrapping_neg, wrapping_offset, write, write_unaligned, diff --git a/tests/ui/manual_isolate_lowest_one.fixed b/tests/ui/manual_isolate_lowest_one.fixed new file mode 100644 index 0000000000000..e135e9d3a2352 --- /dev/null +++ b/tests/ui/manual_isolate_lowest_one.fixed @@ -0,0 +1,92 @@ +#![warn(clippy::manual_isolate_lowest_one)] + +use std::num::NonZero; + +fn main() { + let x_u32: u32 = 5; + let _ = x_u32.isolate_lowest_one(); + //~^ manual_isolate_lowest_one + + let x_i32: i32 = 5; + let _ = x_i32.isolate_lowest_one(); + //~^ manual_isolate_lowest_one + + let x_u64: u64 = 5; + let _ = x_u64.isolate_lowest_one(); + //~^ manual_isolate_lowest_one + + let x_i64: i64 = 5; + let _ = x_i64.isolate_lowest_one(); + //~^ manual_isolate_lowest_one + + let nz_u32 = NonZero::::new(5).unwrap(); + let _ = nz_u32.isolate_lowest_one().get(); + //~^ manual_isolate_lowest_one + let _ = nz_u32.isolate_lowest_one().get(); + //~^ manual_isolate_lowest_one + + let nz_i32 = NonZero::::new(5).unwrap(); + let _ = nz_i32.isolate_lowest_one().get(); + //~^ manual_isolate_lowest_one + let _ = nz_i32.isolate_lowest_one().get(); + //~^ manual_isolate_lowest_one + + let other: u32 = 6; + let _ = x_u32 & other.wrapping_neg(); + let _ = x_u32 | x_u32.wrapping_neg(); + let _ = x_u32 & x_u32.wrapping_sub(1); + let _ = next_u32() & next_u32().wrapping_neg(); + + let values = [x_u32]; + let _ = values[0] & values[0].wrapping_neg(); + let _ = x_u32.count_ones() & x_u32.count_ones().wrapping_neg(); + let other_nz = NonZero::::new(6).unwrap(); + let _ = nz_u32.get() & other_nz.get().wrapping_neg(); + let _ = next_nonzero_u32().get() & next_nonzero_u32().get().wrapping_neg(); + + macro_rules! x_u32_from_macro { + () => { + x_u32 + }; + } + macro_rules! wrapping_neg_from_macro { + () => { + x_u32.wrapping_neg() + }; + } + macro_rules! bitand_wrapping_neg_from_macro { + () => { + x_u32 & x_u32.wrapping_neg() + }; + } + macro_rules! neg_i32_from_macro { + () => { + -x_i32 + }; + } + + let _ = x_u32_from_macro!() & x_u32.wrapping_neg(); + let _ = x_u32 & wrapping_neg_from_macro!(); + let _ = bitand_wrapping_neg_from_macro!(); + let _ = x_i32 & neg_i32_from_macro!(); + let _ = neg_i32_from_macro!() & x_i32; +} + +#[clippy::msrv = "1.96"] +fn older_msrv(x: u32) { + let _ = x & x.wrapping_neg(); +} + +#[clippy::msrv = "1.97"] +fn meets_msrv(x: u32) { + let _ = x.isolate_lowest_one(); + //~^ manual_isolate_lowest_one +} + +fn next_u32() -> u32 { + 5 +} + +fn next_nonzero_u32() -> NonZero { + NonZero::new(5).unwrap() +} diff --git a/tests/ui/manual_isolate_lowest_one.rs b/tests/ui/manual_isolate_lowest_one.rs new file mode 100644 index 0000000000000..d3bd11abdb54d --- /dev/null +++ b/tests/ui/manual_isolate_lowest_one.rs @@ -0,0 +1,92 @@ +#![warn(clippy::manual_isolate_lowest_one)] + +use std::num::NonZero; + +fn main() { + let x_u32: u32 = 5; + let _ = x_u32 & x_u32.wrapping_neg(); + //~^ manual_isolate_lowest_one + + let x_i32: i32 = 5; + let _ = x_i32 & -x_i32; + //~^ manual_isolate_lowest_one + + let x_u64: u64 = 5; + let _ = x_u64.wrapping_neg() & x_u64; + //~^ manual_isolate_lowest_one + + let x_i64: i64 = 5; + let _ = -x_i64 & x_i64; + //~^ manual_isolate_lowest_one + + let nz_u32 = NonZero::::new(5).unwrap(); + let _ = nz_u32.get() & nz_u32.get().wrapping_neg(); + //~^ manual_isolate_lowest_one + let _ = nz_u32.get().wrapping_neg() & nz_u32.get(); + //~^ manual_isolate_lowest_one + + let nz_i32 = NonZero::::new(5).unwrap(); + let _ = nz_i32.get() & -nz_i32.get(); + //~^ manual_isolate_lowest_one + let _ = -nz_i32.get() & nz_i32.get(); + //~^ manual_isolate_lowest_one + + let other: u32 = 6; + let _ = x_u32 & other.wrapping_neg(); + let _ = x_u32 | x_u32.wrapping_neg(); + let _ = x_u32 & x_u32.wrapping_sub(1); + let _ = next_u32() & next_u32().wrapping_neg(); + + let values = [x_u32]; + let _ = values[0] & values[0].wrapping_neg(); + let _ = x_u32.count_ones() & x_u32.count_ones().wrapping_neg(); + let other_nz = NonZero::::new(6).unwrap(); + let _ = nz_u32.get() & other_nz.get().wrapping_neg(); + let _ = next_nonzero_u32().get() & next_nonzero_u32().get().wrapping_neg(); + + macro_rules! x_u32_from_macro { + () => { + x_u32 + }; + } + macro_rules! wrapping_neg_from_macro { + () => { + x_u32.wrapping_neg() + }; + } + macro_rules! bitand_wrapping_neg_from_macro { + () => { + x_u32 & x_u32.wrapping_neg() + }; + } + macro_rules! neg_i32_from_macro { + () => { + -x_i32 + }; + } + + let _ = x_u32_from_macro!() & x_u32.wrapping_neg(); + let _ = x_u32 & wrapping_neg_from_macro!(); + let _ = bitand_wrapping_neg_from_macro!(); + let _ = x_i32 & neg_i32_from_macro!(); + let _ = neg_i32_from_macro!() & x_i32; +} + +#[clippy::msrv = "1.96"] +fn older_msrv(x: u32) { + let _ = x & x.wrapping_neg(); +} + +#[clippy::msrv = "1.97"] +fn meets_msrv(x: u32) { + let _ = x & x.wrapping_neg(); + //~^ manual_isolate_lowest_one +} + +fn next_u32() -> u32 { + 5 +} + +fn next_nonzero_u32() -> NonZero { + NonZero::new(5).unwrap() +} diff --git a/tests/ui/manual_isolate_lowest_one.stderr b/tests/ui/manual_isolate_lowest_one.stderr new file mode 100644 index 0000000000000..eb338a6a626b5 --- /dev/null +++ b/tests/ui/manual_isolate_lowest_one.stderr @@ -0,0 +1,59 @@ +error: manual implementation of `isolate_lowest_one` + --> tests/ui/manual_isolate_lowest_one.rs:7:13 + | +LL | let _ = x_u32 & x_u32.wrapping_neg(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.isolate_lowest_one()`: `x_u32.isolate_lowest_one()` + | + = note: `-D clippy::manual-isolate-lowest-one` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_isolate_lowest_one)]` + +error: manual implementation of `isolate_lowest_one` + --> tests/ui/manual_isolate_lowest_one.rs:11:13 + | +LL | let _ = x_i32 & -x_i32; + | ^^^^^^^^^^^^^^ help: consider using `.isolate_lowest_one()`: `x_i32.isolate_lowest_one()` + +error: manual implementation of `isolate_lowest_one` + --> tests/ui/manual_isolate_lowest_one.rs:15:13 + | +LL | let _ = x_u64.wrapping_neg() & x_u64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.isolate_lowest_one()`: `x_u64.isolate_lowest_one()` + +error: manual implementation of `isolate_lowest_one` + --> tests/ui/manual_isolate_lowest_one.rs:19:13 + | +LL | let _ = -x_i64 & x_i64; + | ^^^^^^^^^^^^^^ help: consider using `.isolate_lowest_one()`: `x_i64.isolate_lowest_one()` + +error: manual implementation of `isolate_lowest_one` + --> tests/ui/manual_isolate_lowest_one.rs:23:13 + | +LL | let _ = nz_u32.get() & nz_u32.get().wrapping_neg(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.isolate_lowest_one()`: `nz_u32.isolate_lowest_one().get()` + +error: manual implementation of `isolate_lowest_one` + --> tests/ui/manual_isolate_lowest_one.rs:25:13 + | +LL | let _ = nz_u32.get().wrapping_neg() & nz_u32.get(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.isolate_lowest_one()`: `nz_u32.isolate_lowest_one().get()` + +error: manual implementation of `isolate_lowest_one` + --> tests/ui/manual_isolate_lowest_one.rs:29:13 + | +LL | let _ = nz_i32.get() & -nz_i32.get(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.isolate_lowest_one()`: `nz_i32.isolate_lowest_one().get()` + +error: manual implementation of `isolate_lowest_one` + --> tests/ui/manual_isolate_lowest_one.rs:31:13 + | +LL | let _ = -nz_i32.get() & nz_i32.get(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.isolate_lowest_one()`: `nz_i32.isolate_lowest_one().get()` + +error: manual implementation of `isolate_lowest_one` + --> tests/ui/manual_isolate_lowest_one.rs:82:13 + | +LL | let _ = x & x.wrapping_neg(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.isolate_lowest_one()`: `x.isolate_lowest_one()` + +error: aborting due to 9 previous errors + From 41feaace631c055c0e56811be6a439f3c7f2c351 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Fri, 29 May 2026 13:17:11 +0000 Subject: [PATCH 010/100] faster has_arg search --- src/driver.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/driver.rs b/src/driver.rs index c682f294048ba..a94c70f6f0087 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -52,7 +52,10 @@ fn arg_value<'a>(args: &'a [String], find_arg: &str, pred: impl Fn(&str) -> bool } fn has_arg(args: &[String], find_arg: &str) -> bool { - args.iter().any(|arg| find_arg == arg.split('=').next().unwrap()) + args.iter().any(|arg| { + arg.strip_prefix(find_arg) + .is_some_and(|s| s.is_empty() || s.starts_with('=')) + }) } #[test] From 4858a73fc6ee2d64cdc0371da80e2d9ff9fdfd3c Mon Sep 17 00:00:00 2001 From: Valdemar Erk Date: Thu, 18 Dec 2025 11:00:24 +0100 Subject: [PATCH 011/100] add new lint: `for_unbounded_range` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/loops/for_unbounded_range.rs | 42 +++++++++++++++++++ clippy_lints/src/loops/infinite_loop.rs | 32 ++++++++------ clippy_lints/src/loops/mod.rs | 32 ++++++++++++++ tests/ui/for_unbounded_range.fixed | 35 ++++++++++++++++ tests/ui/for_unbounded_range.rs | 35 ++++++++++++++++ tests/ui/for_unbounded_range.stderr | 32 ++++++++++++++ .../manual_memcpy/without_loop_counters.fixed | 1 + .../ui/manual_memcpy/without_loop_counters.rs | 1 + .../without_loop_counters.stderr | 12 +++--- tests/ui/ty_fn_sig.rs | 2 +- 12 files changed, 206 insertions(+), 20 deletions(-) create mode 100644 clippy_lints/src/loops/for_unbounded_range.rs create mode 100644 tests/ui/for_unbounded_range.fixed create mode 100644 tests/ui/for_unbounded_range.rs create mode 100644 tests/ui/for_unbounded_range.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 33669d186e910..73e913cf2609a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6840,6 +6840,7 @@ Released 2018-09-13 [`for_loop_over_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_option [`for_loop_over_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_result [`for_loops_over_fallibles`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loops_over_fallibles +[`for_unbounded_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_unbounded_range [`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy [`forget_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_non_drop [`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index b5047c628d0f0..d9eeba275224d 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -276,6 +276,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::loops::EXPLICIT_INTO_ITER_LOOP_INFO, crate::loops::EXPLICIT_ITER_LOOP_INFO, crate::loops::FOR_KV_MAP_INFO, + crate::loops::FOR_UNBOUNDED_RANGE_INFO, crate::loops::INFINITE_LOOP_INFO, crate::loops::ITER_NEXT_LOOP_INFO, crate::loops::MANUAL_FIND_INFO, diff --git a/clippy_lints/src/loops/for_unbounded_range.rs b/clippy_lints/src/loops/for_unbounded_range.rs new file mode 100644 index 0000000000000..4691ee02d9539 --- /dev/null +++ b/clippy_lints/src/loops/for_unbounded_range.rs @@ -0,0 +1,42 @@ +use super::FOR_UNBOUNDED_RANGE; +use super::infinite_loop::LoopVisitor; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::higher; +use rustc_ast::Label; +use rustc_hir::Expr; +use rustc_hir::intravisit::Visitor as _; +use rustc_lint::LateContext; +use rustc_span::Span; + +pub fn check<'tcx>( + cx: &LateContext<'tcx>, + label: Option