fix/issue#11243: allow 3-digit-grouped binary in non_octal_unix_permissions
fixes [Issue#11243](https://github.com/rust-lang/rust-clippy/issues/11243)
Issue#11243 suggest lint `non_octal_unix_permissions` should not report binary format literal unix permissions as an error, and we think binary format is a good way to understand these permissions.
To solve this problem, we need to add check for binary literal, which is written in function `check_binary_unix_permissions` , only `binary, 3 groups and each group length equals to 3` is a legal format.
changelog: [`non_octal_unix_permissions`]: Add check for binary format literal unix permissions like 0b111_111_111
This works for most of its call sites. This is nice, because `emit` very
much makes sense as a consuming operation -- indeed,
`DiagnosticBuilderState` exists to ensure no diagnostic is emitted
twice, but it uses runtime checks.
For the small number of call sites where a consuming emit doesn't work,
the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will
be removed in subsequent commits.)
Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes
consuming, while `delay_as_bug_without_consuming` is added (which will
also be removed in subsequent commits.)
All this requires significant changes to `DiagnosticBuilder`'s chaining
methods. Currently `DiagnosticBuilder` method chaining uses a
non-consuming `&mut self -> &mut Self` style, which allows chaining to
be used when the chain ends in `emit()`, like so:
```
struct_err(msg).span(span).emit();
```
But it doesn't work when producing a `DiagnosticBuilder` value,
requiring this:
```
let mut err = self.struct_err(msg);
err.span(span);
err
```
This style of chaining won't work with consuming `emit` though. For
that, we need to use to a `self -> Self` style. That also would allow
`DiagnosticBuilder` production to be chained, e.g.:
```
self.struct_err(msg).span(span)
```
However, removing the `&mut self -> &mut Self` style would require that
individual modifications of a `DiagnosticBuilder` go from this:
```
err.span(span);
```
to this:
```
err = err.span(span);
```
There are *many* such places. I have a high tolerance for tedious
refactorings, but even I gave up after a long time trying to convert
them all.
Instead, this commit has it both ways: the existing `&mut self -> Self`
chaining methods are kept, and new `self -> Self` chaining methods are
added, all of which have a `_mv` suffix (short for "move"). Changes to
the existing `forward!` macro lets this happen with very little
additional boilerplate code. I chose to add the suffix to the new
chaining methods rather than the existing ones, because the number of
changes required is much smaller that way.
This doubled chainging is a bit clumsy, but I think it is worthwhile
because it allows a *lot* of good things to subsequently happen. In this
commit, there are many `mut` qualifiers removed in places where
diagnostics are emitted without being modified. In subsequent commits:
- chaining can be used more, making the code more concise;
- more use of chaining also permits the removal of redundant diagnostic
APIs like `struct_err_with_code`, which can be replaced easily with
`struct_err` + `code_mv`;
- `emit_without_diagnostic` can be removed, which simplifies a lot of
machinery, removing the need for `DiagnosticBuilderState`.
Fixed ICE introduced in #12004
Issue: in https://github.com/rust-lang/rust-clippy/pull/12004, we emit a lint for `filter(Option::is_some)`. If the
parent expression is a `.map` we don't emit that lint as there exists a
more specialized lint for that.
The ICE introduced in https://github.com/rust-lang/rust-clippy/pull/12004 is a consequence of the assumption that a
parent expression after a filter would be a method call with the filter
call being the receiver. However, it is entirely possible to have a
closure of the form
```
|| { vec![Some(1), None].into_iter().filter(Option::is_some) }
```
The previous implementation looked at the parent expression; namely the
closure, and tried to check the parameters by indexing [0] on an empty
list.
This commit is an overhaul of the lint with significantly more FP tests
and checks.
Impl details:
1. We verify that the filter method we are in is a proper trait method
to avoid FPs.
2. We check that the parent expression is not a map by checking whether
it exists; if is a trait method; and then a method call.
3. We check that we don't have comments in the span.
4. We verify that we are in an Iterator of Option and Result.
5. We check the contents of the filter.
1. For closures we peel it. If it is not a single expression, we don't
lint. We then try again by checking the peeled expression.
2. For paths, we do a typecheck to avoid FPs for types that impl
functions with the same names.
3. For calls, we verify the type, via the path, and that the param of
the closure is the single argument to the call.
4. For method calls we verify that the receiver is the parameter of
the closure. Since we handle single, non-block exprs, the
parameter can't be shadowed, so no FP.
This commit also adds additional FP tests.
Fixes: #12058
Adding `@xFrednet` as you've the most context for this as you reviewed it last time.
`@rustbot` r? `@xFrednet`
---
changelog: none
(Will be backported and therefore don't effect stable)
Issue: in #12004, we emit a lint for `filter(Option::is_some)`. If the
parent expression is a `.map` we don't emit that lint as there exists a
more specialized lint for that.
The ICE introduced in #12004 is a consequence of the assumption that a
parent expression after a filter would be a method call with the filter
call being the receiver. However, it is entirely possible to have a
closure of the form
```
|| { vec![Some(1), None].into_iter().filter(Option::is_some) }
```
The previous implementation looked at the parent expression; namely the
closure, and tried to check the parameters by indexing [0] on an empty
list.
This commit is an overhaul of the lint with significantly more FP tests
and checks.
Impl details:
1. We verify that the filter method we are in is a proper trait method
to avoid FPs.
2. We check that the parent expression is not a map by checking whether
it exists; if is a trait method; and then a method call.
3. We check that we don't have comments in the span.
4. We verify that we are in an Iterator of Option and Result.
5. We check the contents of the filter.
1. For closures we peel it. If it is not a single expression, we don't
lint.
2. For paths, we do a typecheck to avoid FPs for types that impl
functions with the same names.
3. For calls, we verify the type, via the path, and that the param of
the closure is the single argument to the call.
4. For method calls we verify that the receiver is the parameter of
the closure. Since we handle single, non-block exprs, the
parameter can't be shadowed, so no FP.
This commit also adds additional FP tests.
Handle "calls" inside the closure as well in `map_clone` lint
Follow-up of https://github.com/rust-lang/rust-clippy/pull/12104.
I just realized that I didn't handle the case where the `clone` method was made as a call and not a method call.
r? `@llogiq`
changelog: Handle "calls" inside the closure as well in `map_clone` lint
Do not suggest `bool::then()` and `bool::then_some` in `const` contexts
Fix#12103
changelog: [`if_then_some_else_none`]: Do not trigger in `const` contexts
improve [`cast_sign_loss`], to skip warning on always positive expressions
fixes: #11642
changelog: improve [`cast_sign_loss`] to skip warning on always positive expressions
Turns out this is change became quite big, and I still can't cover all the cases, like method calls such as `POSITIVE_NUM.mul(POSITIVE_NUM)`, or `NEGATIVE_NUM.div(NEGATIVE_NUM)`... but well, if I do, I'm scared that this will goes forever, so I stopped, unless it needs to be done, lol.
Do not suggest `[T; n]` instead of `vec![T; n]` if `T` is not `Copy`
changelog: [`useless_vec`]: do not suggest replacing `&vec![T; N]` by `&[T; N]` if `T` is not `Copy`
Fix#11958
Extend `map_clone` lint to also work on non-explicit closures
I found it weird that this case was not handled by the current line so I added it. The only thing is that I don't see an obvious way to infer the current type to determine if it's copyable or not, so for now I always suggest `cloned` and I added a FIXME.
r? `@llogiq`
changelog: Extend `map_clone` lint to also work on non-explicit closures
rustc_span: Optimize syntax context comparisons
Including comparisons with root context.
- `eq_ctxt` doesn't require retrieving full `SpanData`, or taking the span interner lock twice.
- Checking `SyntaxContext` for "rootness" is cheaper than extracting a full outer `ExpnData` for it and checking *it* for rootness.
The internal lint for `eq_ctxt` is also tweaked to detect `a.ctxt() != b.ctxt()` in addition to `a.ctxt() == b.ctxt()`.
don't change eagerness for struct literal syntax with significant drop
Fixes the bug reported by `@ju1ius` in https://github.com/rust-lang/rust-clippy/issues/9427#issuecomment-1878428001.
`eager_or_lazy` already understands to suppress eagerness changes when the expression type has a significant drop impl, but only for initialization of tuple structs or unit structs. This changes it to also avoid changing it for `Self { .. }` and `TypeWithDrop { .. }`
changelog: [`unnecessary_lazy_eval`]: don't suggest changing eagerness for struct literal syntax when type has a significant drop impl
Fix scoping for let chains in match guards
If let guards were previously represented as a different type of guard in HIR and THIR. This meant that let chains in match guards were not handled correctly because they were treated exactly like normal guards.
- Remove `hir::Guard` and `thir::Guard`.
- Make the scoping different between normal guards and if let guards also check for let chains.
closes#118593
Hide foreign `#[doc(hidden)]` paths in import suggestions
Stops the compiler from suggesting to import foreign `#[doc(hidden)]` paths.
```@rustbot``` label A-suggestion-diagnostics
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 {
| ++++
```
Polish `missing_enforced_import_renames` documentation
* Fixes a typo in the name of the lint (`enforce-import-renames` instead of `enforced-import-renames`).
* Copyedit “Why” paragraph.
* Make the example configuration use a multi-line list, since it is not particularly expected that a real project will have *exactly one* rename to enforce (and the old formatting had unbalanced whitespace).
changelog: none
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