Refactor some of `dereference.rs` to util functions
I've seen a few lints that need to be able to tell if changing the type of an expression would be a vaild suggestion. This extracts part of how that's done from `explicit_auto_deref`.
changelog: None
Fix async functions handling for `needless_pass_by_ref_mut` lint
Fixes https://github.com/rust-lang/rust-clippy/issues/11179.
The problem with async is that "internals" are actually inside a closure from the `ExprUseVisitor` point of view, meaning we need to actually run the check on the closures' body as well.
changelog: none
r? `@llogiq`
Make `comparison_to_empty` work on `if let`/`let` chains
This adds `LetChain` to `clippy_utils::higher`, other lints may benefit from such a change as well :D
changelog: Enhancement: [`comparison_to_empty`]: Now lints on `if let`
[`unused_async`]: don't lint if paths reference async fn without immediate call
Fixes#9695Fixes#9359
Clippy shouldn't lint unused `async` if there are paths referencing them if that path isn't the receiver of a function call, because that means that the function might be passed to some other function:
```rs
async fn f() {} // No await statements, so unused at this point
fn requires_fn_future<F: Future<Output = ()>>(_: fn() -> F) {}
requires_fn_future(f); // `f`'s asyncness is actually not unused.
```
(This isn't limited to just passing the function as a parameter to another function, it could also first be stored in a variable and later passed to another function as an argument)
This requires delaying the linting until post-crate and collecting path references to local async functions along the way.
changelog: [`unused_async`]: don't lint if paths reference async fn that require asyncness
new lint: `redundant_locals`
This lint checks for code like the following:
```rs
let x = 1;
let x = x;
```
It checks (afaik) all cases where a binding is shadowed by its own value in the same block, including function parameters. This has no effect and is almost certainly accidental, so it's in the `correctness` category like `self_assignment`.
This also lays the groundwork for a more generalized version of #5102.
changelog: new lint: [`redundant_local`]
fix dogfood lints in `redundant_local`
keep `redundant_local` from running in proc macros
rewrite `redundant_local` as late pass
make redundant_local's `find_binding` more readable
pluralize `redundant_locals` name
add test for `redundant_locals` in macros
test `redundant_locals` in proc macros
use more destructuring in `redundant_locals`
fix: format redundant_locals.rs
ignore needless_pass_by_mut_ref in redundant_locals test
New lint [`absolute_paths`]
Closes#10568
Maybe we should make the max segments allowed a configuration option? I see quite a bit of 3-segment paths in clippy, and while I think only really `<mod/type>::<item>` or `<item>` should be (usually) used but anything above may be too widespread 😕
PS, despite this being "max segments allowed" it only lints if it's absolute, as is the point of the lint, e.g., `std::io::ErrorKind::etc` is linted but `io::ErrorKind::NotFound::etc` isn't
changelog: New lint [`absolute_paths`]
Allow `Self::cmp(self, other)` as a correct impl
Fixes#11178
Also no longer checks if the method name is *just* cmp, but the path. That was an oversight on my part ^^
r? `@xFrednet`
(and `@blyxyas` too!)
changelog: [`incorrect_partial_ord_impl_on_ord_type`]: Now allows non-method calls to `cmp` like `Self::cmp(self, other)`
fix: false positive for `option_env!` in `ifs_same_cond`
Clippy had a false positive for with `ifs_same_cond` when two if-let expressions have an `option_env!` macro. The fix is similar to the `env!` macro fix.
The following example had a clippy error:
```rust
if let Some(env1) = option_env!("ENV1") {
// ...
} else if let Some(env2) = option_env!("ENV2") {
// ...
}
```
See https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=01b85c61b56ddd900117fb247af04824
changelog: [`ifs_same_cond`]: fix false positive when using `option_env!` in if-let expressions.
[`unnecessary_literal_unwrap`]: Fix ICE on None.unwrap_or_default()
Fixes#11099Fixes#11064
I'm running into #11099 (cc `@y21)` on my Rust codebase. Clippy ICEs on this code when evaluating the `unnecessary_literal_unwrap` lint:
```rust
fn main() {
let val1: u8 = None.unwrap_or_default();
}
```
This fixes that ICE and adds an message specifically for that case:
```
error: used `unwrap_or_default()` on `None` value
--> $DIR/unnecessary_literal_unwrap.rs:26:5
|
LL | None::<String>.unwrap_or_default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap_or_default()`: `String::default()`
```
This PR also fixes the same ICE with `None.unwrap_or_else` (by giving the generic error message for the lint in that case).
changelog: Fix ICE in `unnecessary_literal_unwrap` on `None.unwrap_or_default()`
Clippy had a false positive for with `ifs_same_cond` when two
if-let expressions have an `option_env!` macro. The fix is similar to the
`env!` macro fix.
The following example had a clippy error:
```rust
if let Some(env1) = option_env!("ENV1") {
// ...
} else if let Some(env2) = option_env!("ENV2") {
// ...
}
```
See https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=01b85c61b56ddd900117fb247af04824
changelog: Fix [`ifs_same_cond`] false positive when using `option_env!` in if-let expressions.
Add Centri3 and blyxyas to the reviewer rotation
And with that you will now be picked automatically by rustbot to review pull requests.
Welcome to the team!
Thank you for making Clippy better!
r? `@xFrednet`
changelog: New team members `@Centri3` and `@blyxyas`
Implement rust-lang/compiler-team#578.
When an ICE is encountered on nightly releases, the new rustc panic
handler will also write the contents of the backtrace to disk. If any
`delay_span_bug`s are encountered, their backtrace is also added to the
file. The platform and rustc version will also be collected.
[`manual_filter_map`]: lint on `matches` and pattern matching
Fixes#8010
Previously this lint only worked specifically for a very limited set of methods on the filter call (`.filter(|opt| opt.is_some())` and `.filter(|res| res.is_ok())`). This PR extends it to also recognize `matches!` in the `filter` and pattern matching with `if let` or `match` in the `map`.
Example:
```rs
enum Enum {
A(i32),
B,
}
let _ = [Enum::A(123), Enum::B].into_iter()
.filter(|x| matches!(x, Enum::A(_)))
.map(|x| if let Enum::A(s) = x { s } else { unreachable!() });
```
Now suggests:
```diff
- .filter(|x| matches!(x, Enum::A(_))).map(if let Enum::A(s) = x { s } else { unreachable!() })
+ .filter_map(|x| match x { Enum::A(s) => Some(s), _ => None })
```
Adding this required a somewhat large change in code because it originally seemed to be specifically written with only method calls in the filter in mind, and `matches!` has different behavior in the map, so this new setup should make it possible to support more "generic" cases that need different handling for the filter and map calls.
changelog: [`manual_filter_map`]: lint on `matches` and pattern matching (and some internal refactoring)
Fix `unwrap_or_else_default` false positive
This PR fixes a false positive in the handling of `unwrap_or_else` with a default value when the value is needed for type inference.
An easy example to exhibit the false positive is the following:
```rust
let option = None;
option.unwrap_or_else(Vec::new).push(1);
```
The following code would not compile, because the fact that the value is a `Vec` has been lost:
```rust
let option = None;
option.unwrap_or_default().push(1);
```
The fix is to:
- implement a heuristic to tell whether an expression's type can be determined purely from its subexpressions, and the arguments and locals they use;
- apply the heuristic to `unwrap_or_else`'s receiver.
The heuristic returns false when applied to `option` in the above example, but it returns true when applied to `option` in either of the following examples:
```rust
let option: Option<Vec<u64>> = None;
option.unwrap_or_else(Vec::new).push(1);
```
```rust
let option = None::<Vec<u64>>;
option.unwrap_or_else(Vec::new).push(1);
```
(Aside: https://github.com/rust-lang/rust-clippy/pull/10120 unfairly contained multiple changes in one PR. I am trying to break that PR up into smaller pieces.)
---
changelog: FP: [`unwrap_or_else_default`]: No longer lints if the default value is needed for type inference
Remove `#![allow(unused)]` and `--crate-name` from `cargo dev new_lint` generated tests
changelog: none
Also removes some unused flags from `ui-cargo` tests because the entrypoint is now the `Cargo.toml`, not the `.rs` files
New lint [`iter_skip_zero`]
Idea came from my contribution to `unnecessary_cast` recently. Sorry about that 😅
Could be an issue if somebody manually implements `skip`, but I don't think anybody will (and this would be an issue with other lints too, afaik)
changelog: New lint [`iter_skip_zero`]
New lint [`string_lit_chars_any`]
Closes#10389
This lint can probably be deprecated if/when rustc optimizes `.chars().any(...)`.
changelog: New lint [`string_lit_chars_any`]