Don't emit `struct_field_names` lint if all fields are booleans and don't start with the type's name
Fixes#11936.
I only checked that all fields are booleans and not the prefix (nor the suffix) because when I started to list accepted prefixes (like "is", "has", "should", "could", etc), the list was starting to get a bit too long and I thought it was not really worth for such a small change.
r? `@llogiq`
changelog: Don't emit `struct_field_names` lint if all fields are booleans and don't start with the type's name
Don't lint `let_unit_value` when `()` is explicit
since these are explicitly written (and not the result of a function call or anything else), they should be allowed, as they are both useful in some cases described in #9048Fixes#9048
changelog: [`let_unit_value`]: Don't lint when `()` is explicit
Tweak suggestions for bare trait used as a type
```
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/not-on-bare-trait-2021.rs:11:11
|
LL | fn bar(x: Foo) -> Foo {
| ^^^
|
help: use a generic type parameter, constrained by the trait `Foo`
|
LL | fn bar<T: Foo>(x: T) -> Foo {
| ++++++++ ~
help: you can also use `impl Foo`, but users won't be able to specify the type paramer when calling the `fn`, having to rely exclusively on type inference
|
LL | fn bar(x: impl Foo) -> Foo {
| ++++
help: alternatively, use a trait object to accept any type that implements `Foo`, accessing its methods at runtime using dynamic dispatch
|
LL | fn bar(x: &dyn Foo) -> Foo {
| ++++
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/not-on-bare-trait-2021.rs:11:19
|
LL | fn bar(x: Foo) -> Foo {
| ^^^
|
help: use `impl Foo` to return an opaque type, as long as you return a single underlying type
|
LL | fn bar(x: Foo) -> impl Foo {
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn bar(x: Foo) -> Box<dyn Foo> {
| +++++++ +
```
Fix#119525:
```
error[E0038]: the trait `Ord` cannot be made into an object
--> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
|
LL | fn ord_prefer_dot(s: String) -> Ord {
| ^^^ `Ord` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: the trait cannot be made into an object because it uses `Self` as a type parameter
::: $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: the trait cannot be made into an object because it uses `Self` as a type parameter
help: consider using an opaque type instead
|
LL | fn ord_prefer_dot(s: String) -> impl Ord {
| ++++
```
Don't look for safety comments in doc tests
Fixes#12048.
What happened in the linked issue is that the lint checks for lines that start with `//` and have `SAFETY:` somewhere in it above the function item.
This works for regular comments, but when the `//` is the start of a doc comment (e.g. `/// // SAFETY: ...`) and it's part of a doc test (i.e. within \`\`\`), we probably shouldn't lint that, since the user most likely meant to refer to a different node than the one currently being checked. For example in the linked issue, the safety comment refers to `unsafe { *five_pointer }`, but the lint believes it's part of the function item.
We also can't really easily test whether the `// SAFETY:` comment within a doc comment is necessary or not, since I think that would require creating a new compiler session to re-parse the contents of the doc comment. We already do this for one of the doc markdown lints, to look for a main function in doc tests, but I don't know how to feel about doing that in more places, so probably best to just ignore them?
changelog: [`unnecessary_safety_comment`]: don't look for safety comments in doc tests
Add .as_ref() to suggestion to remove .to_string()
The case of `.to_owned().split(…)` is treated specially in the `unnecessary_to_owned` lint. Test cases check that it works both for slices and for strings, but they missed a corner case: `x.to_string().split(…)` when `x` implements `AsRef<str>` but not `Deref<Target = str>`. In this case, it is wrong to suggest to remove `.to_string()` without adding `.as_ref()` instead.
Fix#12068
changelog: [`unnecessary_to_owned`]: suggest replacing `.to_string()` by `.as_ref()`
new lint: `option_as_ref_cloned`
Closes#12009
Adds a new lint that looks for `.as_ref().cloned()` on `Option`s. That's the same as just `.clone()`-ing the option directly.
changelog: new lint: [`option_as_ref_cloned`]
Extend `unconditional_recursion` lint to check for `Default` trait implementation
In case the `Default` trait is implemented manually and is calling a static method (let's call it `a`) and then `a` is using `Self::default()`, it makes an infinite call recursion difficult to see without debugging. This extension checks that there is no such recursion possible.
r? `@llogiq`
changelog: Extend `unconditional_recursion` lint to check for `Default` trait implementation
Lint nested binary operations and handle field projections in `eager_transmute`
This PR makes the lint a bit stronger. Previously it would only lint `(x < 4).then_some(transmute(x))` (that is, a single binary op in the condition). With this change, it understands:
- multiple, nested binary ops: `(x < 4 && x > 1).then_some(...)`
- local references with projections: `(x.field < 4 && x.field > 1).then_some(transmute(x.field))`
changelog: [`eager_transmute`]: lint nested binary operations and look through field/array accesses
r? llogiq (since you reviewed my initial PR #11981, I figured you have the most context here, sorry if you are too busy with other PRs, feel free to reassign to someone else then)
Fix false positive `unconditional_recursion`
Fixes#12052.
Only checking if both variables are `local` was not enough, we also need to confirm they have the same type as `Self`.
changelog: Fix false positive for `unconditional_recursion` lint
Fixes: #12050 - `identity_op` correctly suggests a deference for coerced references
When `identity_op` identifies a `no_op`, provides a suggestion, it also checks the type of the type of the variable. If the variable is a reference that's been coerced into a value, e.g.
```
let x = &0i32;
let _ = x + 0;
```
the suggestion will now use a derefence. This is done by identifying whether the variable is a reference to an integral value, and then whether it gets dereferenced.
changelog: false positive: [`identity_op`]: corrected suggestion for reference coerced to value.
fixes: #12050
This commit:
- now makes `HirEqInterExpr::eq_block` take comments into account. Identical code with varying comments will no longer be considered equal.
- makes necessary adjustments to UI tests.
Adds a new lint to suggest using `const` on `thread_local!`
initializers that can be evaluated at compile time.
Impl details:
The lint relies on the expansion of `thread_local!`. For non
const-labelled initializers, `thread_local!` produces a function
called `__init` that lazily initializes the value. We check the function
and decide whether the body can be const. The body of the function is
exactly the initializer. If so, we lint the body.
changelog: new lint [`thread_local_initializer_can_be_made_const`]
Extend UNCONDITIONAL_RECURSION to check for ToString implementations
Follow-up of https://github.com/rust-lang/rust-clippy/pull/11938.
r? `@llogiq`
changelog: Extend `UNCONDITIONAL_RECURSION` to check for `ToString` implementations
New Lint: empty_enum_variants_with_brackets
This PR:
- adds a new early pass lint that checks for enum variants with no fields that were defined using brackets. **Category: Restriction**
- adds relevant UI tests for the new lint.
Closes#12007
```
changelog: New lint: [`empty_enum_variants_with_brackets`]
```
don't lint [`default_numeric_fallback`] on return and local assigned macro calls with type stated
fixes: #11535
changelog: don't lint [`default_numeric_fallback`] on return and local assigned macro calls with type stated
feat: add `manual_is_variant_and` lint
changelog: add a new lint [`manual_is_variant_and`].
- Replace `option.map(f).unwrap_or_default()` and `result.map(f).unwrap_or_default()` with `option.is_some_and(f)` and `result.is_ok_and(f)` where `f` is a function or closure that returns `bool`.
- MSRV is set to 1.70.0 for this lint; when `is_some_and` and `is_ok_and` was stabilised
---
For example, for the following code:
```rust
let opt = Some(0);
opt.map(|x| x > 1).unwrap_or_default();
```
It suggests to instead write:
```rust
let opt = Some(0);
opt.is_some_and(|x| x > 1)
```
make [`mutex_atomic`] more type aware
fixes: #9872
---
changelog: [`mutex_atomic`] now suggests more specific atomic types and skips mutex i128 and u128
When `identity_op` identifies a `no_op`, provides a suggestion, it also
checks the type of the type of the variable. If the variable is
a reference that's been coerced into a value, e.g.
```
let x = &0i32;
let _ = x + 0;
```
the suggestion will now use a derefence. This is done by identifying
whether the variable is a reference to an integral value, and then
whether it gets dereferenced.
changelog: false positive: [`identity_op`]: corrected suggestion for
reference coerced to value.
fixes: #12050
new lint: `eager_transmute`
A small but still hopefully useful lint that looks for patterns such as `(x < 5).then_some(transmute(x))`.
This is almost certainly wrong because it evaluates the transmute eagerly and can lead to surprises such as the check being completely removed and always evaluating to `Some` no matter what `x` is (it is UB after all when the integer is not a valid bitpattern for the transmuted-to type). [Example](https://godbolt.org/z/xoY34fPzh).
The user most likely meant to use `then` instead.
I can't remember where I saw this but this is inspired by a real bug that happened in practice.
This could probably be a correctness lint?
changelog: new lint: [`eager_int_transmute`]
Return with a question mark was triggered in situations where the `?`
desuraging was performing error conversion via `Into`/`From`.
The desugared `?` produces a match over an expression with type
`std::ops::ControlFlow<B,C>` with `B:Result<Infallible, E:Error>` and
`C:Result<_, E':Error>`, and the arms perform the conversion. The patch
adds another check in the lint that checks that `E == E'`. If `E == E'`,
then the `?` is indeed unnecessary.
changelog: False Positive: `needless_return_with_question_mark` when
implicit Error Conversion occurs.
Make some non-diagnostic-affecting `QPath::LangItem` into regular `QPath`s
The rest of 'em affect diagnostics, so leave them alone... for now.
cc #115178
New lints `iter_filter_is_some` and `iter_filter_is_ok`
Adds a pair of lints that check for cases of an iterator over `Result` and `Option` followed by `filter` without being followed by `map` as that is covered already by a different, specialized lint.
Fixes#11843
PS, I also made some minor documentations fixes in a case where a double tick (`) was included.
---
changelog: New Lint: [`iter_filter_is_some`]
[#12004](https://github.com/rust-lang/rust/pull/12004)
changelog: New Lint: [`iter_filter_is_ok`]
[#12004](https://github.com/rust-lang/rust/pull/12004)
Do not consider `async { (impl IntoFuture).await }` as redundant
changelog: [`redundant_async_block`]: do not trigger on `IntoFuture` instances
Fix#11959
[`question_mark`]: also trigger on `return` statements
This fixes the false negative mentioned in #11993: the lint only used to check for `return` expressions, and not a statement containing a `return` expression (doesn't close the issue tho since there's still a useful suggestion that we could make, which is to suggest `.ok_or()?`/`.ok_or_else()?` for `else { return Err(..) }`)
changelog: [`question_mark`]: also trigger on `return` statements
fix typo in infinite loop lint
*Please write a short comment explaining your change (or "none" for internal only changes)*
changelog: This fixes a small typo introduced in https://github.com/rust-lang/rust-clippy/pull/11829
Extend `UNNECESSARY_TO_OWNED` to handle `split`
Fixes https://github.com/rust-lang/rust-clippy/issues/9965.
When you have `to_string().split('a')` or equivalent, it'll suggest to remove the `to_owned`/`to_string` part.
r? `@flip1995`
changelog: Extend `UNNECESSARY_TO_OWNED` to handle `split`
Check whether out of bound when access a known length array with a constant index
fixes [Issue#11762](https://github.com/rust-lang/rust-clippy/issues/11762)
Issue#11762 points that `Array references with known length are not flagged when indexed out of bounds`.
To fix this problem, it is needed to add check for `Expr::Index`. We expand this issue include reference and direct accessing a array.
When we access a array with a constant index `off`, and already know the length `size`, if `off >= size`, these code will throw an error, instead rustc's lint checking them or runtime panic happening.
changelog: [`out_of_bound_indexing`]: Add check for illegal accessing known length array with a constant index
Adds a pair of lints that check for cases of an iterator over `Result`
and `Option` followed by `filter` without being followed by `map` as
that is covered already by a different, specialized lint.
changelog: New Lint: [`iter_filter_is_some`]
changelog: New Lint: [`iter_filter_is_ok`]
New Lint: `result_filter_map` / Mirror of `option_filter_map`
Added the `Result` mirror of `option_filter_map`.
changelog: New Lint: [`result_filter_map`]
I had to move around some code because the function def was too long 🙃.
I have also added some pattern checks on `option_filter_map`
don't visit nested bodies in `is_const_evaluatable`
Fixes#11939
This ICE happened in `if_let_some_else_none`, but the root problem is in one of the utils that it uses.
It is (was) possible for `is_const_evalutable` to visit nested bodies which would lead to it trying to get the type of one of the expressions with the wrong typeck table, which won't have the type stored.
Notably, for the expression `Bytes::from_static(&[0; 256 * 1024]);` in the linked issue, the array length is an anonymous const in which type checking happens on its own, so we can't use the typeck table of the enclosing function in there.
Visiting nested bodies is also not needed for checking whether an expression can be const, so I think it's safe to ignore just ignore them altogether.
changelog: Fix ICE when checking for constness in nested bodies
Add new `unconditional_recursion` lint
Currently, rustc `unconditional_recursion` doesn't detect cases like:
```rust
enum Foo {
A,
B,
}
impl PartialEq for Foo {
fn eq(&self, other: &Self) -> bool {
self == other
}
}
```
This is because the lint is currently implemented only for one level, and in the above code, `self == other` will then call `impl PartialEq for &T`, escaping from the detection. The fix for it seems to be a bit tricky (I started investigating potential solution to add one extra level of recursion [here](https://github.com/rust-lang/rust/compare/master...GuillaumeGomez:rust:trait-impl-recursion?expand=1) but completely broken at the moment).
I expect that this situation will remain for a while. In the meantime, I think it's acceptable to check it directly into clippy for the time being as a lot of easy cases like this one can be easily checked (next I plan to extend it to cover other traits like `ToString`).
changelog: Add new `unconditional_recursion` lint
Added the `Result` mirror of `option_filter_map` to catch
```
.into_iter().filter(Result::is_ok).map(Result::unwrap)
```
changelog: New Lint: [`result_filter_map`]
Co-authored-by: Alex Macleod <alex@macleod.io>
Fix binder handling in `unnecessary_to_owned`
fixes#11952
The use of `rebind` instead of `EarlyBinder::bind` isn't technically needed, but it is the semantically correct operation.
changelog: None
[`doc_markdown`] Recognize words followed by empty parentheses `()` for quoting
*Please write a short comment explaining your change (or "none" for internal only changes)*
changelog: [`doc_markdown`] Recognize words followed by empty parentheses for quoting, e.g. `func()`.
---
Developers often write function/method names with trailing `()`, but `doc_markdown` lint did not consider that.
Old clippy suggestion was not very good:
```patch
-/// There is no try (do() or do_not()).
+/// There is no try (do() or `do_not`()).
```
New behavior recognizes function names such as `do()` even they contain no `_`/`::`; and backticks are suggested outside of the `()`:
```patch
-/// There is no try (do() or do_not()).
+/// There is no try (`do()` or `do_not()`).
```
Useless vec false positive
changelog: [`useless_vec`]: fix false positive in macros.
fixes#11861
We delay the emission of `useless_vec` lints to the check_crate_post stage, which allows us to effectively undo lints if we find that a `vec![]` expression is being used multiple times after macro expansion.
new lint to detect infinite loop
closes: #11438
changelog: add new lint to detect infinite loop
~*I'll change the lint name*~. Should I name it `infinite_loop` or `infinite_loops` is fine? Ahhhh, English is hard...
uninhabited_reference: new lint
Close#11851
The lint is implemented on function parameters and return types, as this is the place where the risk of exchanging references to uninhabited types is the highest. Other constructs, such as in a local variable,
would require the use of `unsafe` and will clearly be done on purpose.
changelog: [`uninhabited_reference`]: new lint
Add a function to check whether binary oprands are nontrivial
fixes [#issue11885](https://github.com/rust-lang/rust-clippy/issues/11885)
It's hard to check whether operator is overrided through context of lint.
So, assume non-trivial structure like tuple, array or sturt, using a overrided binary operator in this lint, which might cause a side effict.
This is not detected before.
Althrough this might weaken the ability of this lint, it may more useful than before. Maybe this lint will cause an error, but now, it not. And assuming side effect of non-trivial structure with operator is not a bad thing, right?
changelog: Fix: [`no_effect`] check if binary operands are nontrivial
fix(ptr_as_ptr): handle `std::ptr::null{_mut}`
close rust-lang#11066
close rust-lang#11665
close rust-lang#11911
*Please write a short comment explaining your change (or "none" for internal only changes)*
changelog: [`ptr_as_ptr`]: handle `std::ptr::null` and `std::ptr::null_mut`
needless_borrows_for_generic_args: Handle when field operand impl Drop
Before this fix, the lint had a false positive, namely when a reference was taken to a field when the field operand implements a custom Drop. The compiler will refuse to partially move a type that implements Drop, because that would put the type in a weird state.
## False Positive Example (Fixed)
```rs
struct CustomDrop(String);
impl Drop for CustomDrop {
fn drop(&mut self) {}
}
fn check_str<P: AsRef<str>>(_to: P) {}
fn test() {
let owner = CustomDrop(String::default());
check_str(&owner.0); // Don't lint. `owner` can't be partially moved because it impl Drop
}
```
changelog: [`needless_borrows_for_generic_args`]: Handle when field operand impl Drop
Update regex-syntax to support new word boundry assertions
From the regex v1.10.0 release notes [1]:
This is a new minor release of regex that adds support for start
and end word boundary assertions. [...]
The new word boundary assertions are:
• \< or \b{start}: a Unicode start-of-word boundary (\W|\A
on the left, \w on the right).
• \> or \b{end}: a Unicode end-of-word boundary (\w on the
left, \W|\z on the right)).
• \b{start-half}: half of a Unicode start-of-word boundary
(\W|\A on the left).
• \b{end-half}: half of a Unicode end-of-word boundary
(\W|\z on the right).
[1]: https://github.com/rust-lang/regex/blob/master/CHANGELOG.md#1100-2023-10-09
changelog: [`regex`]: add support for start and end word boundary assertions ("\<", "\b{start}", etc.) introduced in regex v0.10
Check whether operator is overrided with a `struct` operand.
The struct here refers to `struct`, `enum`, `union`.
Add and fix test for `no_effect` lint.
From the regex v1.10.0 release notes [1]:
This is a new minor release of regex that adds support for start
and end word boundary assertions. [...]
The new word boundary assertions are:
• \< or \b{start}: a Unicode start-of-word boundary (\W|\A
on the left, \w on the right).
• \> or \b{end}: a Unicode end-of-word boundary (\w on the
left, \W|\z on the right)).
• \b{start-half}: half of a Unicode start-of-word boundary
(\W|\A on the left).
• \b{end-half}: half of a Unicode end-of-word boundary
(\W|\z on the right).
[1]: https://github.com/rust-lang/regex/blob/master/CHANGELOG.md#1100-2023-10-09
expending lint [`blocks_in_if_conditions`] to check match expr as well
closes: #11814
changelog: rename lint `blocks_in_if_conditions` to [`blocks_in_conditions`] and expand it to check blocks in match scrutinees
[`missing_asserts_for_indexing`]: accept length equality checks
Fixes#11835
The lint now allows indexing with indices 0 and 1 when an `assert!(x.len() == 2);` is found.
(Also fixed a typo in the doc example)
changelog: [`missing_asserts_for_indexing`]: accept len equality checks as a valid assertion
Stabilize C string literals
RFC: https://rust-lang.github.io/rfcs/3348-c-str-literal.html
Tracking issue: https://github.com/rust-lang/rust/issues/105723
Documentation PR (reference manual): https://github.com/rust-lang/reference/pull/1423
# Stabilization report
Stabilizes C string and raw C string literals (`c"..."` and `cr#"..."#`), which are expressions of type [`&CStr`](https://doc.rust-lang.org/stable/core/ffi/struct.CStr.html). Both new literals require Rust edition 2021 or later.
```rust
const HELLO: &core::ffi::CStr = c"Hello, world!";
```
C strings may contain any byte other than `NUL` (`b'\x00'`), and their in-memory representation is guaranteed to end with `NUL`.
## Implementation
Originally implemented by PR https://github.com/rust-lang/rust/pull/108801, which was reverted due to unintentional changes to lexer behavior in Rust editions < 2021.
The current implementation landed in PR https://github.com/rust-lang/rust/pull/113476, which restricts C string literals to Rust edition >= 2021.
## Resolutions to open questions from the RFC
* Adding C character literals (`c'.'`) of type `c_char` is not part of this feature.
* Support for `c"..."` literals does not prevent `c'.'` literals from being added in the future.
* C string literals should not be blocked on making `&CStr` a thin pointer.
* It's possible to declare constant expressions of type `&'static CStr` in stable Rust (as of v1.59), so C string literals are not adding additional coupling on the internal representation of `CStr`.
* The unstable `concat_bytes!` macro should not accept `c"..."` literals.
* C strings have two equally valid `&[u8]` representations (with or without terminal `NUL`), so allowing them to be used in `concat_bytes!` would be ambiguous.
* Adding a type to represent C strings containing valid UTF-8 is not part of this feature.
* Support for a hypothetical `&Utf8CStr` may be explored in the future, should such a type be added to Rust.
Before this fix, the lint had a false positive, namely when a reference
was taken to a field when the field operand implements a custom Drop.
The compiler will refuse to partially move a type that implements Drop,
because that would put the operand in a weird state. See added
regression test.
`option_if_let_else`: do not trigger on expressions returning `()`
Fix#11893
Trigerring on expressions returning `()` uses the arguments of the `map_or_else()` rewrite only for their side effects. This does lead to code which is harder to read than the original.
changelog: [`option_if_let_else`]: do not trigger on unit expressions
add lint against unit tests in doctests
During RustLab, Alice Ryhl brought to my attention that the Andoid team stumbled over the fact that if one attempts to write a unit test within a doctest, it will be summarily ignored. So this lint should help people wondering why their tests won't run.
---
changelog: New lint: [`test_attr_in_doctest`]
[#11872](https://github.com/rust-lang/rust-clippy/pull/11872)
Fix#11893
Trigerring on expressions returning `()` uses the arguments of the
`map_or_else()` rewrite only for their side effects. This does lead
to code which is harder to read than the original.
[`redundant_guards`]: catch `is_empty`, `starts_with` and `ends_with` on slices and `str`s
Fixes#11807
Few things worth mentioning:
- Taking `snippet`s is now done at callsite, instead of passing a span and doing it in `emit_redundant_guards`. This is because we now need custom suggestion strings in certain places, like `""` for `str::is_empty`.
- This now uses `snippet` instead of `snippet_with_applicability`. I don't think this really makes any difference for `MaybeIncorrect`, though?
- This could also lint byte strings, as they're of type `&[u8; N]`, but that can be ugly so I decided to leave it out for now
changelog: [`redundant_guards`]: catch `str::is_empty`, `slice::is_empty`, `slice::starts_with` and `slice::ends_with`
[`redundant_closure_call`]: avoid duplicated `async` keyword when triggering on closure that returns `async` block
close#11357
----
*Please write a short comment explaining your change (or "none" for internal only changes)*
changelog: [`redundant_closure_call`]: avoid duplicated `async` keyword when triggering on closure that returns `async` block
Don't suggest `a.mul_add(b, c)` if parameters are not float
clippy::suboptimal_flops used to not check if the second parameter to f32/f64.mul_add() was float. Since the method is only defined to take `Self` as parameters, the suggestion was wrong.
Fixes#11831
changelog: [`suboptimal_float`]: Don't suggest `a.mul_add(b, c)` if parameters are not f32/f64
[`ptr_arg`]: recognize methods that also exist on slices
Fixes#11816
Not a new lint, just a very small improvement to the existing `ptr_arg` lint which would have caught the linked issue.
The problem was that the lint checks if a `Vec`-specific method was called, that is, if the receiver is `Vec<_>`.
This is the case for `len` and `is_empty`, however these methods also exist on slices so we can still lint there.
This logic exists in a different lint, so we can just reuse that here.
Interestingly, there was even a comment up top that explained what it should have been doing, but the logic for it just wasn't there?
changelog: [`ptr_arg`]: recognize methods that also exist on slices
<sub>Also, this is my 100th PR to clippy 🎉 </sub>
`manual_try_fold`: check that `fold` is really `Iterator::fold`
Fix#11876
changelog: [`manual_try_fold`]: suggest using `try_fold` only for `Iterator::fold` uses
Create new lint `option_map_or_err_ok`
Fixes#10045.
For the following code:
```rust
let opt = Some(1);
opt.map_or(Err("error"), Ok);
```
It suggests to instead write:
```rust
let opt = Some(1);
opt.ok_or("error");
```
r? `@flip1995`
changelog: Create new lint `option_map_or_err_ok`
suggest alternatives to iterate an array of ranges
works towards #7125
changelog: [`single_element_loop`]: suggest better syntax when iterating over an array of a single range
`@thinkerdreamer` and myself worked on this issue during a workshop by `@llogiq` at the RustLab 2023 conference. It is our first contribution to clippy.
When iterating over an array of only one element, _which is a range_, our change suggests to replace the array with the contained range itself. Additionally, a hint is printed stating that the user probably intended to iterate over the range and not the array. If the single element in the array is not a range, the previous suggestion in the form of `let {pat_snip} = {prefix}{arg_snip};{block_str}`is used.
This change lints the array with the single range directly, so any prefixes or suffixes are covered as well.
[`deprecated_semver`]: Allow `#[deprecated(since = "TBD")]`
"TBD" is allowed by rustdoc, saying that it will be deprecated in a future version. rustc will also not actually warn on it.
I found this while checking the rust-lang/rust with clippy.
changelog: [`deprecated_semver`]: allow using `since = "TBD"`
[`missing_asserts_for_indexing`]: work with bodies instead of blocks separately
Fixes#11856
Before this change, this lint would check blocks independently of each other, which means that it misses `assert!()`s from parent blocks.
```rs
// check_block
assert!(x.len() > 1);
{
// check_block
// no assert here
let _ = x[0] + x[1];
}
```
This PR changes it to work with bodies rather than individual blocks. That means that a function will be checked in one go and we can remember if an `assert!` occurred anywhere.
Eventually it would be nice to have a more control flow-aware analysis, possibly by rewriting it as a MIR lint, but that's more complicated and I wanted this fixed first.
changelog: [`missing_asserts_for_indexing`]: accept `assert!`s from parent blocks
Fix iter_kv_map false positive into_keys and into_values suggestion
fixes: #11752
changelog: [`iter_kv_map`]: fix false positive: Don't suggest `into_keys()` and `into_values()` if the MSRV is to low
Add tests for issues #10285, #10286, #10289, #10287Fixes#10285.
Fixes#10286.
Fixes#10289.
Fixes#10287.
This PR simply adds tests for the listed issues as they're already implemented so we can close them.
r? `@blyxyas`
changelog:none
Split `doc.rs` up into a subdirectory
So, first, sorry for the bad diff. 😅
In #11798, `@flip1995` suggested splitting `doc.rs` up, much like how we have the `methods/`, `matches/`, `types/` subdirectories.
I agree with this, the file is getting bigger as we add more and more doc lints that it makes sense to do this refactoring.
This is purely an internal change that moves things around a bit.
(**EDIT:** depending on the outcome of https://github.com/rust-lang/rust-clippy/pull/11801#issuecomment-1816715615 , this may change the lint group name from `doc_markdoc` to `doc`).
I tried to not change any of the actual logic of the lints and as such some things weren't as easy to move to a separate file. So we still have some `span_lint*` calls in the `doc/mod.rs` file, which I think is fine. This is also the case in `methods/mod.rs`.
Also worth mentioning that the lints missing_errors_doc, missing_panics_doc, missing_safety_doc and unnecessary_safety_doc have a lot of the same logic so it didn't make much sense for each of these to be in their own file. Instead I just put them all in `missing_headers.rs`
I also added a bit of documentation to the involved `check_{attrs,doc}` methods.
changelog: none
Improve maybe misused cfg
Follow-up of the improvements that were suggested to me in https://github.com/rust-lang/rust-clippy/pull/11821:
* I unified the output to use the same terms.
* I updated the code to prevent creating a new symbol.
r? `@blyxyas`
changelog: [`maybe_misued_cfg`]: Output and code improvements
Verify Borrow<T> semantics for types that implement Hash, Borrow<str> and Borrow<[u8]>.
Fixes#11710
The essence of the issue is that types that implement Borrow<T> provide a facet or a representation of the underlying type. Under these semantics `hash(a) == hash(a.borrow())`.
This is a problem when a type implements `Borrow<str>`, `Borrow<[u8]>` and Hash, it is expected that the hash of all three types is identical. The problem is that the hash of [u8] is not the same as that of a String, even when the byte reference ([u8]) is derived from `.as_bytes()`
- [x] Followed [lint naming conventions][lint_naming]
- [x] Added passing UI tests (including committed `.stderr` file)
- [x] `cargo test` passes locally
- [x] Executed `cargo dev update_lints`
- [x] Added lint documentation
- [x] Run `cargo dev fmt`
---
- [x] Explanation of the issue in the code
- [x] Tests reproducing the issue
- [x] Lint rule and emission
---
changelog: New lint: [`impl_hash_borrow_with_str_and_bytes`]
[#11781](https://github.com/rust-lang/rust-clippy/pull/11781)
Implements a lint to prevent implementation of Hash, Borrow<str> and
Borrow<[u8]> as it breaks Borrow<T> "semantics". According to the book,
types that implement Borrow<A> and Borrow<B> must ensure equality of
borrow results under Eq,Ord and Hash.
> In particular Eq, Ord and Hash must be equivalent for borrowed and
owned values: x.borrow() == y.borrow() should give the same result as x == y.
In the same way, hash(x) == hash(x as Borrow<[u8]>) != hash(x as Borrow<str>).
changelog: newlint [`impl_hash_with_borrow_str_and_bytes`]
clippy::suboptimal_flops used to not check if the second parameter to f32/f64.mul_add() was float. Since the method is
only defined to take `Self` as paremters, the suggestion was wrong.
Fixes#11831
teach `eager_or_lazy` about panicky arithmetic operations
Fixes#9422Fixes#9814Fixes#11793
It's a bit sad that we have to do this because arithmetic operations seemed to me like the prime example where a closure would not be necessary, but this has "side effects" (changes behavior when going from lazy to eager) as some of these panic on overflow/underflow if compiled with `-Coverflow-checks` (which is the default in debug mode).
Given the number of backlinks in the mentioned issues, this seems to be a FP that is worth fixing, probably.
changelog: [`unnecessary_lazy_evaluations`]: don't lint if closure has panicky arithmetic operations
Extend `maybe_misused_cfg` lint over `cfg(test)`
Fixes#11240.
One thought I had is that we could use the levenshtein distance (of 1) to ensure this is indeed `test` that was targeted. But maybe it's overkill, not sure.
changelog: [`maybe_misused_cfg`]: Extend lint over `cfg(test)`
r? `@blyxyas`
This was made possible by the removal of plugin support, which
simplified lint store creation.
This simplifies the places in rustc and rustdoc that call
`describe_lints`, which are early on. The lint store is now built before
those places, so they don't have to create their own lint store for
temporary use, they can just use the main one.
Change `if_same_then_else` to be a `style` lint
CC #3770
From https://github.com/rust-lang/rust-clippy/issues/3770#issuecomment-687565594 (`@flip1995):`
> Oh I thought I replied to this: I definitely see now that having this
> as a correctness lint might be the wrong categorization. What we might
> want to do is to just allow this lint, if there are comments in the
> arm bodies. But a good first step would be to downgrade this lint to
> style or complexity. I would vote for style since merging two arms is
> not always less complex.
changelog: [`if_same_then_else`]: Change to be a `style` lint
[`impl_trait_in_params`]: avoid ICE when function with `impl Trait` type has no parameters
Fixes#11803
If I'm reading the old code correctly, it was taking the span of the first parameter (without checking that it exists, which caused the ICE) and uses that to figure out where the generic parameter to insert should go (cc `@blyxyas` you wrote the lint, is that correct?).
This seemed equivalent to just `generics.span`, which doesn't require calculating the spans like that and simplifies it a fair bit
changelog: don't ICE when function has no parameters but generics have an `impl Trait` type
CC #3770
From https://github.com/rust-lang/rust-clippy/issues/3770#issuecomment-687565594 (@flip1995):
> Oh I thought I replied to this: I definitely see now that having this
> as a correctness lint might be the wrong categorization. What we might
> want to do is to just allow this lint, if there are comments in the
> arm bodies. But a good first step would be to downgrade this lint to
> style or complexity. I would vote for style since merging two arms is
> not always less complex.
Implement new lint `iter_over_hash_type`
Implements and fixes https://github.com/rust-lang/rust-clippy/issues/11788
This PR adds a new *restriction* lint `iter_over_hash_type` which prevents `Hash`-types (that is, `HashSet` and `HashMap`) from being used as the iterator in `for` loops.
The justification for this is because in `Hash`-based types, the ordering of items is not guaranteed and may vary between executions of the same program on the same hardware. In addition, it reduces readability due to the unclear iteration order.
The implementation of this lint also ensures the following:
- Calls to `HashMap::keys`, `HashMap::values`, and `HashSet::iter` are also denied when used in `for` loops,
- When this expression is used in procedural macros, it is not linted/denied.
changelog: add new `iter_over_hash_type` lint to prevent unordered iterations through hashed data structures
Don't check for late-bound vars, check for escaping bound vars
Fixes an assertion that didn't make sense. Many valid and well-formed types *have* late-bound vars (e.g. `for<'a> fn(&'a ())`), they just must not have *escaping* late-bound vars in order to be normalized correctly.
Addresses rust-lang/rust-clippy#11230, cc `@jyn514` and `@matthiaskrgr`
changelog: don't check for late-bound vars, check for escaping bound vars. Addresses rust-lang/rust-clippy#11230
Fixes to `manual_let_else`'s divergence check
A few changes to the divergence check in `manual_let_else` and moves it the implementation to `clippy_utils` since it's generally useful:
* Handle internal `break` and `continue` expressions.
e.g. The first loop is divergent, but the second is not.
```rust
{
loop {
break 'outer;
};
}
{
loop {
break;
};
}
```
* Match rust's definition of divergence which is defined via the type system.
e.g. The following is not considered divergent by rustc as the inner block has a result type of `()`:
```rust
{
'a: {
panic!();
break 'a;
};
}
```
* Handle when adding a single semicolon would make the expression divergent.
e.g. The following would be a divergent if a semicolon were added after the `if` expression:
```rust
{ if panic!() { 0 } else { 1 } }
```
changelog: None
Lint `needless_borrow` and `explicit_auto_deref` on most union field accesses
Changes both lints to follow rustc's rules around auto-deref through `ManuallyDrop` union fields rather than just bailing on union fields.
changelog: [`needless_borrow`] & [`explicit_auto_deref`]: Lint on most union field accesses
[`map_identity`]: respect match ergonomics
Fixes#11764
Note: the original tests before this were slightly wrong themselves already and had to be changed. They were calling `map` on an iterator of `&(i32, i32)`s, so this PR would stop linting there, but they were meant to test something else unrelated to binding modes, so I just changed them to remove the references so that it iterates over owned values and they all bind by value. This way they continue to test what they checked for before: the identity function for tuple patterns.
changelog: [`map_identity`]: respect match ergonomics
Disable `vec_box` when using different allocators
Fixes#7114
This PR disables the `vec_box` lint when the `Box` and `Vec` use different allocators (but not when they use the same - custom - allocator).
For example - `Vec<Box<i32, DummyAllocator>>` will disable the lint, and `Vec<Box<i32, DummyAllocator>, DummyAllocator>` will not disable the lint.
In addition, the applicability of this lint has been changed to `Unspecified` due to the automatic fixes potentially breaking code such as the following:
```rs
fn foo() -> Vec<Box<i32>> { // -> Vec<i32>
vec![Box::new(1)]
}
```
It should be noted that the `if_chain->let-chains` fix has also been applied to this lint, so the diff does contain many changes.
changelog: disable `vec_box` lint when using nonstandard allocators
Fix `dbg_macro` semi span calculation
`span_including_semi` was using a `BytePos` to index into a file's source which happened to work because the root file of the test started at `BytePos` 0, it didn't work for other files
changelog: none
new lint: `unnecessary_fallible_conversions`
Closes#11577
A new lint that looks for calls such as `i64::try_from(1i32)` and suggests `i64::from(1i32)`. See lint description (and linked issue) for more details for why.
There's a tiny bit of overlap with the `useless_conversion` lint, in that the other one warns `T::try_from(T)` (i.e., fallibly converting to the same type), so this lint ignores cases like `i32::try_from(1i32)` to avoid emitting two warnings for the same expression.
Also, funnily enough, with this one exception, this lint would warn on exactly every case in the `useless_conversion_try` ui test that `useless_conversion` didn't cover (but never two warnings at the same time), which is neat. I did add an `#![allow]` though since we don't want interleaved warnings from multiple lints in the same uitest.
changelog: new lint: `unnecessary_fallible_conversions`
fix enum_variant_names depending lint depending on order
changelog: [`enum_variant_names`]: fix single word variants preventing lint of later variant pre/postfixed with the enum name
fixes#11494
Single word variants prevented checking the `check_enum_start` and `check_enum_end` for being run on later variants
Fix missing parenthesis in suboptimal floating point help
This fixes#11559 by adding a branch in the `Neg` implementation for `Sugg` that adds parentheses to keep precedence in order, then using that in the suggestion. I also removed some needless `.to_string()`s while I was at it.
---
changelog: none
[`iter_without_into_iter`]: fix papercuts in suggestion and restrict linting to exported types
See #11692 for more context.
tldr: the lint `iter_without_into_iter` has suggestions that don't compile, which imo isn't that problematic because it does have the appropriate `Applicability` that tells external tools that it shouldn't be auto-applied.
However there were some obvious "errors" in the suggestion that really should've been included in my initial PR adding the lint, which is fixed by this PR:
- `IntoIterator::into_iter` needs a `self` argument.
- `IntoIterator::Iter` associated type doesn't exist. This should've just been `Item`.
This still doesn't make it machine applicable, and the remaining things are imho quite non-trivial to implement, as I've explained in https://github.com/rust-lang/rust-clippy/issues/11692#issuecomment-1773886111.
I personally think it's fine to leave it there and let the user change the remaining errors when copy-pasting the suggestion (e.g. errors caused by lifetimes that were permitted in fn return-position but are not in associated types).
This is how many of our other lint suggestions already work.
Also, we now restrict linting to only exported types. This required moving basically all of the tests around since they were previously in the `main` function. Same for `into_iter_without_iter`. The git diff is a bit useless here...
changelog: [`iter_without_into_iter`]: fix papercuts in suggestion and restrict linting to exported types
(cc `@lopopolo,` figured I should mention you since you created the issue)
Add `waker_clone_and_wake` lint to check needless `Waker` clones
Check for patterns of `waker.clone().wake()` and replace them with `waker.wake_by_ref()`.
An alternative name could be `waker_clone_then_wake`
changelog: [ `waker_clone_wake`]: new lint
Validate `feature` and `since` values inside `#[stable(…)]`
Previously the string passed to `#[unstable(feature = "...")]` would be validated as an identifier, but not `#[stable(feature = "...")]`. In the standard library there were `stable` attributes containing the empty string, and kebab-case string, neither of which should be allowed.
Pre-existing validation of `unstable`:
```rust
// src/lib.rs
#![allow(internal_features)]
#![feature(staged_api)]
#![unstable(feature = "kebab-case", issue = "none")]
#[unstable(feature = "kebab-case", issue = "none")]
pub struct Struct;
```
```console
error[E0546]: 'feature' is not an identifier
--> src/lib.rs:5:1
|
5 | #![unstable(feature = "kebab-case", issue = "none")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
For an `unstable` attribute, the need for an identifier is obvious because the downstream code needs to write a `#![feature(...)]` attribute containing that identifier. `#![feature(kebab-case)]` is not valid syntax and `#![feature(kebab_case)]` would not work if that is not the name of the feature.
Having a valid identifier even in `stable` is less essential but still useful because it allows for informative diagnostic about the stabilization of a feature. Compare:
```rust
// src/lib.rs
#![allow(internal_features)]
#![feature(staged_api)]
#![stable(feature = "kebab-case", since = "1.0.0")]
#[stable(feature = "kebab-case", since = "1.0.0")]
pub struct Struct;
```
```rust
// src/main.rs
#![feature(kebab_case)]
use repro::Struct;
fn main() {}
```
```console
error[E0635]: unknown feature `kebab_case`
--> src/main.rs:3:12
|
3 | #![feature(kebab_case)]
| ^^^^^^^^^^
```
vs the situation if we correctly use `feature = "snake_case"` and `#![feature(snake_case)]`, as enforced by this PR:
```console
warning: the feature `snake_case` has been stable since 1.0.0 and no longer requires an attribute to enable
--> src/main.rs:3:12
|
3 | #![feature(snake_case)]
| ^^^^^^^^^^
|
= note: `#[warn(stable_features)]` on by default
```
report `unused_import` for empty reexports even it is pub
Fixes#116032
An easy fix. r? `@petrochenkov`
(Discovered this issue while reviewing #115993.)
suggest passing function instead of calling it in closure for [`option_if_let_else`]
fixes: #11429
changelog: suggest passing function instead of calling it in closure for [`option_if_let_else`]
Avoid a `track_errors` by bubbling up most errors from `check_well_formed`
I believe `track_errors` is mostly papering over issues that a sufficiently convoluted query graph can hit. I made this change, while the actual change I want to do is to stop bailing out early on errors, and instead use this new `ErrorGuaranteed` to invoke `check_well_formed` for individual items before doing all the `typeck` logic on them.
This works towards resolving https://github.com/rust-lang/rust/issues/97477 and various other ICEs, as well as allowing us to use parallel rustc more (which is currently rather limited/bottlenecked due to the very sequential nature in which we do `rustc_hir_analysis::check_crate`)
cc `@SparrowLii` `@Zoxc` for the new `try_par_for_each_in` function