Without this check, the lint would suggest that
```rust
match test {
true if option == 5 => 10,
_ => 1,
};
```
is replaced by `if test { 10 } else { 1 }`.
changelog: [`match_bool`]: omit suggestion when guards are present in
`match` expression
Before edition 2024, some temporaries used in scrutinees of a `match`
used as the last expression of a block may outlive some referenced local
variables. Prevent those cases from happening by checking that alive
temporaries with significant drop do have a static lifetime.
The check is performed only for edition 2021 and earlier, and for the
last statement if it would become the last expression of the block.
changelog: [`unnecessary_semicolon`]: prevent borrow errors in editions
lower than 2024
r? @y21
Using `Vec::extend(std::iter::repeat_n(item, N))` allows to use the more
natural number of elements to add `N`, as is probably done in the
original loop, instead of computing the difference between the existing
number of elements and the wanted one.
Before MSRV 1.82, the older suggestion to use `Vec::resize()` is still
issued.
Inspired by #6156 (which predates `repeat_n()`).
changelog: [`same_item_push`]: recommend using `Vec::extend()` to extend
a vector
Before edition 2024, some temporaries used in scrutinees in a `match`
used as the last expression of a block may outlive some referenced
local variables. Prevent those cases from happening by checking that
alive temporaries with significant drop do have a static lifetime.
The check is performed only for edition 2021 and earlier, and for the
last statement if it would become the last expression of the block.
- The lint no longer triggers if one of the operands in the boolean
expression comes from a macro expansion.
- Parenthesis are now removed inside the generated block if they are no
longer necessary.
- Error markers have been added.
changelog: [`short_circuit_statement`]: better handling of macros and
better looking suggestions
remove support for the (unstable) #[start] attribute
As explained by `@Noratrieb:`
`#[start]` should be deleted. It's nothing but an accidentally leaked implementation detail that's a not very useful mix between "portable" entrypoint logic and bad abstraction.
I think the way the stable user-facing entrypoint should work (and works today on stable) is pretty simple:
- `std`-using cross-platform programs should use `fn main()`. the compiler, together with `std`, will then ensure that code ends up at `main` (by having a platform-specific entrypoint that gets directed through `lang_start` in `std` to `main` - but that's just an implementation detail)
- `no_std` platform-specific programs should use `#![no_main]` and define their own platform-specific entrypoint symbol with `#[no_mangle]`, like `main`, `_start`, `WinMain` or `my_embedded_platform_wants_to_start_here`. most of them only support a single platform anyways, and need cfg for the different platform's ways of passing arguments or other things *anyways*
`#[start]` is in a super weird position of being neither of those two. It tries to pretend that it's cross-platform, but its signature is a total lie. Those arguments are just stubbed out to zero on ~~Windows~~ wasm, for example. It also only handles the platform-specific entrypoints for a few platforms that are supported by `std`, like Windows or Unix-likes. `my_embedded_platform_wants_to_start_here` can't use it, and neither could a libc-less Linux program.
So we have an attribute that only works in some cases anyways, that has a signature that's a total lie (and a signature that, as I might want to add, has changed recently, and that I definitely would not be comfortable giving *any* stability guarantees on), and where there's a pretty easy way to get things working without it in the first place.
Note that this feature has **not** been RFCed in the first place.
*This comment was posted [in May](https://github.com/rust-lang/rust/issues/29633#issuecomment-2088596042) and so far nobody spoke up in that issue with a usecase that would require keeping the attribute.*
Closes https://github.com/rust-lang/rust/issues/29633
try-job: x86_64-gnu-nopt
try-job: x86_64-msvc-1
try-job: x86_64-msvc-2
try-job: test-various
- The lint no longer triggers if the expression comes from macro
expansion
- Parenthesis are now removed inside the generated block if they are no
longer necessary.
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
Without this check, the lint would suggest that
```rust
match test {
true if option == 5 => 10,
_ => 1,
};
```
is replaced by `if test { 10 } else { 1 }`.
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.
By assuming that a recursive type is normalizable within the deeper
calls to `is_normalizable_helper()`, more cases can be handled by this
function.
In order to fix stack overflows, a recursion limit has also been added
for recursive generic type instantiations.
Counting in bytes for a pointer to `u8` is legitimate and must not
trigger the lint. Also, this prevents linting the
`{std,core}::ptr::write_bytes` as it manipulates bytes.
Using `Vec::extend(std::iter::repeat_n(item, N))` allows to use the more
natural number of elements to add `N`, as is probably done in the original
loop, instead of computing the difference between the existing number of
elements and the wanted one.
Before MSRV 1.82, the older suggestion to use `Vec::resize()` is still
issued.
deprecate `std::intrinsics::transmute` etc, use `std::mem::*` instead
The `rustc_allowed_through_unstable_modules` attribute lets users call `std::mem::transmute` as `std::intrinsics::transmute`. The former is a reexport of the latter, and for a long time we didn't properly check stability for reexports, so making this a hard error now would be a breaking change for little gain. But at the same time, `std::intrinsics::transmute` is not the intended path for this function, so I think it is a good idea to show a deprecation warning when that path is used. This PR implements that, for all the functions in `std::intrinsics` that carry the attribute.
I assume this will need ``@rust-lang/libs-api`` FCP.
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