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.
[`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
Rewrite [`tuple_array_conversions`]
Fixes#11100Fixes#11144Fixes#11124#11082 still needs discussion and #11085 likely can't be fixed.
changelog: [`tuple_array_conversions`]: Move to `pedantic`
changelog: [`tuple_array_conversions`]: Don't lint if mutability of references changes
changelog: [`tuple_array_conversions`]: Don't lint if bindings don't come from the exact same pattern
changelog: [`tuple_array_conversions`]: Don't lint if bindings are used for more than just the conversion
Add `imports_granularity = "Module"` to rustfmt.toml
This lets rustfmt split/merge imports, `Module` seems to be the most common style in clippy
https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#imports_granularity
changelog: none
Almost all the updates other than the config file change are from `cargo dev fmt` or blessed tests, the exceptions being
- `tests/ui/single_component_path_imports.rs`
- `tests/ui/single_component_path_imports_nested_first.rs`
- `tests/ui/single_component_path_imports_self_after.rs`
- `tests/ui/single_component_path_imports_self_before.rs`
- `tests/ui/unsafe_removed_from_name.rs` (added a test with merged imports as a drive by)
- `tests/ui/wildcard_imports.rs`
- `tests/ui/wildcard_imports_2021.rs`
[`arithmetic_side_effect`]: allow different types on the right hand side for `Wrapping<T>`
Fixes#11145
This lint has a list of allowed types, one of which is `Wrapping<T>`, but it was only actually allowed if the type on the right hand side was also `Wrapping<T>`, which meant that, for example, `Wrapping<u32> += u32` would still lint. It now allows binary ops involving `Wrapping<T>` regardless of the type on the rhs.
These impls have only existed since Rust 1.60.0, so that is probably why the lint was previously not handling this correctly
changelog: [`arithmetic_side_effect`]: allow different types on the right hand side for `Wrapping<T>` (e.g. `Wrapping<T> += T`)
[`unnecessary_literal_unwrap`]: also lint `unwrap_(err_)unchecked`
Closes#11093
changelog: [`unnecessary_literal_unwrap`]: also lint `unwrap_unchecked` and `unwrap_err_unchecked`
Use depinfo to discover UI test dependencies
changelog: none
context: https://rust-lang.zulipchat.com/#narrow/stream/257328-clippy/topic/Building.20test.20dependencies
This restores [the old `EXTERN_FLAGS` method](4cf5bdc60c/tests/compile-test.rs (L67-L75)) of passing `--extern` flags for building UI tests with minor changes
- Unused deps were removed
- It's now a `Vec` of args instead of a command string
- It uses a `BTreeMap` so the extern flags are in alphabetical order and deterministic
I don't know if the `HOST_LIBS` part is still required, but I figured it best to leave it in for now. If the change is accepted we can take a look if it's needed in `rust-lang/rust` after the next sync
This isn't as pleasant as having a `Cargo.toml`, though there is something satisfying about knowing the dependencies are already built and not needing to invoke `cargo`
r? `@flip1995`
This commit fixes#11025 by removing checks for `todo!`,
`unimplemented!` and `unreachable!`.
Signed-off-by: Panagiotis Foliadis <pfoliadis@hotmail.com>
Uplift `clippy::fn_null_check` lint
This PR aims at uplifting the `clippy::fn_null_check` lint into rustc.
## `incorrect_fn_null_checks`
(warn-by-default)
The `incorrect_fn_null_checks` lint checks for expression that checks if a function pointer is null.
### Example
```rust
let fn_ptr: fn() = /* somehow obtained nullable function pointer */
if (fn_ptr as *const ()).is_null() { /* ... */ }
```
### Explanation
Function pointers are assumed to be non-null, checking for their nullity is incorrect.
-----
Mostly followed the instructions for uplifting a clippy lint described here: https://github.com/rust-lang/rust/pull/99696#pullrequestreview-1134072751
`@rustbot` label: +I-lang-nominated
r? compiler
[`unnecessary_literal_unwrap`]: don't lint if binding initializer comes from expansion
Fixes https://github.com/rust-lang/rust-clippy/discussions/11109
changelog: [`unnecessary_literal_unwrap`]: don't lint if binding initializer comes from expansion
"try this" -> "try"
Current help messages contain a mix of "try", "try this", and one "try this instead". In the spirit of #10631, this PR adopts the first, as it is the most concise.
It also updates the `lint_message_conventions` test to catch cases of "try this".
(Aside: #10120 unfairly contained multiple changes in one PR. I am trying to break that PR up into smaller pieces.)
changelog: Make help messages more concise ("try this" -> "try").
Add `needless_pass_by_ref_mut` lint
changelog: [`needless_pass_by_ref_mut`]: This PR add a new lint `needless_pass_by_ref_mut` which emits a warning in case a `&mut` function argument isn't used mutably. It doesn't warn on trait and trait impls functions.
Fixes#8863.
cargo dev fmt
cargo test passes
cargo test passes
refactor a lil
Update bool_comparison.stderr
heavily refactor + bump `clippy::version`
refactor
refactor
check bounds to increase accuracy, and add todos
new lint: `read_line_without_trim`
This adds a new lint that checks for calls to `Stdin::read_line` with a reference to a string that is then attempted to parse into an integer type without first trimming it, which is always going to fail at runtime.
This is something that I've seen happen a lot to beginners, because it's easy to run into when following the example of chapter 2 in the book where it shows how to program a guessing game.
It would be nice if we could point beginners to clippy and tell them "let's see what clippy has to say" and have clippy explain to them why it fails 👀
I think this lint can later be "generalized" to work not just for `Stdin` but also any `BufRead` (which seems to be where the guarantee about the trailing newline comes from) and also, matching/comparing it to a string slice that doesn't end in a newline character (e.g. `input == "foo"` is always going to fail)
changelog: new lint: [`read_line_without_trim`]
[`useless_vec`]: add more tests and don't lint inside of macros
Closes#11084.
I realized that the fix I added in #11081 itself also causes an error in a suggestion when inside of a macro. Example:
```rs
macro_rules! x {
() => {
for _ in vec![1, 2] {}
}
}
x!();
```
Here it would suggest replacing `vec![1, 2]` with `[x!()]`, because that's what the source callsite is (reminder: it does this to get the correct span of `x!()` for code like `for _ in vec![x!()]`), but that's wrong when *inside* macros, so I decided to make it not lint if the whole loop construct is inside a macro to avoid this issue.
changelog: [`useless_vec`]: add more tests and don't lint inside of macros
r? `@Alexendoo` since these were your tests, I figured it makes most sense to assign you
Don't lint manual_let_else in cases where ? would work
Don't lint `manual_let_else` where the question mark operator `?` would be sufficient, that is, mostly in cases like:
```Rust
let v = if let Some(v) = ex { v } else { return None };
```
Also, this PR emits the `question_mark` lint for `let...else` patterns that could be written with `?` (also, only `return None` like cases).
```
changelog: [`manual_let_else`]: don't lint in cases where question_mark already lints
changelog: [`question_mark`]: lint for `let Some(...) = ex else { return None };`
```
Fixes #8755
[`useless_vec`]: use the source span for initializer
Fixes#11075.
changelog: [`useless_vec`]: use the source span for the initializer expression when inside of a macro
[`arc_with_non_send_sync`]: don't lint if type has nested type parameters
Fixes#11076
changelog: [`arc_with_non_send_sync`]: don't lint if type has nested type parameters
r? `@Manishearth`
new lint: `type_id_on_box`
Closes#7687.
A new lint that detects calling `.type_id()` on `Box<dyn Any>` (and not on the underlying `dyn Any`), which can make up for some pretty confusing bugs!
changelog: new lint: [`type_id_on_box`]
Add `SPEEDTEST`
In the `master` branch, we currently don't have any way to test the performance of a single lint in changes.
This PR adds `SPEEDTEST`, the environment variable which lets you do a speed test on a lint / category of tests with various configuration options.
Maybe we should merge this with `lintcheck` 🤔
See the book page for more information.
changelog:none
`let_and_return`: lint 'static lifetimes, don't lint borrows in closures
Fixes#11056
Now also ignores functions returning `'static` lifetimes, since I noticed the `stdin.lock()` example was still being linted but doesn't need to be since https://github.com/rust-lang/rust/pull/93965
changelog: none
New lint [`tuple_array_conversions`]
Closes#10748
PS, the implementation is a bit ugly 😅 ~~I will likely refactor soon enough :)~~ Done :D
changelog: New lint [`tuple_array_conversions`]
Also, lint question_mark for `let...else` clauses that can be simplified to use `?`.
This lint isn't perfect as it doesn't support the unstable try blocks.
[significant_drop_tightening] Fix#10413Fix#10413
This is quite a rewrite that unfortunately took a large amount of time. I tried my best to comment what is going on to easy review but feel free to ask any question.
The problem basically is that the current algorithm is only taking into consideration single blocks which means that things like the following don't work or show unpredictable results.
```rust
let mutex = Mutex::new(1);
{
let lock = mutex.lock().unwrap();
{
let _ = *lock;
}
}
```
The solve the issue, each path that refers a lock is now being tracked individually.
```
changelog: [`significant_drop_tightening`]: Lift the restriction of only considerate single blocks
```
New lint [`redundant_at_rest_pattern`]
Closes#11011
It's always a great feeling when a new lint triggers on clippy itself 😄
changelog: New lint [`redundant_at_rest_pattern`]
suggests `is_some_and` over `map().unwrap`
changelog: Enhancement: [`option_map_unwrap_or`] now considers the [`msrv`] config when creating the suggestion.
* modified option_map_unwrap_or lint to recognise when an `Option<T>` is mapped to an `Option<bool>` with false being used when `None` is detected; suggests the use of `is_some_and` instead
* msrv is set to 1.70.0 for this lint; when `is_some_and` was stabilised
fixes#9125
[`question_mark`]: don't lint inside of `try` block
Fixes#8628.
Diff looks a bit noisy because I had to move the two functions into an impl, because they now need to access the structs `try_block_depth` field to see if they're inside a try block.
changelog: [`question_mark`]: don't lint inside of `try` block
[`option_if_let_else`]: suggest `.as_ref()` if scrutinee is of type `&Option<_>`
Fixes#10729
`Option::map_or` takes ownership, so if matching on an `&Option<_>`, we need to suggest `.as_ref()` before calling `map_or` to get the same effect and to not cause a borrowck error.
changelog: [`option_if_let_else`]: suggest `.as_ref()`/`.as_mut()` if scrutinee is of type `&Option<_>`/`&mut Option<_>`
[`unused_async`]: don't lint if function is part of a trait
Fixes#10459.
We shouldn't lint if the function is part of a trait, because the user won't be able to easily remove the `async`, as this will then not match with the function signature in the trait definition
changelog: [`unused_async`]: don't lint if function is part of a trait
Use substring matching for TESTNAME
Restores the previous behaviour of matching using a substring match rather than needing a full match
changelog: none
Add `BLESS` for compile-test and some cleanup
changelog: none
Allows passing the environment variable `BLESS` to bless tests, which is useful when you want to bless internal tests - `BLESS= cargo uitest -Finternal`
Also updates a place in the docs referring to `cargo dev bless` and removes some unused test deps