Auto merge of #9417 - Jarcho:ice_9414, r=Alexendoo
Don't use `hir_ty_to_ty` in `result_large_err`
fixes #9414
This occurs starting with 2022-09-01. I checked that this does fix the ICE on rust-lang/rust@9353538. Not sure which pr caused the late-bound region to leak through `hir_ty_to_ty`.
Auto merge of #9412 - xFrednet:jst-r-bool-to-int-lint, r=xFrednet
New lint `bool_to_int_with_if`
This is a rebased version of https://github.com/rust-lang/rust-clippy/pull/9086 I could sadly not push directly push to the PR branch as it's protected.
The lint implementation comes from `@jst-r.` Thank you for the work you put into this :)
Auto merge of #9404 - lukaslueg:issue9402, r=giraffate
Fix `suboptimal_float` not linting on `{const}.powf({const})`
There used to be an early return if the receiver was an effective const but the method was not linted, not taking into account later cases where the receiver and the arguments are both effective consts for different methods. Removed the early return.
Fixes #9402
Fixes #9201
changelog: Fix `suboptimal_flops`, `imprecise_flops` not linting on `{const}.powf({const})` et al
bors [Wed, 31 Aug 2022 21:45:18 +0000 (21:45 +0000)]
Auto merge of #101249 - matthiaskrgr:rollup-wahnoz8, r=matthiaskrgr
Rollup of 10 pull requests
Successful merges:
- #100787 (Pretty printing give proper error message without panic)
- #100838 (Suggest moving redundant generic args of an assoc fn to its trait)
- #100844 (migrate rustc_query_system to use SessionDiagnostic)
- #101140 (Update Clippy)
- #101161 (Fix uintended diagnostic caused by `drain(..)`)
- #101165 (Use more `into_iter` rather than `drain(..)`)
- #101229 (Link “? operator” to relevant chapter in The Book)
- #101230 (lint: avoid linting diag functions with diag lints)
- #101236 (Avoid needless buffer zeroing in `std::sys::windows::fs`)
- #101240 (Fix a typo on `wasm64-unknown-unknown` doc)
bors [Tue, 30 Aug 2022 18:20:45 +0000 (18:20 +0000)]
Auto merge of #9373 - lukaslueg:result_large_err, r=Alexendoo
Initial implementation `result_large_err`
This is a shot at #6560, #4652, and #3884. The lint checks for `Result` being returned from functions/methods where the `Err` variant is larger than a configurable threshold (the default of which is 128 bytes). There has been some discussion around this, which I'll try to quickly summarize:
* A large `Err`-variant may force an equally large `Result` if `Err` is actually bigger than `Ok`.
* There is a cost involved in large `Result`, as LLVM may choose to `memcpy` them around above a certain size.
* We usually expect the `Err` variant to be seldomly used, but pay the cost every time.
* `Result` returned from library code has a high chance of bubbling up the call stack, getting stuffed into `MyLibError { IoError(std::io::Error), ParseError(parselib::Error), ...}`, exacerbating the problem.
This PR deliberately does not take into account comparing the `Ok` to the `Err` variant (e.g. a ratio, or one being larger than the other). Rather we choose an absolute threshold for `Err`'s size, above which we warn. The reason for this is that `Err`s probably get `map_err`'ed further up the call stack, and we can't draw conclusions from the ratio at the point where the `Result` is returned. A relative threshold would also be less predictable, while not accounting for the cost of LLVM being forced to generate less efficient code if the `Err`-variant is _large_ in absolute terms.
We lint private functions as well as public functions, as the perf-cost applies to in-crate code as well.
In order to account for type-parameters, I conjured up `fn approx_ty_size`. The function relies on `LateContext::layout_of` to compute the actual size, and in case of failure (e.g. due to generics) tries to come up with an "at least size". In the latter case, the size of obviously wrong, but the inspected size certainly can't be smaller than that. Please give the approach a heavy dose of review, as I'm not actually familiar with the type-system at all (read: I have no idea what I'm doing).
The approach does, however flimsy it is, allow us to successfully lint situations like
// We know `UnionError<T>` will be at least 512 bytes, no matter what `T` is
pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> {
Ok(())
}
```
I've given some refactoring to `functions/result_unit_err.rs` to re-use some bits. This is also the groundwork for #6409
The default threshold is 128 because of https://github.com/rust-lang/rust-clippy/issues/4652#issue-505670554
`lintcheck` does not trigger this lint for a threshold of 128. It does warn for 64, though.
The suggestion currently is the following, which is just a placeholder for discussion to be had. I did have the computed size in a `span_label`. However, that might cause both ui-tests here and lints elsewhere to become flaky wrt to their output (as the size is platform dependent).
```
error: the `Err`-variant returned via this `Result` is very large
--> $DIR/result_large_err.rs:36:34
|
LL | pub fn param_large_error<R>() -> Result<(), (u128, R, FullyDefinedLargeError)> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The `Err` variant is unusually large, at least 128 bytes
```
Jason Newcomb [Tue, 30 Aug 2022 04:33:56 +0000 (00:33 -0400)]
Fix the order of `trait_duplication_in_bounds`
* Emit the lint in source order
* Make suggestions with multiple traits be in source order rather than alphabetical
bors [Mon, 29 Aug 2022 18:07:50 +0000 (18:07 +0000)]
Auto merge of #9247 - clubby789:raw_slice_pointer_cast, r=Alexendoo
New lint: Raw slice pointer cast
Adds a lint to check for a raw slice being created and cast back to a pointer, suggesting `ptr::slice_from_raw_parts`, to identify UB such as https://github.com/SimonSapin/rust-typed-arena/pull/54.
```
changelog: [`cast_slice_from_raw_parts`]: Add lint to check for `slice::from_raw_parts(.., ..) as *const _`
```
bors [Sun, 28 Aug 2022 10:59:16 +0000 (10:59 +0000)]
Auto merge of #9389 - lukaslueg:penmacro, r=llogiq
Don't lint literal `None` from expansion
This addresses https://github.com/rust-lang/rust-clippy/pull/9288#issuecomment-1229398524: If the literal `None` is from expansion, we never lint. This is correct because e.g. replacing the call to `option_env!` with whatever that macro expanded to at the time of linting is certainly wrong.
changelog: Don't lint [`partialeq_to_none`] for macro-expansions
bors [Sat, 27 Aug 2022 17:38:40 +0000 (17:38 +0000)]
Auto merge of #8984 - xanathar:pr/suspicious_to_owned, r=llogiq
Implemented `suspicious_to_owned` lint to check if `to_owned` is called on a `Cow`
changelog: Add lint ``[`suspicious_to_owned`]``
-----------------
Hi,
posting this unsolicited PR as I've been burned by this issue :)
Being unsolicited, feel free to reject it or reassign a different lint level etc.
This lint checks whether `to_owned` is called on `Cow<'_, _>`. This is done because `to_owned` is very similarly named to `into_owned`, but the effect of calling those two methods is completely different (one makes the `Cow::Borrowed` into a `Cow::Owned`, the other just clones the `Cow`). If the cow is then passed to code for which the type is not checked (e.g. generics, closures, etc.) it might slip through and if the cow data is coming from an unsafe context there is the potential for accidentally cause undefined behavior.
Even if not falling into this painful case, there's really no reason to call `to_owned` on a `Cow` other than confusing people reading the code: either `into_owned` or `clone` should be called.
Note that this overlaps perfectly with `implicit_clone` as a warning, but `implicit_clone` is classified pedantic (while the consequences for `Cow` might be of a wider blast radius than just pedantry); given the overlap, I set-up the lint so that if `suspicious_to_owned` triggers `implicit_clone` will not trigger. I'm not 100% sure this is done in the correct way (I tried to copy what other lints were doing) so please provide feedback on it if it isn't.
### Checklist
- \[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`
bors [Sat, 27 Aug 2022 08:37:29 +0000 (08:37 +0000)]
Auto merge of #9381 - lukaslueg:issue9361, r=dswij
Don't lint `needless_return` if `return` has attrs
Fixes #9361
The lint used to have a mechanic to allow `cfg`-attrs on naked `return`-statements. This was well-intentioned, yet we can have any kind of attribute, e.g. `allow`, `expect` or even custom `derive`. So the mechanic was simply removed. We now never lint on a naked `return`-statement that has attributes on it.
Turns out that the ui-test had a Catch22 in it: In `check_expect()` the `#[expect(clippy::needless_return)]` is an attribute on the `return` statement that can and will be rustfixed away without side effects. But any other attribute would also have been removed, which is what #9361 is about. The test proved the wrong thing. Removed the test, the body is tested elsewhere as well.
changelog: Ignore [`needless_return`] on `return`s with attrs
Implemented suspicious_to_owned lint to check if `to_owned` is called on a `Cow`.
This is done because `to_owned` is very similarly named to `into_owned`, but the
effect of calling those two methods is completely different. This creates
confusion (stemming from the ambiguity of the 'owned' term in the context of
`Cow`s) and might not be what the writer intended.
Joshua Nelson [Thu, 14 Jul 2022 13:30:38 +0000 (08:30 -0500)]
Stabilize `#![feature(label_break_value)]`
# Stabilization proposal
The feature was implemented in https://github.com/rust-lang/rust/pull/50045 by est31 and has been in nightly since 2018-05-16 (over 4 years now).
There are [no open issues][issue-label] other than the tracking issue. There is a strong consensus that `break` is the right keyword and we should not use `return`.
There have been several concerns raised about this feature on the tracking issue (other than the one about tests, which has been fixed, and an interaction with try blocks, which has been fixed).
1. nrc's original comment about cost-benefit analysis: https://github.com/rust-lang/rust/issues/48594#issuecomment-422235234
2. joshtriplett's comments about seeing use cases: https://github.com/rust-lang/rust/issues/48594#issuecomment-422281176
3. withoutboats's comments that Rust does not need more control flow constructs: https://github.com/rust-lang/rust/issues/48594#issuecomment-450050630
Many different examples of code that's simpler using this feature have been provided:
- A lexer by rpjohnst which must repeat code without label-break-value: https://github.com/rust-lang/rust/issues/48594#issuecomment-422502014
- A snippet by SergioBenitez which avoids using a new function and adding several new return points to a function: https://github.com/rust-lang/rust/issues/48594#issuecomment-427628251. This particular case would also work if `try` blocks were stabilized (at the cost of making the code harder to optimize).
- Several examples by JohnBSmith: https://github.com/rust-lang/rust/issues/48594#issuecomment-434651395
- Several examples by Centril: https://github.com/rust-lang/rust/issues/48594#issuecomment-440154733
- An example by petrochenkov where this is used in the compiler itself to avoid duplicating error checking code: https://github.com/rust-lang/rust/issues/48594#issuecomment-443557569
- Amanieu recently provided another example related to complex conditions, where try blocks would not have helped: https://github.com/rust-lang/rust/issues/48594#issuecomment-1184213006
Additionally, petrochenkov notes that this is strictly more powerful than labelled loops due to macros which accidentally exit a loop instead of being consumed by the macro matchers: https://github.com/rust-lang/rust/issues/48594#issuecomment-450246249
nrc later resolved their concern, mostly because of the aforementioned macro problems.
joshtriplett suggested that macros could be able to generate IR directly
(https://github.com/rust-lang/rust/issues/48594#issuecomment-451685983) but there are no open RFCs,
and the design space seems rather speculative.
joshtriplett later resolved his concerns, due to a symmetry between this feature and existing labelled break: https://github.com/rust-lang/rust/issues/48594#issuecomment-632960804
withoutboats has regrettably left the language team.
joshtriplett later posted that the lang team would consider starting an FCP given a stabilization report: https://github.com/rust-lang/rust/issues/48594#issuecomment-1111269353
label-break-value is permitted within `try` blocks:
```rust
let _: Result<(), ()> = try {
'foo: {
Err(())?;
break 'foo;
}
};
```
label-break-value is disallowed within closures, generators, and async blocks:
```rust
'a: {
|| break 'a
//~^ ERROR use of unreachable label `'a`
//~| ERROR `break` inside of a closure
}
```
label-break-value is disallowed on [_BlockExpression_]; it can only occur as a [_LoopExpression_]:
```rust
fn labeled_match() {
match false 'b: { //~ ERROR block label not supported here
_ => {}
}
}
macro_rules! m {
($b:block) => {
'lab: $b; //~ ERROR cannot use a `block` macro fragment here
unsafe $b; //~ ERROR cannot use a `block` macro fragment here
|x: u8| -> () $b; //~ ERROR cannot use a `block` macro fragment here
}
}
bors [Sun, 21 Aug 2022 09:58:24 +0000 (09:58 +0000)]
Auto merge of #8992 - kyoto7250:fix_8753, r=flip1995
feat(fix): Do not lint if the target code is inside a loop
close #8753
we consider the following code.
```rust
fn main() {
let vec = vec![1];
let w: Vec<usize> = vec.iter().map(|i| i * i).collect(); // <- once.
for i in 0..2 {
let _ = w.contains(&i);
}
}
```
and the clippy will issue the following warning.
```rust
warning: avoid using `collect()` when not needed
--> src/main.rs:3:51
|
3 | let w: Vec<usize> = vec.iter().map(|i| i * i).collect();
| ^^^^^^^
...
6 | let _ = w.contains(&i);
| -------------- the iterator could be used here instead
|
= note: `#[warn(clippy::needless_collect)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect
help: check if the original Iterator contains an element instead of collecting then checking
|
3 ~
4 |
5 | for i in 0..2 {
6 ~ let _ = vec.iter().map(|i| i * i).any(|x| x == i);
```
Rewrite the code as indicated.
```rust
fn main() {
let vec = vec![1];
for i in 0..2 {
let _ = vec.iter().map(|i| i * i).any(|x| x == i); // <- execute `map` every loop.
}
}
```
this code is valid in the compiler, but, it is different from the code before the rewrite.
So, we should not lint, If `collect` is outside of a loop.
Thank you in advance.
---
changelog: Do not lint if the target code is inside a loop in `needless_collect`
bors [Sun, 21 Aug 2022 08:32:44 +0000 (08:32 +0000)]
Auto merge of #8696 - J-ZhengLi:issue8492, r=flip1995
check for if-some-or-ok-else-none-or-err
fixes: #8492
---
changelog: make [`option_if_let_else`] to check for match expression with both Option and Result; **TODO: Change lint name? Add new lint with similar functionality?**
bors [Sat, 20 Aug 2022 18:02:34 +0000 (18:02 +0000)]
Auto merge of #8857 - smoelius:fix-8855, r=flip1995
Add test for #8855
Fix #8855
Here is what I think is going on.
First, the expression `format!("{:>6} {:>6}", a, b.to_string())` expands to:
```rust
{
let res =
::alloc::fmt::format(::core::fmt::Arguments::new_v1_formatted(&["",
" "],
&[::core::fmt::ArgumentV1::new_display(&a),
::core::fmt::ArgumentV1::new_display(&b.to_string())],
&[::core::fmt::rt::v1::Argument {
position: 0usize,
format: ::core::fmt::rt::v1::FormatSpec {
fill: ' ',
align: ::core::fmt::rt::v1::Alignment::Right,
flags: 0u32,
precision: ::core::fmt::rt::v1::Count::Implied,
width: ::core::fmt::rt::v1::Count::Is(6usize),
},
},
::core::fmt::rt::v1::Argument {
position: 1usize,
format: ::core::fmt::rt::v1::FormatSpec {
fill: ' ',
align: ::core::fmt::rt::v1::Alignment::Right,
flags: 0u32,
precision: ::core::fmt::rt::v1::Count::Implied,
width: ::core::fmt::rt::v1::Count::Is(6usize),
},
}], unsafe { ::core::fmt::UnsafeArg::new() }));
res
}
```
When I dump the expressions that get past the call to `has_string_formatting` [here](https://github.com/rust-lang/rust-clippy/blob/b312ad7d0cf0f30be2bd4658b71a3520a2e76709/clippy_lints/src/format_args.rs#L83), I see more than I would expect.
In particular, I see this subexpression of the above:
```
&[::core::fmt::ArgumentV1::new_display(&a),
::core::fmt::ArgumentV1::new_display(&b.to_string())],
```
This suggests to me that more expressions are getting past [this call](https://github.com/rust-lang/rust-clippy/blob/b312ad7d0cf0f30be2bd4658b71a3520a2e76709/clippy_lints/src/format_args.rs#L71) to `FormatArgsExpn::parse` than should.
Those expressions are then visited, but no `::core::fmt::rt::v1::Argument`s are found and pushed [here](https://github.com/rust-lang/rust-clippy/blob/b312ad7d0cf0f30be2bd4658b71a3520a2e76709/clippy_utils/src/macros.rs#L407).
As a result, the expressions appear unformatted, hence, the false positive.
My proposed fix is to restrict `FormatArgsExpn::parse` so that it only matches `Call` expressions.
bors [Fri, 19 Aug 2022 16:11:48 +0000 (16:11 +0000)]
Auto merge of #8804 - Jarcho:in_recursion, r=Alexendoo
Rework `only_used_in_recursion`
fixes #8782
fixes #8629
fixes #8560
fixes #8556
This is a complete rewrite of the lint. This loses some capabilities of the old implementation. Namely the ability to track through tuple and slice patterns, as well as the ability to trace through assignments.
The two reported bugs are fixed with this. One was caused by using the name of the method rather than resolving to the `DefId` of the called method. The second was cause by using the existence of a cycle in the dependency graph to determine whether the parameter was used in recursion even though there were other ways to create a cycle in the graph.
Implementation wise this switches from using a visitor to walking up the tree from every use of each parameter until it has been determined the parameter is used for something other than recursion. This is likely to perform better as it avoids walking the entire function a second time, and it is unlikely to walk up the HIR tree very much. Some cases would perform worse though.
cc `@buttercrab`
changelog: Scale back `only_used_in_recursion` to fix false positives
changelog: Move `only_used_in_recursion` back to `complexity`
bors [Fri, 19 Aug 2022 15:55:05 +0000 (15:55 +0000)]
Auto merge of #9349 - Alexendoo:format-args-expn, r=flip1995
Refactor `FormatArgsExpn`
It now for each format argument `{..}` has:
- The `Expr` it points to, and how it does so (named/named inline/numbered/implicit)
- The parsed `FormatSpec` (format trait/fill/align/etc., the precision/width and any value they point to)
- Many spans
The caller no longer needs to pair up arguments to their value, or separately interpret the `specs` `Expr`s when it isn't `None`
The gist is that it combines the result of [`rustc_parse_format::Parser`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse_format/struct.Parser.html) with the macro expansion itself
This unfortunately makes the code a bit longer, however we need to use both as neither have all the information we're after. `rustc_parse_format` doesn't have the information to resolve named arguments to their values. The macro expansion doesn't contain whether the positions are implicit/numbered/named, or the spans for format arguments
Wanted by #9233 and #8518 to be able to port the changes from #9040
Also fixes #8643, previously the format args seem to have been paired up with the wrong values somehow
changelog: [`format_in_format_args`]: Fix false positive due to misattributed arguments