Skip to content

Commit 55b8a36

Browse files
committed
Merge commit 'f6d310692116e9a527ce6d0b3526c965d9c5d7b9' into clippy-subtree-update
2 parents 18b439f + f6d3106 commit 55b8a36

145 files changed

Lines changed: 3428 additions & 695 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/tools/clippy/CHANGELOG.md

Lines changed: 118 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,124 @@ document.
66

77
## Unreleased / Beta / In Rust Nightly
88

9-
[500e0ff...master](https://github.com/rust-lang/rust-clippy/compare/500e0ff...master)
9+
[df995e...master](https://github.com/rust-lang/rust-clippy/compare/df995e...master)
10+
11+
## Rust 1.95
12+
13+
Current stable, released 2026-04-16
14+
15+
[View all 107 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2026-01-09T11%3A07%3A27Z..2026-02-23T22%3A37%3A09Z+base%3Amaster)
16+
17+
### New Lints
18+
19+
* Added [`unnecessary_trailing_comma`] to `pedantic`
20+
[#16530](https://github.com/rust-lang/rust-clippy/pull/16530)
21+
* Added [`disallowed_fields`] to `style`
22+
[#16218](https://github.com/rust-lang/rust-clippy/pull/16218)
23+
* Added [`manual_checked_ops`] to `complexity`
24+
[#16149](https://github.com/rust-lang/rust-clippy/pull/16149)
25+
* Added [`duration_suboptimal_units`] to `pedantic`
26+
[#16250](https://github.com/rust-lang/rust-clippy/pull/16250)
27+
* Added [`manual_take`] to `complexity`
28+
[#16368](https://github.com/rust-lang/rust-clippy/pull/16368)
29+
30+
### Enhancements
31+
32+
* [`explicit_counter_loop`] fix FN when loop counter starts at non-zero
33+
[#16620](https://github.com/rust-lang/rust-clippy/pull/16620)
34+
* [`manual_is_variant_and`] extend to cover `filter` chaining `is_some`
35+
[#16521](https://github.com/rust-lang/rust-clippy/pull/16521)
36+
* [`manual_is_variant_and`] enhance to cover manual `is_none_or`
37+
[#16424](https://github.com/rust-lang/rust-clippy/pull/16424)
38+
* [`collapsible_match`] extend to cover if-elses
39+
[#16560](https://github.com/rust-lang/rust-clippy/pull/16560)
40+
* [`useless_conversion`] also fire inside compiler desugarings
41+
[#16594](https://github.com/rust-lang/rust-clippy/pull/16594)
42+
* [`unwrap_used`] and [`expect_used`] add `allow-unwrap-types` configuration
43+
[#16605](https://github.com/rust-lang/rust-clippy/pull/16605)
44+
* [`unwrap_used`] and [`expect_used`] optimize `allow-unwrap-types` evaluation to eliminate performance regression
45+
[#16652](https://github.com/rust-lang/rust-clippy/pull/16652)
46+
* [`unchecked_time_subtraction`] extend to better handle `Duration` literals
47+
[#16528](https://github.com/rust-lang/rust-clippy/pull/16528)
48+
* [`unnecessary_fold`] match against an accumulator on both sides
49+
[#16604](https://github.com/rust-lang/rust-clippy/pull/16604)
50+
* [`iter_kv_map`] extend to cover `flat_map` and `filter_map`
51+
[#16519](https://github.com/rust-lang/rust-clippy/pull/16519)
52+
* [`question_mark`] enhance to cover `else if`
53+
[#16455](https://github.com/rust-lang/rust-clippy/pull/16455)
54+
* [`double_comparisons`] check for expressions such as `x != y && x >= y`
55+
[#16033](https://github.com/rust-lang/rust-clippy/pull/16033)
56+
* [`needless_collect`] enhance to cover vec `push`-alike cases
57+
[#16305](https://github.com/rust-lang/rust-clippy/pull/16305)
58+
* [`strlen_on_c_strings`] changes suggestion to use `CStr::count_bytes()`
59+
[#16323](https://github.com/rust-lang/rust-clippy/pull/16323)
60+
* [`transmuting_null`] now checks for `ptr::without_provenance` and `ptr::without_provenance_mut`
61+
[#16336](https://github.com/rust-lang/rust-clippy/pull/16336)
62+
* [`map_unwrap_or`] add cover for `Result::unwrap_or`
63+
[#15718](https://github.com/rust-lang/rust-clippy/pull/15718)
64+
* [`clone_on_ref_ptr`] don't add a `&` to the receiver if it's a reference
65+
[#15742](https://github.com/rust-lang/rust-clippy/pull/15742)
66+
* [`double_must_use`], [`drop_non_drop`], [`let_underscore_must_use`] consider `Result<T, U>` and
67+
`ControlFlow<U, T>` as `T` wrt `#[must_use]` if `U` is uninhabited
68+
[#16353](https://github.com/rust-lang/rust-clippy/pull/16353)
69+
* [`str_to_string`] handle a case when `ToString::to_string` is passed as function parameter
70+
[#16512](https://github.com/rust-lang/rust-clippy/pull/16512)
71+
* [`must_use_candidate`] no longer lints `main` functions with return values
72+
[#16552](https://github.com/rust-lang/rust-clippy/pull/16552)
73+
* [`needless_continue`] `allow` and `expect` attributes can also be used on the statement
74+
[#16265](https://github.com/rust-lang/rust-clippy/pull/16265)
75+
* [`int_plus_one`] fix FN with negative literals, e.g. `-1 + x <= y`
76+
[#16373](https://github.com/rust-lang/rust-clippy/pull/16373)
77+
78+
### False Positive Fixes
79+
80+
* [`assertions_on_result_states`] and [`missing_assert_message`] fix FP on edition 2015 and 2018
81+
[#16473](https://github.com/rust-lang/rust-clippy/pull/16473)
82+
* [`redundant_iter_cloned`] fix FP with move closures and coroutines
83+
[#16494](https://github.com/rust-lang/rust-clippy/pull/16494)
84+
* [`str_to_string`] fix FP on non-str types
85+
[#16571](https://github.com/rust-lang/rust-clippy/pull/16571)
86+
* [`unnecessary_cast`] do not warn on casts of external function return type
87+
[#16415](https://github.com/rust-lang/rust-clippy/pull/16415)
88+
* [`cmp_owned`] fix FP when `to_string` comes from macro input
89+
[#16468](https://github.com/rust-lang/rust-clippy/pull/16468)
90+
* [`useless_attribute`] fix FP on `exported_private_dependencies` lint attributes
91+
[#16470](https://github.com/rust-lang/rust-clippy/pull/16470)
92+
* [`manual_dangling_ptr`] fix FP when pointee type is not `Sized`
93+
[#16469](https://github.com/rust-lang/rust-clippy/pull/16469)
94+
* [`test_attr_in_doctest`] fix FP on `test_harness`
95+
[#16454](https://github.com/rust-lang/rust-clippy/pull/16454)
96+
* [`doc_paragraphs_missing_punctuation`] allow unpunctuated paragraphs before lists and code blocks
97+
[#16487](https://github.com/rust-lang/rust-clippy/pull/16487)
98+
* [`elidable_lifetime_names`] skip linting proc-macro generated code
99+
[#16402](https://github.com/rust-lang/rust-clippy/pull/16402)
100+
* [`undocumented_unsafe_blocks`] recognize safety comments inside blocks and on same line in macros
101+
[#16339](https://github.com/rust-lang/rust-clippy/pull/16339)
102+
103+
### ICE Fixes
104+
105+
* [`match_same_arms`] fix ICE in `match_same_arms`
106+
[#16685](https://github.com/rust-lang/rust-clippy/pull/16685)
107+
* [`nonminimal_bool`] fix ICE in `swap_binop()` by using the proper `TypeckResults`
108+
[#16659](https://github.com/rust-lang/rust-clippy/pull/16659)
109+
* [`redundant_closure_for_method_calls`] fix ICE when computing the path from a type to itself
110+
[#16362](https://github.com/rust-lang/rust-clippy/pull/16362)
111+
112+
### Documentation Improvements
113+
114+
* [`cast_possible_wrap`] mention `cast_{un,}signed()` methods in the documentation
115+
[#16407](https://github.com/rust-lang/rust-clippy/pull/16407)
116+
* [`ignore_without_reason`] and [`redundant_test_prefix`] mention an extra `clippy` argument
117+
needed to check tests
118+
[#16205](https://github.com/rust-lang/rust-clippy/pull/16205)
119+
* [`doc_paragraphs_missing_punctuation`] improve its documentation
120+
[#16377](https://github.com/rust-lang/rust-clippy/pull/16377)
121+
* [`missing_trait_methods`] better help message
122+
[#16380](https://github.com/rust-lang/rust-clippy/pull/16380)
123+
* [`strlen_on_c_strings`] mention the specific type (`CString` or `CStr`)
124+
[#16391](https://github.com/rust-lang/rust-clippy/pull/16391)
125+
* [`suspicious_to_owned`] improve lint messages
126+
[#16376](https://github.com/rust-lang/rust-clippy/pull/16376)
10127

11128
## Rust 1.94
12129

@@ -104,11 +221,6 @@ Current stable, released 2026-03-05
104221
* [`needless_type_cast`] do not ICE on struct constructor
105222
[#16245](https://github.com/rust-lang/rust-clippy/pull/16245)
106223

107-
### New Lints
108-
109-
* Added [`unnecessary_trailing_comma`] to `style` (single-line format-like macros only)
110-
[#13965](https://github.com/rust-lang/rust-clippy/issues/13965)
111-
112224
## Rust 1.93
113225

114226
Current stable, released 2026-01-22

src/tools/clippy/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "clippy"
3-
version = "0.1.96"
3+
version = "0.1.97"
44
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
55
repository = "https://github.com/rust-lang/rust-clippy"
66
readme = "README.md"
@@ -33,7 +33,7 @@ color-print = "0.3.4"
3333
anstream = "0.6.18"
3434

3535
[dev-dependencies]
36-
cargo_metadata = "0.18.1"
36+
cargo_metadata = "0.23"
3737
ui_test = "0.30.2"
3838
regex = "1.5.5"
3939
serde = { version = "1.0.145", features = ["derive"] }

src/tools/clippy/book/src/lint_configuration.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
928928
* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
929929
* [`manual_midpoint`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_midpoint)
930930
* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive)
931+
* [`manual_noop_waker`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_noop_waker)
931932
* [`manual_option_as_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_option_as_slice)
932933
* [`manual_pattern_char_comparison`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison)
933934
* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains)

src/tools/clippy/clippy_config/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "clippy_config"
3-
version = "0.1.96"
3+
version = "0.1.97"
44
edition = "2024"
55
publish = false
66

src/tools/clippy/clippy_config/src/conf.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,7 @@ define_Conf! {
789789
manual_let_else,
790790
manual_midpoint,
791791
manual_non_exhaustive,
792+
manual_noop_waker,
792793
manual_option_as_slice,
793794
manual_pattern_char_comparison,
794795
manual_range_contains,

src/tools/clippy/clippy_lints/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "clippy_lints"
3-
version = "0.1.96"
3+
version = "0.1.97"
44
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
55
repository = "https://github.com/rust-lang/rust-clippy"
66
readme = "README.md"
@@ -10,7 +10,7 @@ edition = "2024"
1010

1111
[dependencies]
1212
arrayvec = { version = "0.7", default-features = false }
13-
cargo_metadata = "0.18"
13+
cargo_metadata = "0.23"
1414
clippy_config = { path = "../clippy_config" }
1515
clippy_utils = { path = "../clippy_utils" }
1616
declare_clippy_lint = { path = "../declare_clippy_lint" }

src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,16 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
306306
cur_f = Some(field);
307307
}
308308
},
309-
ItemKind::Trait(_constness, is_auto, _safety, _impl_restriction, _ident, _generics, _generic_bounds, item_ref)
310-
if self.enable_ordering_for_trait && *is_auto == IsAuto::No =>
311-
{
309+
ItemKind::Trait(
310+
_constness,
311+
is_auto,
312+
_safety,
313+
_impl_restriction,
314+
_ident,
315+
_generics,
316+
_generic_bounds,
317+
item_ref,
318+
) if self.enable_ordering_for_trait && *is_auto == IsAuto::No => {
312319
let mut cur_t: Option<(TraitItemId, Ident)> = None;
313320

314321
for &item in *item_ref {

src/tools/clippy/clippy_lints/src/booleans.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ declare_clippy_lint! {
3030
/// Ignores short circuiting behavior of `||` and
3131
/// `&&`. Ignores `|`, `&` and `^`.
3232
///
33+
/// Creates a big toll on performance, **only enable sporadically**
34+
///
3335
/// ### Example
3436
/// ```ignore
3537
/// if a && true {}
@@ -43,7 +45,7 @@ declare_clippy_lint! {
4345
/// ```
4446
#[clippy::version = "pre 1.29.0"]
4547
pub NONMINIMAL_BOOL,
46-
complexity,
48+
pedantic,
4749
"boolean expressions that can be written more concisely"
4850
}
4951

@@ -57,6 +59,7 @@ declare_clippy_lint! {
5759
///
5860
/// ### Known problems
5961
/// Ignores short circuiting behavior.
62+
/// Creates a big toll on performance, **only enable sporadically**
6063
///
6164
/// ### Example
6265
/// ```rust,ignore
@@ -70,7 +73,7 @@ declare_clippy_lint! {
7073
/// ```
7174
#[clippy::version = "pre 1.29.0"]
7275
pub OVERLY_COMPLEX_BOOL_EXPR,
73-
correctness,
76+
pedantic,
7477
"boolean expressions that contain terminals which can be eliminated"
7578
}
7679

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use rustc_ast::ast::{BorrowKind, Expr, ExprKind, Mutability};
3-
use rustc_ast::token::{Lit, LitKind};
1+
use std::borrow::Cow;
2+
3+
use clippy_utils::diagnostics::span_lint_and_then;
4+
use clippy_utils::source::snippet_with_applicability;
5+
use clippy_utils::sugg::Sugg;
6+
use clippy_utils::{get_parent_expr, span_contains_cfg, span_contains_comment};
7+
use rustc_ast::LitKind;
48
use rustc_errors::Applicability;
5-
use rustc_lint::{EarlyContext, EarlyLintPass};
9+
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
10+
use rustc_lint::{LateContext, LateLintPass};
611
use rustc_session::declare_lint_pass;
12+
use rustc_span::Span;
713

814
declare_clippy_lint! {
915
/// ### What it does
@@ -30,47 +36,73 @@ declare_clippy_lint! {
3036

3137
declare_lint_pass!(ByteCharSlice => [BYTE_CHAR_SLICES]);
3238

33-
impl EarlyLintPass for ByteCharSlice {
34-
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
39+
impl<'tcx> LateLintPass<'tcx> for ByteCharSlice {
40+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
3541
if !expr.span.from_expansion()
36-
&& let Some(slice) = is_byte_char_slices(expr)
42+
&& let Some((has_ref, slice)) = is_byte_char_slices(cx, expr)
3743
{
38-
span_lint_and_sugg(
44+
span_lint_and_then(
3945
cx,
4046
BYTE_CHAR_SLICES,
4147
expr.span,
4248
"can be more succinctly written as a byte str",
43-
"try",
44-
format!("b\"{slice}\""),
45-
Applicability::MachineApplicable,
49+
|diag| {
50+
let mut app = Applicability::MachineApplicable;
51+
let mut sugg = Sugg::hir_from_snippet(cx, expr, |_| {
52+
let mut slice = slice.iter().fold("b\"".to_owned(), |mut acc, span| {
53+
let snippet = snippet_with_applicability(cx, *span, "b'?'", &mut app);
54+
acc.push_str(match &snippet[2..snippet.len() - 1] {
55+
"\"" => "\\\"",
56+
"\\'" => "'",
57+
other => other,
58+
});
59+
acc
60+
});
61+
slice.push('"');
62+
Cow::Owned(slice)
63+
});
64+
if !has_ref && !cx.typeck_results().expr_ty_adjusted(expr).is_array_slice() {
65+
sugg = sugg.deref();
66+
}
67+
68+
diag.span_suggestion(expr.span, "try", sugg, app);
69+
},
4670
);
4771
}
4872
}
4973
}
5074

5175
/// Checks whether the slice is that of byte chars, and if so, builds a byte-string out of it
52-
fn is_byte_char_slices(expr: &Expr) -> Option<String> {
53-
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, expr) = &expr.kind
54-
&& let ExprKind::Array(members) = &expr.kind
76+
fn is_byte_char_slices<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<(bool, Vec<Span>)> {
77+
let (has_ref, expr) = if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = expr.kind {
78+
(true, inner)
79+
} else if let Some(parent) = get_parent_expr(cx, expr) // Already checked by the parent expr.
80+
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) = parent.kind
81+
{
82+
return None;
83+
} else {
84+
(false, expr)
85+
};
86+
87+
if let ExprKind::Array(members) = expr.kind
5588
&& !members.is_empty()
89+
&& !span_contains_comment(cx, expr.span)
90+
&& !span_contains_cfg(cx, expr.span)
5691
{
57-
members
92+
return members
5893
.iter()
59-
.map(|member| match &member.kind {
60-
ExprKind::Lit(Lit {
61-
kind: LitKind::Byte,
62-
symbol,
63-
..
64-
}) => Some(symbol.as_str()),
65-
_ => None,
66-
})
67-
.map(|maybe_quote| match maybe_quote {
68-
Some("\"") => Some("\\\""),
69-
Some("\\'") => Some("'"),
70-
other => other,
94+
.try_fold(Vec::new(), |mut acc, member| {
95+
if let ExprKind::Lit(lit) = member.kind
96+
&& let LitKind::Byte(_) = lit.node
97+
&& expr.span.eq_ctxt(member.span)
98+
{
99+
acc.push(lit.span);
100+
return Some(acc);
101+
}
102+
None
71103
})
72-
.collect::<Option<String>>()
73-
} else {
74-
None
104+
.map(|s| (has_ref, s));
75105
}
106+
107+
None
76108
}

src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, allowed_duplicate
3232
{
3333
for (name, group) in &packages
3434
.iter()
35-
.filter(|p| !allowed_duplicate_crates.contains(&p.name))
35+
.filter(|p| !allowed_duplicate_crates.contains(p.name.as_str()))
3636
.group_by(|p| &p.name)
3737
{
3838
let group: Vec<&Package> = group.collect();

0 commit comments

Comments
 (0)