mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 07:00:55 +00:00
Auto merge of #115183 - flip1995:clippyup, r=Manishearth,oli-obk
Update Clippy r? `@oli-obk` Assigning you, because something broke with ui_test: ``` tests/ui/crashes/ice-7272.rs FAILED: command: "<unknown>" A bug in `ui_test` occurred: called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" } full stderr: ``` (and that 103 times) Thought I would ping you, before starting to investigate. Maybe you know what's going on.
This commit is contained in:
commit
af02b43015
1885 changed files with 16712 additions and 9889 deletions
107
CHANGELOG.md
107
CHANGELOG.md
|
@ -6,18 +6,105 @@ document.
|
|||
|
||||
## Unreleased / Beta / In Rust Nightly
|
||||
|
||||
[435a8ad8...master](https://github.com/rust-lang/rust-clippy/compare/435a8ad8...master)
|
||||
[37f4c172...master](https://github.com/rust-lang/rust-clippy/compare/37f4c172...master)
|
||||
|
||||
## Rust 1.72
|
||||
|
||||
Current stable, released 2023-08-24
|
||||
|
||||
[View all 131 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-05-22T14%3A53%3A59Z..2023-07-01T22%3A57%3A20Z+base%3Amaster)
|
||||
|
||||
### New Lints
|
||||
|
||||
* [`manual_try_fold`]
|
||||
[#11012](https://github.com/rust-lang/rust-clippy/pull/11012)
|
||||
* [`tuple_array_conversions`]
|
||||
[#11020](https://github.com/rust-lang/rust-clippy/pull/11020)
|
||||
* [`redundant_at_rest_pattern`]
|
||||
[#11013](https://github.com/rust-lang/rust-clippy/pull/11013)
|
||||
* [`needless_pub_self`]
|
||||
[#10967](https://github.com/rust-lang/rust-clippy/pull/10967)
|
||||
* [`pub_with_shorthand`]
|
||||
[#10967](https://github.com/rust-lang/rust-clippy/pull/10967)
|
||||
* [`pub_without_shorthand`]
|
||||
[#10967](https://github.com/rust-lang/rust-clippy/pull/10967)
|
||||
* [`manual_range_patterns`]
|
||||
[#10968](https://github.com/rust-lang/rust-clippy/pull/10968)
|
||||
* [`needless_raw_string_hashes`]
|
||||
[#10884](https://github.com/rust-lang/rust-clippy/pull/10884)
|
||||
* [`needless_raw_strings`]
|
||||
[#10884](https://github.com/rust-lang/rust-clippy/pull/10884)
|
||||
* [`incorrect_clone_impl_on_copy_type`]
|
||||
[#10925](https://github.com/rust-lang/rust-clippy/pull/10925)
|
||||
* [`drain_collect`]
|
||||
[#10835](https://github.com/rust-lang/rust-clippy/pull/10835)
|
||||
* [`single_range_in_vec_init`]
|
||||
[#10934](https://github.com/rust-lang/rust-clippy/pull/10934)
|
||||
* [`unnecessary_literal_unwrap`]
|
||||
[#10358](https://github.com/rust-lang/rust-clippy/pull/10358)
|
||||
* [`large_stack_frames`]
|
||||
[#10827](https://github.com/rust-lang/rust-clippy/pull/10827)
|
||||
* [`min_ident_chars`]
|
||||
[#10916](https://github.com/rust-lang/rust-clippy/pull/10916)
|
||||
* [`needless_if`]
|
||||
[#10921](https://github.com/rust-lang/rust-clippy/pull/10921)
|
||||
* [`excessive_nesting`]
|
||||
[#10672](https://github.com/rust-lang/rust-clippy/pull/10672)
|
||||
* [`arc_with_non_send_sync`]
|
||||
[#10898](https://github.com/rust-lang/rust-clippy/pull/10898)
|
||||
* [`redundant_type_annotations`]
|
||||
[#10570](https://github.com/rust-lang/rust-clippy/pull/10570)
|
||||
* [`host_endian_bytes`]
|
||||
[#10826](https://github.com/rust-lang/rust-clippy/pull/10826)
|
||||
* [`little_endian_bytes`]
|
||||
[#10826](https://github.com/rust-lang/rust-clippy/pull/10826)
|
||||
* [`big_endian_bytes`]
|
||||
[#10826](https://github.com/rust-lang/rust-clippy/pull/10826)
|
||||
* [`ptr_cast_constness`]
|
||||
[#10779](https://github.com/rust-lang/rust-clippy/pull/10779)
|
||||
* [`needless_else`]
|
||||
[#10810](https://github.com/rust-lang/rust-clippy/pull/10810)
|
||||
|
||||
### Moves and Deprecations
|
||||
|
||||
* Moved [`redundant_clone`] to `nursery` (Now allow-by-default)
|
||||
[#10873](https://github.com/rust-lang/rust-clippy/pull/10873)
|
||||
|
||||
### Enhancements
|
||||
|
||||
* [`undocumented_unsafe_blocks`]: Added [`accept-comment-above-attributes`] configuration
|
||||
[#10986](https://github.com/rust-lang/rust-clippy/pull/10986)
|
||||
* [`undocumented_unsafe_blocks`]: Added [`accept-comment-above-statement`] configuration.
|
||||
[#10886](https://github.com/rust-lang/rust-clippy/pull/10886)
|
||||
* [`missing_panics_doc`]: No longer lints on `todo!()`
|
||||
[#10976](https://github.com/rust-lang/rust-clippy/pull/10976)
|
||||
* [`module_inception`]: Added `allow-private-module-inception` configuration.
|
||||
[#10917](https://github.com/rust-lang/rust-clippy/pull/10917)
|
||||
* Errors and warnings generated while parsing `clippy.toml` now point to the location in the TOML
|
||||
file the error/warning occurred in.
|
||||
[#10607](https://github.com/rust-lang/rust-clippy/pull/10607)
|
||||
|
||||
### False Positive Fixes
|
||||
|
||||
* [`excessive_precision`]: No longer lints overflowing literals
|
||||
[#10952](https://github.com/rust-lang/rust-clippy/pull/10952)
|
||||
|
||||
### Suggestion Fixes/Improvements
|
||||
|
||||
* [`option_map_unwrap_or`]: The suggestion now considers the set [`msrv`] config value
|
||||
[#11030](https://github.com/rust-lang/rust-clippy/pull/11030)
|
||||
|
||||
### Documentation Improvements
|
||||
|
||||
* [Clippy's lint list] now stores filter parameters in the URL, to allow easy sharing
|
||||
[#10834](https://github.com/rust-lang/rust-clippy/pull/10834)
|
||||
|
||||
## Rust 1.71
|
||||
|
||||
Current stable, released 2023-07-13
|
||||
Released 2023-07-13
|
||||
|
||||
<!-- FIXME: Remove the request for feedback, with the next changelog -->
|
||||
|
||||
We're trying out a new shorter changelog format, that only contains significant changes.
|
||||
You can check out the list of merged pull requests for a list of all changes.
|
||||
If you have any feedback related to the new format, please share it in
|
||||
[#10847](https://github.com/rust-lang/rust-clippy/issues/10847)
|
||||
Note: Clippy will use a shorter changelog format from now on, if you want a detailed list of
|
||||
all changes, please check out the list of merged pull requests.
|
||||
|
||||
[View all 78 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-04-11T20%3A05%3A26Z..2023-05-20T13%3A48%3A17Z+base%3Amaster)
|
||||
|
||||
|
@ -4677,6 +4764,7 @@ Released 2018-09-13
|
|||
[pull3665]: https://github.com/rust-lang/rust-clippy/pull/3665
|
||||
[adding_lints]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/adding_lints.md
|
||||
[`README.md`]: https://github.com/rust-lang/rust-clippy/blob/master/README.md
|
||||
[Clippy's lint list]: https://rust-lang.github.io/rust-clippy/master/index.html
|
||||
|
||||
<!-- lint disable no-unused-definitions -->
|
||||
<!-- begin autogenerated links to lint list -->
|
||||
|
@ -4897,6 +4985,7 @@ Released 2018-09-13
|
|||
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
|
||||
[`implicit_saturating_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_add
|
||||
[`implicit_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_sub
|
||||
[`implied_bounds_in_impls`]: https://rust-lang.github.io/rust-clippy/master/index.html#implied_bounds_in_impls
|
||||
[`impossible_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#impossible_comparisons
|
||||
[`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops
|
||||
[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
|
||||
|
@ -5211,6 +5300,7 @@ Released 2018-09-13
|
|||
[`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
|
||||
[`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once
|
||||
[`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts
|
||||
[`reserve_after_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#reserve_after_initialization
|
||||
[`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs
|
||||
[`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used
|
||||
[`result_large_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err
|
||||
|
@ -5241,6 +5331,7 @@ Released 2018-09-13
|
|||
[`short_circuit_statement`]: https://rust-lang.github.io/rust-clippy/master/index.html#short_circuit_statement
|
||||
[`should_assert_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_assert_eq
|
||||
[`should_implement_trait`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
|
||||
[`should_panic_without_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_panic_without_expect
|
||||
[`significant_drop_in_scrutinee`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_in_scrutinee
|
||||
[`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_tightening
|
||||
[`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names
|
||||
|
|
|
@ -148,7 +148,7 @@ pub mod else_if_without_else;
|
|||
|
||||
pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
|
||||
// ...
|
||||
store.register_early_pass(|| box else_if_without_else::ElseIfWithoutElse);
|
||||
store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse));
|
||||
// ...
|
||||
|
||||
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "clippy"
|
||||
version = "0.1.73"
|
||||
version = "0.1.74"
|
||||
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
|
||||
repository = "https://github.com/rust-lang/rust-clippy"
|
||||
readme = "README.md"
|
||||
|
@ -27,7 +27,7 @@ tempfile = { version = "3.2", optional = true }
|
|||
termize = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
ui_test = "0.11.5"
|
||||
ui_test = "0.18.1"
|
||||
tester = "0.9"
|
||||
regex = "1.5"
|
||||
toml = "0.7.3"
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
- [Development](development/README.md)
|
||||
- [Basics](development/basics.md)
|
||||
- [Adding Lints](development/adding_lints.md)
|
||||
- [Defining Lints](development/defining_lints.md)
|
||||
- [Lint Passes](development/lint_passes.md)
|
||||
- [Type Checking](development/type_checking.md)
|
||||
- [Method Checking](development/method_checking.md)
|
||||
- [Macro Expansions](development/macro_expansions.md)
|
||||
- [Common Tools](development/common_tools_writing_lints.md)
|
||||
- [Infrastructure](development/infrastructure/README.md)
|
||||
|
|
|
@ -161,8 +161,8 @@ The process of generating the `.stderr` file is the same, and prepending the
|
|||
## Rustfix tests
|
||||
|
||||
If the lint you are working on is making use of structured suggestions, the test
|
||||
file should include a `//@run-rustfix` comment at the top. This will
|
||||
additionally run [rustfix] for that test. Rustfix will apply the suggestions
|
||||
will create a `.fixed` file by running [rustfix] for that test.
|
||||
Rustfix will apply the suggestions
|
||||
from the lint to the code of the test file and compare that to the contents of a
|
||||
`.fixed` file.
|
||||
|
||||
|
|
205
book/src/development/defining_lints.md
Normal file
205
book/src/development/defining_lints.md
Normal file
|
@ -0,0 +1,205 @@
|
|||
# Define New Lints
|
||||
|
||||
The first step in the journey of a new lint is the definition
|
||||
and registration of the lint in Clippy's codebase.
|
||||
We can use the Clippy dev tools to handle this step since setting up the
|
||||
lint involves some boilerplate code.
|
||||
|
||||
#### Lint types
|
||||
|
||||
A lint type is the category of items and expressions in which your lint focuses on.
|
||||
|
||||
As of the writing of this documentation update, there are 12 _types_ of lints
|
||||
besides the numerous standalone lints living under `clippy_lints/src/`:
|
||||
|
||||
- `cargo`
|
||||
- `casts`
|
||||
- `functions`
|
||||
- `loops`
|
||||
- `matches`
|
||||
- `methods`
|
||||
- `misc_early`
|
||||
- `operators`
|
||||
- `transmute`
|
||||
- `types`
|
||||
- `unit_types`
|
||||
- `utils / internal` (Clippy internal lints)
|
||||
|
||||
These types group together lints that share some common behaviors. For instance,
|
||||
`functions` groups together lints that deal with some aspects of functions in
|
||||
Rust, like definitions, signatures and attributes.
|
||||
|
||||
For more information, feel free to compare the lint files under any category
|
||||
with [All Clippy lints][all_lints] or ask one of the maintainers.
|
||||
|
||||
## Lint name
|
||||
|
||||
A good lint name is important, make sure to check the [lint naming
|
||||
guidelines][lint_naming]. Don't worry, if the lint name doesn't fit, a Clippy
|
||||
team member will alert you in the PR process.
|
||||
|
||||
---
|
||||
|
||||
We'll name our example lint that detects functions named "foo" `foo_functions`.
|
||||
Check the [lint naming guidelines][lint_naming] to see why this name makes
|
||||
sense.
|
||||
|
||||
## Add and Register the Lint
|
||||
|
||||
Now that a name is chosen, we shall register `foo_functions` as a lint to the
|
||||
codebase. There are two ways to register a lint.
|
||||
|
||||
### Standalone
|
||||
|
||||
If you believe that this new lint is a standalone lint (that doesn't belong to
|
||||
any specific [type](#lint-types) like `functions` or `loops`), you can run the
|
||||
following command in your Clippy project:
|
||||
|
||||
```sh
|
||||
$ cargo dev new_lint --name=lint_name --pass=late --category=pedantic
|
||||
```
|
||||
|
||||
There are two things to note here:
|
||||
|
||||
1. `--pass`: We set `--pass=late` in this command to do a late lint pass. The
|
||||
alternative is an `early` lint pass. We will discuss this difference in a
|
||||
later chapter.
|
||||
<!-- FIXME: Link that "later chapter" when lint_passes.md is merged -->
|
||||
2. `--category`: If not provided, the `category` of this new lint will default
|
||||
to `nursery`.
|
||||
|
||||
The `cargo dev new_lint` command will create a new file:
|
||||
`clippy_lints/src/foo_functions.rs` as well as [register the
|
||||
lint](#lint-registration).
|
||||
|
||||
Overall, you should notice that the following files are modified or created:
|
||||
|
||||
```sh
|
||||
$ git status
|
||||
On branch foo_functions
|
||||
Changes not staged for commit:
|
||||
(use "git add <file>..." to update what will be committed)
|
||||
(use "git restore <file>..." to discard changes in working directory)
|
||||
modified: CHANGELOG.md
|
||||
modified: clippy_lints/src/lib.register_lints.rs
|
||||
modified: clippy_lints/src/lib.register_pedantic.rs
|
||||
modified: clippy_lints/src/lib.rs
|
||||
|
||||
Untracked files:
|
||||
(use "git add <file>..." to include in what will be committed)
|
||||
clippy_lints/src/foo_functions.rs
|
||||
tests/ui/foo_functions.rs
|
||||
```
|
||||
|
||||
|
||||
### Specific Type
|
||||
|
||||
> **Note**: Lint types are listed in the ["Lint types"](#lint-types) section
|
||||
|
||||
If you believe that this new lint belongs to a specific type of lints,
|
||||
you can run `cargo dev new_lint` with a `--type` option.
|
||||
|
||||
Since our `foo_functions` lint is related to function calls, one could
|
||||
argue that we should put it into a group of lints that detect some behaviors
|
||||
of functions, we can put it in the `functions` group.
|
||||
|
||||
Let's run the following command in your Clippy project:
|
||||
|
||||
```sh
|
||||
$ cargo dev new_lint --name=foo_functions --type=functions --category=pedantic
|
||||
```
|
||||
|
||||
This command will create, among other things, a new file:
|
||||
`clippy_lints/src/{type}/foo_functions.rs`.
|
||||
In our case, the path will be `clippy_lints/src/functions/foo_functions.rs`.
|
||||
|
||||
Notice how this command has a `--type` flag instead of `--pass`. Unlike a standalone
|
||||
definition, this lint won't be registered in the traditional sense. Instead, you will
|
||||
call your lint from within the type's lint pass, found in `clippy_lints/src/{type}/mod.rs`.
|
||||
|
||||
A _type_ is just the name of a directory in `clippy_lints/src`, like `functions` in
|
||||
the example command. Clippy groups together some lints that share common behaviors,
|
||||
so if your lint falls into one, it would be best to add it to that type.
|
||||
|
||||
Overall, you should notice that the following files are modified or created:
|
||||
|
||||
```sh
|
||||
$ git status
|
||||
On branch foo_functions
|
||||
Changes not staged for commit:
|
||||
(use "git add <file>..." to update what will be committed)
|
||||
(use "git restore <file>..." to discard changes in working directory)
|
||||
modified: CHANGELOG.md
|
||||
modified: clippy_lints/src/declared_lints.rs
|
||||
modified: clippy_lints/src/functions/mod.rs
|
||||
|
||||
Untracked files:
|
||||
(use "git add <file>..." to include in what will be committed)
|
||||
clippy_lints/src/functions/foo_functions.rs
|
||||
tests/ui/foo_functions.rs
|
||||
```
|
||||
|
||||
|
||||
## The `define_clippy_lints` macro
|
||||
|
||||
After `cargo dev new_lint`, you should see a macro with the name
|
||||
`define_clippy_lints`. It will be in the same file if you defined a standalone
|
||||
lint, and it will be in `mod.rs` if you defined a type-specific lint.
|
||||
|
||||
The macro looks something like this:
|
||||
|
||||
```rust
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
///
|
||||
/// // Describe here what does the lint do.
|
||||
///
|
||||
/// Triggers when detects...
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
///
|
||||
/// // Describe why this pattern would be bad
|
||||
///
|
||||
/// It can lead to...
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// // example code where clippy issues a warning
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// // example code which does not raise clippy warning
|
||||
/// ```
|
||||
#[clippy::version = "1.70.0"] // <- In which version was this implemented, keep it up to date!
|
||||
pub LINT_NAME, // <- The lint name IN_ALL_CAPS
|
||||
pedantic, // <- The lint group
|
||||
"default lint description" // <- A lint description, e.g. "A function has an unit return type."
|
||||
}
|
||||
```
|
||||
|
||||
## Lint registration
|
||||
|
||||
If we run the `cargo dev new_lint` command for a new lint, the lint will be
|
||||
automatically registered and there is nothing more to do.
|
||||
|
||||
However, sometimes we might want to declare a new lint by hand. In this case,
|
||||
we'd use `cargo dev update_lints` command afterwards.
|
||||
|
||||
When a lint is manually declared, we might need to register the lint pass
|
||||
manually in the `register_plugins` function in `clippy_lints/src/lib.rs`:
|
||||
|
||||
```rust
|
||||
store.register_late_pass(|_| Box::new(foo_functions::FooFunctions));
|
||||
```
|
||||
|
||||
As you might have guessed, where there's something late, there is something
|
||||
early: in Clippy there is a `register_early_pass` method as well. More on early
|
||||
vs. late passes in a later chapter.
|
||||
<!-- FIXME: Link that "later chapter" when lint_passes.md is merged -->
|
||||
|
||||
Without a call to one of `register_early_pass` or `register_late_pass`, the lint
|
||||
pass in question will not be run.
|
||||
|
||||
|
||||
[all_lints]: https://rust-lang.github.io/rust-clippy/master/
|
||||
[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
|
93
book/src/development/method_checking.md
Normal file
93
book/src/development/method_checking.md
Normal file
|
@ -0,0 +1,93 @@
|
|||
# Method Checking
|
||||
|
||||
In some scenarios we might want to check for methods when developing
|
||||
a lint. There are two kinds of questions that we might be curious about:
|
||||
|
||||
- Invocation: Does an expression call a specific method?
|
||||
- Definition: Does an `impl` define a method?
|
||||
|
||||
## Checking if an `expr` is calling a specific method
|
||||
|
||||
Suppose we have an `expr`, we can check whether it calls a specific
|
||||
method, e.g. `our_fancy_method`, by performing a pattern match on
|
||||
the [`ExprKind`] that we can access from `expr.kind`:
|
||||
|
||||
```rust
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_span::sym;
|
||||
use clippy_utils::is_trait_method;
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for OurFancyMethodLint {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
|
||||
// Check our expr is calling a method with pattern matching
|
||||
if let hir::ExprKind::MethodCall(path, _, [self_arg, ..]) = &expr.kind
|
||||
// Check if the name of this method is `our_fancy_method`
|
||||
&& path.ident.name == sym!(our_fancy_method)
|
||||
// We can check the type of the self argument whenever necessary.
|
||||
// (It's necessary if we want to check that method is specifically belonging to a specific trait,
|
||||
// for example, a `map` method could belong to user-defined trait instead of to `Iterator`)
|
||||
// See the next section for more information.
|
||||
&& is_trait_method(cx, self_arg, sym::OurFancyTrait)
|
||||
{
|
||||
println!("`expr` is a method call for `our_fancy_method`");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Take a closer look at the `ExprKind` enum variant [`MethodCall`] for more
|
||||
information on the pattern matching. As mentioned in [Define
|
||||
Lints](defining_lints.md#lint-types), the `methods` lint type is full of pattern
|
||||
matching with `MethodCall` in case the reader wishes to explore more.
|
||||
|
||||
Additionally, we use the [`clippy_utils::sym!`][sym] macro to conveniently
|
||||
convert an input `our_fancy_method` into a `Symbol` and compare that symbol to
|
||||
the [`Ident`]'s name in the [`PathSegment`] in the [`MethodCall`].
|
||||
|
||||
## Checking if a `impl` block implements a method
|
||||
|
||||
While sometimes we want to check whether a method is being called or not, other
|
||||
times we want to know if our `Ty` defines a method.
|
||||
|
||||
To check if our `impl` block defines a method `our_fancy_method`, we will
|
||||
utilize the [`check_impl_item`] method that is available in our beloved
|
||||
[`LateLintPass`] (for more information, refer to the ["Lint
|
||||
Passes"](lint_passes.md) chapter in the Clippy book). This method provides us
|
||||
with an [`ImplItem`] struct, which represents anything within an `impl` block.
|
||||
|
||||
Let us take a look at how we might check for the implementation of
|
||||
`our_fancy_method` on a type:
|
||||
|
||||
```rust
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::return_ty;
|
||||
use rustc_hir::{ImplItem, ImplItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
|
||||
// Check if item is a method/function
|
||||
if let ImplItemKind::Fn(ref signature, _) = impl_item.kind
|
||||
// Check the method is named `our_fancy_method`
|
||||
&& impl_item.ident.name == sym!(our_fancy_method)
|
||||
// We can also check it has a parameter `self`
|
||||
&& signature.decl.implicit_self.has_implicit_self()
|
||||
// We can go even further and even check if its return type is `String`
|
||||
&& is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym::String)
|
||||
{
|
||||
println!("`our_fancy_method` is implemented!");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[`check_impl_item`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_lint/trait.LateLintPass.html#method.check_impl_item
|
||||
[`ExprKind`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/hir/enum.ExprKind.html
|
||||
[`Ident`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_span/symbol/struct.Ident.html
|
||||
[`ImplItem`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_hir/hir/struct.ImplItem.html
|
||||
[`LateLintPass`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_lint/trait.LateLintPass.html
|
||||
[`MethodCall`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/hir/enum.ExprKind.html#variant.MethodCall
|
||||
[`PathSegment`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/hir/struct.PathSegment.html
|
||||
[sym]: https://doc.rust-lang.org/stable/nightly-rustc/clippy_utils/macro.sym.html
|
|
@ -9,16 +9,12 @@ accessed by the `SPEEDTEST` (and `SPEEDTEST_*`) environment variables.
|
|||
To do a simple speed test of a lint (e.g. `allow_attributes`), use this command.
|
||||
|
||||
```sh
|
||||
$ SPEEDTEST=ui TESTNAME="allow_attributes" cargo uitest -- --nocapture
|
||||
$ SPEEDTEST=ui TESTNAME="allow_attributes" cargo uitest
|
||||
```
|
||||
|
||||
This will test all `ui` tests (`SPEEDTEST=ui`) whose names start with `allow_attributes`. By default, `SPEEDTEST` will
|
||||
iterate your test 1000 times. But you can change this with `SPEEDTEST_ITERATIONS`.
|
||||
|
||||
```sh
|
||||
$ SPEEDTEST=toml SPEEDTEST_ITERATIONS=100 TESTNAME="semicolon_block" cargo uitest -- --nocapture
|
||||
$ SPEEDTEST=toml SPEEDTEST_ITERATIONS=100 TESTNAME="semicolon_block" cargo uitest
|
||||
```
|
||||
|
||||
> **WARNING**: Be sure to use `-- --nocapture` at the end of the command to see the average test time. If you don't
|
||||
> use `-- --nocapture` (e.g. `SPEEDTEST=ui` `TESTNAME="let_underscore_untyped" cargo uitest -- --nocapture`), this
|
||||
> will not show up.
|
||||
|
|
|
@ -690,7 +690,6 @@ fn gen_deprecated_lints_test(lints: &[DeprecatedLint]) -> String {
|
|||
fn gen_renamed_lints_test(lints: &[RenamedLint]) -> String {
|
||||
let mut seen_lints = HashSet::new();
|
||||
let mut res: String = GENERATED_FILE_COMMENT.into();
|
||||
res.push_str("//@run-rustfix\n\n");
|
||||
for lint in lints {
|
||||
if seen_lints.insert(&lint.new_name) {
|
||||
writeln!(res, "#![allow({})]", lint.new_name).unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "clippy_lints"
|
||||
version = "0.1.73"
|
||||
version = "0.1.74"
|
||||
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
|
||||
repository = "https://github.com/rust-lang/rust-clippy"
|
||||
readme = "README.md"
|
||||
|
|
|
@ -6,7 +6,11 @@ use clippy_utils::macros::{is_panic, macro_backtrace};
|
|||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::{AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
|
||||
use rustc_ast::token::{Token, TokenKind};
|
||||
use rustc_ast::tokenstream::TokenTree;
|
||||
use rustc_ast::{
|
||||
AttrArgs, AttrArgsEq, AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem,
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{
|
||||
Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
|
||||
|
@ -339,6 +343,41 @@ declare_clippy_lint! {
|
|||
"ensures that all `allow` and `expect` attributes have a reason"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for `#[should_panic]` attributes without specifying the expected panic message.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// The expected panic message should be specified to ensure that the test is actually
|
||||
/// panicking with the expected message, and not another unrelated panic.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// fn random() -> i32 { 0 }
|
||||
///
|
||||
/// #[should_panic]
|
||||
/// #[test]
|
||||
/// fn my_test() {
|
||||
/// let _ = 1 / random();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// fn random() -> i32 { 0 }
|
||||
///
|
||||
/// #[should_panic = "attempt to divide by zero"]
|
||||
/// #[test]
|
||||
/// fn my_test() {
|
||||
/// let _ = 1 / random();
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.73.0"]
|
||||
pub SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
pedantic,
|
||||
"ensures that all `should_panic` attributes specify its expected panic message"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for `any` and `all` combinators in `cfg` with only one condition.
|
||||
|
@ -395,6 +434,7 @@ declare_lint_pass!(Attributes => [
|
|||
DEPRECATED_SEMVER,
|
||||
USELESS_ATTRIBUTE,
|
||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||
|
@ -442,6 +482,9 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
|
|||
}
|
||||
}
|
||||
}
|
||||
if attr.has_name(sym::should_panic) {
|
||||
check_should_panic_reason(cx, attr);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
|
@ -550,6 +593,35 @@ fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<Symbol> {
|
|||
None
|
||||
}
|
||||
|
||||
fn check_should_panic_reason(cx: &LateContext<'_>, attr: &Attribute) {
|
||||
if let AttrKind::Normal(normal_attr) = &attr.kind {
|
||||
if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args {
|
||||
// `#[should_panic = ".."]` found, good
|
||||
return;
|
||||
}
|
||||
|
||||
if let AttrArgs::Delimited(args) = &normal_attr.item.args
|
||||
&& let mut tt_iter = args.tokens.trees()
|
||||
&& let Some(TokenTree::Token(Token { kind: TokenKind::Ident(sym::expected, _), .. }, _)) = tt_iter.next()
|
||||
&& let Some(TokenTree::Token(Token { kind: TokenKind::Eq, .. }, _)) = tt_iter.next()
|
||||
&& let Some(TokenTree::Token(Token { kind: TokenKind::Literal(_), .. }, _)) = tt_iter.next()
|
||||
{
|
||||
// `#[should_panic(expected = "..")]` found, good
|
||||
return;
|
||||
}
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
attr.span,
|
||||
"#[should_panic] attribute without a reason",
|
||||
"consider specifying the expected panic",
|
||||
r#"#[should_panic(expected = /* panic message */)]"#.into(),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) {
|
||||
for lint in items {
|
||||
if let Some(lint_name) = extract_clippy_lint(lint) {
|
||||
|
|
|
@ -5,6 +5,7 @@ use rustc_hir::{Expr, ExprKind, GenericArg};
|
|||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::CAST_PTR_ALIGNMENT;
|
||||
|
||||
|
@ -76,13 +77,14 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
|||
ExprKind::Call(func, [arg, ..]) if arg.hir_id == e.hir_id => {
|
||||
static PATHS: &[&[&str]] = &[
|
||||
paths::PTR_READ_UNALIGNED.as_slice(),
|
||||
paths::PTR_WRITE_UNALIGNED.as_slice(),
|
||||
paths::PTR_UNALIGNED_VOLATILE_LOAD.as_slice(),
|
||||
paths::PTR_UNALIGNED_VOLATILE_STORE.as_slice(),
|
||||
];
|
||||
|
||||
if let ExprKind::Path(path) = &func.kind
|
||||
&& let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
|
||||
&& match_any_def_paths(cx, def_id, PATHS).is_some()
|
||||
&& (match_any_def_paths(cx, def_id, PATHS).is_some()
|
||||
|| cx.tcx.is_diagnostic_item(sym::ptr_write_unaligned, def_id))
|
||||
{
|
||||
true
|
||||
} else {
|
||||
|
|
|
@ -418,7 +418,7 @@ declare_clippy_lint! {
|
|||
/// let mut_ptr = ptr.cast_mut();
|
||||
/// let ptr = mut_ptr.cast_const();
|
||||
/// ```
|
||||
#[clippy::version = "1.71.0"]
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub PTR_CAST_CONSTNESS,
|
||||
pedantic,
|
||||
"casting using `as` from and to raw pointers to change constness when specialized methods apply"
|
||||
|
|
|
@ -58,6 +58,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::attrs::MAYBE_MISUSED_CFG_INFO,
|
||||
crate::attrs::MISMATCHED_TARGET_OS_INFO,
|
||||
crate::attrs::NON_MINIMAL_CFG_INFO,
|
||||
crate::attrs::SHOULD_PANIC_WITHOUT_EXPECT_INFO,
|
||||
crate::attrs::USELESS_ATTRIBUTE_INFO,
|
||||
crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO,
|
||||
crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO,
|
||||
|
@ -208,6 +209,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::implicit_return::IMPLICIT_RETURN_INFO,
|
||||
crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
|
||||
crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO,
|
||||
crate::implied_bounds_in_impls::IMPLIED_BOUNDS_IN_IMPLS_INFO,
|
||||
crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO,
|
||||
crate::incorrect_impls::INCORRECT_CLONE_IMPL_ON_COPY_TYPE_INFO,
|
||||
crate::incorrect_impls::INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE_INFO,
|
||||
|
@ -578,6 +580,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::reference::DEREF_ADDROF_INFO,
|
||||
crate::regex::INVALID_REGEX_INFO,
|
||||
crate::regex::TRIVIAL_REGEX_INFO,
|
||||
crate::reserve_after_initialization::RESERVE_AFTER_INITIALIZATION_INFO,
|
||||
crate::return_self_not_must_use::RETURN_SELF_NOT_MUST_USE_INFO,
|
||||
crate::returns::LET_AND_RETURN_INFO,
|
||||
crate::returns::NEEDLESS_RETURN_INFO,
|
||||
|
|
|
@ -21,7 +21,7 @@ declare_clippy_lint! {
|
|||
/// let _x = 2i32.to_ne_bytes();
|
||||
/// let _y = 2i64.to_ne_bytes();
|
||||
/// ```
|
||||
#[clippy::version = "1.71.0"]
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub HOST_ENDIAN_BYTES,
|
||||
restriction,
|
||||
"disallows usage of the `to_ne_bytes` method"
|
||||
|
@ -40,7 +40,7 @@ declare_clippy_lint! {
|
|||
/// let _x = 2i32.to_le_bytes();
|
||||
/// let _y = 2i64.to_le_bytes();
|
||||
/// ```
|
||||
#[clippy::version = "1.71.0"]
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub LITTLE_ENDIAN_BYTES,
|
||||
restriction,
|
||||
"disallows usage of the `to_le_bytes` method"
|
||||
|
@ -59,7 +59,7 @@ declare_clippy_lint! {
|
|||
/// let _x = 2i32.to_be_bytes();
|
||||
/// let _y = 2i64.to_be_bytes();
|
||||
/// ```
|
||||
#[clippy::version = "1.71.0"]
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub BIG_ENDIAN_BYTES,
|
||||
restriction,
|
||||
"disallows usage of the `to_be_bytes` method"
|
||||
|
|
|
@ -56,7 +56,7 @@ declare_clippy_lint! {
|
|||
/// // lib.rs
|
||||
/// pub mod a;
|
||||
/// ```
|
||||
#[clippy::version = "1.70.0"]
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub EXCESSIVE_NESTING,
|
||||
complexity,
|
||||
"checks for blocks nested beyond a certain threshold"
|
||||
|
|
202
clippy_lints/src/implied_bounds_in_impls.rs
Normal file
202
clippy_lints/src/implied_bounds_in_impls.rs
Normal file
|
@ -0,0 +1,202 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet;
|
||||
use rustc_errors::{Applicability, SuggestionStyle};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{
|
||||
Body, FnDecl, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind, ItemKind, TraitBoundModifier, TraitItem,
|
||||
TraitItemKind, TyKind,
|
||||
};
|
||||
use rustc_hir_analysis::hir_ty_to_ty;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{self, ClauseKind, TyCtxt};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Looks for bounds in `impl Trait` in return position that are implied by other bounds.
|
||||
/// This can happen when a trait is specified that another trait already has as a supertrait
|
||||
/// (e.g. `fn() -> impl Deref + DerefMut<Target = i32>` has an unnecessary `Deref` bound,
|
||||
/// because `Deref` is a supertrait of `DerefMut`)
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Specifying more bounds than necessary adds needless complexity for the reader.
|
||||
///
|
||||
/// ### Limitations
|
||||
/// This lint does not check for implied bounds transitively. Meaning that
|
||||
/// it does't check for implied bounds from supertraits of supertraits
|
||||
/// (e.g. `trait A {} trait B: A {} trait C: B {}`, then having an `fn() -> impl A + C`)
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// # use std::ops::{Deref,DerefMut};
|
||||
/// fn f() -> impl Deref<Target = i32> + DerefMut<Target = i32> {
|
||||
/// // ^^^^^^^^^^^^^^^^^^^ unnecessary bound, already implied by the `DerefMut` trait bound
|
||||
/// Box::new(123)
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// # use std::ops::{Deref,DerefMut};
|
||||
/// fn f() -> impl DerefMut<Target = i32> {
|
||||
/// Box::new(123)
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.73.0"]
|
||||
pub IMPLIED_BOUNDS_IN_IMPLS,
|
||||
complexity,
|
||||
"specifying bounds that are implied by other bounds in `impl Trait` type"
|
||||
}
|
||||
declare_lint_pass!(ImpliedBoundsInImpls => [IMPLIED_BOUNDS_IN_IMPLS]);
|
||||
|
||||
/// This function tries to, for all type parameters in a supertype predicate `GenericTrait<U>`,
|
||||
/// check if the substituted type in the implied-by bound matches with what's subtituted in the
|
||||
/// implied type.
|
||||
///
|
||||
/// Consider this example.
|
||||
/// ```rust,ignore
|
||||
/// trait GenericTrait<T> {}
|
||||
/// trait GenericSubTrait<T, U, V>: GenericTrait<U> {}
|
||||
/// ^ trait_predicate_args: [Self#0, U#2]
|
||||
/// impl GenericTrait<i32> for () {}
|
||||
/// impl GenericSubTrait<(), i32, ()> for () {}
|
||||
/// impl GenericSubTrait<(), [u8; 8], ()> for () {}
|
||||
///
|
||||
/// fn f() -> impl GenericTrait<i32> + GenericSubTrait<(), [u8; 8], ()> {
|
||||
/// ^^^ implied_args ^^^^^^^^^^^^^^^ implied_by_args
|
||||
/// (we are interested in `[u8; 8]` specifically, as that
|
||||
/// is what `U` in `GenericTrait<U>` is substituted with)
|
||||
/// ()
|
||||
/// }
|
||||
/// ```
|
||||
/// Here i32 != [u8; 8], so this will return false.
|
||||
fn is_same_generics(
|
||||
tcx: TyCtxt<'_>,
|
||||
trait_predicate_args: &[ty::GenericArg<'_>],
|
||||
implied_by_args: &[GenericArg<'_>],
|
||||
implied_args: &[GenericArg<'_>],
|
||||
) -> bool {
|
||||
trait_predicate_args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.skip(1) // skip `Self` implicit arg
|
||||
.all(|(arg_index, arg)| {
|
||||
if let Some(ty) = arg.as_type()
|
||||
&& let &ty::Param(ty::ParamTy{ index, .. }) = ty.kind()
|
||||
// Since `trait_predicate_args` and type params in traits start with `Self=0`
|
||||
// and generic argument lists `GenericTrait<i32>` don't have `Self`,
|
||||
// we need to subtract 1 from the index.
|
||||
&& let GenericArg::Type(ty_a) = implied_by_args[index as usize - 1]
|
||||
&& let GenericArg::Type(ty_b) = implied_args[arg_index - 1]
|
||||
{
|
||||
hir_ty_to_ty(tcx, ty_a) == hir_ty_to_ty(tcx, ty_b)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
|
||||
if let FnRetTy::Return(ty) = decl.output
|
||||
&&let TyKind::OpaqueDef(item_id, ..) = ty.kind
|
||||
&& let item = cx.tcx.hir().item(item_id)
|
||||
&& let ItemKind::OpaqueTy(opaque_ty) = item.kind
|
||||
// Very often there is only a single bound, e.g. `impl Deref<..>`, in which case
|
||||
// we can avoid doing a bunch of stuff unnecessarily.
|
||||
&& opaque_ty.bounds.len() > 1
|
||||
{
|
||||
// Get all the (implied) trait predicates in the bounds.
|
||||
// For `impl Deref + DerefMut` this will contain [`Deref`].
|
||||
// The implied `Deref` comes from `DerefMut` because `trait DerefMut: Deref {}`.
|
||||
// N.B. (G)ATs are fine to disregard, because they must be the same for all of its supertraits.
|
||||
// Example:
|
||||
// `impl Deref<Target = i32> + DerefMut<Target = u32>` is not allowed.
|
||||
// `DerefMut::Target` needs to match `Deref::Target`.
|
||||
let implied_bounds: Vec<_> = opaque_ty.bounds.iter().filter_map(|bound| {
|
||||
if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound
|
||||
&& let [.., path] = poly_trait.trait_ref.path.segments
|
||||
&& poly_trait.bound_generic_params.is_empty()
|
||||
&& let Some(trait_def_id) = path.res.opt_def_id()
|
||||
&& let predicates = cx.tcx.super_predicates_of(trait_def_id).predicates
|
||||
&& !predicates.is_empty() // If the trait has no supertrait, there is nothing to add.
|
||||
{
|
||||
Some((bound.span(), path.args.map_or([].as_slice(), |a| a.args), predicates))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect();
|
||||
|
||||
// Lint all bounds in the `impl Trait` type that are also in the `implied_bounds` vec.
|
||||
// This involves some extra logic when generic arguments are present, since
|
||||
// simply comparing trait `DefId`s won't be enough. We also need to compare the generics.
|
||||
for (index, bound) in opaque_ty.bounds.iter().enumerate() {
|
||||
if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound
|
||||
&& let [.., path] = poly_trait.trait_ref.path.segments
|
||||
&& let implied_args = path.args.map_or([].as_slice(), |a| a.args)
|
||||
&& let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id()
|
||||
&& let Some(implied_by_span) = implied_bounds.iter().find_map(|&(span, implied_by_args, preds)| {
|
||||
preds.iter().find_map(|(clause, _)| {
|
||||
if let ClauseKind::Trait(tr) = clause.kind().skip_binder()
|
||||
&& tr.def_id() == def_id
|
||||
&& is_same_generics(cx.tcx, tr.trait_ref.args, implied_by_args, implied_args)
|
||||
{
|
||||
Some(span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
{
|
||||
let implied_by = snippet(cx, implied_by_span, "..");
|
||||
span_lint_and_then(
|
||||
cx, IMPLIED_BOUNDS_IN_IMPLS,
|
||||
poly_trait.span,
|
||||
&format!("this bound is already specified as the supertrait of `{implied_by}`"),
|
||||
|diag| {
|
||||
// If we suggest removing a bound, we may also need extend the span
|
||||
// to include the `+` token, so we don't end up with something like `impl + B`
|
||||
|
||||
let implied_span_extended = if let Some(next_bound) = opaque_ty.bounds.get(index + 1) {
|
||||
poly_trait.span.to(next_bound.span().shrink_to_lo())
|
||||
} else {
|
||||
poly_trait.span
|
||||
};
|
||||
|
||||
diag.span_suggestion_with_style(
|
||||
implied_span_extended,
|
||||
"try removing this bound",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
SuggestionStyle::ShowAlways
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LateLintPass<'_> for ImpliedBoundsInImpls {
|
||||
fn check_fn(
|
||||
&mut self,
|
||||
cx: &LateContext<'_>,
|
||||
_: FnKind<'_>,
|
||||
decl: &FnDecl<'_>,
|
||||
_: &Body<'_>,
|
||||
_: Span,
|
||||
_: LocalDefId,
|
||||
) {
|
||||
check(cx, decl);
|
||||
}
|
||||
fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
|
||||
if let TraitItemKind::Fn(sig, ..) = &item.kind {
|
||||
check(cx, sig.decl);
|
||||
}
|
||||
}
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &ImplItem<'_>) {
|
||||
if let ImplItemKind::Fn(sig, ..) = &item.kind {
|
||||
check(cx, sig.decl);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -72,7 +72,7 @@ declare_clippy_lint! {
|
|||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.71.0"]
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub LARGE_STACK_FRAMES,
|
||||
nursery,
|
||||
"checks for functions that allocate a lot of stack space"
|
||||
|
|
|
@ -152,6 +152,7 @@ mod implicit_hasher;
|
|||
mod implicit_return;
|
||||
mod implicit_saturating_add;
|
||||
mod implicit_saturating_sub;
|
||||
mod implied_bounds_in_impls;
|
||||
mod inconsistent_struct_constructor;
|
||||
mod incorrect_impls;
|
||||
mod index_refutable_slice;
|
||||
|
@ -285,6 +286,7 @@ mod ref_option_ref;
|
|||
mod ref_patterns;
|
||||
mod reference;
|
||||
mod regex;
|
||||
mod reserve_after_initialization;
|
||||
mod return_self_not_must_use;
|
||||
mod returns;
|
||||
mod same_name_method;
|
||||
|
@ -1095,6 +1097,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
});
|
||||
store.register_late_pass(|_| Box::new(redundant_locals::RedundantLocals));
|
||||
store.register_late_pass(|_| Box::new(ignored_unit_patterns::IgnoredUnitPatterns));
|
||||
store.register_late_pass(|_| Box::<reserve_after_initialization::ReserveAfterInitialization>::default());
|
||||
store.register_late_pass(|_| Box::new(implied_bounds_in_impls::ImpliedBoundsInImpls));
|
||||
// add lints here, do not remove this comment, it's used in `new_lint`
|
||||
}
|
||||
|
||||
|
|
|
@ -12,13 +12,15 @@ use rustc_semver::RustcVersion;
|
|||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
const ACCEPTABLE_METHODS: [&[&str]; 4] = [
|
||||
const ACCEPTABLE_METHODS: [&[&str]; 5] = [
|
||||
&paths::BINARYHEAP_ITER,
|
||||
&paths::HASHSET_ITER,
|
||||
&paths::BTREESET_ITER,
|
||||
&paths::SLICE_INTO,
|
||||
&paths::VEC_DEQUE_ITER,
|
||||
];
|
||||
const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 6] = [
|
||||
const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 7] = [
|
||||
(sym::BinaryHeap, Some(msrvs::BINARY_HEAP_RETAIN)),
|
||||
(sym::BTreeSet, Some(msrvs::BTREE_SET_RETAIN)),
|
||||
(sym::BTreeMap, Some(msrvs::BTREE_MAP_RETAIN)),
|
||||
(sym::HashSet, Some(msrvs::HASH_SET_RETAIN)),
|
||||
|
|
|
@ -17,6 +17,7 @@ pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv
|
|||
let return_type = cx.typeck_results().expr_ty(expr);
|
||||
let input_type = cx.typeck_results().expr_ty(recv);
|
||||
let (input_type, ref_count) = peel_mid_ty_refs(input_type);
|
||||
if !(ref_count > 0 && is_diag_trait_item(cx, method_def_id, sym::ToOwned));
|
||||
if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did()));
|
||||
if return_type == input_type;
|
||||
if let Some(clone_trait) = cx.tcx.lang_items().clone_trait();
|
||||
|
|
|
@ -1,21 +1,45 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::{implements_trait, is_copy};
|
||||
use rustc_ast::BindingAnnotation;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Expr;
|
||||
use rustc_hir::{Body, Expr, ExprKind, HirId, HirIdSet, PatKind};
|
||||
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::mir::{FakeReadCause, Mutability};
|
||||
use rustc_middle::ty::{self, BorrowKind};
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::ITER_OVEREAGER_CLONED;
|
||||
use crate::redundant_clone::REDUNDANT_CLONE;
|
||||
use crate::rustc_trait_selection::infer::TyCtxtInferExt;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) enum Op<'a> {
|
||||
// rm `.cloned()`
|
||||
// e.g. `count`
|
||||
RmCloned,
|
||||
|
||||
// rm `.cloned()`
|
||||
// e.g. `map` `for_each`
|
||||
NeedlessMove(&'a str, &'a Expr<'a>),
|
||||
|
||||
// later `.cloned()`
|
||||
// and add `&` to the parameter of closure parameter
|
||||
// e.g. `find` `filter`
|
||||
FixClosure(&'a str, &'a Expr<'a>),
|
||||
|
||||
// later `.cloned()`
|
||||
// e.g. `skip` `take`
|
||||
LaterCloned,
|
||||
}
|
||||
|
||||
pub(super) fn check<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
expr: &'tcx Expr<'_>,
|
||||
cloned_call: &'tcx Expr<'_>,
|
||||
cloned_recv: &'tcx Expr<'_>,
|
||||
is_count: bool,
|
||||
op: Op<'tcx>,
|
||||
needs_into_iter: bool,
|
||||
) {
|
||||
let typeck = cx.typeck_results();
|
||||
|
@ -35,10 +59,47 @@ pub(super) fn check<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
let (lint, msg, trailing_clone) = if is_count {
|
||||
(REDUNDANT_CLONE, "unneeded cloning of iterator items", "")
|
||||
} else {
|
||||
(ITER_OVEREAGER_CLONED, "unnecessarily eager cloning of iterator items", ".cloned()")
|
||||
if let Op::NeedlessMove(_, expr) = op {
|
||||
let rustc_hir::ExprKind::Closure(closure) = expr.kind else { return } ;
|
||||
let body @ Body { params: [p], .. } = cx.tcx.hir().body(closure.body) else { return };
|
||||
let mut delegate = MoveDelegate {used_move : HirIdSet::default()};
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
|
||||
ExprUseVisitor::new(
|
||||
&mut delegate,
|
||||
&infcx,
|
||||
closure.body.hir_id.owner.def_id,
|
||||
cx.param_env,
|
||||
cx.typeck_results(),
|
||||
)
|
||||
.consume_body(body);
|
||||
|
||||
let mut to_be_discarded = false;
|
||||
|
||||
p.pat.walk(|it| {
|
||||
if delegate.used_move.contains(&it.hir_id){
|
||||
to_be_discarded = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
match it.kind {
|
||||
PatKind::Binding(BindingAnnotation(_, Mutability::Mut), _, _, _)
|
||||
| PatKind::Ref(_, Mutability::Mut) => {
|
||||
to_be_discarded = true;
|
||||
false
|
||||
}
|
||||
_ => { true }
|
||||
}
|
||||
});
|
||||
|
||||
if to_be_discarded {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let (lint, msg, trailing_clone) = match op {
|
||||
Op::RmCloned | Op::NeedlessMove(_, _) => (REDUNDANT_CLONE, "unneeded cloning of iterator items", ""),
|
||||
Op::LaterCloned | Op::FixClosure(_, _) => (ITER_OVEREAGER_CLONED, "unnecessarily eager cloning of iterator items", ".cloned()"),
|
||||
};
|
||||
|
||||
span_lint_and_then(
|
||||
|
@ -47,13 +108,54 @@ pub(super) fn check<'tcx>(
|
|||
expr.span,
|
||||
msg,
|
||||
|diag| {
|
||||
let method_span = expr.span.with_lo(cloned_call.span.hi());
|
||||
if let Some(mut snip) = snippet_opt(cx, method_span) {
|
||||
snip.push_str(trailing_clone);
|
||||
let replace_span = expr.span.with_lo(cloned_recv.span.hi());
|
||||
diag.span_suggestion(replace_span, "try", snip, Applicability::MachineApplicable);
|
||||
match op {
|
||||
Op::RmCloned | Op::LaterCloned => {
|
||||
let method_span = expr.span.with_lo(cloned_call.span.hi());
|
||||
if let Some(mut snip) = snippet_opt(cx, method_span) {
|
||||
snip.push_str(trailing_clone);
|
||||
let replace_span = expr.span.with_lo(cloned_recv.span.hi());
|
||||
diag.span_suggestion(replace_span, "try", snip, Applicability::MachineApplicable);
|
||||
}
|
||||
}
|
||||
Op::FixClosure(name, predicate_expr) => {
|
||||
if let Some(predicate) = snippet_opt(cx, predicate_expr.span) {
|
||||
let new_closure = if let ExprKind::Closure(_) = predicate_expr.kind {
|
||||
predicate.replacen('|', "|&", 1)
|
||||
} else {
|
||||
format!("|&x| {predicate}(x)")
|
||||
};
|
||||
let snip = format!(".{name}({new_closure}).cloned()" );
|
||||
let replace_span = expr.span.with_lo(cloned_recv.span.hi());
|
||||
diag.span_suggestion(replace_span, "try", snip, Applicability::MachineApplicable);
|
||||
}
|
||||
}
|
||||
Op::NeedlessMove(_, _) => {
|
||||
let method_span = expr.span.with_lo(cloned_call.span.hi());
|
||||
if let Some(snip) = snippet_opt(cx, method_span) {
|
||||
let replace_span = expr.span.with_lo(cloned_recv.span.hi());
|
||||
diag.span_suggestion(replace_span, "try", snip, Applicability::MaybeIncorrect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
struct MoveDelegate {
|
||||
used_move: HirIdSet,
|
||||
}
|
||||
|
||||
impl<'tcx> Delegate<'tcx> for MoveDelegate {
|
||||
fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, _: HirId) {
|
||||
if let PlaceBase::Local(l) = place_with_id.place.base {
|
||||
self.used_move.insert(l);
|
||||
}
|
||||
}
|
||||
|
||||
fn borrow(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId, _: BorrowKind) {}
|
||||
|
||||
fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
|
||||
}
|
||||
|
|
|
@ -301,7 +301,7 @@ declare_clippy_lint! {
|
|||
/// let val2 = 1;
|
||||
/// let val3 = 1;
|
||||
/// ```
|
||||
#[clippy::version = "1.69.0"]
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub UNNECESSARY_LITERAL_UNWRAP,
|
||||
complexity,
|
||||
"using `unwrap()` related calls on `Result` and `Option` constructors"
|
||||
|
@ -3328,7 +3328,7 @@ declare_clippy_lint! {
|
|||
/// mem::take(v)
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.71.0"]
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub DRAIN_COLLECT,
|
||||
perf,
|
||||
"calling `.drain(..).collect()` to move all elements into a new collection"
|
||||
|
@ -3919,7 +3919,7 @@ impl Methods {
|
|||
}
|
||||
},
|
||||
("count", []) if is_trait_method(cx, expr, sym::Iterator) => match method_call(recv) {
|
||||
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, true, false),
|
||||
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::RmCloned , false),
|
||||
Some((name2 @ ("into_iter" | "iter" | "iter_mut"), recv2, [], _, _)) => {
|
||||
iter_count::check(cx, expr, recv2, name2);
|
||||
},
|
||||
|
@ -3973,6 +3973,13 @@ impl Methods {
|
|||
string_extend_chars::check(cx, expr, recv, arg);
|
||||
extend_with_drain::check(cx, expr, recv, arg);
|
||||
},
|
||||
(name @ ( "filter" | "find" ) , [arg]) => {
|
||||
if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
|
||||
// if `arg` has side-effect, the semantic will change
|
||||
iter_overeager_cloned::check(cx, expr, recv, recv2,
|
||||
iter_overeager_cloned::Op::FixClosure(name, arg), false);
|
||||
}
|
||||
}
|
||||
("filter_map", [arg]) => {
|
||||
unnecessary_filter_map::check(cx, expr, arg, name);
|
||||
filter_map_bool_then::check(cx, expr, arg, call_span);
|
||||
|
@ -3987,16 +3994,18 @@ impl Methods {
|
|||
},
|
||||
("flatten", []) => match method_call(recv) {
|
||||
Some(("map", recv, [map_arg], map_span, _)) => map_flatten::check(cx, expr, recv, map_arg, map_span),
|
||||
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true),
|
||||
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::LaterCloned , true),
|
||||
_ => {},
|
||||
},
|
||||
("fold", [init, acc]) => {
|
||||
manual_try_fold::check(cx, expr, init, acc, call_span, &self.msrv);
|
||||
unnecessary_fold::check(cx, expr, init, acc, span);
|
||||
},
|
||||
("for_each", [_]) => {
|
||||
if let Some(("inspect", _, [_], span2, _)) = method_call(recv) {
|
||||
inspect_for_each::check(cx, expr, span2);
|
||||
("for_each", [arg]) => {
|
||||
match method_call(recv) {
|
||||
Some(("inspect", _, [_], span2, _)) => inspect_for_each::check(cx, expr, span2),
|
||||
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::NeedlessMove(name, arg), false),
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
("get", [arg]) => {
|
||||
|
@ -4021,7 +4030,8 @@ impl Methods {
|
|||
},
|
||||
("last", []) => {
|
||||
if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
|
||||
iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
|
||||
iter_overeager_cloned::check(cx, expr, recv, recv2,
|
||||
iter_overeager_cloned::Op::LaterCloned , false);
|
||||
}
|
||||
},
|
||||
("lock", []) => {
|
||||
|
@ -4030,8 +4040,10 @@ impl Methods {
|
|||
(name @ ("map" | "map_err"), [m_arg]) => {
|
||||
if name == "map" {
|
||||
map_clone::check(cx, expr, recv, m_arg, &self.msrv);
|
||||
if let Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) = method_call(recv) {
|
||||
iter_kv_map::check(cx, map_name, expr, recv2, m_arg);
|
||||
match method_call(recv) {
|
||||
Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) => iter_kv_map::check(cx, map_name, expr, recv2, m_arg),
|
||||
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::NeedlessMove(name, m_arg), false),
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
map_err_ignore::check(cx, expr, m_arg);
|
||||
|
@ -4058,7 +4070,7 @@ impl Methods {
|
|||
("next", []) => {
|
||||
if let Some((name2, recv2, args2, _, _)) = method_call(recv) {
|
||||
match (name2, args2) {
|
||||
("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
|
||||
("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::LaterCloned, false),
|
||||
("filter", [arg]) => filter_next::check(cx, expr, recv2, arg),
|
||||
("filter_map", [arg]) => filter_map_next::check(cx, expr, recv2, arg, &self.msrv),
|
||||
("iter", []) => iter_next_slice::check(cx, expr, recv2),
|
||||
|
@ -4071,7 +4083,7 @@ impl Methods {
|
|||
},
|
||||
("nth", [n_arg]) => match method_call(recv) {
|
||||
Some(("bytes", recv2, [], _, _)) => bytes_nth::check(cx, expr, recv2, n_arg),
|
||||
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
|
||||
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::LaterCloned , false),
|
||||
Some(("iter", recv2, [], _, _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
|
||||
Some(("iter_mut", recv2, [], _, _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
|
||||
_ => iter_nth_zero::check(cx, expr, recv, n_arg),
|
||||
|
@ -4126,7 +4138,8 @@ impl Methods {
|
|||
iter_skip_zero::check(cx, expr, arg);
|
||||
|
||||
if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
|
||||
iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
|
||||
iter_overeager_cloned::check(cx, expr, recv, recv2,
|
||||
iter_overeager_cloned::Op::LaterCloned , false);
|
||||
}
|
||||
}
|
||||
("sort", []) => {
|
||||
|
@ -4152,7 +4165,8 @@ impl Methods {
|
|||
("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
|
||||
("take", [_arg]) => {
|
||||
if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
|
||||
iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
|
||||
iter_overeager_cloned::check(cx, expr, recv, recv2,
|
||||
iter_overeager_cloned::Op::LaterCloned, false);
|
||||
}
|
||||
},
|
||||
("take", []) => needless_option_take::check(cx, expr, recv),
|
||||
|
|
|
@ -65,11 +65,26 @@ pub(super) fn check<'tcx>(
|
|||
};
|
||||
|
||||
let sugg = match (name, call_expr.is_some()) {
|
||||
("unwrap_or", true) | ("unwrap_or_else", false) => "unwrap_or_default",
|
||||
("or_insert", true) | ("or_insert_with", false) => "or_default",
|
||||
("unwrap_or", true) | ("unwrap_or_else", false) => sym!(unwrap_or_default),
|
||||
("or_insert", true) | ("or_insert_with", false) => sym!(or_default),
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let receiver_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs();
|
||||
let has_suggested_method = receiver_ty.ty_adt_def().is_some_and(|adt_def| {
|
||||
cx.tcx
|
||||
.inherent_impls(adt_def.did())
|
||||
.iter()
|
||||
.flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg))
|
||||
.any(|assoc| {
|
||||
assoc.fn_has_self_parameter
|
||||
&& cx.tcx.fn_sig(assoc.def_id).skip_binder().inputs().skip_binder().len() == 1
|
||||
})
|
||||
});
|
||||
if !has_suggested_method {
|
||||
return false;
|
||||
}
|
||||
|
||||
// needs to target Default::default in particular or be *::new and have a Default impl
|
||||
// available
|
||||
if (is_new(fun) && output_type_implements_default(fun))
|
||||
|
|
|
@ -27,7 +27,7 @@ declare_clippy_lint! {
|
|||
/// println!("Check successful!");
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.71.0"]
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub NEEDLESS_ELSE,
|
||||
style,
|
||||
"empty else branch"
|
||||
|
|
|
@ -130,6 +130,11 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
|
|||
}
|
||||
|
||||
let generics_sugg = snippet(cx, generics.span, "");
|
||||
let where_clause_sugg = if generics.has_where_clause_predicates {
|
||||
format!("\n{}\n", snippet(cx, generics.where_clause_span, ""))
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let self_ty_fmt = self_ty.to_string();
|
||||
let self_type_snip = snippet(cx, impl_self_ty.span, &self_ty_fmt);
|
||||
span_lint_hir_and_then(
|
||||
|
@ -145,8 +150,12 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
|
|||
cx,
|
||||
item.span,
|
||||
"try adding this",
|
||||
&create_new_without_default_suggest_msg(&self_type_snip, &generics_sugg),
|
||||
Applicability::MaybeIncorrect,
|
||||
&create_new_without_default_suggest_msg(
|
||||
&self_type_snip,
|
||||
&generics_sugg,
|
||||
&where_clause_sugg
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -159,10 +168,14 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
|
|||
}
|
||||
}
|
||||
|
||||
fn create_new_without_default_suggest_msg(self_type_snip: &str, generics_sugg: &str) -> String {
|
||||
fn create_new_without_default_suggest_msg(
|
||||
self_type_snip: &str,
|
||||
generics_sugg: &str,
|
||||
where_clause_sugg: &str,
|
||||
) -> String {
|
||||
#[rustfmt::skip]
|
||||
format!(
|
||||
"impl{generics_sugg} Default for {self_type_snip} {{
|
||||
"impl{generics_sugg} Default for {self_type_snip}{where_clause_sugg} {{
|
||||
fn default() -> Self {{
|
||||
Self::new()
|
||||
}}
|
||||
|
|
|
@ -278,7 +278,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
|
|||
|
||||
fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
// (fn_path, arg_indices) - `arg_indices` are the `arg` positions where null would cause U.B.
|
||||
const INVALID_NULL_PTR_USAGE_TABLE: [(&[&str], &[usize]); 16] = [
|
||||
const INVALID_NULL_PTR_USAGE_TABLE: [(&[&str], &[usize]); 13] = [
|
||||
(&paths::SLICE_FROM_RAW_PARTS, &[0]),
|
||||
(&paths::SLICE_FROM_RAW_PARTS_MUT, &[0]),
|
||||
(&paths::PTR_COPY, &[0, 1]),
|
||||
|
@ -291,20 +291,33 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
|||
(&paths::PTR_SLICE_FROM_RAW_PARTS_MUT, &[0]),
|
||||
(&paths::PTR_SWAP, &[0, 1]),
|
||||
(&paths::PTR_SWAP_NONOVERLAPPING, &[0, 1]),
|
||||
(&paths::PTR_WRITE, &[0]),
|
||||
(&paths::PTR_WRITE_UNALIGNED, &[0]),
|
||||
(&paths::PTR_WRITE_VOLATILE, &[0]),
|
||||
(&paths::PTR_WRITE_BYTES, &[0]),
|
||||
];
|
||||
let invalid_null_ptr_usage_table_diag_items: [(Option<DefId>, &[usize]); 3] = [
|
||||
(cx.tcx.get_diagnostic_item(sym::ptr_write), &[0]),
|
||||
(cx.tcx.get_diagnostic_item(sym::ptr_write_unaligned), &[0]),
|
||||
(cx.tcx.get_diagnostic_item(sym::ptr_write_volatile), &[0]),
|
||||
];
|
||||
|
||||
if_chain! {
|
||||
if let ExprKind::Call(fun, args) = expr.kind;
|
||||
if let ExprKind::Path(ref qpath) = fun.kind;
|
||||
if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
|
||||
let fun_def_path = cx.get_def_path(fun_def_id).into_iter().map(Symbol::to_ident_string).collect::<Vec<_>>();
|
||||
if let Some(&(_, arg_indices)) = INVALID_NULL_PTR_USAGE_TABLE
|
||||
if let Some(arg_indices) = INVALID_NULL_PTR_USAGE_TABLE
|
||||
.iter()
|
||||
.find(|&&(fn_path, _)| fn_path == fun_def_path);
|
||||
.find_map(|&(fn_path, indices)| if fn_path == fun_def_path { Some(indices) } else { None })
|
||||
.or_else(|| {
|
||||
invalid_null_ptr_usage_table_diag_items
|
||||
.iter()
|
||||
.find_map(|&(def_id, indices)| {
|
||||
if def_id == Some(fun_def_id) {
|
||||
Some(indices)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
});
|
||||
then {
|
||||
for &arg_idx in arg_indices {
|
||||
if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg)) {
|
||||
|
|
|
@ -31,7 +31,7 @@ declare_clippy_lint! {
|
|||
/// ```rust
|
||||
/// let foo = String::new();
|
||||
/// ```
|
||||
#[clippy::version = "1.70.0"]
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub REDUNDANT_TYPE_ANNOTATIONS,
|
||||
restriction,
|
||||
"warns about needless / redundant type annotations."
|
||||
|
|
134
clippy_lints/src/reserve_after_initialization.rs
Normal file
134
clippy_lints/src/reserve_after_initialization.rs
Normal file
|
@ -0,0 +1,134 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::{is_from_proc_macro, path_to_local_id};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Local, PatKind, QPath, Stmt, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Informs the user about a more concise way to create a vector with a known capacity.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// The `Vec::with_capacity` constructor is less complex.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// let mut v: Vec<usize> = vec![];
|
||||
/// v.reserve(10);
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// let mut v: Vec<usize> = Vec::with_capacity(10);
|
||||
/// ```
|
||||
#[clippy::version = "1.73.0"]
|
||||
pub RESERVE_AFTER_INITIALIZATION,
|
||||
complexity,
|
||||
"`reserve` called immediatly after `Vec` creation"
|
||||
}
|
||||
impl_lint_pass!(ReserveAfterInitialization => [RESERVE_AFTER_INITIALIZATION]);
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ReserveAfterInitialization {
|
||||
searcher: Option<VecReserveSearcher>,
|
||||
}
|
||||
|
||||
struct VecReserveSearcher {
|
||||
local_id: HirId,
|
||||
err_span: Span,
|
||||
init_part: String,
|
||||
space_hint: String,
|
||||
}
|
||||
impl VecReserveSearcher {
|
||||
fn display_err(&self, cx: &LateContext<'_>) {
|
||||
if self.space_hint.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let s = format!("{}Vec::with_capacity({});", self.init_part, self.space_hint);
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
RESERVE_AFTER_INITIALIZATION,
|
||||
self.err_span,
|
||||
"call to `reserve` immediately after creation",
|
||||
"consider using `Vec::with_capacity(/* Space hint */)`",
|
||||
s,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for ReserveAfterInitialization {
|
||||
fn check_block(&mut self, _: &LateContext<'tcx>, _: &'tcx Block<'tcx>) {
|
||||
self.searcher = None;
|
||||
}
|
||||
|
||||
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
|
||||
if let Some(init_expr) = local.init
|
||||
&& let PatKind::Binding(BindingAnnotation::MUT, id, _, None) = local.pat.kind
|
||||
&& !in_external_macro(cx.sess(), local.span)
|
||||
&& let Some(init) = get_vec_init_kind(cx, init_expr)
|
||||
&& !matches!(init, VecInitKind::WithExprCapacity(_) | VecInitKind::WithConstCapacity(_))
|
||||
{
|
||||
self.searcher = Some(VecReserveSearcher {
|
||||
local_id: id,
|
||||
err_span: local.span,
|
||||
init_part: snippet(cx, local.span.shrink_to_lo()
|
||||
.to(init_expr.span.source_callsite().shrink_to_lo()), "..")
|
||||
.into_owned(),
|
||||
space_hint: String::new()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if self.searcher.is_none()
|
||||
&& let ExprKind::Assign(left, right, _) = expr.kind
|
||||
&& let ExprKind::Path(QPath::Resolved(None, path)) = left.kind
|
||||
&& let Res::Local(id) = path.res
|
||||
&& !in_external_macro(cx.sess(), expr.span)
|
||||
&& let Some(init) = get_vec_init_kind(cx, right)
|
||||
&& !matches!(init, VecInitKind::WithExprCapacity(_) | VecInitKind::WithConstCapacity(_))
|
||||
{
|
||||
self.searcher = Some(VecReserveSearcher {
|
||||
local_id: id,
|
||||
err_span: expr.span,
|
||||
init_part: snippet(cx, left.span.shrink_to_lo()
|
||||
.to(right.span.source_callsite().shrink_to_lo()), "..")
|
||||
.into_owned(), // see `assign_expression` test
|
||||
space_hint: String::new()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
|
||||
if let Some(searcher) = self.searcher.take() {
|
||||
if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind
|
||||
&& let ExprKind::MethodCall(name, self_arg, [space_hint], _) = expr.kind
|
||||
&& path_to_local_id(self_arg, searcher.local_id)
|
||||
&& name.ident.as_str() == "reserve"
|
||||
&& !is_from_proc_macro(cx, expr)
|
||||
{
|
||||
self.searcher = Some(VecReserveSearcher {
|
||||
err_span: searcher.err_span.to(stmt.span),
|
||||
space_hint: snippet(cx, space_hint.span, "..").into_owned(),
|
||||
.. searcher
|
||||
});
|
||||
} else {
|
||||
searcher.display_err(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx Block<'tcx>) {
|
||||
if let Some(searcher) = self.searcher.take() {
|
||||
searcher.display_err(cx);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -189,8 +189,8 @@ fn all_bindings_are_for_conv<'tcx>(
|
|||
tys.len() == elements.len() && tys.iter().chain(final_tys.iter().copied()).all_equal()
|
||||
},
|
||||
(ToType::Tuple, ty::Array(ty, len)) => {
|
||||
len.eval_target_usize(cx.tcx, cx.param_env) as usize == elements.len()
|
||||
&& final_tys.iter().chain(once(ty)).all_equal()
|
||||
let Some(len) = len.try_eval_target_usize(cx.tcx, cx.param_env) else { return false };
|
||||
len as usize == elements.len() && final_tys.iter().chain(once(ty)).all_equal()
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "clippy_utils"
|
||||
version = "0.1.73"
|
||||
version = "0.1.74"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@ use crate::tokenize_with_text;
|
|||
use rustc_ast::ast::InlineAsmTemplatePiece;
|
||||
use rustc_data_structures::fx::FxHasher;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::MatchSource::TryDesugar;
|
||||
use rustc_hir::{
|
||||
ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
|
||||
GenericArgs, Guard, HirId, HirIdMap, InlineAsmOperand, Let, Lifetime, LifetimeName, Pat, PatField, PatKind, Path,
|
||||
PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
|
||||
};
|
||||
use rustc_hir::MatchSource::TryDesugar;
|
||||
use rustc_lexer::{tokenize, TokenKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::TypeckResults;
|
||||
|
|
|
@ -20,7 +20,7 @@ macro_rules! msrv_aliases {
|
|||
// names may refer to stabilized feature flags or library items
|
||||
msrv_aliases! {
|
||||
1,71,0 { TUPLE_ARRAY_CONVERSIONS }
|
||||
1,70,0 { OPTION_IS_SOME_AND }
|
||||
1,70,0 { OPTION_IS_SOME_AND, BINARY_HEAP_RETAIN }
|
||||
1,68,0 { PATH_MAIN_SEPARATOR_STR }
|
||||
1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
|
||||
1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
|
||||
|
|
|
@ -15,6 +15,7 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
|
|||
];
|
||||
#[cfg(feature = "internal")]
|
||||
pub const DIAGNOSTIC_BUILDER: [&str; 3] = ["rustc_errors", "diagnostic_builder", "DiagnosticBuilder"];
|
||||
pub const BINARYHEAP_ITER: [&str; 5] = ["alloc", "collections", "binary_heap", "BinaryHeap", "iter"];
|
||||
pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
|
||||
pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
|
||||
pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
|
||||
|
@ -86,10 +87,7 @@ pub const PTR_REPLACE: [&str; 3] = ["core", "ptr", "replace"];
|
|||
pub const PTR_SWAP: [&str; 3] = ["core", "ptr", "swap"];
|
||||
pub const PTR_UNALIGNED_VOLATILE_LOAD: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_load"];
|
||||
pub const PTR_UNALIGNED_VOLATILE_STORE: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_store"];
|
||||
pub const PTR_WRITE: [&str; 3] = ["core", "ptr", "write"];
|
||||
pub const PTR_WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"];
|
||||
pub const PTR_WRITE_UNALIGNED: [&str; 3] = ["core", "ptr", "write_unaligned"];
|
||||
pub const PTR_WRITE_VOLATILE: [&str; 3] = ["core", "ptr", "write_volatile"];
|
||||
pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
|
||||
pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
|
||||
pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "declare_clippy_lint"
|
||||
version = "0.1.73"
|
||||
version = "0.1.74"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2023-08-10"
|
||||
channel = "nightly-2023-08-24"
|
||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
#![feature(test)] // compiletest_rs requires this attribute
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(is_sorted)]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
#![allow(unused_extern_crates)]
|
||||
|
||||
use compiletest::{status_emitter, CommandBuilder, OutputConflictHandling};
|
||||
use ui_test as compiletest;
|
||||
use ui_test::Mode as TestMode;
|
||||
use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, Mode, OutputConflictHandling, RustfixMode};
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::env::{self, remove_var, set_var, var_os};
|
||||
use std::env::{self, set_var, var_os};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -30,6 +27,8 @@ extern crate quote;
|
|||
extern crate syn;
|
||||
extern crate tokio;
|
||||
|
||||
mod test_utils;
|
||||
|
||||
/// All crates used in UI tests are listed here
|
||||
static TEST_DEPENDENCIES: &[&str] = &[
|
||||
"clippy_lints",
|
||||
|
@ -105,33 +104,44 @@ static EXTERN_FLAGS: LazyLock<Vec<String>> = LazyLock::new(|| {
|
|||
.collect()
|
||||
});
|
||||
|
||||
mod test_utils;
|
||||
|
||||
// whether to run internal tests or not
|
||||
const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal");
|
||||
|
||||
fn base_config(test_dir: &str) -> compiletest::Config {
|
||||
let mut config = compiletest::Config {
|
||||
mode: TestMode::Yolo,
|
||||
stderr_filters: vec![],
|
||||
fn canonicalize(path: impl AsRef<Path>) -> PathBuf {
|
||||
let path = path.as_ref();
|
||||
fs::create_dir_all(path).unwrap();
|
||||
fs::canonicalize(path).unwrap_or_else(|err| panic!("{} cannot be canonicalized: {err}", path.display()))
|
||||
}
|
||||
|
||||
fn base_config(test_dir: &str) -> (Config, Args) {
|
||||
let bless = var_os("RUSTC_BLESS").is_some_and(|v| v != "0") || env::args().any(|arg| arg == "--bless");
|
||||
|
||||
let args = Args {
|
||||
filters: env::var("TESTNAME")
|
||||
.map(|filters| filters.split(',').map(str::to_string).collect())
|
||||
.unwrap_or_default(),
|
||||
quiet: false,
|
||||
check: !bless,
|
||||
threads: match std::env::var_os("RUST_TEST_THREADS") {
|
||||
Some(n) => n.to_str().unwrap().parse().unwrap(),
|
||||
None => std::thread::available_parallelism().unwrap(),
|
||||
},
|
||||
skip: Vec::new(),
|
||||
};
|
||||
|
||||
let mut config = Config {
|
||||
mode: Mode::Yolo { rustfix: RustfixMode::Everything },
|
||||
stderr_filters: vec![(Match::PathBackslash, b"/")],
|
||||
stdout_filters: vec![],
|
||||
output_conflict_handling: if var_os("RUSTC_BLESS").is_some_and(|v| v != "0")
|
||||
|| env::args().any(|arg| arg == "--bless")
|
||||
{
|
||||
output_conflict_handling: if bless {
|
||||
OutputConflictHandling::Bless
|
||||
} else {
|
||||
OutputConflictHandling::Error("cargo uibless".into())
|
||||
},
|
||||
target: None,
|
||||
out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap_or("target".into())).join("ui_test"),
|
||||
..compiletest::Config::rustc(Path::new("tests").join(test_dir))
|
||||
out_dir: canonicalize(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())).join("ui_test"),
|
||||
..Config::rustc(Path::new("tests").join(test_dir))
|
||||
};
|
||||
|
||||
if let Some(_path) = option_env!("RUSTC_LIB_PATH") {
|
||||
//let path = PathBuf::from(path);
|
||||
//config.run_lib_path = path.clone();
|
||||
//config.compile_lib_path = path;
|
||||
}
|
||||
let current_exe_path = env::current_exe().unwrap();
|
||||
let deps_path = current_exe_path.parent().unwrap();
|
||||
let profile_path = deps_path.parent().unwrap();
|
||||
|
@ -155,52 +165,35 @@ fn base_config(test_dir: &str) -> compiletest::Config {
|
|||
config.program.args.push(dep.into());
|
||||
}
|
||||
|
||||
// Normalize away slashes in windows paths.
|
||||
config.stderr_filter(r"\\", "/");
|
||||
|
||||
//config.build_base = profile_path.join("test").join(test_dir);
|
||||
config.program.program = profile_path.join(if cfg!(windows) {
|
||||
"clippy-driver.exe"
|
||||
} else {
|
||||
"clippy-driver"
|
||||
});
|
||||
config
|
||||
}
|
||||
|
||||
fn test_filter() -> Box<dyn Sync + Fn(&Path) -> bool> {
|
||||
if let Ok(filters) = env::var("TESTNAME") {
|
||||
let filters: Vec<_> = filters.split(',').map(ToString::to_string).collect();
|
||||
Box::new(move |path| filters.iter().any(|f| path.to_string_lossy().contains(f)))
|
||||
} else {
|
||||
Box::new(|_| true)
|
||||
}
|
||||
(config, args)
|
||||
}
|
||||
|
||||
fn run_ui() {
|
||||
let config = base_config("ui");
|
||||
//config.rustfix_coverage = true;
|
||||
// use tests/clippy.toml
|
||||
let _g = VarGuard::set("CARGO_MANIFEST_DIR", fs::canonicalize("tests").unwrap());
|
||||
let _threads = VarGuard::set(
|
||||
"RUST_TEST_THREADS",
|
||||
// if RUST_TEST_THREADS is set, adhere to it, otherwise override it
|
||||
env::var("RUST_TEST_THREADS").unwrap_or_else(|_| {
|
||||
std::thread::available_parallelism()
|
||||
.map_or(1, std::num::NonZeroUsize::get)
|
||||
.to_string()
|
||||
}),
|
||||
);
|
||||
let (mut config, args) = base_config("ui");
|
||||
config
|
||||
.program
|
||||
.envs
|
||||
.push(("CLIPPY_CONF_DIR".into(), Some(canonicalize("tests").into())));
|
||||
|
||||
let test_filter = test_filter();
|
||||
let quiet = args.quiet;
|
||||
|
||||
compiletest::run_tests_generic(
|
||||
config,
|
||||
move |path| compiletest::default_file_filter(path) && test_filter(path),
|
||||
compiletest::default_per_file_config,
|
||||
status_emitter::Text,
|
||||
ui_test::run_tests_generic(
|
||||
vec![config],
|
||||
args,
|
||||
ui_test::default_file_filter,
|
||||
ui_test::default_per_file_config,
|
||||
if quiet {
|
||||
status_emitter::Text::quiet()
|
||||
} else {
|
||||
status_emitter::Text::verbose()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
check_rustfix_coverage();
|
||||
}
|
||||
|
||||
fn run_internal_tests() {
|
||||
|
@ -208,51 +201,61 @@ fn run_internal_tests() {
|
|||
if !RUN_INTERNAL_TESTS {
|
||||
return;
|
||||
}
|
||||
let mut config = base_config("ui-internal");
|
||||
let (mut config, args) = base_config("ui-internal");
|
||||
if let OutputConflictHandling::Error(err) = &mut config.output_conflict_handling {
|
||||
*err = "cargo uitest --features internal -- -- --bless".into();
|
||||
}
|
||||
let test_filter = test_filter();
|
||||
let quiet = args.quiet;
|
||||
|
||||
compiletest::run_tests_generic(
|
||||
config,
|
||||
move |path| compiletest::default_file_filter(path) && test_filter(path),
|
||||
compiletest::default_per_file_config,
|
||||
status_emitter::Text,
|
||||
ui_test::run_tests_generic(
|
||||
vec![config],
|
||||
args,
|
||||
ui_test::default_file_filter,
|
||||
ui_test::default_per_file_config,
|
||||
if quiet {
|
||||
status_emitter::Text::quiet()
|
||||
} else {
|
||||
status_emitter::Text::verbose()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn run_ui_toml() {
|
||||
let mut config = base_config("ui-toml");
|
||||
let (mut config, args) = base_config("ui-toml");
|
||||
|
||||
config.stderr_filter(
|
||||
®ex::escape(
|
||||
&fs::canonicalize("tests")
|
||||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.display()
|
||||
.to_string()
|
||||
.replace('\\', "/"),
|
||||
config.stderr_filters = vec![
|
||||
(
|
||||
Match::Exact(
|
||||
canonicalize("tests")
|
||||
.parent()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.as_bytes()
|
||||
.to_vec(),
|
||||
),
|
||||
b"$DIR",
|
||||
),
|
||||
"$$DIR",
|
||||
);
|
||||
(Match::Exact(b"\\".to_vec()), b"/"),
|
||||
];
|
||||
|
||||
let test_filter = test_filter();
|
||||
let quiet = args.quiet;
|
||||
|
||||
ui_test::run_tests_generic(
|
||||
config,
|
||||
|path| compiletest::default_file_filter(path) && test_filter(path),
|
||||
|config, path| {
|
||||
let mut config = config.clone();
|
||||
vec![config],
|
||||
args,
|
||||
ui_test::default_file_filter,
|
||||
|config, path, _file_contents| {
|
||||
config
|
||||
.program
|
||||
.envs
|
||||
.push(("CLIPPY_CONF_DIR".into(), Some(path.parent().unwrap().into())));
|
||||
Some(config)
|
||||
},
|
||||
status_emitter::Text,
|
||||
if quiet {
|
||||
status_emitter::Text::quiet()
|
||||
} else {
|
||||
status_emitter::Text::verbose()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -262,7 +265,7 @@ fn run_ui_cargo() {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut config = base_config("ui-cargo");
|
||||
let (mut config, args) = base_config("ui-cargo");
|
||||
config.program.input_file_flag = CommandBuilder::cargo().input_file_flag;
|
||||
config.program.out_dir_flag = CommandBuilder::cargo().out_dir_flag;
|
||||
config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()];
|
||||
|
@ -280,30 +283,41 @@ fn run_ui_cargo() {
|
|||
});
|
||||
config.edition = None;
|
||||
|
||||
config.stderr_filter(
|
||||
®ex::escape(
|
||||
&fs::canonicalize("tests")
|
||||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.display()
|
||||
.to_string()
|
||||
.replace('\\', "/"),
|
||||
config.stderr_filters = vec![
|
||||
(
|
||||
Match::Exact(
|
||||
canonicalize("tests")
|
||||
.parent()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.as_bytes()
|
||||
.to_vec(),
|
||||
),
|
||||
b"$DIR",
|
||||
),
|
||||
"$$DIR",
|
||||
);
|
||||
(Match::Exact(b"\\".to_vec()), b"/"),
|
||||
];
|
||||
|
||||
let test_filter = test_filter();
|
||||
let quiet = args.quiet;
|
||||
|
||||
ui_test::run_tests_generic(
|
||||
config,
|
||||
|path| test_filter(path) && path.ends_with("Cargo.toml"),
|
||||
|config, path| {
|
||||
let mut config = config.clone();
|
||||
config.out_dir = PathBuf::from("target/ui_test_cargo/").join(path.parent().unwrap());
|
||||
Some(config)
|
||||
vec![config],
|
||||
args,
|
||||
|path, args, _config| path.ends_with("Cargo.toml") && ui_test::default_filter_by_arg(path, args),
|
||||
|config, path, _file_contents| {
|
||||
config.out_dir = canonicalize(
|
||||
std::env::current_dir()
|
||||
.unwrap()
|
||||
.join("target")
|
||||
.join("ui_test_cargo/")
|
||||
.join(path.parent().unwrap()),
|
||||
);
|
||||
},
|
||||
if quiet {
|
||||
status_emitter::Text::quiet()
|
||||
} else {
|
||||
status_emitter::Text::verbose()
|
||||
},
|
||||
status_emitter::Text,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -328,7 +342,6 @@ fn main() {
|
|||
"cargo" => run_ui_cargo as fn(),
|
||||
"toml" => run_ui_toml as fn(),
|
||||
"internal" => run_internal_tests as fn(),
|
||||
"rustfix-coverage-known-exceptions-accuracy" => rustfix_coverage_known_exceptions_accuracy as fn(),
|
||||
"ui-cargo-toml-metadata" => ui_cargo_toml_metadata as fn(),
|
||||
|
||||
_ => panic!("unknown speedtest: {speedtest} || accepted speedtests are: [ui, cargo, toml, internal]"),
|
||||
|
@ -349,95 +362,20 @@ fn main() {
|
|||
f();
|
||||
sum += start.elapsed().as_millis();
|
||||
}
|
||||
println!("average {} time: {} millis.", speedtest.to_uppercase(), sum / 1000);
|
||||
println!(
|
||||
"average {} time: {} millis.",
|
||||
speedtest.to_uppercase(),
|
||||
sum / u128::from(iterations)
|
||||
);
|
||||
} else {
|
||||
run_ui();
|
||||
run_ui_toml();
|
||||
run_ui_cargo();
|
||||
run_internal_tests();
|
||||
rustfix_coverage_known_exceptions_accuracy();
|
||||
ui_cargo_toml_metadata();
|
||||
}
|
||||
}
|
||||
|
||||
const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[
|
||||
"assign_ops2.rs",
|
||||
"borrow_deref_ref_unfixable.rs",
|
||||
"cast_size_32bit.rs",
|
||||
"char_lit_as_u8.rs",
|
||||
"cmp_owned/without_suggestion.rs",
|
||||
"dbg_macro.rs",
|
||||
"deref_addrof_double_trigger.rs",
|
||||
"doc/unbalanced_ticks.rs",
|
||||
"eprint_with_newline.rs",
|
||||
"explicit_counter_loop.rs",
|
||||
"iter_skip_next_unfixable.rs",
|
||||
"let_and_return.rs",
|
||||
"literals.rs",
|
||||
"map_flatten.rs",
|
||||
"map_unwrap_or.rs",
|
||||
"match_bool.rs",
|
||||
"mem_replace_macro.rs",
|
||||
"needless_arbitrary_self_type_unfixable.rs",
|
||||
"needless_borrow_pat.rs",
|
||||
"needless_for_each_unfixable.rs",
|
||||
"nonminimal_bool.rs",
|
||||
"print_literal.rs",
|
||||
"redundant_static_lifetimes_multiple.rs",
|
||||
"ref_binding_to_reference.rs",
|
||||
"repl_uninit.rs",
|
||||
"result_map_unit_fn_unfixable.rs",
|
||||
"search_is_some.rs",
|
||||
"single_component_path_imports_nested_first.rs",
|
||||
"string_add.rs",
|
||||
"suspicious_to_owned.rs",
|
||||
"toplevel_ref_arg_non_rustfix.rs",
|
||||
"unit_arg.rs",
|
||||
"unnecessary_clone.rs",
|
||||
"unnecessary_lazy_eval_unfixable.rs",
|
||||
"write_literal.rs",
|
||||
"write_literal_2.rs",
|
||||
];
|
||||
|
||||
fn check_rustfix_coverage() {
|
||||
let missing_coverage_path = Path::new("debug/test/ui/rustfix_missing_coverage.txt");
|
||||
let missing_coverage_path = if let Ok(target_dir) = std::env::var("CARGO_TARGET_DIR") {
|
||||
PathBuf::from(target_dir).join(missing_coverage_path)
|
||||
} else {
|
||||
missing_coverage_path.to_path_buf()
|
||||
};
|
||||
|
||||
if let Ok(missing_coverage_contents) = std::fs::read_to_string(missing_coverage_path) {
|
||||
assert!(RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS.iter().is_sorted_by_key(Path::new));
|
||||
|
||||
for rs_file in missing_coverage_contents.lines() {
|
||||
let rs_path = Path::new(rs_file);
|
||||
if rs_path.starts_with("tests/ui/crashes") {
|
||||
continue;
|
||||
}
|
||||
assert!(rs_path.starts_with("tests/ui/"), "{rs_file:?}");
|
||||
let filename = rs_path.strip_prefix("tests/ui/").unwrap();
|
||||
assert!(
|
||||
RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS
|
||||
.binary_search_by_key(&filename, Path::new)
|
||||
.is_ok(),
|
||||
"`{rs_file}` runs `MachineApplicable` diagnostics but is missing a `run-rustfix` annotation. \
|
||||
Please either add `//@run-rustfix` at the top of the file or add the file to \
|
||||
`RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS` in `tests/compile-test.rs`.",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rustfix_coverage_known_exceptions_accuracy() {
|
||||
for filename in RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS {
|
||||
let rs_path = Path::new("tests/ui").join(filename);
|
||||
assert!(rs_path.exists(), "`{}` does not exist", rs_path.display());
|
||||
let fixed_path = rs_path.with_extension("fixed");
|
||||
assert!(!fixed_path.exists(), "`{}` exists", fixed_path.display());
|
||||
}
|
||||
}
|
||||
|
||||
fn ui_cargo_toml_metadata() {
|
||||
let ui_cargo_path = Path::new("tests/ui-cargo");
|
||||
let cargo_common_metadata_path = ui_cargo_path.join("cargo_common_metadata");
|
||||
|
@ -473,27 +411,3 @@ fn ui_cargo_toml_metadata() {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores an env var on drop
|
||||
#[must_use]
|
||||
struct VarGuard {
|
||||
key: &'static str,
|
||||
value: Option<OsString>,
|
||||
}
|
||||
|
||||
impl VarGuard {
|
||||
fn set(key: &'static str, val: impl AsRef<OsStr>) -> Self {
|
||||
let value = var_os(key);
|
||||
set_var(key, val);
|
||||
Self { key, value }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for VarGuard {
|
||||
fn drop(&mut self) {
|
||||
match self.value.as_deref() {
|
||||
None => remove_var(self.key),
|
||||
Some(value) => set_var(self.key, value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ fn old_test_headers() {
|
|||
continue;
|
||||
}
|
||||
|
||||
let file = fs::read_to_string(entry.path()).unwrap();
|
||||
let file = fs::read_to_string(entry.path()).unwrap_or_else(|err| panic!("{}: {err}", entry.path().display()));
|
||||
|
||||
if let Some(header) = old_headers.find(&file) {
|
||||
println!("Found header `{}` in {}", header.as_str(), entry.path().display());
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![deny(clippy::internal)]
|
||||
#![allow(clippy::missing_clippy_version_attribute)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![deny(clippy::internal)]
|
||||
#![allow(clippy::missing_clippy_version_attribute)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: this call is collapsible
|
||||
--> $DIR/collapsible_span_lint_calls.rs:36:9
|
||||
--> $DIR/collapsible_span_lint_calls.rs:35:9
|
||||
|
|
||||
LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
LL | | db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable);
|
||||
|
@ -7,14 +7,14 @@ LL | | });
|
|||
| |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable)`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/collapsible_span_lint_calls.rs:2:9
|
||||
--> $DIR/collapsible_span_lint_calls.rs:1:9
|
||||
|
|
||||
LL | #![deny(clippy::internal)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(clippy::collapsible_span_lint_calls)]` implied by `#[deny(clippy::internal)]`
|
||||
|
||||
error: this call is collapsible
|
||||
--> $DIR/collapsible_span_lint_calls.rs:39:9
|
||||
--> $DIR/collapsible_span_lint_calls.rs:38:9
|
||||
|
|
||||
LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
LL | | db.span_help(expr.span, help_msg);
|
||||
|
@ -22,7 +22,7 @@ LL | | });
|
|||
| |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg)`
|
||||
|
||||
error: this call is collapsible
|
||||
--> $DIR/collapsible_span_lint_calls.rs:42:9
|
||||
--> $DIR/collapsible_span_lint_calls.rs:41:9
|
||||
|
|
||||
LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
LL | | db.help(help_msg);
|
||||
|
@ -30,7 +30,7 @@ LL | | });
|
|||
| |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg)`
|
||||
|
||||
error: this call is collapsible
|
||||
--> $DIR/collapsible_span_lint_calls.rs:45:9
|
||||
--> $DIR/collapsible_span_lint_calls.rs:44:9
|
||||
|
|
||||
LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
LL | | db.span_note(expr.span, note_msg);
|
||||
|
@ -38,7 +38,7 @@ LL | | });
|
|||
| |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg)`
|
||||
|
||||
error: this call is collapsible
|
||||
--> $DIR/collapsible_span_lint_calls.rs:48:9
|
||||
--> $DIR/collapsible_span_lint_calls.rs:47:9
|
||||
|
|
||||
LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
LL | | db.note(note_msg);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![deny(clippy::internal)]
|
||||
#![allow(clippy::missing_clippy_version_attribute, clippy::let_unit_value)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![deny(clippy::internal)]
|
||||
#![allow(clippy::missing_clippy_version_attribute, clippy::let_unit_value)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
error: interning a defined symbol
|
||||
--> $DIR/interning_defined_symbol.rs:18:13
|
||||
--> $DIR/interning_defined_symbol.rs:17:13
|
||||
|
|
||||
LL | let _ = Symbol::intern("f32");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::f32`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/interning_defined_symbol.rs:2:9
|
||||
--> $DIR/interning_defined_symbol.rs:1:9
|
||||
|
|
||||
LL | #![deny(clippy::internal)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(clippy::interning_defined_symbol)]` implied by `#[deny(clippy::internal)]`
|
||||
|
||||
error: interning a defined symbol
|
||||
--> $DIR/interning_defined_symbol.rs:21:13
|
||||
--> $DIR/interning_defined_symbol.rs:20:13
|
||||
|
|
||||
LL | let _ = sym!(f32);
|
||||
| ^^^^^^^^^ help: try: `rustc_span::sym::f32`
|
||||
|
||||
error: interning a defined symbol
|
||||
--> $DIR/interning_defined_symbol.rs:24:13
|
||||
--> $DIR/interning_defined_symbol.rs:23:13
|
||||
|
|
||||
LL | let _ = Symbol::intern("proc-macro");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::proc_dash_macro`
|
||||
|
||||
error: interning a defined symbol
|
||||
--> $DIR/interning_defined_symbol.rs:27:13
|
||||
--> $DIR/interning_defined_symbol.rs:26:13
|
||||
|
|
||||
LL | let _ = Symbol::intern("self");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::symbol::kw::SelfLower`
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
//@run-rustfix
|
||||
|
||||
#![deny(clippy::internal)]
|
||||
#![allow(clippy::missing_clippy_version_attribute)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
//@run-rustfix
|
||||
|
||||
#![deny(clippy::internal)]
|
||||
#![allow(clippy::missing_clippy_version_attribute)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
error: `extract_msrv_attr!` macro missing from `LateLintPass` implementation
|
||||
--> $DIR/invalid_msrv_attr_impl.rs:30:1
|
||||
--> $DIR/invalid_msrv_attr_impl.rs:28:1
|
||||
|
|
||||
LL | impl LateLintPass<'_> for Pass {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/invalid_msrv_attr_impl.rs:3:9
|
||||
--> $DIR/invalid_msrv_attr_impl.rs:1:9
|
||||
|
|
||||
LL | #![deny(clippy::internal)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
@ -17,7 +17,7 @@ LL + extract_msrv_attr!(LateContext);
|
|||
|
|
||||
|
||||
error: `extract_msrv_attr!` macro missing from `EarlyLintPass` implementation
|
||||
--> $DIR/invalid_msrv_attr_impl.rs:34:1
|
||||
--> $DIR/invalid_msrv_attr_impl.rs:32:1
|
||||
|
|
||||
LL | impl EarlyLintPass for Pass {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
//@run-rustfix
|
||||
|
||||
#![deny(clippy::internal)]
|
||||
#![allow(clippy::missing_clippy_version_attribute)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
//@run-rustfix
|
||||
|
||||
#![deny(clippy::internal)]
|
||||
#![allow(clippy::missing_clippy_version_attribute)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
error: usage of `outer_expn().expn_data()`
|
||||
--> $DIR/outer_expn_data.rs:25:34
|
||||
--> $DIR/outer_expn_data.rs:23:34
|
||||
|
|
||||
LL | let _ = expr.span.ctxt().outer_expn().expn_data();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `outer_expn_data()`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/outer_expn_data.rs:3:9
|
||||
--> $DIR/outer_expn_data.rs:1:9
|
||||
|
|
||||
LL | #![deny(clippy::internal)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
//@aux-build:paths.rs
|
||||
#![deny(clippy::internal)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
//@aux-build:paths.rs
|
||||
#![deny(clippy::internal)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -1,72 +1,72 @@
|
|||
error: use of a def path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path.rs:37:13
|
||||
--> $DIR/unnecessary_def_path.rs:36:13
|
||||
|
|
||||
LL | let _ = match_type(cx, ty, &OPTION);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unnecessary_def_path.rs:3:9
|
||||
--> $DIR/unnecessary_def_path.rs:2:9
|
||||
|
|
||||
LL | #![deny(clippy::internal)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(clippy::unnecessary_def_path)]` implied by `#[deny(clippy::internal)]`
|
||||
|
||||
error: use of a def path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path.rs:38:13
|
||||
--> $DIR/unnecessary_def_path.rs:37:13
|
||||
|
|
||||
LL | let _ = match_type(cx, ty, RESULT);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
|
||||
|
||||
error: use of a def path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path.rs:39:13
|
||||
--> $DIR/unnecessary_def_path.rs:38:13
|
||||
|
|
||||
LL | let _ = match_type(cx, ty, &["core", "result", "Result"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
|
||||
|
||||
error: use of a def path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path.rs:43:13
|
||||
--> $DIR/unnecessary_def_path.rs:42:13
|
||||
|
|
||||
LL | let _ = clippy_utils::ty::match_type(cx, ty, rc_path);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Rc)`
|
||||
|
||||
error: use of a def path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path.rs:45:13
|
||||
--> $DIR/unnecessary_def_path.rs:44:13
|
||||
|
|
||||
LL | let _ = match_type(cx, ty, &paths::OPTION);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)`
|
||||
|
||||
error: use of a def path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path.rs:46:13
|
||||
--> $DIR/unnecessary_def_path.rs:45:13
|
||||
|
|
||||
LL | let _ = match_type(cx, ty, paths::RESULT);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
|
||||
|
||||
error: use of a def path to a `LangItem`
|
||||
--> $DIR/unnecessary_def_path.rs:48:13
|
||||
--> $DIR/unnecessary_def_path.rs:47:13
|
||||
|
|
||||
LL | let _ = match_type(cx, ty, &["alloc", "boxed", "Box"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_lang_item(cx, ty, LangItem::OwnedBox)`
|
||||
|
||||
error: use of a def path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path.rs:49:13
|
||||
--> $DIR/unnecessary_def_path.rs:48:13
|
||||
|
|
||||
LL | let _ = match_type(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit)`
|
||||
|
||||
error: use of a def path to a `LangItem`
|
||||
--> $DIR/unnecessary_def_path.rs:51:13
|
||||
--> $DIR/unnecessary_def_path.rs:50:13
|
||||
|
|
||||
LL | let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did)`
|
||||
|
||||
error: use of a def path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path.rs:52:13
|
||||
--> $DIR/unnecessary_def_path.rs:51:13
|
||||
|
|
||||
LL | let _ = match_def_path(cx, did, &["core", "option", "Option"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.is_diagnostic_item(sym::Option, did)`
|
||||
|
||||
error: use of a def path to a `LangItem`
|
||||
--> $DIR/unnecessary_def_path.rs:53:13
|
||||
--> $DIR/unnecessary_def_path.rs:52:13
|
||||
|
|
||||
LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did)`
|
||||
|
@ -74,25 +74,25 @@ LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]);
|
|||
= help: if this `DefId` came from a constructor expression or pattern then the parent `DefId` should be used instead
|
||||
|
||||
error: use of a def path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path.rs:55:13
|
||||
--> $DIR/unnecessary_def_path.rs:54:13
|
||||
|
|
||||
LL | let _ = match_trait_method(cx, expr, &["core", "convert", "AsRef"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_trait_method(cx, expr, sym::AsRef)`
|
||||
|
||||
error: use of a def path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path.rs:57:13
|
||||
--> $DIR/unnecessary_def_path.rs:56:13
|
||||
|
|
||||
LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_path_diagnostic_item(cx, expr, sym::Option)`
|
||||
|
||||
error: use of a def path to a `LangItem`
|
||||
--> $DIR/unnecessary_def_path.rs:58:13
|
||||
--> $DIR/unnecessary_def_path.rs:57:13
|
||||
|
|
||||
LL | let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id))`
|
||||
|
||||
error: use of a def path to a `LangItem`
|
||||
--> $DIR/unnecessary_def_path.rs:59:13
|
||||
--> $DIR/unnecessary_def_path.rs:58:13
|
||||
|
|
||||
LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option", "Some"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome)`
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![feature(rustc_private)]
|
||||
#![deny(clippy::internal)]
|
||||
#![allow(
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![feature(rustc_private)]
|
||||
#![deny(clippy::internal)]
|
||||
#![allow(
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
error: unnecessary `Symbol` to string conversion
|
||||
--> $DIR/unnecessary_symbol_str.rs:16:5
|
||||
--> $DIR/unnecessary_symbol_str.rs:15:5
|
||||
|
|
||||
LL | Symbol::intern("foo").as_str() == "clippy";
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") == rustc_span::sym::clippy`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unnecessary_symbol_str.rs:3:9
|
||||
--> $DIR/unnecessary_symbol_str.rs:2:9
|
||||
|
|
||||
LL | #![deny(clippy::internal)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(clippy::unnecessary_symbol_str)]` implied by `#[deny(clippy::internal)]`
|
||||
|
||||
error: unnecessary `Symbol` to string conversion
|
||||
--> $DIR/unnecessary_symbol_str.rs:17:5
|
||||
--> $DIR/unnecessary_symbol_str.rs:16:5
|
||||
|
|
||||
LL | Symbol::intern("foo").to_string() == "self";
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") == rustc_span::symbol::kw::SelfLower`
|
||||
|
||||
error: unnecessary `Symbol` to string conversion
|
||||
--> $DIR/unnecessary_symbol_str.rs:18:5
|
||||
--> $DIR/unnecessary_symbol_str.rs:17:5
|
||||
|
|
||||
LL | Symbol::intern("foo").to_ident_string() != "Self";
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") != rustc_span::symbol::kw::SelfUpper`
|
||||
|
||||
error: unnecessary `Symbol` to string conversion
|
||||
--> $DIR/unnecessary_symbol_str.rs:19:5
|
||||
--> $DIR/unnecessary_symbol_str.rs:18:5
|
||||
|
|
||||
LL | &*Ident::empty().as_str() == "clippy";
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ident::empty().name == rustc_span::sym::clippy`
|
||||
|
||||
error: unnecessary `Symbol` to string conversion
|
||||
--> $DIR/unnecessary_symbol_str.rs:20:5
|
||||
--> $DIR/unnecessary_symbol_str.rs:19:5
|
||||
|
|
||||
LL | "clippy" == Ident::empty().to_string();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::clippy == Ident::empty().name`
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//@aux-build:../../ui/auxiliary/proc_macros.rs:proc-macro
|
||||
//@aux-build:../../ui/auxiliary/proc_macros.rs
|
||||
//@aux-build:helper.rs
|
||||
//@revisions: allow_crates disallow_crates
|
||||
//@[allow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![warn(clippy::uninlined_format_args)]
|
||||
#![allow(clippy::unnecessary_literal_unwrap)]
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![warn(clippy::uninlined_format_args)]
|
||||
#![allow(clippy::unnecessary_literal_unwrap)]
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: variables can be used directly in the `format!` string
|
||||
--> $DIR/uninlined_format_args.rs:10:5
|
||||
--> $DIR/uninlined_format_args.rs:9:5
|
||||
|
|
||||
LL | println!("val='{}'", local_i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -12,7 +12,7 @@ LL + println!("val='{local_i32}'");
|
|||
|
|
||||
|
||||
error: variables can be used directly in the `format!` string
|
||||
--> $DIR/uninlined_format_args.rs:11:5
|
||||
--> $DIR/uninlined_format_args.rs:10:5
|
||||
|
|
||||
LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -24,7 +24,7 @@ LL + println!("Hello {} is {local_f64:.local_i32$}", "x");
|
|||
|
|
||||
|
||||
error: literal with an empty format string
|
||||
--> $DIR/uninlined_format_args.rs:11:35
|
||||
--> $DIR/uninlined_format_args.rs:10:35
|
||||
|
|
||||
LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64);
|
||||
| ^^^
|
||||
|
@ -37,7 +37,7 @@ LL + println!("Hello x is {:.*}", local_i32, local_f64);
|
|||
|
|
||||
|
||||
error: variables can be used directly in the `format!` string
|
||||
--> $DIR/uninlined_format_args.rs:12:5
|
||||
--> $DIR/uninlined_format_args.rs:11:5
|
||||
|
|
||||
LL | println!("Hello {} is {:.*}", local_i32, 5, local_f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -49,7 +49,7 @@ LL + println!("Hello {local_i32} is {local_f64:.*}", 5);
|
|||
|
|
||||
|
||||
error: variables can be used directly in the `format!` string
|
||||
--> $DIR/uninlined_format_args.rs:13:5
|
||||
--> $DIR/uninlined_format_args.rs:12:5
|
||||
|
|
||||
LL | println!("Hello {} is {2:.*}", local_i32, 5, local_f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -61,7 +61,7 @@ LL + println!("Hello {local_i32} is {local_f64:.*}", 5);
|
|||
|
|
||||
|
||||
error: variables can be used directly in the `format!` string
|
||||
--> $DIR/uninlined_format_args.rs:14:5
|
||||
--> $DIR/uninlined_format_args.rs:13:5
|
||||
|
|
||||
LL | println!("{}, {}", local_i32, local_opt.unwrap());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(unused)]
|
||||
#![warn(clippy::large_const_arrays, clippy::large_stack_arrays)]
|
||||
|
||||
//@no-rustfix
|
||||
const ABOVE: [u8; 11] = [0; 11];
|
||||
const BELOW: [u8; 10] = [0; 10];
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//@compile-flags: --test
|
||||
#![warn(clippy::dbg_macro)]
|
||||
|
||||
//@no-rustfix
|
||||
fn foo(n: u32) -> u32 {
|
||||
if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
|
||||
}
|
||||
|
|
12
tests/ui-toml/doc_valid_idents_append/doc_markdown.fixed
Normal file
12
tests/ui-toml/doc_valid_idents_append/doc_markdown.fixed
Normal file
|
@ -0,0 +1,12 @@
|
|||
#![warn(clippy::doc_markdown)]
|
||||
|
||||
/// This is a special interface for ClipPy which doesn't require backticks
|
||||
fn allowed_name() {}
|
||||
|
||||
/// OAuth and LaTeX are inside Clippy's default list.
|
||||
fn default_name() {}
|
||||
|
||||
/// `TestItemThingyOfCoolness` might sound cool but is not on the list and should be linted.
|
||||
fn unknown_name() {}
|
||||
|
||||
fn main() {}
|
12
tests/ui-toml/doc_valid_idents_replace/doc_markdown.fixed
Normal file
12
tests/ui-toml/doc_valid_idents_replace/doc_markdown.fixed
Normal file
|
@ -0,0 +1,12 @@
|
|||
#![warn(clippy::doc_markdown)]
|
||||
|
||||
/// This is a special interface for ClipPy which doesn't require backticks
|
||||
fn allowed_name() {}
|
||||
|
||||
/// `OAuth` and `LaTeX` are inside Clippy's default list.
|
||||
fn default_name() {}
|
||||
|
||||
/// `TestItemThingyOfCoolness` might sound cool but is not on the list and should be linted.
|
||||
fn unknown_name() {}
|
||||
|
||||
fn main() {}
|
|
@ -1,4 +1,4 @@
|
|||
//@aux-build:proc_macros.rs:proc-macro
|
||||
//@aux-build:proc_macros.rs
|
||||
#![rustfmt::skip]
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![allow(unused)]
|
||||
|
|
27
tests/ui-toml/large_futures/large_futures.fixed
Normal file
27
tests/ui-toml/large_futures/large_futures.fixed
Normal file
|
@ -0,0 +1,27 @@
|
|||
#![warn(clippy::large_futures)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
pub async fn should_warn() {
|
||||
let x = [0u8; 1024];
|
||||
async {}.await;
|
||||
dbg!(x);
|
||||
}
|
||||
|
||||
pub async fn should_not_warn() {
|
||||
let x = [0u8; 1020];
|
||||
async {}.await;
|
||||
dbg!(x);
|
||||
}
|
||||
|
||||
pub async fn bar() {
|
||||
Box::pin(should_warn()).await;
|
||||
|
||||
async {
|
||||
let x = [0u8; 1024];
|
||||
dbg!(x);
|
||||
}
|
||||
.await;
|
||||
|
||||
should_not_warn().await;
|
||||
}
|
23
tests/ui-toml/lint_decimal_readability/test.fixed
Normal file
23
tests/ui-toml/lint_decimal_readability/test.fixed
Normal file
|
@ -0,0 +1,23 @@
|
|||
#![allow(clippy::excessive_precision)]
|
||||
#![warn(clippy::unreadable_literal)]
|
||||
|
||||
fn allow_inconsistent_digit_grouping() {
|
||||
#![allow(clippy::inconsistent_digit_grouping)]
|
||||
let _pass1 = 100_200_300.123456789;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
allow_inconsistent_digit_grouping();
|
||||
|
||||
let _pass1 = 100_200_300.100_200_300;
|
||||
let _pass2 = 1.123456789;
|
||||
let _pass3 = 1.0;
|
||||
let _pass4 = 10000.00001;
|
||||
let _pass5 = 1.123456789e1;
|
||||
|
||||
// due to clippy::inconsistent-digit-grouping
|
||||
let _fail1 = 100_200_300.123_456_789;
|
||||
|
||||
// fail due to the integer part
|
||||
let _fail2 = 100_200_300.300_200_100;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#![deny(clippy::index_refutable_slice)]
|
||||
|
||||
fn below_limit() {
|
||||
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
|
||||
if let Some([_, _, _, _, _, _, _, slice_7, ..]) = slice {
|
||||
//~^ ERROR: binding can be a slice pattern
|
||||
// This would usually not be linted but is included now due to the
|
||||
// index limit in the config file
|
||||
println!("{}", slice_7);
|
||||
}
|
||||
}
|
||||
|
||||
fn above_limit() {
|
||||
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
|
||||
if let Some(slice) = slice {
|
||||
// This will not be linted as 8 is above the limit
|
||||
println!("{}", slice[8]);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
below_limit();
|
||||
above_limit();
|
||||
}
|
98
tests/ui-toml/min_rust_version/min_rust_version.fixed
Normal file
98
tests/ui-toml/min_rust_version/min_rust_version.fixed
Normal file
|
@ -0,0 +1,98 @@
|
|||
#![allow(clippy::redundant_clone, clippy::unnecessary_operation)]
|
||||
#![warn(clippy::manual_non_exhaustive, clippy::borrow_as_ptr, clippy::manual_bits)]
|
||||
|
||||
use std::mem::{size_of, size_of_val};
|
||||
use std::ops::Deref;
|
||||
|
||||
mod enums {
|
||||
enum E {
|
||||
A,
|
||||
B,
|
||||
#[doc(hidden)]
|
||||
_C,
|
||||
}
|
||||
|
||||
// user forgot to remove the marker
|
||||
#[non_exhaustive]
|
||||
enum Ep {
|
||||
A,
|
||||
B,
|
||||
#[doc(hidden)]
|
||||
_C,
|
||||
}
|
||||
}
|
||||
|
||||
fn option_as_ref_deref() {
|
||||
let mut opt = Some(String::from("123"));
|
||||
|
||||
let _ = opt.as_ref().map(String::as_str);
|
||||
let _ = opt.as_ref().map(|x| x.as_str());
|
||||
let _ = opt.as_mut().map(String::as_mut_str);
|
||||
let _ = opt.as_mut().map(|x| x.as_mut_str());
|
||||
}
|
||||
|
||||
fn match_like_matches() {
|
||||
let _y = match Some(5) {
|
||||
Some(0) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn match_same_arms() {
|
||||
match (1, 2, 3) {
|
||||
(1, .., 3) => 42,
|
||||
(.., 3) => 42,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
fn match_same_arms2() {
|
||||
let _ = match Some(42) {
|
||||
Some(_) => 24,
|
||||
None => 24,
|
||||
};
|
||||
}
|
||||
|
||||
fn manual_strip_msrv() {
|
||||
let s = "hello, world!";
|
||||
if s.starts_with("hello, ") {
|
||||
assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
|
||||
}
|
||||
}
|
||||
|
||||
fn check_index_refutable_slice() {
|
||||
// This shouldn't trigger `clippy::index_refutable_slice` as the suggestion
|
||||
// would only be valid from 1.42.0 onward
|
||||
let slice: Option<&[u32]> = Some(&[1]);
|
||||
if let Some(slice) = slice {
|
||||
println!("{}", slice[0]);
|
||||
}
|
||||
}
|
||||
|
||||
fn map_clone_suggest_copied() {
|
||||
// This should still trigger the lint but suggest `cloned()` instead of `copied()`
|
||||
let _: Option<u64> = Some(&16).cloned();
|
||||
}
|
||||
|
||||
fn borrow_as_ptr() {
|
||||
let val = 1;
|
||||
let _p = &val as *const i32;
|
||||
|
||||
let mut val_mut = 1;
|
||||
let _p_mut = &mut val_mut as *mut i32;
|
||||
}
|
||||
|
||||
fn manual_bits() {
|
||||
size_of::<i8>() * 8;
|
||||
size_of_val(&0u32) * 8;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
option_as_ref_deref();
|
||||
match_like_matches();
|
||||
match_same_arms();
|
||||
match_same_arms2();
|
||||
manual_strip_msrv();
|
||||
check_index_refutable_slice();
|
||||
borrow_as_ptr();
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#![warn(clippy::missing_enforced_import_renames)]
|
||||
|
||||
use std::alloc as colla;
|
||||
use std::option::Option as Maybe;
|
||||
use std::process::{exit as goodbye, Child as Kid};
|
||||
use std::thread::sleep as thread_sleep;
|
||||
#[rustfmt::skip]
|
||||
use std::{
|
||||
any::{type_name as ident, Any},
|
||||
clone as foo,
|
||||
sync :: Mutex as StdMutie,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
use std::collections::BTreeMap as Map;
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
//@aux-build:proc_macro_derive.rs:proc-macro
|
||||
//@run-rustfix
|
||||
//@aux-build:proc_macro_derive.rs
|
||||
|
||||
#![warn(clippy::nonstandard_macro_braces)]
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//@aux-build:proc_macro_derive.rs:proc-macro
|
||||
//@run-rustfix
|
||||
//@aux-build:proc_macro_derive.rs
|
||||
|
||||
#![warn(clippy::nonstandard_macro_braces)]
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: use of irregular braces for `vec!` macro
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:44:13
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:43:13
|
||||
|
|
||||
LL | let _ = vec! {1, 2, 3};
|
||||
| ^^^^^^^^^^^^^^ help: consider writing: `vec![1, 2, 3]`
|
||||
|
@ -7,31 +7,31 @@ LL | let _ = vec! {1, 2, 3};
|
|||
= note: `-D clippy::nonstandard-macro-braces` implied by `-D warnings`
|
||||
|
||||
error: use of irregular braces for `format!` macro
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:45:13
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:44:13
|
||||
|
|
||||
LL | let _ = format!["ugh {} stop being such a good compiler", "hello"];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `format!("ugh {} stop being such a good compiler", "hello")`
|
||||
|
||||
error: use of irregular braces for `matches!` macro
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:46:13
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:45:13
|
||||
|
|
||||
LL | let _ = matches!{{}, ()};
|
||||
| ^^^^^^^^^^^^^^^^ help: consider writing: `matches!({}, ())`
|
||||
|
||||
error: use of irregular braces for `quote!` macro
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:47:13
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:46:13
|
||||
|
|
||||
LL | let _ = quote!(let x = 1;);
|
||||
| ^^^^^^^^^^^^^^^^^^ help: consider writing: `quote!{let x = 1;}`
|
||||
|
||||
error: use of irregular braces for `quote::quote!` macro
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:48:13
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:47:13
|
||||
|
|
||||
LL | let _ = quote::quote!(match match match);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `quote::quote!{match match match}`
|
||||
|
||||
error: use of irregular braces for `vec!` macro
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:19:9
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:18:9
|
||||
|
|
||||
LL | vec!{0, 0, 0}
|
||||
| ^^^^^^^^^^^^^ help: consider writing: `vec![0, 0, 0]`
|
||||
|
@ -42,13 +42,13 @@ LL | let _ = test!(); // trigger when macro def is inside our own crate
|
|||
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: use of irregular braces for `type_pos!` macro
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:57:12
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:56:12
|
||||
|
|
||||
LL | let _: type_pos!(usize) = vec![];
|
||||
| ^^^^^^^^^^^^^^^^ help: consider writing: `type_pos![usize]`
|
||||
|
||||
error: use of irregular braces for `eprint!` macro
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:59:5
|
||||
--> $DIR/conf_nonstandard_macro_braces.rs:58:5
|
||||
|
|
||||
LL | eprint!("test if user config overrides defaults");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `eprint!["test if user config overrides defaults"]`
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![allow(
|
||||
unused,
|
||||
clippy::unused_unit,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![allow(
|
||||
unused,
|
||||
clippy::unused_unit,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: consider moving the `;` outside the block for consistent formatting
|
||||
--> $DIR/both.rs:43:5
|
||||
--> $DIR/both.rs:42:5
|
||||
|
|
||||
LL | { unit_fn_block(); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -12,7 +12,7 @@ LL + { unit_fn_block() };
|
|||
|
|
||||
|
||||
error: consider moving the `;` outside the block for consistent formatting
|
||||
--> $DIR/both.rs:44:5
|
||||
--> $DIR/both.rs:43:5
|
||||
|
|
||||
LL | unsafe { unit_fn_block(); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -24,7 +24,7 @@ LL + unsafe { unit_fn_block() };
|
|||
|
|
||||
|
||||
error: consider moving the `;` inside the block for consistent formatting
|
||||
--> $DIR/both.rs:49:5
|
||||
--> $DIR/both.rs:48:5
|
||||
|
|
||||
LL | / {
|
||||
LL | | unit_fn_block();
|
||||
|
@ -40,7 +40,7 @@ LL ~ }
|
|||
|
|
||||
|
||||
error: consider moving the `;` outside the block for consistent formatting
|
||||
--> $DIR/both.rs:63:5
|
||||
--> $DIR/both.rs:62:5
|
||||
|
|
||||
LL | { m!(()); }
|
||||
| ^^^^^^^^^^^
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![allow(
|
||||
unused,
|
||||
clippy::unused_unit,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![allow(
|
||||
unused,
|
||||
clippy::unused_unit,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: consider moving the `;` inside the block for consistent formatting
|
||||
--> $DIR/semicolon_inside_block.rs:48:5
|
||||
--> $DIR/semicolon_inside_block.rs:47:5
|
||||
|
|
||||
LL | / {
|
||||
LL | | unit_fn_block();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![allow(
|
||||
unused,
|
||||
clippy::unused_unit,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@run-rustfix
|
||||
#![allow(
|
||||
unused,
|
||||
clippy::unused_unit,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: consider moving the `;` outside the block for consistent formatting
|
||||
--> $DIR/semicolon_outside_block.rs:42:5
|
||||
--> $DIR/semicolon_outside_block.rs:41:5
|
||||
|
|
||||
LL | { unit_fn_block(); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -12,7 +12,7 @@ LL + { unit_fn_block() };
|
|||
|
|
||||
|
||||
error: consider moving the `;` outside the block for consistent formatting
|
||||
--> $DIR/semicolon_outside_block.rs:43:5
|
||||
--> $DIR/semicolon_outside_block.rs:42:5
|
||||
|
|
||||
LL | unsafe { unit_fn_block(); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -24,7 +24,7 @@ LL + unsafe { unit_fn_block() };
|
|||
|
|
||||
|
||||
error: consider moving the `;` outside the block for consistent formatting
|
||||
--> $DIR/semicolon_outside_block.rs:62:5
|
||||
--> $DIR/semicolon_outside_block.rs:61:5
|
||||
|
|
||||
LL | { m!(()); }
|
||||
| ^^^^^^^^^^^
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)"
|
||||
//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)"
|
||||
|
||||
//@no-rustfix
|
||||
#![warn(clippy::trivially_copy_pass_by_ref)]
|
||||
#![allow(clippy::needless_pass_by_ref_mut)]
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//@aux-build:proc_macro_unsafe.rs:proc-macro
|
||||
//@aux-build:proc_macro_unsafe.rs
|
||||
|
||||
#![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)]
|
||||
#![allow(deref_nullptr, clippy::let_unit_value, clippy::missing_safety_doc)]
|
||||
|
|
95
tests/ui-toml/unwrap_used/unwrap_used.fixed
Normal file
95
tests/ui-toml/unwrap_used/unwrap_used.fixed
Normal file
|
@ -0,0 +1,95 @@
|
|||
//@compile-flags: --test
|
||||
|
||||
#![allow(
|
||||
unused_mut,
|
||||
clippy::get_first,
|
||||
clippy::from_iter_instead_of_collect,
|
||||
clippy::useless_vec
|
||||
)]
|
||||
#![warn(clippy::unwrap_used)]
|
||||
#![warn(clippy::get_unwrap)]
|
||||
|
||||
use std::collections::{BTreeMap, HashMap, VecDeque};
|
||||
|
||||
struct GetFalsePositive {
|
||||
arr: [u32; 3],
|
||||
}
|
||||
|
||||
impl GetFalsePositive {
|
||||
fn get(&self, pos: usize) -> Option<&u32> {
|
||||
self.arr.get(pos)
|
||||
}
|
||||
fn get_mut(&mut self, pos: usize) -> Option<&mut u32> {
|
||||
self.arr.get_mut(pos)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
|
||||
let mut some_slice = &mut [0, 1, 2, 3];
|
||||
let mut some_vec = vec![0, 1, 2, 3];
|
||||
let mut some_vecdeque: VecDeque<_> = some_vec.iter().cloned().collect();
|
||||
let mut some_hashmap: HashMap<u8, char> = HashMap::from_iter(vec![(1, 'a'), (2, 'b')]);
|
||||
let mut some_btreemap: BTreeMap<u8, char> = BTreeMap::from_iter(vec![(1, 'a'), (2, 'b')]);
|
||||
let mut false_positive = GetFalsePositive { arr: [0, 1, 2] };
|
||||
|
||||
{
|
||||
// Test `get().unwrap()`
|
||||
let _ = &boxed_slice[1];
|
||||
let _ = &some_slice[0];
|
||||
let _ = &some_vec[0];
|
||||
let _ = &some_vecdeque[0];
|
||||
let _ = &some_hashmap[&1];
|
||||
let _ = &some_btreemap[&1];
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let _ = false_positive.get(0).unwrap();
|
||||
// Test with deref
|
||||
let _: u8 = boxed_slice[1];
|
||||
}
|
||||
|
||||
{
|
||||
// Test `get_mut().unwrap()`
|
||||
boxed_slice[0] = 1;
|
||||
some_slice[0] = 1;
|
||||
some_vec[0] = 1;
|
||||
some_vecdeque[0] = 1;
|
||||
// Check false positives
|
||||
#[allow(clippy::unwrap_used)]
|
||||
{
|
||||
*some_hashmap.get_mut(&1).unwrap() = 'b';
|
||||
*some_btreemap.get_mut(&1).unwrap() = 'b';
|
||||
*false_positive.get_mut(0).unwrap() = 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Test `get().unwrap().foo()` and `get_mut().unwrap().bar()`
|
||||
let _ = some_vec[0..1].to_vec();
|
||||
let _ = some_vec[0..1].to_vec();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
|
||||
let _ = &boxed_slice[1];
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod issue9612 {
|
||||
// should not lint in `#[cfg(test)]` modules
|
||||
#[test]
|
||||
fn test_fn() {
|
||||
let _a: u8 = 2.try_into().unwrap();
|
||||
let _a: u8 = 3.try_into().expect("");
|
||||
|
||||
util();
|
||||
}
|
||||
|
||||
fn util() {
|
||||
let _a: u8 = 4.try_into().unwrap();
|
||||
let _a: u8 = 5.try_into().expect("");
|
||||
// should still warn
|
||||
let _ = &Box::new([0])[1];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#![warn(clippy::upper_case_acronyms)]
|
||||
|
||||
struct HttpResponse; // not linted by default, but with cfg option
|
||||
|
||||
struct CString; // not linted
|
||||
|
||||
enum Flags {
|
||||
Ns, // not linted
|
||||
Cwr,
|
||||
Ece,
|
||||
Urg,
|
||||
Ack,
|
||||
Psh,
|
||||
Rst,
|
||||
Syn,
|
||||
Fin,
|
||||
}
|
||||
|
||||
// linted with cfg option, beware that lint suggests `GccllvmSomething` instead of
|
||||
// `GccLlvmSomething`
|
||||
struct GccllvmSomething;
|
||||
|
||||
// don't warn on public items
|
||||
pub struct MIXEDCapital;
|
||||
|
||||
pub struct FULLCAPITAL;
|
||||
|
||||
// enum variants should not be linted if the num is pub
|
||||
pub enum ParseError<T> {
|
||||
FULLCAPITAL(u8),
|
||||
MIXEDCapital(String),
|
||||
Utf8(std::string::FromUtf8Error),
|
||||
Parse(T, String),
|
||||
}
|
||||
|
||||
// private, do lint here
|
||||
enum ParseErrorPrivate<T> {
|
||||
Wasd(u8),
|
||||
WasdMixed(String),
|
||||
Utf8(std::string::FromUtf8Error),
|
||||
Parse(T, String),
|
||||
}
|
||||
|
||||
fn main() {}
|
16
tests/ui-toml/vec_box_sized/test.fixed
Normal file
16
tests/ui-toml/vec_box_sized/test.fixed
Normal file
|
@ -0,0 +1,16 @@
|
|||
struct S {
|
||||
x: u64,
|
||||
}
|
||||
|
||||
struct C {
|
||||
y: u16,
|
||||
}
|
||||
|
||||
struct Foo(Vec<u8>);
|
||||
struct Bar(Vec<u16>);
|
||||
struct Quux(Vec<Box<u32>>);
|
||||
struct Baz(Vec<Box<(u16, u16)>>);
|
||||
struct BarBaz(Vec<Box<S>>);
|
||||
struct FooBarBaz(Vec<C>);
|
||||
|
||||
fn main() {}
|
|
@ -12,27 +12,46 @@ fn main() {
|
|||
const Z: u32 = 0;
|
||||
let u: u32 = 42;
|
||||
u <= 0;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
u <= Z;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
u < Z;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
Z >= u;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
Z > u;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
u > u32::MAX;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
u >= u32::MAX;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
u32::MAX < u;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
u32::MAX <= u;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
1-1 > u;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
u >= !0;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
u <= 12 - 2*6;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
let i: i8 = 0;
|
||||
i < -127 - 1;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
i8::MAX >= i;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
3-7 < i32::MIN;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
let b = false;
|
||||
b >= true;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
false > b;
|
||||
//~^ ERROR: this comparison involving the minimum or maximum element for this type con
|
||||
u > 0; // ok
|
||||
// this is handled by clippy::unit_cmp
|
||||
() < {};
|
||||
//~^ ERROR: <-comparison of unit values detected. This will always be false
|
||||
//~| NOTE: `#[deny(clippy::unit_cmp)]` on by default
|
||||
}
|
||||
|
||||
use std::cmp::{Ordering, PartialEq, PartialOrd};
|
||||
|
|
|
@ -8,7 +8,7 @@ LL | u <= 0;
|
|||
= note: `-D clippy::absurd-extreme-comparisons` implied by `-D warnings`
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:15:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:16:5
|
||||
|
|
||||
LL | u <= Z;
|
||||
| ^^^^^^
|
||||
|
@ -16,7 +16,7 @@ LL | u <= Z;
|
|||
= help: because `Z` is the minimum value for this type, the case where the two sides are not equal never occurs, consider using `u == Z` instead
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:16:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:18:5
|
||||
|
|
||||
LL | u < Z;
|
||||
| ^^^^^
|
||||
|
@ -24,7 +24,7 @@ LL | u < Z;
|
|||
= help: because `Z` is the minimum value for this type, this comparison is always false
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:17:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:20:5
|
||||
|
|
||||
LL | Z >= u;
|
||||
| ^^^^^^
|
||||
|
@ -32,7 +32,7 @@ LL | Z >= u;
|
|||
= help: because `Z` is the minimum value for this type, the case where the two sides are not equal never occurs, consider using `Z == u` instead
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:18:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:22:5
|
||||
|
|
||||
LL | Z > u;
|
||||
| ^^^^^
|
||||
|
@ -40,7 +40,7 @@ LL | Z > u;
|
|||
= help: because `Z` is the minimum value for this type, this comparison is always false
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:19:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:24:5
|
||||
|
|
||||
LL | u > u32::MAX;
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -48,7 +48,7 @@ LL | u > u32::MAX;
|
|||
= help: because `u32::MAX` is the maximum value for this type, this comparison is always false
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:20:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:26:5
|
||||
|
|
||||
LL | u >= u32::MAX;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -56,7 +56,7 @@ LL | u >= u32::MAX;
|
|||
= help: because `u32::MAX` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `u == u32::MAX` instead
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:21:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:28:5
|
||||
|
|
||||
LL | u32::MAX < u;
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -64,7 +64,7 @@ LL | u32::MAX < u;
|
|||
= help: because `u32::MAX` is the maximum value for this type, this comparison is always false
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:22:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:30:5
|
||||
|
|
||||
LL | u32::MAX <= u;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -72,7 +72,7 @@ LL | u32::MAX <= u;
|
|||
= help: because `u32::MAX` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `u32::MAX == u` instead
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:23:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:32:5
|
||||
|
|
||||
LL | 1-1 > u;
|
||||
| ^^^^^^^
|
||||
|
@ -80,7 +80,7 @@ LL | 1-1 > u;
|
|||
= help: because `1-1` is the minimum value for this type, this comparison is always false
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:24:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:34:5
|
||||
|
|
||||
LL | u >= !0;
|
||||
| ^^^^^^^
|
||||
|
@ -88,7 +88,7 @@ LL | u >= !0;
|
|||
= help: because `!0` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `u == !0` instead
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:25:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:36:5
|
||||
|
|
||||
LL | u <= 12 - 2*6;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -96,7 +96,7 @@ LL | u <= 12 - 2*6;
|
|||
= help: because `12 - 2*6` is the minimum value for this type, the case where the two sides are not equal never occurs, consider using `u == 12 - 2*6` instead
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:27:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:39:5
|
||||
|
|
||||
LL | i < -127 - 1;
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -104,7 +104,7 @@ LL | i < -127 - 1;
|
|||
= help: because `-127 - 1` is the minimum value for this type, this comparison is always false
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:28:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:41:5
|
||||
|
|
||||
LL | i8::MAX >= i;
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -112,7 +112,7 @@ LL | i8::MAX >= i;
|
|||
= help: because `i8::MAX` is the maximum value for this type, this comparison is always true
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:29:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:43:5
|
||||
|
|
||||
LL | 3-7 < i32::MIN;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
@ -120,7 +120,7 @@ LL | 3-7 < i32::MIN;
|
|||
= help: because `i32::MIN` is the minimum value for this type, this comparison is always false
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:31:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:46:5
|
||||
|
|
||||
LL | b >= true;
|
||||
| ^^^^^^^^^
|
||||
|
@ -128,7 +128,7 @@ LL | b >= true;
|
|||
= help: because `true` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `b == true` instead
|
||||
|
||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:32:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:48:5
|
||||
|
|
||||
LL | false > b;
|
||||
| ^^^^^^^^^
|
||||
|
@ -136,7 +136,7 @@ LL | false > b;
|
|||
= help: because `false` is the minimum value for this type, this comparison is always false
|
||||
|
||||
error: <-comparison of unit values detected. This will always be false
|
||||
--> $DIR/absurd-extreme-comparisons.rs:35:5
|
||||
--> $DIR/absurd-extreme-comparisons.rs:52:5
|
||||
|
|
||||
LL | () < {};
|
||||
| ^^^^^^^
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//@run-rustfix
|
||||
//@aux-build:proc_macros.rs:proc-macro
|
||||
//@aux-build:proc_macros.rs
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::allow_attributes)]
|
||||
#![feature(lint_reasons)]
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//@run-rustfix
|
||||
//@aux-build:proc_macros.rs:proc-macro
|
||||
//@aux-build:proc_macros.rs
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::allow_attributes)]
|
||||
#![feature(lint_reasons)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: #[allow] attribute found
|
||||
--> $DIR/allow_attributes.rs:14:3
|
||||
--> $DIR/allow_attributes.rs:13:3
|
||||
|
|
||||
LL | #[allow(dead_code)]
|
||||
| ^^^^^ help: replace it with: `expect`
|
||||
|
@ -7,7 +7,7 @@ LL | #[allow(dead_code)]
|
|||
= note: `-D clippy::allow-attributes` implied by `-D warnings`
|
||||
|
||||
error: #[allow] attribute found
|
||||
--> $DIR/allow_attributes.rs:23:30
|
||||
--> $DIR/allow_attributes.rs:22:30
|
||||
|
|
||||
LL | #[cfg_attr(panic = "unwind", allow(dead_code))]
|
||||
| ^^^^^ help: replace it with: `expect`
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//@aux-build:proc_macros.rs:proc-macro
|
||||
//@aux-build:proc_macros.rs
|
||||
#![feature(lint_reasons)]
|
||||
#![deny(clippy::allow_attributes_without_reason)]
|
||||
#![allow(unfulfilled_lint_expectations)]
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
//@run-rustfix
|
||||
//@edition:2018
|
||||
//@aux-build:proc_macros.rs:proc-macro
|
||||
//@aux-build:proc_macros.rs
|
||||
|
||||
#![feature(exclusive_range_pattern)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
//@run-rustfix
|
||||
//@edition:2018
|
||||
//@aux-build:proc_macros.rs:proc-macro
|
||||
//@aux-build:proc_macros.rs
|
||||
|
||||
#![feature(exclusive_range_pattern)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:19:17
|
||||
--> $DIR/almost_complete_range.rs:18:17
|
||||
|
|
||||
LL | let _ = ('a') ..'z';
|
||||
| ^^^^^^--^^^
|
||||
|
@ -9,7 +9,7 @@ LL | let _ = ('a') ..'z';
|
|||
= note: `-D clippy::almost-complete-range` implied by `-D warnings`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:20:17
|
||||
--> $DIR/almost_complete_range.rs:19:17
|
||||
|
|
||||
LL | let _ = 'A' .. ('Z');
|
||||
| ^^^^--^^^^^^
|
||||
|
@ -17,7 +17,7 @@ LL | let _ = 'A' .. ('Z');
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:21:17
|
||||
--> $DIR/almost_complete_range.rs:20:17
|
||||
|
|
||||
LL | let _ = ((('0'))) .. ('9');
|
||||
| ^^^^^^^^^^--^^^^^^
|
||||
|
@ -25,7 +25,7 @@ LL | let _ = ((('0'))) .. ('9');
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:28:13
|
||||
--> $DIR/almost_complete_range.rs:27:13
|
||||
|
|
||||
LL | let _ = (b'a')..(b'z');
|
||||
| ^^^^^^--^^^^^^
|
||||
|
@ -33,7 +33,7 @@ LL | let _ = (b'a')..(b'z');
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:29:13
|
||||
--> $DIR/almost_complete_range.rs:28:13
|
||||
|
|
||||
LL | let _ = b'A'..b'Z';
|
||||
| ^^^^--^^^^
|
||||
|
@ -41,7 +41,7 @@ LL | let _ = b'A'..b'Z';
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:30:13
|
||||
--> $DIR/almost_complete_range.rs:29:13
|
||||
|
|
||||
LL | let _ = b'0'..b'9';
|
||||
| ^^^^--^^^^
|
||||
|
@ -49,7 +49,7 @@ LL | let _ = b'0'..b'9';
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:36:13
|
||||
--> $DIR/almost_complete_range.rs:35:13
|
||||
|
|
||||
LL | let _ = inline!('a')..'z';
|
||||
| ^^^^^^^^^^^^--^^^
|
||||
|
@ -57,7 +57,7 @@ LL | let _ = inline!('a')..'z';
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:37:13
|
||||
--> $DIR/almost_complete_range.rs:36:13
|
||||
|
|
||||
LL | let _ = inline!('A')..'Z';
|
||||
| ^^^^^^^^^^^^--^^^
|
||||
|
@ -65,7 +65,7 @@ LL | let _ = inline!('A')..'Z';
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:38:13
|
||||
--> $DIR/almost_complete_range.rs:37:13
|
||||
|
|
||||
LL | let _ = inline!('0')..'9';
|
||||
| ^^^^^^^^^^^^--^^^
|
||||
|
@ -73,7 +73,7 @@ LL | let _ = inline!('0')..'9';
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:41:9
|
||||
--> $DIR/almost_complete_range.rs:40:9
|
||||
|
|
||||
LL | b'a'..b'z' if true => 1,
|
||||
| ^^^^--^^^^
|
||||
|
@ -81,7 +81,7 @@ LL | b'a'..b'z' if true => 1,
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:42:9
|
||||
--> $DIR/almost_complete_range.rs:41:9
|
||||
|
|
||||
LL | b'A'..b'Z' if true => 2,
|
||||
| ^^^^--^^^^
|
||||
|
@ -89,7 +89,7 @@ LL | b'A'..b'Z' if true => 2,
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:43:9
|
||||
--> $DIR/almost_complete_range.rs:42:9
|
||||
|
|
||||
LL | b'0'..b'9' if true => 3,
|
||||
| ^^^^--^^^^
|
||||
|
@ -97,7 +97,7 @@ LL | b'0'..b'9' if true => 3,
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:51:9
|
||||
--> $DIR/almost_complete_range.rs:50:9
|
||||
|
|
||||
LL | 'a'..'z' if true => 1,
|
||||
| ^^^--^^^
|
||||
|
@ -105,7 +105,7 @@ LL | 'a'..'z' if true => 1,
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:52:9
|
||||
--> $DIR/almost_complete_range.rs:51:9
|
||||
|
|
||||
LL | 'A'..'Z' if true => 2,
|
||||
| ^^^--^^^
|
||||
|
@ -113,7 +113,7 @@ LL | 'A'..'Z' if true => 2,
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:53:9
|
||||
--> $DIR/almost_complete_range.rs:52:9
|
||||
|
|
||||
LL | '0'..'9' if true => 3,
|
||||
| ^^^--^^^
|
||||
|
@ -121,7 +121,7 @@ LL | '0'..'9' if true => 3,
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:66:17
|
||||
--> $DIR/almost_complete_range.rs:65:17
|
||||
|
|
||||
LL | let _ = 'a'..'z';
|
||||
| ^^^--^^^
|
||||
|
@ -131,7 +131,7 @@ LL | let _ = 'a'..'z';
|
|||
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:67:17
|
||||
--> $DIR/almost_complete_range.rs:66:17
|
||||
|
|
||||
LL | let _ = 'A'..'Z';
|
||||
| ^^^--^^^
|
||||
|
@ -141,7 +141,7 @@ LL | let _ = 'A'..'Z';
|
|||
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:68:17
|
||||
--> $DIR/almost_complete_range.rs:67:17
|
||||
|
|
||||
LL | let _ = '0'..'9';
|
||||
| ^^^--^^^
|
||||
|
@ -151,7 +151,7 @@ LL | let _ = '0'..'9';
|
|||
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:75:9
|
||||
--> $DIR/almost_complete_range.rs:74:9
|
||||
|
|
||||
LL | 'a'..'z' => 1,
|
||||
| ^^^--^^^
|
||||
|
@ -159,7 +159,7 @@ LL | 'a'..'z' => 1,
|
|||
| help: use an inclusive range: `...`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:76:9
|
||||
--> $DIR/almost_complete_range.rs:75:9
|
||||
|
|
||||
LL | 'A'..'Z' => 2,
|
||||
| ^^^--^^^
|
||||
|
@ -167,7 +167,7 @@ LL | 'A'..'Z' => 2,
|
|||
| help: use an inclusive range: `...`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:77:9
|
||||
--> $DIR/almost_complete_range.rs:76:9
|
||||
|
|
||||
LL | '0'..'9' => 3,
|
||||
| ^^^--^^^
|
||||
|
@ -175,7 +175,7 @@ LL | '0'..'9' => 3,
|
|||
| help: use an inclusive range: `...`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:84:13
|
||||
--> $DIR/almost_complete_range.rs:83:13
|
||||
|
|
||||
LL | let _ = 'a'..'z';
|
||||
| ^^^--^^^
|
||||
|
@ -183,7 +183,7 @@ LL | let _ = 'a'..'z';
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:85:13
|
||||
--> $DIR/almost_complete_range.rs:84:13
|
||||
|
|
||||
LL | let _ = 'A'..'Z';
|
||||
| ^^^--^^^
|
||||
|
@ -191,7 +191,7 @@ LL | let _ = 'A'..'Z';
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:86:13
|
||||
--> $DIR/almost_complete_range.rs:85:13
|
||||
|
|
||||
LL | let _ = '0'..'9';
|
||||
| ^^^--^^^
|
||||
|
@ -199,7 +199,7 @@ LL | let _ = '0'..'9';
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:88:9
|
||||
--> $DIR/almost_complete_range.rs:87:9
|
||||
|
|
||||
LL | 'a'..'z' => 1,
|
||||
| ^^^--^^^
|
||||
|
@ -207,7 +207,7 @@ LL | 'a'..'z' => 1,
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:89:9
|
||||
--> $DIR/almost_complete_range.rs:88:9
|
||||
|
|
||||
LL | 'A'..'Z' => 1,
|
||||
| ^^^--^^^
|
||||
|
@ -215,7 +215,7 @@ LL | 'A'..'Z' => 1,
|
|||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii range
|
||||
--> $DIR/almost_complete_range.rs:90:9
|
||||
--> $DIR/almost_complete_range.rs:89:9
|
||||
|
|
||||
LL | '0'..'9' => 3,
|
||||
| ^^^--^^^
|
||||
|
|
|
@ -2,63 +2,86 @@
|
|||
#[allow(clippy::similar_names)]
|
||||
fn main() {
|
||||
let my_e = 2.7182;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::E` found
|
||||
let almost_e = 2.718;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::E` found
|
||||
let no_e = 2.71;
|
||||
|
||||
let my_1_frac_pi = 0.3183;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_1_PI` found
|
||||
let no_1_frac_pi = 0.31;
|
||||
|
||||
let my_frac_1_sqrt_2 = 0.70710678;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
|
||||
let almost_frac_1_sqrt_2 = 0.70711;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
|
||||
let my_frac_1_sqrt_2 = 0.707;
|
||||
|
||||
let my_frac_2_pi = 0.63661977;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_2_PI` found
|
||||
let no_frac_2_pi = 0.636;
|
||||
|
||||
let my_frac_2_sq_pi = 1.128379;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found
|
||||
let no_frac_2_sq_pi = 1.128;
|
||||
|
||||
let my_frac_pi_2 = 1.57079632679;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_PI_2` found
|
||||
let no_frac_pi_2 = 1.5705;
|
||||
|
||||
let my_frac_pi_3 = 1.04719755119;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_PI_3` found
|
||||
let no_frac_pi_3 = 1.047;
|
||||
|
||||
let my_frac_pi_4 = 0.785398163397;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_PI_4` found
|
||||
let no_frac_pi_4 = 0.785;
|
||||
|
||||
let my_frac_pi_6 = 0.523598775598;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_PI_6` found
|
||||
let no_frac_pi_6 = 0.523;
|
||||
|
||||
let my_frac_pi_8 = 0.3926990816987;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_PI_8` found
|
||||
let no_frac_pi_8 = 0.392;
|
||||
|
||||
let my_ln_10 = 2.302585092994046;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::LN_10` found
|
||||
let no_ln_10 = 2.303;
|
||||
|
||||
let my_ln_2 = 0.6931471805599453;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::LN_2` found
|
||||
let no_ln_2 = 0.693;
|
||||
|
||||
let my_log10_e = 0.4342944819032518;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::LOG10_E` found
|
||||
let no_log10_e = 0.434;
|
||||
|
||||
let my_log2_e = 1.4426950408889634;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::LOG2_E` found
|
||||
let no_log2_e = 1.442;
|
||||
|
||||
let log2_10 = 3.321928094887362;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::LOG2_10` found
|
||||
let no_log2_10 = 3.321;
|
||||
|
||||
let log10_2 = 0.301029995663981;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::LOG10_2` found
|
||||
let no_log10_2 = 0.301;
|
||||
|
||||
let my_pi = 3.1415;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::PI` found
|
||||
let almost_pi = 3.14;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::PI` found
|
||||
let no_pi = 3.15;
|
||||
|
||||
let my_sq2 = 1.4142;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::SQRT_2` found
|
||||
let no_sq2 = 1.414;
|
||||
|
||||
let my_tau = 6.2832;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::TAU` found
|
||||
let almost_tau = 6.28;
|
||||
//~^ ERROR: approximate value of `f{32, 64}::consts::TAU` found
|
||||
let no_tau = 6.3;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ LL | let my_e = 2.7182;
|
|||
= note: `-D clippy::approx-constant` implied by `-D warnings`
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::E` found
|
||||
--> $DIR/approx_const.rs:5:20
|
||||
--> $DIR/approx_const.rs:6:20
|
||||
|
|
||||
LL | let almost_e = 2.718;
|
||||
| ^^^^^
|
||||
|
@ -16,7 +16,7 @@ LL | let almost_e = 2.718;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found
|
||||
--> $DIR/approx_const.rs:8:24
|
||||
--> $DIR/approx_const.rs:10:24
|
||||
|
|
||||
LL | let my_1_frac_pi = 0.3183;
|
||||
| ^^^^^^
|
||||
|
@ -24,7 +24,7 @@ LL | let my_1_frac_pi = 0.3183;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
|
||||
--> $DIR/approx_const.rs:11:28
|
||||
--> $DIR/approx_const.rs:14:28
|
||||
|
|
||||
LL | let my_frac_1_sqrt_2 = 0.70710678;
|
||||
| ^^^^^^^^^^
|
||||
|
@ -32,7 +32,7 @@ LL | let my_frac_1_sqrt_2 = 0.70710678;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
|
||||
--> $DIR/approx_const.rs:12:32
|
||||
--> $DIR/approx_const.rs:16:32
|
||||
|
|
||||
LL | let almost_frac_1_sqrt_2 = 0.70711;
|
||||
| ^^^^^^^
|
||||
|
@ -40,7 +40,7 @@ LL | let almost_frac_1_sqrt_2 = 0.70711;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found
|
||||
--> $DIR/approx_const.rs:15:24
|
||||
--> $DIR/approx_const.rs:20:24
|
||||
|
|
||||
LL | let my_frac_2_pi = 0.63661977;
|
||||
| ^^^^^^^^^^
|
||||
|
@ -48,7 +48,7 @@ LL | let my_frac_2_pi = 0.63661977;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found
|
||||
--> $DIR/approx_const.rs:18:27
|
||||
--> $DIR/approx_const.rs:24:27
|
||||
|
|
||||
LL | let my_frac_2_sq_pi = 1.128379;
|
||||
| ^^^^^^^^
|
||||
|
@ -56,7 +56,7 @@ LL | let my_frac_2_sq_pi = 1.128379;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found
|
||||
--> $DIR/approx_const.rs:21:24
|
||||
--> $DIR/approx_const.rs:28:24
|
||||
|
|
||||
LL | let my_frac_pi_2 = 1.57079632679;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -64,7 +64,7 @@ LL | let my_frac_pi_2 = 1.57079632679;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found
|
||||
--> $DIR/approx_const.rs:24:24
|
||||
--> $DIR/approx_const.rs:32:24
|
||||
|
|
||||
LL | let my_frac_pi_3 = 1.04719755119;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -72,7 +72,7 @@ LL | let my_frac_pi_3 = 1.04719755119;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found
|
||||
--> $DIR/approx_const.rs:27:24
|
||||
--> $DIR/approx_const.rs:36:24
|
||||
|
|
||||
LL | let my_frac_pi_4 = 0.785398163397;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
@ -80,7 +80,7 @@ LL | let my_frac_pi_4 = 0.785398163397;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found
|
||||
--> $DIR/approx_const.rs:30:24
|
||||
--> $DIR/approx_const.rs:40:24
|
||||
|
|
||||
LL | let my_frac_pi_6 = 0.523598775598;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
@ -88,7 +88,7 @@ LL | let my_frac_pi_6 = 0.523598775598;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found
|
||||
--> $DIR/approx_const.rs:33:24
|
||||
--> $DIR/approx_const.rs:44:24
|
||||
|
|
||||
LL | let my_frac_pi_8 = 0.3926990816987;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
@ -96,7 +96,7 @@ LL | let my_frac_pi_8 = 0.3926990816987;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::LN_10` found
|
||||
--> $DIR/approx_const.rs:36:20
|
||||
--> $DIR/approx_const.rs:48:20
|
||||
|
|
||||
LL | let my_ln_10 = 2.302585092994046;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
@ -104,7 +104,7 @@ LL | let my_ln_10 = 2.302585092994046;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::LN_2` found
|
||||
--> $DIR/approx_const.rs:39:19
|
||||
--> $DIR/approx_const.rs:52:19
|
||||
|
|
||||
LL | let my_ln_2 = 0.6931471805599453;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
@ -112,7 +112,7 @@ LL | let my_ln_2 = 0.6931471805599453;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::LOG10_E` found
|
||||
--> $DIR/approx_const.rs:42:22
|
||||
--> $DIR/approx_const.rs:56:22
|
||||
|
|
||||
LL | let my_log10_e = 0.4342944819032518;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
@ -120,7 +120,7 @@ LL | let my_log10_e = 0.4342944819032518;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::LOG2_E` found
|
||||
--> $DIR/approx_const.rs:45:21
|
||||
--> $DIR/approx_const.rs:60:21
|
||||
|
|
||||
LL | let my_log2_e = 1.4426950408889634;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
@ -128,7 +128,7 @@ LL | let my_log2_e = 1.4426950408889634;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::LOG2_10` found
|
||||
--> $DIR/approx_const.rs:48:19
|
||||
--> $DIR/approx_const.rs:64:19
|
||||
|
|
||||
LL | let log2_10 = 3.321928094887362;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
@ -136,7 +136,7 @@ LL | let log2_10 = 3.321928094887362;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::LOG10_2` found
|
||||
--> $DIR/approx_const.rs:51:19
|
||||
--> $DIR/approx_const.rs:68:19
|
||||
|
|
||||
LL | let log10_2 = 0.301029995663981;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
@ -144,7 +144,7 @@ LL | let log10_2 = 0.301029995663981;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::PI` found
|
||||
--> $DIR/approx_const.rs:54:17
|
||||
--> $DIR/approx_const.rs:72:17
|
||||
|
|
||||
LL | let my_pi = 3.1415;
|
||||
| ^^^^^^
|
||||
|
@ -152,7 +152,7 @@ LL | let my_pi = 3.1415;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::PI` found
|
||||
--> $DIR/approx_const.rs:55:21
|
||||
--> $DIR/approx_const.rs:74:21
|
||||
|
|
||||
LL | let almost_pi = 3.14;
|
||||
| ^^^^
|
||||
|
@ -160,7 +160,7 @@ LL | let almost_pi = 3.14;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::SQRT_2` found
|
||||
--> $DIR/approx_const.rs:58:18
|
||||
--> $DIR/approx_const.rs:78:18
|
||||
|
|
||||
LL | let my_sq2 = 1.4142;
|
||||
| ^^^^^^
|
||||
|
@ -168,7 +168,7 @@ LL | let my_sq2 = 1.4142;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::TAU` found
|
||||
--> $DIR/approx_const.rs:61:18
|
||||
--> $DIR/approx_const.rs:82:18
|
||||
|
|
||||
LL | let my_tau = 6.2832;
|
||||
| ^^^^^^
|
||||
|
@ -176,7 +176,7 @@ LL | let my_tau = 6.2832;
|
|||
= help: consider using the constant directly
|
||||
|
||||
error: approximate value of `f{32, 64}::consts::TAU` found
|
||||
--> $DIR/approx_const.rs:62:22
|
||||
--> $DIR/approx_const.rs:84:22
|
||||
|
|
||||
LL | let almost_tau = 6.28;
|
||||
| ^^^^
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//@aux-build:proc_macros.rs:proc-macro
|
||||
//@aux-build:proc_macros.rs
|
||||
#![warn(clippy::arc_with_non_send_sync)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//@aux-build:proc_macro_derive.rs:proc-macro
|
||||
//@aux-build:proc_macro_derive.rs
|
||||
|
||||
#![allow(
|
||||
clippy::assign_op_pattern,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue