This PR fixes an issue with the `significant_drop_in_scrutinee`, where
the lint generates invalid Rust syntax when suggesting fixes for match
expressions that are part of larger expressions, such as in assignment
contexts. For example:
```rust
let mutex = Mutex::new(State {});
let _ = match mutex.lock().unwrap().foo() {
true => 0,
false => 1,
};
```
would suggest:
```rust
let _ = let value = mutex.lock().unwrap().foo();
match value {
```
With this PR, it now suggests:
```rust
let value = mutex.lock().unwrap().foo();
let _ = match value {
```
closes: #13986
changelog: [`significant_drop_in_scrutinee`] Fix incorrect suggestion
for `significant_drop_in_scrutinee` lint in expression context
This lint detects and removes the unnecessary semicolon after a `match`
or `if` statement returning `()`. It seems to be quite a common
"mistake", given the number of hits (88) we had in the Clippy sources
themselves.
The lint doesn't bother about loops, as `rustfmt` already removes the
extra semicolon. It doesn't handle blocks either, as an extra block
level, followed or not by a semicolon, is likely intentional.
I propose to put the lint in `pedantic`, as putting it in `style` seems
quite hazardous given the number of hits.
Note: there exists a `redundant-semicolon` lint in the compiler, but it
is an early lint and cannot check that the expression evaluates to `()`,
so it ignores the cases we're handling here.
----
changelog: [`unnecessary_semicolon`]: new lint
A multipart suggestion will be used whenever the method call can be
replaced by another one with the first argument removed. It helps place
the new method call in context, especially when it is part of a larger
expression.
This fixes#13995 by applying a suggestion made by @y21.
r? @y21
changelog: [`unnecessary_map_or`]: better representation of suggestions
by placing them in context
A multipart suggestion will be used whenever the method call can be
replaced by another one with the first argument removed. It helps place
the new method call in context, especially when it is part of a larger
expression.
changelog: [`useless-nonzero-new_unchecked`]: new lint
Close#13991
### What it does
Checks for `NonZero*::new_unchecked(<literal>)` being used in a `const`
context.
### Why is this bad?
Using `NonZero*::new_unchecked()` is an `unsafe` function and requires
an `unsafe` context. When used with an
integer literal in a `const` context, `NonZero*::new().unwrap()` will
provide the same result with identical
runtime performances while not requiring `unsafe`.
### Example
```no_run
const PLAYERS: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(3) };
```
Use instead:
```no_run
const PLAYERS: NonZeroUsize = NonZeroUsize::new(3).unwrap();
```
Commit 9ef6e2199c introduced a check to
ensure that Clippy doesn't consider a lifetime present in an explicit
self types as being the default for an elided output lifetime. For
example, elision did not work in the case like:
```rust
fn func(self: &Rc<Self>, &str) -> &str { … }
```
Since Rust 1.81.0, the lifetime in the self type is now considered the
default for elision. Elision should then be suggested when appropriate.
changelog: [`needless_lifetimes`]: suggest elision of lifetimes present
in explicit self types as well
r? @Alexendoo
because of #8278
Temporaries created inside the expansion of `.await` will be dropped and
need no checking. Looking inside the expansion will trigger false
positives.
changelog: [`significant_drop_in_scrutinee`]: do not falsely warn for
temporaries created by `.await` expansion
Fix#13927
Commit 9ef6e2199c introduced a check to
ensure that Clippy doesn't consider a lifetime present in an explicit
self type as being the default for an elided output lifetime. For
example, elision did not work in the case like:
```rust
fn func(self: &Rc<Self>, &str) -> &str { … }
```
Since Rust 1.81.0, the lifetime in the self type is now considered
the default for elision. Elision should then be suggested when
appropriate.
changelog: [`slow_vector_initialization`]: auto-fix when appropriate
I made a change for `slow_vector_initialization` lint suggestion to use
`vec!` with size and remove the unneeded `resize` (or similar one) call
in #13912, while only the former one was suggested in the previous
implementation. Now, I think this lint can be automatically fixed with
no unnecessary code in some cases. I wrote “in some cases” because if
there are comments between vector declaration and `resize`, Clippy
shouldn't apply auto-fix because the comment may informational.
Some widely used crates, such as `pin-project-lite`, make use of a
`pub(crate)` construct in a private module inside a public macro. This
makes unrelated project trigger the lint.
There is also an unfortunate situation for Clippy itself: when a new
version of `pin-project-lite` or similar lint-trigerring crates is
released, those lints which can be found in hundreds of occurrences in
dependent crates will change, and appear as diffs in unrelated Clippy PR
because the base lintcheck run will be cached with the ancient release
of the crates. We currently have the situation
[here](https://github.com/rust-lang/rust-clippy/actions/runs/12635410895?pr=13851#user-content-redundant-pub-crate-removed),
which 219 lints removed and 219 lints added because of a
`pin-project-lite` version change between runs, and the fact that
`redundant_pub_crate` triggers on external macros.
Also:
- Fix#10636
- Fix#12213
changelog: [`redundant_pub_crate`]: do not trigger on external macros
changelog: [`manual_ok_err`]: new lint
Detect manual implementations of `.ok()` or `.err()`, as in
```rust
let a = match func() {
Ok(v) => Some(v),
Err(_) => None,
};
let b = if let Err(v) = func() {
Some(v)
} else {
None
};
```
which can be replaced by
```rust
let a = func().ok();
let b = func().err();
```
This pattern was detected in the wild in the Rust reimplementation of
coreutils:
https://github.com/uutils/coreutils/pull/6886#pullrequestreview-2465160137
Some lifetimes in function return types are not bound to concrete
content and can be set arbitrarily. Clippy should not propose to replace
them by the default `'_` lifetime if such a lifetime cannot be
determined unambigously.
I added a field to the `LifetimeChecker` and `Usage` to flag lifetimes
that cannot be replaced by default ones, but it feels a bit hacky.
Fix#13923
changelog: [`needless_lifetimes`]: remove false positives by checking
that lifetimes can indeed be elided
Fixes#13913 .
changelog: [`manual_is_ascii_check`]: fix type suggestions for
references
Previously it only derived `char` and `u8` types, now it should always
annotate the lambda parameter with the correct type (e.g. `&char`).
I'm quite new to Rust and this is my first contact with clippy, so I'm
open for suggetions :)
Some lifetimes in function return types are not bound to concrete
content and can be set arbitrarily. Clippy should not propose to replace
them by the default `'_` lifetime if such a lifetime cannot be
determined unambigously.
Removing `.map(identity)` may result in invalid code if the receiver of
`map()` is an immutable binding, and the result of `map()` is used as
the receiver of a method call expecting a mutable reference.
Fix#13904
changelog: [`map_identity`]: do not lint if this would cause mandatory
mutability to be lost
When the expression is transformed into an equality, parentheses are
needed only if the resulting equality is used:
- as a receiver in a method call
- as part of a binary or unary expression
- as part of a cast
In other cases, which will be the majority, no parentheses are required.
This makes the lint suggestions cleaner.
changelog: `none`
Fixes https://github.com/rust-lang/rust-clippy/issues/8528.
Similar to #13911, if there are code comments, we don't want to remove
them automatically.
changelog: Don't emit machine applicable `map_flatten` lint if there are
code comments
r? @xFrednet
Fixes#13692.
If the `vec!` macro call contains comments, we should not provide
suggestions and let users handle it however they see fit.
changelog: Only emit `useless_vec` suggestion if the macro does not
contain code comments
fixes: #4077
Continuation of #11546. r? @y21 if you don't mind?
changelog: [`needless_continue`] lint if the last stmt in loop is
`continue` recurisvely
When the expression is transformed into an equality, parentheses are
needed only if the resulting equality is used:
- as a receiver in a method call
- as part of a binary or unary expression
- as part of a cast
In other cases, which will be the majority, no parentheses are required.
This makes the lint suggestions cleaner.
I [recently realized that `.last()` might not call `next_back()` when it
is
available](https://qsantos.fr/2025/01/01/rust-gotcha-last-on-doubleendediterator/).
Although the implementor could make sure to implement `last()` to do so,
this is not what will happen by default. As a result, I think it is
useful to add a lint to promote using `.next_back()` over `.last()` on
`DoubleEndedIterator`.
If this is merged, we might want to close #1822.
changelog: [`double_ended_iterator_last`]: Add lint for calling
`Iterator::last()` on `DoubleEndedIterator`