Consider middle segments of paths in `unused_qualifications`
Currently `unused_qualifications` looks at the last segment of a path to see if it can be trimmed, this PR extends the check to the middle segments also
```rust
// currently linted
use std::env::args();
std::env::args(); // Removes `std::env::`
```
```rust
// newly linted
use std::env;
std::env::args(); // Removes `std::`
```
Paths with generics in them are now linted as long as the part being trimmed is before any generic args, e.g. it will now suggest trimming `std::vec::` from `std::vec::Vec<usize>`
Paths with any segments that are from an expansion are no longer linted
Fixes#100979Fixes#96698
Split Diagnostics for Uncommon Codepoints: Add Individual Identifier Types
This pull request further modifies the `uncommon_codepoints` lint, adding the individual identifier types of `Technical`, `Not_NFKC`, `Exclusion` and `Limited_Use` to the diagnostic message.
Example rendered diagnostic:
```
error: identifier contains a Unicode codepoint that is not used in normalized strings: 'ij'
--> $DIR/lint-uncommon-codepoints.rs:6:4
|
LL | fn dijkstra() {}
| ^^^^^^^
= note: this character is included in the Not_NFKC Unicode general security profile
```
Second step of #120228.
When encountering `<&T as Clone>::clone(x)` because `T: Clone`, suggest `#[derive(Clone)]`
CC #40699.
```
warning: call to `.clone()` on a reference in this situation does nothing
--> $DIR/noop-method-call.rs:23:71
|
LL | let non_clone_type_ref_clone: &PlainType<u32> = non_clone_type_ref.clone();
| ^^^^^^^^
|
= note: the type `PlainType<u32>` does not implement `Clone`, so calling `clone` on `&PlainType<u32>` copies the reference, which does not do anything and can be removed
help: remove this redundant call
|
LL - let non_clone_type_ref_clone: &PlainType<u32> = non_clone_type_ref.clone();
LL + let non_clone_type_ref_clone: &PlainType<u32> = non_clone_type_ref;
|
help: if you meant to clone `PlainType<u32>`, implement `Clone` for it
|
LL + #[derive(Clone)]
LL | struct PlainType<T>(T);
|
```
Downgrade ambiguous_wide_pointer_comparisons suggestions to MaybeIncorrect
In certain cases like #121330, it is possible to have more than one suggestion from the `ambiguous_wide_pointer_comparisons` lint (which before this PR are `MachineApplicable`). When this gets passed to rustfix, rustfix makes *multiple* changes according to the suggestions which result in incorrect code.
This is a temporary workaround. The real long term solution to problems like these is to address <https://github.com/rust-lang/rust/issues/53934>.
This PR also includes a drive-by edit to the panic message emitted by compiletest because "ui" test suite now uses `//`@`` directives.
Fixes#121330.
Use correct param-env in `MissingCopyImplementations`
We shouldn't assume the param-env is empty for this lint, since although we check the struct has no parameters, there still may be trivial where-clauses.
fixes#125394
Expand `for_loops_over_fallibles` lint to lint on fallibles behind references.
Extends the scope of the (warn-by-default) lint `for_loops_over_fallibles` from just `for _ in x` where `x: Option<_>/Result<_, _>` to also cover `x: &(mut) Option<_>/Result<_>`
```rs
fn main() {
// Current lints
for _ in Some(42) {}
for _ in Ok::<_, i32>(42) {}
// New lints
for _ in &Some(42) {}
for _ in &mut Some(42) {}
for _ in &Ok::<_, i32>(42) {}
for _ in &mut Ok::<_, i32>(42) {}
// Should not lint
for _ in Some(42).into_iter() {}
for _ in Some(42).iter() {}
for _ in Some(42).iter_mut() {}
for _ in Ok::<_, i32>(42).into_iter() {}
for _ in Ok::<_, i32>(42).iter() {}
for _ in Ok::<_, i32>(42).iter_mut() {}
}
```
<details><summary><code>cargo build</code> diff</summary>
```diff
diff --git a/old.out b/new.out
index 84215aa..ca195a7 100644
--- a/old.out
+++ b/new.out
`@@` -1,33 +1,93 `@@`
warning: for loop over an `Option`. This is more readably written as an `if let` statement
--> src/main.rs:3:14
|
3 | for _ in Some(42) {}
| ^^^^^^^^
|
= note: `#[warn(for_loops_over_fallibles)]` on by default
help: to check pattern in a loop use `while let`
|
3 | while let Some(_) = Some(42) {}
| ~~~~~~~~~~~~~~~ ~~~
help: consider using `if let` to clear intent
|
3 | if let Some(_) = Some(42) {}
| ~~~~~~~~~~~~ ~~~
warning: for loop over a `Result`. This is more readably written as an `if let` statement
--> src/main.rs:4:14
|
4 | for _ in Ok::<_, i32>(42) {}
| ^^^^^^^^^^^^^^^^
|
help: to check pattern in a loop use `while let`
|
4 | while let Ok(_) = Ok::<_, i32>(42) {}
| ~~~~~~~~~~~~~ ~~~
help: consider using `if let` to clear intent
|
4 | if let Ok(_) = Ok::<_, i32>(42) {}
| ~~~~~~~~~~ ~~~
-warning: `for-loops-over-fallibles` (bin "for-loops-over-fallibles") generated 2 warnings
- Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
+warning: for loop over a `&Option`. This is more readably written as an `if let` statement
+ --> src/main.rs:7:14
+ |
+7 | for _ in &Some(42) {}
+ | ^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+7 | while let Some(_) = &Some(42) {}
+ | ~~~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+7 | if let Some(_) = &Some(42) {}
+ | ~~~~~~~~~~~~ ~~~
+
+warning: for loop over a `&mut Option`. This is more readably written as an `if let` statement
+ --> src/main.rs:8:14
+ |
+8 | for _ in &mut Some(42) {}
+ | ^^^^^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+8 | while let Some(_) = &mut Some(42) {}
+ | ~~~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+8 | if let Some(_) = &mut Some(42) {}
+ | ~~~~~~~~~~~~ ~~~
+
+warning: for loop over a `&Result`. This is more readably written as an `if let` statement
+ --> src/main.rs:9:14
+ |
+9 | for _ in &Ok::<_, i32>(42) {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+9 | while let Ok(_) = &Ok::<_, i32>(42) {}
+ | ~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+9 | if let Ok(_) = &Ok::<_, i32>(42) {}
+ | ~~~~~~~~~~ ~~~
+
+warning: for loop over a `&mut Result`. This is more readably written as an `if let` statement
+ --> src/main.rs:10:14
+ |
+10 | for _ in &mut Ok::<_, i32>(42) {}
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+10 | while let Ok(_) = &mut Ok::<_, i32>(42) {}
+ | ~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+10 | if let Ok(_) = &mut Ok::<_, i32>(42) {}
+ | ~~~~~~~~~~ ~~~
+
+warning: `for-loops-over-fallibles` (bin "for-loops-over-fallibles") generated 6 warnings
+ Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
```
</details>
-----
Question:
* ~~Currently, the article `an` is used for `&Option`, and `&mut Option` in the lint diagnostic, since that's what `Option` uses. Is this okay or should it be changed? (likewise, `a` is used for `&Result` and `&mut Result`)~~ The article `a` is used for `&Option`, `&mut Option`, `&Result`, `&mut Result` and (as before) `Result`. Only `Option` uses `an` (as before).
`@rustbot` label +A-lint
expand: fix minor diagnostics bug
The error mentions `///`, when it's actually `//!`:
```
error[E0658]: attributes on expressions are experimental
--> test.rs:4:9
|
4 | //! wah
| ^^^^^^^
|
= note: see issue https://github.com/rust-lang/rust/issues/15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
= help: `///` is for documentation comments. For a plain comment, use `//`.
```
Some minor (English only) heroics are performed to print error messages
like "5th rule of macro `m` is never used". The form "rule #5 of macro
`m` is never used" is just as good and much simpler to implement.
Fix insufficient logic when searching for the underlying allocation
This PR fixes the logic inside the `invalid_reference_casting` lint, when trying to lint on bigger memory layout casts.
More specifically when looking for the "underlying allocation" we were wrongly assuming that when we got `&mut slice[index]` that `slice[index]` was the allocation, but it's not.
Fixes https://github.com/rust-lang/rust/issues/124685
Couldn't find documentation supporting that single-variant
`#[repr(Rust)]` enums with RHS assigned work as expected with this
change.
```rust
enum Variants {
A = 17,
} // Would this be zero sized optimized guaranteed?
```
The error mentions `///`, when it's actually `//!`:
error[E0658]: attributes on expressions are experimental
--> test.rs:4:9
|
4 | //! wah
| ^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
= help: `///` is for documentation comments. For a plain comment, use `//`.
It is possible to have more than one valid suggestion, which when
applied together via rustfix causes the code to no longer compile.
This is a temporary workaround; the real long term solution to these
issues is to solve <https://github.com/rust-lang/rust/issues/53934>.
macro_rules: Preserve all metavariable spans in a global side table
This PR preserves spans of `tt` metavariables used to pass tokens to declarative macros.
Such metavariable spans can then be used in span combination operations like `Span::to` to improve all kinds of diagnostics.
Spans of non-`tt` metavariables are currently kept in nonterminal tokens, but the long term plan is remove all nonterminal tokens from rustc parser and rely on the proc macro model with invisible delimiters (#114647, #67062).
In particular, `NtIdent` nonterminal (corresponding to `ident` metavariables) becomes easy to remove when this PR lands (#119412 does it).
The metavariable spans are kept in a global side table keyed by `Span`s of original tokens.
The alternative to the side table is keeping them in `SpanData` instead, but the performance regressions would be large because any spans from tokens passed to declarative macros would stop being inline and would work through span interner instead, and the penalty would be paid even if we never use the metavar span for the given original span.
(But also see the comment on `fn maybe_use_metavar_location` describing the map collision issues with the side table approach.)
There are also other alternatives - keeping the metavar span in `Token` or `TokenTree`, but associating it with `Span` itsel is the most natural choice because metavar spans are used in span combining operations, and those operations are not necessarily tied to tokens.
fixes#117448
For example unnecessary imports in std::prelude that can be eliminated:
```rust
use std::option::Option::Some;//~ WARNING the item `Some` is imported redundantly
use std::option::Option::None; //~ WARNING the item `None` is imported redundantly
```
This fixes the issue wherein the lint didn't fire for promoteds
in the case of SHL/SHR operators in non-optimized builds
and all arithmetic operators in optimized builds
Be less confident when `dyn` suggestion is not checked for object safety
#120275 no longer checks bare traits for object safety when making a `dyn` suggestion on Rust < 2021. In this case, qualify the suggestion with a note that the trait must be object safe, to prevent user confusion as seen in #116434
r? ```@fmease```
large_assignments: Allow moves into functions
Moves into functions are typically implemented with pointer passing
rather than memcpy's at the llvm-ir level, so allow moves into
functions.
Part of the "Differentiate between Operand::Move and Operand::Copy" step of https://github.com/rust-lang/rust/issues/83518.
r? `@oli-obk` (who I think is still E-mentor?)
Make privacy visitor use types more (instead of HIR)
r? ``@petrochenkov``
This is a prerequisite to normalizing projections, as otherwise we have too many invalid bound vars (hir_ty_to_ty is creating types that have bound vars, but no binder).
The commits are still chaotic, I'm gonna clean them up, but I just wanted to let you know about the general direction and wondering if we could land this before adding normalization, as normalization is where behavioral changes happen, and I'd like to keep that part as minimal as possible.
[context can be found on zulip](https://rust-lang.zulipchat.com/#narrow/stream/315482-t-compiler.2Fetc.2Fopaque-types/topic/weak.20type.20aliases.20and.20privacy)
Mark "unused binding" suggestion as maybe incorrect
Ignoring unused bindings should be a determination made by a human, `rustfix` shouldn't auto-apply the suggested change.
Fix#54196.
make matching on NaN a hard error, and remove the rest of illegal_floating_point_literal_pattern
These arms would never be hit anyway, so the pattern makes little sense. We have had a future-compat lint against float matches in general for a *long* time, so I hope we can get away with immediately making this a hard error.
This is part of implementing https://github.com/rust-lang/rfcs/pull/3535.
Closes https://github.com/rust-lang/rust/issues/41620 by removing the lint.
https://github.com/rust-lang/reference/pull/1456 updates the reference to match.
Fix unused_parens issue when cast is followed LT
Fixes#117142
The original check only checks `a as (i32) < 0`, this fix extends it to handle `b + a as (i32) < 0`.
A better way is maybe we suggest `(a as i32) < 0` instead of suppressing the warning, maybe following PR could improve it.
rustc_span: More consistent span combination operations
Also add more tests for using `tt` in addition to `ident`, and some other minor tweaks, see individual commits.
This is a part of https://github.com/rust-lang/rust/pull/119412 that doesn't yet add side tables for metavariable spans.
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
PR #82639 changed UI tests so `-Z unstable-options` aren't passed to UI
tests by default. This completely broke `use_suggestion_json.rs`, which
uses the unstable `--error-format=pretty-json` option. The expected
output went from 400 lines of pretty JSON error messages to a single
JSON error saying "`--error-format=pretty-json` is unstable"!
This commit adds `-Z unstable-options` back and reinstates the old
expected output, with some minor changes to account for shifted spans
and slightly JSON output changes since then.
Switch from using `//~ERROR` annotations with `--error-format` to `error-pattern`
Fixes#118752
As noticed by ```@jyn514``` while working on a patch, tests failed due to `//~ERROR` annotations used in combination with the older `--error-format` which is now `error-pattern`.
rustc_lint: Prevent triplication of various lints
Prevent triplication of various lints. The triplication happens because we run the same lint three times (or less in some cases):
* In `BuiltinCombinedPreExpansionLintPass`
* In `BuiltinCombinedEarlyLintPass`
* In `shallow_lint_levels_on()`
Only run the lints one time by checking the `lint_added_lints` bool.
Set your GitHub diff setting to ignore whitespaces changes when reviewing this PR, since I had to enclose a block inside an if.
Closes#73301
(I found this while exploring the code related to [this](https://github.com/rust-lang/rust/pull/119251#discussion_r1435677330) comment.)
Prevent multiple 'ignored unless specified at crate level' lints. The
multiplication happens because we run the same lint three times:
* In BuiltinCombinedEarlyLintPass
* In BuiltinCombinedPreExpansionLintPass
* In shallow_lint_levels_on
Only run the lint one time by checking the `lint_added_lints` bool.
Add lint against ambiguous wide pointer comparisons
This PR is the resolution of https://github.com/rust-lang/rust/issues/106447 decided in https://github.com/rust-lang/rust/issues/117717 by T-lang.
## `ambiguous_wide_pointer_comparisons`
*warn-by-default*
The `ambiguous_wide_pointer_comparisons` lint checks comparison of `*const/*mut ?Sized` as the operands.
### Example
```rust
let ab = (A, B);
let a = &ab.0 as *const dyn T;
let b = &ab.1 as *const dyn T;
let _ = a == b;
```
### Explanation
The comparison includes metadata which may not be expected.
-------
This PR also drops `clippy::vtable_address_comparisons` which is superseded by this one.
~~One thing: is the current naming right? `invalid` seems a bit too much.~~
Fixes https://github.com/rust-lang/rust/issues/117717
Enforce `must_use` on associated types and RPITITs that have a must-use trait in bounds
Warn when an RPITIT or (un-normalized) associated type with a `#[must_use]` trait in its bounds is unused.
This is pending T-lang approval, since it changes the semantics of the `#[must_use]` attribute slightly, but I think it strictly catches more strange errors.
I could also limit this to just RPITITs, but that seems less useful.
Fixes#118444
Add support for making lib features internal
We have the notion of an "internal" lang feature: a feature that is never intended to be stabilized, and using which can cause ICEs and other issues without that being considered a bug.
This extends that idea to lib features as well. It is an alternative to https://github.com/rust-lang/rust/pull/115623: instead of using an attribute to declare lib features internal, we simply do this based on the name. Everything ending in `_internals` or `_internal` is considered internal.
Then we rename `core_intrinsics` to `core_intrinsics_internal`, which fixes https://github.com/rust-lang/rust/issues/115597.
Add `$message_type` field to distinguish json diagnostic outputs
Currently the json-formatted outputs have no way to unambiguously determine which kind of message is being output. A consumer can look for specific fields in the json object (eg "message"), but there's no guarantee that in future some other kind of output will have a field of the same name.
This PR adds a `"type"` field to add json outputs which can be used to unambiguously determine which kind of output it is. The mapping is:
`diagnostic`: regular compiler diagnostics
`artifact`: artifact notifications
`future_incompat`: Future incompatibility report
`unused_extern`: Unused crate warnings/errors
This matches the "internally tagged" representation for serde enums.
Fix missing leading space in suggestion
For a local pattern with no space between `let` and `(` e.g.:
```rust
let(_a) = 3;
```
we were previously suggesting this illegal code:
```rust
let_a = 3;
```
After this change the suggestion will instead be:
```rust
let _a = 3;
```
Fixes#117380
For a local pattern with no space between `let` and `(` e.g.:
let(_a) = 3;
we were previously suggesting this illegal code:
let_a =3;
After this change the suggestion will instead be:
let _a =3;
(Note the space after `let`)
Fix overflow checking in range patterns
When a range pattern contains an overflowing literal, if we're not careful we might not notice the overflow and use the wrapped value. This makes for confusing error messages because linting against overflowing literals is only done in a later pass. So when a range is invalid we check for overflows to provide a better error.
This check didn't use to handle negative types; this PR fixes that. First commit adds tests, second cleans up without changing behavior, third does the fix.
EDIT: while I was at it, I fixed a small annoyance about the span of the overflow lint on negated literals.
Fixes https://github.com/rust-lang/rust/issues/94239
Clarify `invalid_reference_casting` lint around interior mutable types
This is PR intends to clarify the `invalid_reference_casting` lint around interior mutable types by adding a note for them saying that they should go through `UnsafeCell::get`.
So for this code:
```rust
let cell = &std::cell::UnsafeCell::new(0);
let _num = &mut *(cell as *const _ as *mut i32);
```
the following note will be added to the lint output:
```diff
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:68:16
|
LL | let _num = &mut *(cell as *const _ as *mut i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
+ = note: even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`
```
Suggestion are welcome around the note contents.
Fixes https://github.com/rust-lang/rust/issues/116410
cc `@RalfJung`
Add a note to duplicate diagnostics
Helps explain why there may be a difference between manual testing and the test suite output and highlights them as something to potentially look into
For existing duplicate diagnostics I just blessed them other than a few files that had other `NOTE` annotations in
Fix `noop_method_call` detection
This needs to be merged before #116198 can compile. The error occurs before the compiler is built so this needs to be a separate PR.
adjust how closure/generator types are printed
I saw `&[closure@$DIR/issue-20862.rs:2:5]` and I thought it is a slice type, because that's usually what `&[_]` is... it took me a while to realize that this is just a confusing printer and actually there's no slice. Let's use something that cannot be mistaken for a regular type.
Improve invalid UTF-8 lint by finding the expression initializer
This PR introduce a small mechanism to walk up the HIR through bindings, if/else, consts, ... when trying lint on invalid UTF-8.
Fixes https://github.com/rust-lang/rust/issues/115208
Currently the json-formatted outputs have no way to unambiguously
determine which kind of message is being output. A consumer can look for
specific fields in the json object (eg "message"), but there's no
guarantee that in future some other kind of output will have a field of
the same name.
This PR adds a `"type"` field to add json outputs which can be used to
unambiguously determine which kind of output it is. The mapping is:
diagnostic: regular compiler diagnostics
artifact: artifact notifications
future_incompat: Report of future incompatibility
unused_extern: Unused crate warnings/errors
This matches the "internally tagged" representation for serde enums.
Make useless_ptr_null_checks smarter about some std functions
This teaches the `useless_ptr_null_checks` lint that some std functions can't ever return null pointers, because they need to point to valid data, get references as input, etc.
This is achieved by introducing an `#[rustc_never_returns_null_ptr]` attribute and adding it to these std functions (gated behind bootstrap `cfg_attr`).
Later on, the attribute could maybe be used to tell LLVM that the returned pointer is never null. I don't expect much impact of that though, as the functions are pretty shallow and usually the input data is already never null.
Follow-up of PR #113657Fixes#114442
Rework `no_coverage` to `coverage(off)`
As discussed at the tail of https://github.com/rust-lang/rust/issues/84605 this replaces the `no_coverage` attribute with a `coverage` attribute that takes sub-parameters (currently `off` and `on`) to control the coverage instrumentation.
Allows future-proofing for things like `coverage(off, reason="Tested live", issue="#12345")` or similar.
Don't ICE when computing ctype's `repr_nullable_ptr` for possibly-unsized ty
We may not always be able to compute the layout of a type like `&T` when `T: ?Sized`, even if we're able to estimate its size skeleton.
r? davidtwco
Fixes#115628
The lint panicked for an input like 'extern "C" fn(Option<&<T as FooTrait>::FooType>)' because the type T therein cannot be normalized. The normalization failure caused SizeSkeleton::compute() to return an error and trigger a panic in the unwrap().
Lint on invalid usage of `UnsafeCell::raw_get` in reference casting
This PR proposes to take into account `UnsafeCell::raw_get` method call for non-Freeze types for the `invalid_reference_casting` lint.
The goal of this is to catch those kind of invalid reference casting:
```rust
fn as_mut<T>(x: &T) -> &mut T {
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
}
```
r? `@est31`
This demonstrates the current behavior of adding lint form the command
line. generally the lint levels are ignored as the current implementation
unconditionally emit errors for those lints.
Add test for unknown_lints from another file.
This adds a test for #84936 which was incidentally fixed via #97266. It is a strange issue where `#![allow(unknown_lints)]` at the crate root was not applying to unknown lints that fired in a non-inline-module. I did not dig further into how #97266 fixed it, but I did verify it. I couldn't find any existing tests which did anything similar.
Closes#84936
Also consider `mem::transmute` with the `invalid_reference_casting` lint
This PR extend the `invalid_reference_casting` lint with regard to the `std::mem::transmute` function.
```
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:27:16
|
LL | let _num = &mut *std::mem::transmute::<_, *mut i32>(&num);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
*I encourage anyone reviewing this PR to do so [without whitespaces](https://github.blog/2011-10-21-github-secrets/#whitespace).*