Improve spans for indexing expressions
fixes#114388
Indexing is similar to method calls in having an arbitrary left-hand-side and then something on the right, which is the main part of the expression. Method calls already have a span for that right part, but indexing does not. This means that long method chains that use indexing have really bad spans, especially when the indexing panics and that span in coverted into a panic location.
This does the same thing as method calls for the AST and HIR, storing an extra span which is then put into the `fn_span` field in THIR.
r? compiler-errors
Indexing is similar to method calls in having an arbitrary
left-hand-side and then something on the right, which is the main part
of the expression. Method calls already have a span for that right part,
but indexing does not. This means that long method chains that use
indexing have really bad spans, especially when the indexing panics and
that span in coverted into a panic location.
This does the same thing as method calls for the AST and HIR, storing an
extra span which is then put into the `fn_span` field in THIR.
Perform OpaqueCast field projection on HIR, too.
fixes#105819
This is necessary for closure captures in 2021 edition, as they capture individual fields, not the full mentioned variables. So it may try to capture a field of an opaque (because the hidden type is known to be something with a field).
See https://github.com/rust-lang/rust/pull/99806 for when and why we added OpaqueCast to MIR.
[`slow_vector_initialization`]: catch `Vec::new()` followed by `.resize(len, 0)`
Closes#10938
changelog: [`slow_vector_initialization`]: catch `Vec::new()` followed by `.resize(len, 0)`
This is necessary for closure captures in 2021 edition, as they capture individual fields, not the full mentioned variables. So it may try to capture a field of an opaque (because the hidden type is known to be something with a field).
check that the types are equal in `SpanlessEq::eq_expr`
Fixes#11213
changelog: [`if_same_then_else`]: don't lint for integer literals of different types
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
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)`
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)
It makes it sound like the `ExprKind` and `Rvalue` are supposed to represent all pointer related
casts, when in reality their just used to share a some enum variants. Make it clear there these
are only coercion to make it clear why only some pointer related "casts" are in the enum.
Move `TyCtxt::mk_x` to `Ty::new_x` where applicable
Part of rust-lang/compiler-team#616
turns out there's a lot of places we construct `Ty` this is a ridiculously huge PR :S
r? `@oli-obk`
Specialize `try_destructure_mir_constant` for its sole user (pretty printing)
We can't remove the query, as we need to invoke it from rustc_middle, but can only implement it in mir interpretation/const eval.
r? `@RalfJung` for a first round.
While we could move all the logic into pretty printing, that would end up duplicating a bit of code with const eval, which doesn't seem great either.
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
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`]
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
Port clippy away from compiletest to ui_test
Reasons to do this:
* runs completely on stable Rust
* is easier to extend with new features
* has its own dogfood test suite, so changes can be tested in [the `ui_test` repo](https://github.com/oli-obk/ui_test)
* supports dependencies from crates.io without having to manually fiddle with command line flags
* supports `ui-cargo`, `ui`, `ui-toml` out of the box, no need to find and run the tests ourselves
One thing that is a big difference to `compiletest` is that if a test emits *any* error, you need to mark all of them with `//~ ERROR:` annotations. Since many clippy tests did not have annotations, I changed many lints to be `warn` in their test so that only the `stderr` output is tested.
TODO:
* [ ] check that this still works as a subtree in the rustc repo
changelog: none
<!-- changelog_checked -->
Note: at present the latest changes needed for clippy are only available as a git dependency, but I expect to publish a new crates.io version soon
`hir`: Add `Become` expression kind (explicit tail calls experiment)
This adds `hir::ExprKind::Become` alongside ast lowering. During hir-thir lowering we currently lower `become` as `return`, so that we can partially test `become` without ICEing.
cc `@scottmcm`
r? `@Nilstrieb`
Check if `if` conditions always evaluate to true in `never_loop`
This fixes the example provided in #11004, but it shouldn't be closed as this is still an issue on like
```rust
let x = true;
if x { /* etc */ }`
```
This also makes `clippy_utils::consts::constant` handle `ConstBlock` and `DropTemps`.
changelog: [`never_loop`]: Check if `if` conditions always evaluate to true
Syntactically accept `become` expressions (explicit tail calls experiment)
This adds `ast::ExprKind::Become`, implements parsing and properly gates the feature.
cc `@scottmcm`
Add a fully fledged `Clause` type, rename old `Clause` to `ClauseKind`
Does two basic things before I put up a more delicate set of PRs (along the lines of #112714, but hopefully much cleaner) that migrate existing usages of `ty::Predicate` to `ty::Clause` (`predicates_of`/`item_bounds`/`ParamEnv::caller_bounds`).
1. Rename `Clause` to `ClauseKind`, so it's parallel with `PredicateKind`.
2. Add a new `Clause` type which is parallel to `Predicate`.
* This type exposes `Clause::kind(self) -> Binder<'tcx, ClauseKind<'tcx>>` which is parallel to `Predicate::kind` 😸
The new `Clause` type essentially acts as a newtype wrapper around `Predicate` that asserts that it is specifically a `PredicateKind::Clause`. Turns out from experimentation[^1] that this is not negative performance-wise, which is wonderful, since this a much simpler design than something that requires encoding the discriminant into the alignment bits of a predicate kind, or something else like that...
r? ``@lcnr`` or ``@oli-obk``
[^1]: https://github.com/rust-lang/rust/pull/112714#issuecomment-1595653910
[`arithmetic_side_effects`] Fix#10792Fix#10792
```
changelog: [`arithmetic_side_effects`]: Retrieve field values of structures that are in constant environments
```
[`missing_const_for_fn`]: Ensure dropped locals are `~const Destruct`
this will check every local for `TerminatorKind::Drop` to ensure they can be evaluated at compile time, not sure if this is the best way to do this but MIR is confusing and it works so...
fixes#10617
changelog: [`missing_const_for_fn`]: Ensure dropped locals are `~const Destruct`
Extend `explicit_iter_loop` and `explicit_into_iter_loop`
fixes#1518
Some included cleanups
* Split `for_loop` test into different files for each lint (partially).
* Move handling of some `into_iter` cases from `explicit_into_iter`.
---
changelog: Enhancement: [`explicit_iter_loop`]: Now also handles types that implement `IntoIterator`.
[#10416](https://github.com/rust-lang/rust-clippy/pull/10416)
changelog: Sugg: [`explicit_into_iter_loop`]: The suggestion now works on mutable references.
[#10416](https://github.com/rust-lang/rust-clippy/pull/10416)
<!-- changelog_checked -->
[`unnecessary_lazy_eval`]: don't lint on types with deref impl
Fixes#10437.
This PR changes clippy's util module `eager_or_lazy` to also consider deref expressions whose type has a non-builtin deref impl and not suggest replacing it as that might have observable side effects.
A prominent example might be the `lazy_static` macro, which creates a newtype with a `Deref` impl that you need to go through to get access to the inner value. Going from lazy to eager can make a difference there.
changelog: [`unnecessary_lazy_eval`]: don't lint on types with non-builtin deref impl
[`allow_attributes`, `allow_attributes_without_reason`]: Ignore attributes from procedural macros
I use `lint_reasons` and `clap`, which is a bit overzealous when it comes to preventing warnings in its macros; it uses a ton of allow attributes on everything to, as ironic as it is, silence warnings. These two now ignore anything from procedural macros.
PS, I think `allow_attributes.rs` should be merged with `attrs.rs` in the future.
fixes#10377
changelog: [`allow_attributes`, `allow_attributes_without_reason`]: Ignore attributes from procedural macros
move some strings into consts, more tests
s/missing_field_in_debug/missing_fields_in_debug
dont trigger in macro expansions
make dogfood tests happy
minor cleanups
replace HashSet with FxHashSet
replace match_def_path with match_type
if_chain -> let chains, fix markdown, allow newtype pattern
fmt
consider string literal in `.field()` calls as used
don't intern defined symbol, remove mentions of 'debug_tuple'
special-case PD, account for field access through `Deref`
Each of `{D,Subd}iagnosticMessage::{Str,Eager}` has a comment:
```
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
```
This commit answers that question in the affirmative. It's not the most
compelling change ever, but it might be worth merging.
This requires changing the `impl<'a> From<&'a str>` impls to `impl
From<&'static str>`, which involves a bunch of knock-on changes that
require/result in call sites being a little more precise about exactly
what kind of string they use to create errors, and not just `&str`. This
will result in fewer unnecessary allocations, though this will not have
any notable perf effects given that these are error paths.
Note that I was lazy within Clippy, using `to_string` in a few places to
preserve the existing string imprecision. I could have used `impl
Into<{D,Subd}iagnosticMessage>` in various places as is done in the
compiler, but that would have required changes to *many* call sites
(mostly changing `&format("...")` to `format!("...")`) which didn't seem
worthwhile.
[`default_constructed_unit_structs`]: do not lint on type alias paths
Fixes#10755.
Type aliases cannot be used as a constructor, so this lint should not trigger in those cases.
I also changed `clippy_utils::is_ty_alias` to also consider associated types since [they kinda are type aliases too](48ec50ae39/compiler/rustc_resolve/src/late/diagnostics.rs (L1520)).
changelog: [`default_constructed_unit_structs`]: do not lint on type alias paths
Add new lint `ptr_cast_constness`
This adds a new lint which functions as the opposite side of the coin to `ptr_as_ptr`. Rather than linting only as casts that don't change constness, this lints only constness; suggesting to use `pointer::cast_const` or `pointer::cast_mut` instead.
changelog: new lint [`ptr_cast_constness`]
* Don't consider expansions of different macros to be the same, even if they expand to the same tokens
* Don't consider `cfg!` expansions to be equal if they check different configs.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
Switch to `EarlyBinder` for `explicit_item_bounds`
Part of the work to finish https://github.com/rust-lang/rust/issues/105779.
This PR adds `EarlyBinder` to the return type of the `explicit_item_bounds` query and removes `bound_explicit_item_bounds`.
r? `@compiler-errors` (hope it's okay to request you, since you reviewed #110299 and #110498😃)
use `is_inside_const_context` for `in_constant` util fn
Fixes#10452.
This PR improves the `in_constant` util function to detect more cases of const contexts. Previously this function would not detect cases like expressions in array length position or expression in an inline const block `const { .. }`.
changelog: [`bool_to_int_with_if`]: recognize array length operand as being in a const context and don't suggest `usize::from` there