mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 07:00:55 +00:00
Auto merge of #107386 - flip1995:clippyup, r=Manishearth
Update Clippy r? `@Manishearth`
This commit is contained in:
commit
997fe0d57e
57 changed files with 2262 additions and 304 deletions
5
.github/workflows/clippy_bors.yml
vendored
5
.github/workflows/clippy_bors.yml
vendored
|
@ -157,6 +157,11 @@ jobs:
|
|||
- name: Test metadata collection
|
||||
run: cargo collect-metadata
|
||||
|
||||
- name: Test lint_configuration.md is up-to-date
|
||||
run: |
|
||||
echo "run \`cargo collect-metadata\` if this fails"
|
||||
git update-index --refresh
|
||||
|
||||
integration_build:
|
||||
needs: changelog
|
||||
runs-on: ubuntu-latest
|
||||
|
|
199
CHANGELOG.md
199
CHANGELOG.md
|
@ -6,11 +6,204 @@ document.
|
|||
|
||||
## Unreleased / Beta / In Rust Nightly
|
||||
|
||||
[4f142aa1...master](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...master)
|
||||
[d822110d...master](https://github.com/rust-lang/rust-clippy/compare/d822110d...master)
|
||||
|
||||
## Rust 1.67
|
||||
|
||||
Current stable, released 2023-01-26
|
||||
|
||||
[4f142aa1...d822110d](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...d822110d)
|
||||
|
||||
### New Lints
|
||||
|
||||
* [`seek_from_current`]
|
||||
[#9681](https://github.com/rust-lang/rust-clippy/pull/9681)
|
||||
* [`from_raw_with_void_ptr`]
|
||||
[#9690](https://github.com/rust-lang/rust-clippy/pull/9690)
|
||||
* [`misnamed_getters`]
|
||||
[#9770](https://github.com/rust-lang/rust-clippy/pull/9770)
|
||||
* [`seek_to_start_instead_of_rewind`]
|
||||
[#9667](https://github.com/rust-lang/rust-clippy/pull/9667)
|
||||
* [`suspicious_xor_used_as_pow`]
|
||||
[#9506](https://github.com/rust-lang/rust-clippy/pull/9506)
|
||||
* [`unnecessary_safety_doc`]
|
||||
[#9822](https://github.com/rust-lang/rust-clippy/pull/9822)
|
||||
* [`unchecked_duration_subtraction`]
|
||||
[#9570](https://github.com/rust-lang/rust-clippy/pull/9570)
|
||||
* [`manual_is_ascii_check`]
|
||||
[#9765](https://github.com/rust-lang/rust-clippy/pull/9765)
|
||||
* [`unnecessary_safety_comment`]
|
||||
[#9851](https://github.com/rust-lang/rust-clippy/pull/9851)
|
||||
* [`let_underscore_future`]
|
||||
[#9760](https://github.com/rust-lang/rust-clippy/pull/9760)
|
||||
* [`manual_let_else`]
|
||||
[#8437](https://github.com/rust-lang/rust-clippy/pull/8437)
|
||||
|
||||
### Moves and Deprecations
|
||||
|
||||
* Moved [`uninlined_format_args`] to `style` (Now warn-by-default)
|
||||
[#9865](https://github.com/rust-lang/rust-clippy/pull/9865)
|
||||
* Moved [`needless_collect`] to `nursery` (Now allow-by-default)
|
||||
[#9705](https://github.com/rust-lang/rust-clippy/pull/9705)
|
||||
* Moved [`or_fun_call`] to `nursery` (Now allow-by-default)
|
||||
[#9829](https://github.com/rust-lang/rust-clippy/pull/9829)
|
||||
* Uplifted [`let_underscore_lock`] into rustc
|
||||
[#9697](https://github.com/rust-lang/rust-clippy/pull/9697)
|
||||
* Uplifted [`let_underscore_drop`] into rustc
|
||||
[#9697](https://github.com/rust-lang/rust-clippy/pull/9697)
|
||||
* Moved [`bool_to_int_with_if`] to `pedantic` (Now allow-by-default)
|
||||
[#9830](https://github.com/rust-lang/rust-clippy/pull/9830)
|
||||
* Move `index_refutable_slice` to `pedantic` (Now warn-by-default)
|
||||
[#9975](https://github.com/rust-lang/rust-clippy/pull/9975)
|
||||
* Moved [`manual_clamp`] to `nursery` (Now allow-by-default)
|
||||
[#10101](https://github.com/rust-lang/rust-clippy/pull/10101)
|
||||
|
||||
### Enhancements
|
||||
|
||||
* The scope of `#![clippy::msrv]` is now tracked correctly
|
||||
[#9924](https://github.com/rust-lang/rust-clippy/pull/9924)
|
||||
* `#[clippy::msrv]` can now be used as an outer attribute
|
||||
[#9860](https://github.com/rust-lang/rust-clippy/pull/9860)
|
||||
* Clippy will now avoid Cargo's cache, if `Cargo.toml` or `clippy.toml` have changed
|
||||
[#9707](https://github.com/rust-lang/rust-clippy/pull/9707)
|
||||
* [`uninlined_format_args`]: Added a new config `allow-mixed-uninlined-format-args` to allow the
|
||||
lint, if only some arguments can be inlined
|
||||
[#9865](https://github.com/rust-lang/rust-clippy/pull/9865)
|
||||
* [`needless_lifetimes`]: Now provides suggests for individual lifetimes
|
||||
[#9743](https://github.com/rust-lang/rust-clippy/pull/9743)
|
||||
* [`needless_collect`]: Now detects needless `is_empty` and `contains` calls
|
||||
[#8744](https://github.com/rust-lang/rust-clippy/pull/8744)
|
||||
* [`blanket_clippy_restriction_lints`]: Now lints, if `clippy::restriction` is enabled via the
|
||||
command line arguments
|
||||
[#9755](https://github.com/rust-lang/rust-clippy/pull/9755)
|
||||
* [`mutable_key_type`]: Now has the `ignore-interior-mutability` configuration, to add types which
|
||||
should be ignored by the lint
|
||||
[#9692](https://github.com/rust-lang/rust-clippy/pull/9692)
|
||||
* [`uninlined_format_args`]: Now works for multiline `format!` expressions
|
||||
[#9945](https://github.com/rust-lang/rust-clippy/pull/9945)
|
||||
* [`cognitive_complexity`]: Now works for async functions
|
||||
[#9828](https://github.com/rust-lang/rust-clippy/pull/9828)
|
||||
[#9836](https://github.com/rust-lang/rust-clippy/pull/9836)
|
||||
* [`vec_box`]: Now avoids an off-by-one error when using the `vec-box-size-threshold` configuration
|
||||
[#9848](https://github.com/rust-lang/rust-clippy/pull/9848)
|
||||
* [`never_loop`]: Now correctly handles breaks in nested labeled blocks
|
||||
[#9858](https://github.com/rust-lang/rust-clippy/pull/9858)
|
||||
[#9837](https://github.com/rust-lang/rust-clippy/pull/9837)
|
||||
* [`disallowed_methods`], [`disallowed_types`], [`disallowed_macros`]: Now correctly resolve
|
||||
paths, if a crate is used multiple times with different versions
|
||||
[#9800](https://github.com/rust-lang/rust-clippy/pull/9800)
|
||||
* [`disallowed_methods`]: Can now be used for local methods
|
||||
[#9800](https://github.com/rust-lang/rust-clippy/pull/9800)
|
||||
* [`print_stdout`], [`print_stderr`]: Can now be enabled in test with the `allow-print-in-tests`
|
||||
config value
|
||||
[#9797](https://github.com/rust-lang/rust-clippy/pull/9797)
|
||||
* [`from_raw_with_void_ptr`]: Now works for `Rc`, `Arc`, `alloc::rc::Weak` and
|
||||
`alloc::sync::Weak` types.
|
||||
[#9700](https://github.com/rust-lang/rust-clippy/pull/9700)
|
||||
* [`needless_borrowed_reference`]: Now works for struct and tuple patterns with wildcards
|
||||
[#9855](https://github.com/rust-lang/rust-clippy/pull/9855)
|
||||
* [`or_fun_call`]: Now supports `map_or` methods
|
||||
[#9689](https://github.com/rust-lang/rust-clippy/pull/9689)
|
||||
* [`unwrap_used`], [`expect_used`]: No longer lints in test code
|
||||
[#9686](https://github.com/rust-lang/rust-clippy/pull/9686)
|
||||
* [`fn_params_excessive_bools`]: Is now emitted with the lint level at the linted function
|
||||
[#9698](https://github.com/rust-lang/rust-clippy/pull/9698)
|
||||
|
||||
### False Positive Fixes
|
||||
|
||||
* [`new_ret_no_self`]: No longer lints when `impl Trait<Self>` is returned
|
||||
[#9733](https://github.com/rust-lang/rust-clippy/pull/9733)
|
||||
* [`unnecessary_lazy_evaluations`]: No longer lints, if the type has a significant drop
|
||||
[#9750](https://github.com/rust-lang/rust-clippy/pull/9750)
|
||||
* [`option_if_let_else`]: No longer lints, if any arm has guard
|
||||
[#9747](https://github.com/rust-lang/rust-clippy/pull/9747)
|
||||
* [`explicit_auto_deref`]: No longer lints, if the target type is a projection with generic
|
||||
arguments
|
||||
[#9813](https://github.com/rust-lang/rust-clippy/pull/9813)
|
||||
* [`unnecessary_to_owned`]: No longer lints, if the suggestion effects types
|
||||
[#9796](https://github.com/rust-lang/rust-clippy/pull/9796)
|
||||
* [`needless_borrow`]: No longer lints, if the suggestion is affected by `Deref`
|
||||
[#9674](https://github.com/rust-lang/rust-clippy/pull/9674)
|
||||
* [`unused_unit`]: No longer lints, if lifetimes are bound to the return type
|
||||
[#9849](https://github.com/rust-lang/rust-clippy/pull/9849)
|
||||
* [`mut_mut`]: No longer lints cases with unsized mutable references
|
||||
[#9835](https://github.com/rust-lang/rust-clippy/pull/9835)
|
||||
* [`bool_to_int_with_if`]: No longer lints in const context
|
||||
[#9738](https://github.com/rust-lang/rust-clippy/pull/9738)
|
||||
* [`use_self`]: No longer lints in macros
|
||||
[#9704](https://github.com/rust-lang/rust-clippy/pull/9704)
|
||||
* [`unnecessary_operation`]: No longer lints, if multiple macros are involved
|
||||
[#9981](https://github.com/rust-lang/rust-clippy/pull/9981)
|
||||
* [`allow_attributes_without_reason`]: No longer lints inside external macros
|
||||
[#9630](https://github.com/rust-lang/rust-clippy/pull/9630)
|
||||
* [`question_mark`]: No longer lints for `if let Err()` with an `else` branch
|
||||
[#9722](https://github.com/rust-lang/rust-clippy/pull/9722)
|
||||
* [`unnecessary_cast`]: No longer lints if the identifier and cast originate from different macros
|
||||
[#9980](https://github.com/rust-lang/rust-clippy/pull/9980)
|
||||
* [`arithmetic_side_effects`]: Now detects operations with associated constants
|
||||
[#9592](https://github.com/rust-lang/rust-clippy/pull/9592)
|
||||
* [`explicit_auto_deref`]: No longer lints, if the initial value is not a reference or reference
|
||||
receiver
|
||||
[#9997](https://github.com/rust-lang/rust-clippy/pull/9997)
|
||||
* [`module_name_repetitions`], [`single_component_path_imports`]: Now handle `#[allow]`
|
||||
attributes correctly
|
||||
[#9879](https://github.com/rust-lang/rust-clippy/pull/9879)
|
||||
* [`bool_to_int_with_if`]: No longer lints `if let` statements
|
||||
[#9714](https://github.com/rust-lang/rust-clippy/pull/9714)
|
||||
* [`needless_borrow`]: No longer lints, `if`-`else`-statements that require the borrow
|
||||
[#9791](https://github.com/rust-lang/rust-clippy/pull/9791)
|
||||
* [`needless_borrow`]: No longer lints borrows, if moves were illegal
|
||||
[#9711](https://github.com/rust-lang/rust-clippy/pull/9711)
|
||||
* [`manual_swap`]: No longer lints in const context
|
||||
[#9871](https://github.com/rust-lang/rust-clippy/pull/9871)
|
||||
|
||||
### Suggestion Fixes/Improvements
|
||||
|
||||
* [`missing_safety_doc`], [`missing_errors_doc`], [`missing_panics_doc`]: No longer show the
|
||||
entire item in the lint emission.
|
||||
[#9772](https://github.com/rust-lang/rust-clippy/pull/9772)
|
||||
* [`needless_lifetimes`]: Only suggests `'_` when it's applicable
|
||||
[#9743](https://github.com/rust-lang/rust-clippy/pull/9743)
|
||||
* [`use_self`]: Now suggests full paths correctly
|
||||
[#9726](https://github.com/rust-lang/rust-clippy/pull/9726)
|
||||
* [`redundant_closure_call`]: Now correctly deals with macros during suggestion creation
|
||||
[#9987](https://github.com/rust-lang/rust-clippy/pull/9987)
|
||||
* [`unnecessary_cast`]: Suggestions now correctly deal with references
|
||||
[#9996](https://github.com/rust-lang/rust-clippy/pull/9996)
|
||||
* [`unnecessary_join`]: Suggestions now correctly use [turbofish] operators
|
||||
[#9779](https://github.com/rust-lang/rust-clippy/pull/9779)
|
||||
* [`equatable_if_let`]: Can now suggest `matches!` replacements
|
||||
[#9368](https://github.com/rust-lang/rust-clippy/pull/9368)
|
||||
* [`string_extend_chars`]: Suggestions now correctly work for `str` slices
|
||||
[#9741](https://github.com/rust-lang/rust-clippy/pull/9741)
|
||||
* [`redundant_closure_for_method_calls`]: Suggestions now include angle brackets and generic
|
||||
arguments if needed
|
||||
[#9745](https://github.com/rust-lang/rust-clippy/pull/9745)
|
||||
* [`manual_let_else`]: Suggestions no longer expand macro calls
|
||||
[#9943](https://github.com/rust-lang/rust-clippy/pull/9943)
|
||||
* [`infallible_destructuring_match`]: Suggestions now preserve references
|
||||
[#9850](https://github.com/rust-lang/rust-clippy/pull/9850)
|
||||
* [`result_large_err`]: The error now shows the largest enum variant
|
||||
[#9662](https://github.com/rust-lang/rust-clippy/pull/9662)
|
||||
* [`needless_return`]: Suggestions are now formatted better
|
||||
[#9967](https://github.com/rust-lang/rust-clippy/pull/9967)
|
||||
* [`unused_rounding`]: The suggestion now preserves the original float literal notation
|
||||
[#9870](https://github.com/rust-lang/rust-clippy/pull/9870)
|
||||
|
||||
[turbofish]: https://turbo.fish/::%3CClippy%3E
|
||||
|
||||
### ICE Fixes
|
||||
|
||||
* [`result_large_err`]: Fixed ICE for empty enums
|
||||
[#10007](https://github.com/rust-lang/rust-clippy/pull/10007)
|
||||
* [`redundant_allocation`]: Fixed ICE for types with bounded variables
|
||||
[#9773](https://github.com/rust-lang/rust-clippy/pull/9773)
|
||||
* [`unused_rounding`]: Fixed ICE, if `_` was used as a separator
|
||||
[#10001](https://github.com/rust-lang/rust-clippy/pull/10001)
|
||||
|
||||
## Rust 1.66
|
||||
|
||||
Current stable, released 2022-12-15
|
||||
Released 2022-12-15
|
||||
|
||||
[b52fb523...4f142aa1](https://github.com/rust-lang/rust-clippy/compare/b52fb523...4f142aa1)
|
||||
|
||||
|
@ -166,6 +359,7 @@ Current stable, released 2022-12-15
|
|||
|
||||
* [`unnecessary_to_owned`]: Avoid ICEs in favor of false negatives if information is missing
|
||||
[#9505](https://github.com/rust-lang/rust-clippy/pull/9505)
|
||||
[#10027](https://github.com/rust-lang/rust-clippy/pull/10027)
|
||||
* [`manual_range_contains`]: No longer ICEs on values behind references
|
||||
[#9627](https://github.com/rust-lang/rust-clippy/pull/9627)
|
||||
* [`needless_pass_by_value`]: No longer ICEs on unsized `dyn Fn` arguments
|
||||
|
@ -4383,6 +4577,7 @@ Released 2018-09-13
|
|||
[`multi_assignments`]: https://rust-lang.github.io/rust-clippy/master/index.html#multi_assignments
|
||||
[`multiple_crate_versions`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions
|
||||
[`multiple_inherent_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_inherent_impl
|
||||
[`multiple_unsafe_ops_per_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_unsafe_ops_per_block
|
||||
[`must_use_candidate`]: https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate
|
||||
[`must_use_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#must_use_unit
|
||||
[`mut_from_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_from_ref
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "clippy"
|
||||
version = "0.1.68"
|
||||
version = "0.1.69"
|
||||
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
|
||||
repository = "https://github.com/rust-lang/rust-clippy"
|
||||
readme = "README.md"
|
||||
|
|
16
README.md
16
README.md
|
@ -194,11 +194,21 @@ value` mapping e.g.
|
|||
```toml
|
||||
avoid-breaking-exported-api = false
|
||||
disallowed-names = ["toto", "tata", "titi"]
|
||||
cognitive-complexity-threshold = 30
|
||||
```
|
||||
|
||||
See the [list of configurable lints](https://rust-lang.github.io/rust-clippy/master/index.html#Configuration),
|
||||
the lint descriptions contain the names and meanings of these configuration variables.
|
||||
The [table of configurations](https://doc.rust-lang.org/nightly/clippy/lint_configuration.html)
|
||||
contains all config values, their default, and a list of lints they affect.
|
||||
Each [configurable lint](https://rust-lang.github.io/rust-clippy/master/index.html#Configuration)
|
||||
, also contains information about these values.
|
||||
|
||||
For configurations that are a list type with default values such as
|
||||
[disallowed-names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names),
|
||||
you can use the unique value `".."` to extend the default values instead of replacing them.
|
||||
|
||||
```toml
|
||||
# default of disallowed-names is ["foo", "baz", "quux"]
|
||||
disallowed-names = ["bar", ".."] # -> ["bar", "foo", "baz", "quux"]
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
- [Installation](installation.md)
|
||||
- [Usage](usage.md)
|
||||
- [Configuration](configuration.md)
|
||||
- [Lint Configuration](lint_configuration.md)
|
||||
- [Clippy's Lints](lints.md)
|
||||
- [Continuous Integration](continuous_integration/README.md)
|
||||
- [GitHub Actions](continuous_integration/github_actions.md)
|
||||
|
|
|
@ -8,11 +8,21 @@ basic `variable = value` mapping eg.
|
|||
```toml
|
||||
avoid-breaking-exported-api = false
|
||||
disallowed-names = ["toto", "tata", "titi"]
|
||||
cognitive-complexity-threshold = 30
|
||||
```
|
||||
|
||||
See the [list of configurable lints](https://rust-lang.github.io/rust-clippy/master/index.html#Configuration),
|
||||
the lint descriptions contain the names and meanings of these configuration variables.
|
||||
The [table of configurations](./lint_configuration.md)
|
||||
contains all config values, their default, and a list of lints they affect.
|
||||
Each [configurable lint](https://rust-lang.github.io/rust-clippy/master/index.html#Configuration)
|
||||
, also contains information about these values.
|
||||
|
||||
For configurations that are a list type with default values such as
|
||||
[disallowed-names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names),
|
||||
you can use the unique value `".."` to extend the default values instead of replacing them.
|
||||
|
||||
```toml
|
||||
# default of disallowed-names is ["foo", "baz", "quux"]
|
||||
disallowed-names = ["bar", ".."] # -> ["bar", "foo", "baz", "quux"]
|
||||
```
|
||||
|
||||
To deactivate the "for further information visit *lint-link*" message you can define the `CLIPPY_DISABLE_DOCS_LINKS`
|
||||
environment variable.
|
||||
|
|
|
@ -146,7 +146,8 @@ For cargo lints, the process of testing differs in that we are interested in the
|
|||
manifest.
|
||||
|
||||
If our new lint is named e.g. `foo_categories`, after running `cargo dev
|
||||
new_lint` we will find by default two new crates, each with its manifest file:
|
||||
new_lint --name=foo_categories --type=cargo --category=cargo` we will find by
|
||||
default two new crates, each with its manifest file:
|
||||
|
||||
* `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the
|
||||
new lint to raise an error.
|
||||
|
@ -699,6 +700,10 @@ for some users. Adding a configuration is done in the following steps:
|
|||
`clippy.toml` file with the configuration value and a rust file that
|
||||
should be linted by Clippy. The test can otherwise be written as usual.
|
||||
|
||||
5. Update [Lint Configuration](../lint_configuration.md)
|
||||
|
||||
Run `cargo collect-metadata` to generate documentation changes for the book.
|
||||
|
||||
[`clippy_lints::utils::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/conf.rs
|
||||
[`clippy_lints` lib file]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs
|
||||
[`tests/ui`]: https://github.com/rust-lang/rust-clippy/blob/master/tests/ui
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
This document explains how to make additions and changes to the Clippy book, the
|
||||
guide to Clippy that you're reading right now. The Clippy book is formatted with
|
||||
[Markdown](https://www.markdownguide.org) and generated by
|
||||
[mdbook](https://github.com/rust-lang/mdBook).
|
||||
[mdBook](https://github.com/rust-lang/mdBook).
|
||||
|
||||
- [Get mdbook](#get-mdbook)
|
||||
- [Get mdBook](#get-mdbook)
|
||||
- [Make changes](#make-changes)
|
||||
|
||||
## Get mdbook
|
||||
## Get mdBook
|
||||
|
||||
While not strictly necessary since the book source is simply Markdown text
|
||||
files, having mdbook locally will allow you to build, test and serve the book
|
||||
files, having mdBook locally will allow you to build, test and serve the book
|
||||
locally to view changes before you commit them to the repository. You likely
|
||||
already have `cargo` installed, so the easiest option is to simply:
|
||||
|
||||
|
@ -19,7 +19,7 @@ already have `cargo` installed, so the easiest option is to simply:
|
|||
cargo install mdbook
|
||||
```
|
||||
|
||||
See the mdbook [installation](https://github.com/rust-lang/mdBook#installation)
|
||||
See the mdBook [installation](https://github.com/rust-lang/mdBook#installation)
|
||||
instructions for other options.
|
||||
|
||||
## Make changes
|
||||
|
@ -27,7 +27,7 @@ instructions for other options.
|
|||
The book's
|
||||
[src](https://github.com/rust-lang/rust-clippy/tree/master/book/src)
|
||||
directory contains all of the markdown files used to generate the book. If you
|
||||
want to see your changes in real time, you can use the mdbook `serve` command to
|
||||
want to see your changes in real time, you can use the mdBook `serve` command to
|
||||
run a web server locally that will automatically update changes as they are
|
||||
made. From the top level of your `rust-clippy` directory:
|
||||
|
||||
|
@ -38,5 +38,5 @@ mdbook serve book --open
|
|||
Then navigate to `http://localhost:3000` to see the generated book. While the
|
||||
server is running, changes you make will automatically be updated.
|
||||
|
||||
For more information, see the mdbook
|
||||
For more information, see the mdBook
|
||||
[guide](https://rust-lang.github.io/mdBook/).
|
||||
|
|
|
@ -95,11 +95,23 @@ As section headers, we use:
|
|||
Please also be sure to update the Beta/Unreleased sections at the top with the
|
||||
relevant commit ranges.
|
||||
|
||||
If you have the time, it would be appreciated if you double-check, that the
|
||||
`#[clippy::version]` attributes for the added lints contains the correct version.
|
||||
#### 3.1 Include `beta-accepted` PRs
|
||||
|
||||
Look for the [`beta-accepted`] label and make sure to also include the PRs with
|
||||
that label in the changelog. If you can, remove the `beta-accepted` labels
|
||||
**after** the changelog PR was merged.
|
||||
|
||||
> _Note:_ Some of those PRs might even got backported to the previous `beta`.
|
||||
> Those have to be included in the changelog of the _previous_ release.
|
||||
|
||||
### 4. Update `clippy::version` attributes
|
||||
|
||||
Next, make sure to check that the `#[clippy::version]` attributes for the added
|
||||
lints contain the correct version.
|
||||
|
||||
[changelog]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md
|
||||
[forge]: https://forge.rust-lang.org/
|
||||
[rust_master_tools]: https://github.com/rust-lang/rust/tree/master/src/tools/clippy
|
||||
[rust_beta_tools]: https://github.com/rust-lang/rust/tree/beta/src/tools/clippy
|
||||
[rust_stable_tools]: https://github.com/rust-lang/rust/releases
|
||||
[`beta-accepted`]: https://github.com/rust-lang/rust-clippy/issues?q=label%3Abeta-accepted+
|
||||
|
|
523
book/src/lint_configuration.md
Normal file
523
book/src/lint_configuration.md
Normal file
|
@ -0,0 +1,523 @@
|
|||
<!--
|
||||
This file is generated by `cargo collect-metadata`.
|
||||
Please use that command to update the file and do not edit it by hand.
|
||||
-->
|
||||
|
||||
## Lint Configuration Options
|
||||
| <div style="width:290px">Option</div> | Default Value |
|
||||
|--|--|
|
||||
| [arithmetic-side-effects-allowed](#arithmetic-side-effects-allowed) | `{}` |
|
||||
| [arithmetic-side-effects-allowed-binary](#arithmetic-side-effects-allowed-binary) | `[]` |
|
||||
| [arithmetic-side-effects-allowed-unary](#arithmetic-side-effects-allowed-unary) | `{}` |
|
||||
| [avoid-breaking-exported-api](#avoid-breaking-exported-api) | `true` |
|
||||
| [msrv](#msrv) | `None` |
|
||||
| [cognitive-complexity-threshold](#cognitive-complexity-threshold) | `25` |
|
||||
| [disallowed-names](#disallowed-names) | `["foo", "baz", "quux"]` |
|
||||
| [doc-valid-idents](#doc-valid-idents) | `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` |
|
||||
| [too-many-arguments-threshold](#too-many-arguments-threshold) | `7` |
|
||||
| [type-complexity-threshold](#type-complexity-threshold) | `250` |
|
||||
| [single-char-binding-names-threshold](#single-char-binding-names-threshold) | `4` |
|
||||
| [too-large-for-stack](#too-large-for-stack) | `200` |
|
||||
| [enum-variant-name-threshold](#enum-variant-name-threshold) | `3` |
|
||||
| [enum-variant-size-threshold](#enum-variant-size-threshold) | `200` |
|
||||
| [verbose-bit-mask-threshold](#verbose-bit-mask-threshold) | `1` |
|
||||
| [literal-representation-threshold](#literal-representation-threshold) | `16384` |
|
||||
| [trivial-copy-size-limit](#trivial-copy-size-limit) | `None` |
|
||||
| [pass-by-value-size-limit](#pass-by-value-size-limit) | `256` |
|
||||
| [too-many-lines-threshold](#too-many-lines-threshold) | `100` |
|
||||
| [array-size-threshold](#array-size-threshold) | `512000` |
|
||||
| [vec-box-size-threshold](#vec-box-size-threshold) | `4096` |
|
||||
| [max-trait-bounds](#max-trait-bounds) | `3` |
|
||||
| [max-struct-bools](#max-struct-bools) | `3` |
|
||||
| [max-fn-params-bools](#max-fn-params-bools) | `3` |
|
||||
| [warn-on-all-wildcard-imports](#warn-on-all-wildcard-imports) | `false` |
|
||||
| [disallowed-macros](#disallowed-macros) | `[]` |
|
||||
| [disallowed-methods](#disallowed-methods) | `[]` |
|
||||
| [disallowed-types](#disallowed-types) | `[]` |
|
||||
| [unreadable-literal-lint-fractions](#unreadable-literal-lint-fractions) | `true` |
|
||||
| [upper-case-acronyms-aggressive](#upper-case-acronyms-aggressive) | `false` |
|
||||
| [matches-for-let-else](#matches-for-let-else) | `WellKnownTypes` |
|
||||
| [cargo-ignore-publish](#cargo-ignore-publish) | `false` |
|
||||
| [standard-macro-braces](#standard-macro-braces) | `[]` |
|
||||
| [enforced-import-renames](#enforced-import-renames) | `[]` |
|
||||
| [allowed-scripts](#allowed-scripts) | `["Latin"]` |
|
||||
| [enable-raw-pointer-heuristic-for-send](#enable-raw-pointer-heuristic-for-send) | `true` |
|
||||
| [max-suggested-slice-pattern-length](#max-suggested-slice-pattern-length) | `3` |
|
||||
| [max-include-file-size](#max-include-file-size) | `1000000` |
|
||||
| [allow-expect-in-tests](#allow-expect-in-tests) | `false` |
|
||||
| [allow-unwrap-in-tests](#allow-unwrap-in-tests) | `false` |
|
||||
| [allow-dbg-in-tests](#allow-dbg-in-tests) | `false` |
|
||||
| [allow-print-in-tests](#allow-print-in-tests) | `false` |
|
||||
| [large-error-threshold](#large-error-threshold) | `128` |
|
||||
| [ignore-interior-mutability](#ignore-interior-mutability) | `["bytes::Bytes"]` |
|
||||
| [allow-mixed-uninlined-format-args](#allow-mixed-uninlined-format-args) | `true` |
|
||||
| [suppress-restriction-lint-in-const](#suppress-restriction-lint-in-const) | `false` |
|
||||
|
||||
### arithmetic-side-effects-allowed
|
||||
Suppress checking of the passed type names in all types of operations.
|
||||
|
||||
If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
|
||||
|
||||
#### Example
|
||||
|
||||
```toml
|
||||
arithmetic-side-effects-allowed = ["SomeType", "AnotherType"]
|
||||
```
|
||||
|
||||
#### Noteworthy
|
||||
|
||||
A type, say `SomeType`, listed in this configuration has the same behavior of
|
||||
`["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
|
||||
|
||||
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
|
||||
|
||||
* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
|
||||
|
||||
|
||||
### arithmetic-side-effects-allowed-binary
|
||||
Suppress checking of the passed type pair names in binary operations like addition or
|
||||
multiplication.
|
||||
|
||||
Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless
|
||||
of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`.
|
||||
|
||||
Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as
|
||||
`["AnotherType", "SomeType"]`.
|
||||
|
||||
#### Example
|
||||
|
||||
```toml
|
||||
arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
|
||||
```
|
||||
|
||||
**Default Value:** `[]` (`Vec<[String; 2]>`)
|
||||
|
||||
* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
|
||||
|
||||
|
||||
### arithmetic-side-effects-allowed-unary
|
||||
Suppress checking of the passed type names in unary operations like "negation" (`-`).
|
||||
|
||||
#### Example
|
||||
|
||||
```toml
|
||||
arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
|
||||
```
|
||||
|
||||
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
|
||||
|
||||
* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
|
||||
|
||||
|
||||
### avoid-breaking-exported-api
|
||||
Suppress lints whenever the suggested change would cause breakage for other crates.
|
||||
|
||||
**Default Value:** `true` (`bool`)
|
||||
|
||||
* [enum_variant_names](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
|
||||
* [large_types_passed_by_value](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
|
||||
* [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
|
||||
* [unnecessary_wraps](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps)
|
||||
* [unused_self](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self)
|
||||
* [upper_case_acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
|
||||
* [wrong_self_convention](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention)
|
||||
* [box_collection](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection)
|
||||
* [redundant_allocation](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation)
|
||||
* [rc_buffer](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer)
|
||||
* [vec_box](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
|
||||
* [option_option](https://rust-lang.github.io/rust-clippy/master/index.html#option_option)
|
||||
* [linkedlist](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist)
|
||||
* [rc_mutex](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex)
|
||||
|
||||
|
||||
### msrv
|
||||
The minimum rust version that the project supports
|
||||
|
||||
**Default Value:** `None` (`Option<String>`)
|
||||
|
||||
* [manual_split_once](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once)
|
||||
* [manual_str_repeat](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat)
|
||||
* [cloned_instead_of_copied](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied)
|
||||
* [redundant_field_names](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names)
|
||||
* [redundant_static_lifetimes](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes)
|
||||
* [filter_map_next](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next)
|
||||
* [checked_conversions](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions)
|
||||
* [manual_range_contains](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains)
|
||||
* [use_self](https://rust-lang.github.io/rust-clippy/master/index.html#use_self)
|
||||
* [mem_replace_with_default](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default)
|
||||
* [manual_non_exhaustive](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive)
|
||||
* [option_as_ref_deref](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref)
|
||||
* [map_unwrap_or](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or)
|
||||
* [match_like_matches_macro](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro)
|
||||
* [manual_strip](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip)
|
||||
* [missing_const_for_fn](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn)
|
||||
* [unnested_or_patterns](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns)
|
||||
* [from_over_into](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into)
|
||||
* [ptr_as_ptr](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr)
|
||||
* [if_then_some_else_none](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none)
|
||||
* [approx_constant](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant)
|
||||
* [deprecated_cfg_attr](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr)
|
||||
* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
|
||||
* [map_clone](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone)
|
||||
* [borrow_as_ptr](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr)
|
||||
* [manual_bits](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits)
|
||||
* [err_expect](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect)
|
||||
* [cast_abs_to_unsigned](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned)
|
||||
* [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
|
||||
* [manual_clamp](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
|
||||
* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
|
||||
* [unchecked_duration_subtraction](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction)
|
||||
|
||||
|
||||
### cognitive-complexity-threshold
|
||||
The maximum cognitive complexity a function can have
|
||||
|
||||
**Default Value:** `25` (`u64`)
|
||||
|
||||
* [cognitive_complexity](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity)
|
||||
|
||||
|
||||
### disallowed-names
|
||||
The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
|
||||
`".."` can be used as part of the list to indicate, that the configured values should be appended to the
|
||||
default configuration of Clippy. By default any configuration will replace the default value.
|
||||
|
||||
**Default Value:** `["foo", "baz", "quux"]` (`Vec<String>`)
|
||||
|
||||
* [disallowed_names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names)
|
||||
|
||||
|
||||
### doc-valid-idents
|
||||
The list of words this lint should not consider as identifiers needing ticks. The value
|
||||
`".."` can be used as part of the list to indicate, that the configured values should be appended to the
|
||||
default configuration of Clippy. By default any configuraction will replace the default value. For example:
|
||||
* `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
|
||||
* `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
|
||||
|
||||
Default list:
|
||||
|
||||
**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` (`Vec<String>`)
|
||||
|
||||
* [doc_markdown](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown)
|
||||
|
||||
|
||||
### too-many-arguments-threshold
|
||||
The maximum number of argument a function or method can have
|
||||
|
||||
**Default Value:** `7` (`u64`)
|
||||
|
||||
* [too_many_arguments](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments)
|
||||
|
||||
|
||||
### type-complexity-threshold
|
||||
The maximum complexity a type can have
|
||||
|
||||
**Default Value:** `250` (`u64`)
|
||||
|
||||
* [type_complexity](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity)
|
||||
|
||||
|
||||
### single-char-binding-names-threshold
|
||||
The maximum number of single char bindings a scope may have
|
||||
|
||||
**Default Value:** `4` (`u64`)
|
||||
|
||||
* [many_single_char_names](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names)
|
||||
|
||||
|
||||
### too-large-for-stack
|
||||
The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
|
||||
|
||||
**Default Value:** `200` (`u64`)
|
||||
|
||||
* [boxed_local](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local)
|
||||
* [useless_vec](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec)
|
||||
|
||||
|
||||
### enum-variant-name-threshold
|
||||
The minimum number of enum variants for the lints about variant names to trigger
|
||||
|
||||
**Default Value:** `3` (`u64`)
|
||||
|
||||
* [enum_variant_names](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
|
||||
|
||||
|
||||
### enum-variant-size-threshold
|
||||
The maximum size of an enum's variant to avoid box suggestion
|
||||
|
||||
**Default Value:** `200` (`u64`)
|
||||
|
||||
* [large_enum_variant](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant)
|
||||
|
||||
|
||||
### verbose-bit-mask-threshold
|
||||
The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
|
||||
|
||||
**Default Value:** `1` (`u64`)
|
||||
|
||||
* [verbose_bit_mask](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask)
|
||||
|
||||
|
||||
### literal-representation-threshold
|
||||
The lower bound for linting decimal literals
|
||||
|
||||
**Default Value:** `16384` (`u64`)
|
||||
|
||||
* [decimal_literal_representation](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation)
|
||||
|
||||
|
||||
### trivial-copy-size-limit
|
||||
The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
|
||||
|
||||
**Default Value:** `None` (`Option<u64>`)
|
||||
|
||||
* [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
|
||||
|
||||
|
||||
### pass-by-value-size-limit
|
||||
The minimum size (in bytes) to consider a type for passing by reference instead of by value.
|
||||
|
||||
**Default Value:** `256` (`u64`)
|
||||
|
||||
* [large_type_pass_by_move](https://rust-lang.github.io/rust-clippy/master/index.html#large_type_pass_by_move)
|
||||
|
||||
|
||||
### too-many-lines-threshold
|
||||
The maximum number of lines a function or method can have
|
||||
|
||||
**Default Value:** `100` (`u64`)
|
||||
|
||||
* [too_many_lines](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines)
|
||||
|
||||
|
||||
### array-size-threshold
|
||||
The maximum allowed size for arrays on the stack
|
||||
|
||||
**Default Value:** `512000` (`u128`)
|
||||
|
||||
* [large_stack_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays)
|
||||
* [large_const_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays)
|
||||
|
||||
|
||||
### vec-box-size-threshold
|
||||
The size of the boxed type in bytes, where boxing in a `Vec` is allowed
|
||||
|
||||
**Default Value:** `4096` (`u64`)
|
||||
|
||||
* [vec_box](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
|
||||
|
||||
|
||||
### max-trait-bounds
|
||||
The maximum number of bounds a trait can have to be linted
|
||||
|
||||
**Default Value:** `3` (`u64`)
|
||||
|
||||
* [type_repetition_in_bounds](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
|
||||
|
||||
|
||||
### max-struct-bools
|
||||
The maximum number of bool fields a struct can have
|
||||
|
||||
**Default Value:** `3` (`u64`)
|
||||
|
||||
* [struct_excessive_bools](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools)
|
||||
|
||||
|
||||
### max-fn-params-bools
|
||||
The maximum number of bool parameters a function can have
|
||||
|
||||
**Default Value:** `3` (`u64`)
|
||||
|
||||
* [fn_params_excessive_bools](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools)
|
||||
|
||||
|
||||
### warn-on-all-wildcard-imports
|
||||
Whether to allow certain wildcard imports (prelude, super in tests).
|
||||
|
||||
**Default Value:** `false` (`bool`)
|
||||
|
||||
* [wildcard_imports](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports)
|
||||
|
||||
|
||||
### disallowed-macros
|
||||
The list of disallowed macros, written as fully qualified paths.
|
||||
|
||||
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
|
||||
|
||||
* [disallowed_macros](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros)
|
||||
|
||||
|
||||
### disallowed-methods
|
||||
The list of disallowed methods, written as fully qualified paths.
|
||||
|
||||
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
|
||||
|
||||
* [disallowed_methods](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods)
|
||||
|
||||
|
||||
### disallowed-types
|
||||
The list of disallowed types, written as fully qualified paths.
|
||||
|
||||
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
|
||||
|
||||
* [disallowed_types](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types)
|
||||
|
||||
|
||||
### unreadable-literal-lint-fractions
|
||||
Should the fraction of a decimal be linted to include separators.
|
||||
|
||||
**Default Value:** `true` (`bool`)
|
||||
|
||||
* [unreadable_literal](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal)
|
||||
|
||||
|
||||
### upper-case-acronyms-aggressive
|
||||
Enables verbose mode. Triggers if there is more than one uppercase char next to each other
|
||||
|
||||
**Default Value:** `false` (`bool`)
|
||||
|
||||
* [upper_case_acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
|
||||
|
||||
|
||||
### matches-for-let-else
|
||||
Whether the matches should be considered by the lint, and whether there should
|
||||
be filtering for common types.
|
||||
|
||||
**Default Value:** `WellKnownTypes` (`crate::manual_let_else::MatchLintBehaviour`)
|
||||
|
||||
* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
|
||||
|
||||
|
||||
### cargo-ignore-publish
|
||||
For internal testing only, ignores the current `publish` settings in the Cargo manifest.
|
||||
|
||||
**Default Value:** `false` (`bool`)
|
||||
|
||||
* [_cargo_common_metadata](https://rust-lang.github.io/rust-clippy/master/index.html#_cargo_common_metadata)
|
||||
|
||||
|
||||
### standard-macro-braces
|
||||
Enforce the named macros always use the braces specified.
|
||||
|
||||
A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
|
||||
is could be used with a full path two `MacroMatcher`s have to be added one with the full path
|
||||
`crate_name::macro_name` and one with just the macro name.
|
||||
|
||||
**Default Value:** `[]` (`Vec<crate::nonstandard_macro_braces::MacroMatcher>`)
|
||||
|
||||
* [nonstandard_macro_braces](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces)
|
||||
|
||||
|
||||
### enforced-import-renames
|
||||
The list of imports to always rename, a fully qualified path followed by the rename.
|
||||
|
||||
**Default Value:** `[]` (`Vec<crate::utils::conf::Rename>`)
|
||||
|
||||
* [missing_enforced_import_renames](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames)
|
||||
|
||||
|
||||
### allowed-scripts
|
||||
The list of unicode scripts allowed to be used in the scope.
|
||||
|
||||
**Default Value:** `["Latin"]` (`Vec<String>`)
|
||||
|
||||
* [disallowed_script_idents](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents)
|
||||
|
||||
|
||||
### enable-raw-pointer-heuristic-for-send
|
||||
Whether to apply the raw pointer heuristic to determine if a type is `Send`.
|
||||
|
||||
**Default Value:** `true` (`bool`)
|
||||
|
||||
* [non_send_fields_in_send_ty](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty)
|
||||
|
||||
|
||||
### max-suggested-slice-pattern-length
|
||||
When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in
|
||||
the slice pattern that is suggested. If more elements would be necessary, the lint is suppressed.
|
||||
For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
|
||||
|
||||
**Default Value:** `3` (`u64`)
|
||||
|
||||
* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
|
||||
|
||||
|
||||
### max-include-file-size
|
||||
The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
|
||||
|
||||
**Default Value:** `1000000` (`u64`)
|
||||
|
||||
* [large_include_file](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file)
|
||||
|
||||
|
||||
### allow-expect-in-tests
|
||||
Whether `expect` should be allowed within `#[cfg(test)]`
|
||||
|
||||
**Default Value:** `false` (`bool`)
|
||||
|
||||
* [expect_used](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used)
|
||||
|
||||
|
||||
### allow-unwrap-in-tests
|
||||
Whether `unwrap` should be allowed in test cfg
|
||||
|
||||
**Default Value:** `false` (`bool`)
|
||||
|
||||
* [unwrap_used](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used)
|
||||
|
||||
|
||||
### allow-dbg-in-tests
|
||||
Whether `dbg!` should be allowed in test functions
|
||||
|
||||
**Default Value:** `false` (`bool`)
|
||||
|
||||
* [dbg_macro](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro)
|
||||
|
||||
|
||||
### allow-print-in-tests
|
||||
Whether print macros (ex. `println!`) should be allowed in test functions
|
||||
|
||||
**Default Value:** `false` (`bool`)
|
||||
|
||||
* [print_stdout](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout)
|
||||
* [print_stderr](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr)
|
||||
|
||||
|
||||
### large-error-threshold
|
||||
The maximum size of the `Err`-variant in a `Result` returned from a function
|
||||
|
||||
**Default Value:** `128` (`u64`)
|
||||
|
||||
* [result_large_err](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err)
|
||||
|
||||
|
||||
### ignore-interior-mutability
|
||||
A list of paths to types that should be treated like `Arc`, i.e. ignored but
|
||||
for the generic parameters for determining interior mutability
|
||||
|
||||
**Default Value:** `["bytes::Bytes"]` (`Vec<String>`)
|
||||
|
||||
* [mutable_key](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key)
|
||||
|
||||
|
||||
### allow-mixed-uninlined-format-args
|
||||
Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
|
||||
|
||||
**Default Value:** `true` (`bool`)
|
||||
|
||||
* [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
|
||||
|
||||
|
||||
### suppress-restriction-lint-in-const
|
||||
In same
|
||||
cases the restructured operation might not be unavoidable, as the
|
||||
suggested counterparts are unavailable in constant code. This
|
||||
configuration will cause restriction lints to trigger even
|
||||
if no suggestion can be made.
|
||||
|
||||
**Default Value:** `false` (`bool`)
|
||||
|
||||
* [indexing_slicing](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing)
|
||||
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "clippy_lints"
|
||||
version = "0.1.68"
|
||||
version = "0.1.69"
|
||||
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
|
||||
repository = "https://github.com/rust-lang/rust-clippy"
|
||||
readme = "README.md"
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::macros::{find_assert_eq_args, root_macro_call_first_node};
|
||||
use clippy_utils::{diagnostics::span_lint_and_sugg, ty::implements_trait};
|
||||
use clippy_utils::ty::{implements_trait, is_copy};
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, Lit};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::symbol::Ident;
|
||||
|
||||
|
@ -43,9 +44,7 @@ fn is_bool_lit(e: &Expr<'_>) -> bool {
|
|||
) && !e.span.from_expansion()
|
||||
}
|
||||
|
||||
fn is_impl_not_trait_with_bool_out(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
||||
let ty = cx.typeck_results().expr_ty(e);
|
||||
|
||||
fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
cx.tcx
|
||||
.lang_items()
|
||||
.not_trait()
|
||||
|
@ -77,31 +76,57 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
|
|||
return;
|
||||
}
|
||||
let Some ((a, b, _)) = find_assert_eq_args(cx, expr, macro_call.expn) else { return };
|
||||
if !(is_bool_lit(a) ^ is_bool_lit(b)) {
|
||||
|
||||
let a_span = a.span.source_callsite();
|
||||
let b_span = b.span.source_callsite();
|
||||
|
||||
let (lit_span, non_lit_expr) = match (is_bool_lit(a), is_bool_lit(b)) {
|
||||
// assert_eq!(true, b)
|
||||
// ^^^^^^
|
||||
(true, false) => (a_span.until(b_span), b),
|
||||
// assert_eq!(a, true)
|
||||
// ^^^^^^
|
||||
(false, true) => (b_span.with_lo(a_span.hi()), a),
|
||||
// If there are two boolean arguments, we definitely don't understand
|
||||
// what's going on, so better leave things as is...
|
||||
//
|
||||
// Or there is simply no boolean and then we can leave things as is!
|
||||
return;
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
|
||||
if !is_impl_not_trait_with_bool_out(cx, a) || !is_impl_not_trait_with_bool_out(cx, b) {
|
||||
let non_lit_ty = cx.typeck_results().expr_ty(non_lit_expr);
|
||||
|
||||
if !is_impl_not_trait_with_bool_out(cx, non_lit_ty) {
|
||||
// At this point the expression which is not a boolean
|
||||
// literal does not implement Not trait with a bool output,
|
||||
// so we cannot suggest to rewrite our code
|
||||
return;
|
||||
}
|
||||
|
||||
if !is_copy(cx, non_lit_ty) {
|
||||
// Only lint with types that are `Copy` because `assert!(x)` takes
|
||||
// ownership of `x` whereas `assert_eq(x, true)` does not
|
||||
return;
|
||||
}
|
||||
|
||||
let macro_name = macro_name.as_str();
|
||||
let non_eq_mac = ¯o_name[..macro_name.len() - 3];
|
||||
span_lint_and_sugg(
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
BOOL_ASSERT_COMPARISON,
|
||||
macro_call.span,
|
||||
&format!("used `{macro_name}!` with a literal bool"),
|
||||
"replace it with",
|
||||
format!("{non_eq_mac}!(..)"),
|
||||
Applicability::MaybeIncorrect,
|
||||
|diag| {
|
||||
// assert_eq!(...)
|
||||
// ^^^^^^^^^
|
||||
let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!');
|
||||
|
||||
diag.multipart_suggestion(
|
||||
format!("replace it with `{non_eq_mac}!(..)`"),
|
||||
vec![(name_span, non_eq_mac.to_string()), (lit_span, String::new())],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::expr_or_init;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
|
||||
use rustc_errors::{Applicability, SuggestionStyle};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, FloatTy, Ty};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::IntegerType;
|
||||
|
||||
use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
|
||||
|
@ -74,7 +77,14 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
|
||||
pub(super) fn check(
|
||||
cx: &LateContext<'_>,
|
||||
expr: &Expr<'_>,
|
||||
cast_expr: &Expr<'_>,
|
||||
cast_from: Ty<'_>,
|
||||
cast_to: Ty<'_>,
|
||||
cast_to_span: Span,
|
||||
) {
|
||||
let msg = match (cast_from.kind(), cast_to.is_integral()) {
|
||||
(ty::Int(_) | ty::Uint(_), true) => {
|
||||
let from_nbits = apply_reductions(
|
||||
|
@ -139,7 +149,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
|||
);
|
||||
return;
|
||||
}
|
||||
format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}",)
|
||||
format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}")
|
||||
},
|
||||
|
||||
(ty::Float(_), true) => {
|
||||
|
@ -153,5 +163,19 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
|||
_ => return,
|
||||
};
|
||||
|
||||
span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg);
|
||||
let name_of_cast_from = snippet(cx, cast_expr.span, "..");
|
||||
let cast_to_snip = snippet(cx, cast_to_span, "..");
|
||||
let suggestion = format!("{cast_to_snip}::try_from({name_of_cast_from})");
|
||||
|
||||
span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
|
||||
diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...");
|
||||
diag.span_suggestion_with_style(
|
||||
expr.span,
|
||||
"... or use `try_from` and handle the error accordingly",
|
||||
suggestion,
|
||||
Applicability::Unspecified,
|
||||
// always show the suggestion in a separate line
|
||||
SuggestionStyle::ShowAlways,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -80,7 +80,8 @@ declare_clippy_lint! {
|
|||
/// ### What it does
|
||||
/// Checks for casts between numerical types that may
|
||||
/// truncate large values. This is expected behavior, so the cast is `Allow` by
|
||||
/// default.
|
||||
/// default. It suggests user either explicitly ignore the lint,
|
||||
/// or use `try_from()` and handle the truncation, default, or panic explicitly.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// In some problem domains, it is good practice to avoid
|
||||
|
@ -93,6 +94,21 @@ declare_clippy_lint! {
|
|||
/// x as u8
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```
|
||||
/// fn as_u8(x: u64) -> u8 {
|
||||
/// if let Ok(x) = u8::try_from(x) {
|
||||
/// x
|
||||
/// } else {
|
||||
/// todo!();
|
||||
/// }
|
||||
/// }
|
||||
/// // Or
|
||||
/// #[allow(clippy::cast_possible_truncation)]
|
||||
/// fn as_u16(x: u64) -> u16 {
|
||||
/// x as u16
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "pre 1.29.0"]
|
||||
pub CAST_POSSIBLE_TRUNCATION,
|
||||
pedantic,
|
||||
|
@ -712,7 +728,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
|
|||
fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
|
||||
|
||||
if cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
|
||||
cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
|
||||
cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span);
|
||||
if cast_from.is_numeric() {
|
||||
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
|
||||
cast_precision_loss::check(cx, expr, cast_from, cast_to);
|
||||
|
|
|
@ -422,6 +422,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::module_style::MOD_MODULE_FILES_INFO,
|
||||
crate::module_style::SELF_NAMED_MODULE_FILES_INFO,
|
||||
crate::multi_assignments::MULTI_ASSIGNMENTS_INFO,
|
||||
crate::multiple_unsafe_ops_per_block::MULTIPLE_UNSAFE_OPS_PER_BLOCK_INFO,
|
||||
crate::mut_key::MUTABLE_KEY_TYPE_INFO,
|
||||
crate::mut_mut::MUT_MUT_INFO,
|
||||
crate::mut_reference::UNNECESSARY_MUT_PASSED_INFO,
|
||||
|
|
|
@ -251,7 +251,7 @@ declare_clippy_lint! {
|
|||
/// unimplemented!();
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.66.0"]
|
||||
#[clippy::version = "1.67.0"]
|
||||
pub UNNECESSARY_SAFETY_DOC,
|
||||
restriction,
|
||||
"`pub fn` or `pub trait` with `# Safety` docs"
|
||||
|
|
|
@ -277,7 +277,7 @@ impl LateLintPass<'_> for EnumVariantNames {
|
|||
Some(c) if is_word_beginning(c) => span_lint(
|
||||
cx,
|
||||
MODULE_NAME_REPETITIONS,
|
||||
item.span,
|
||||
item.ident.span,
|
||||
"item name starts with its containing module's name",
|
||||
),
|
||||
_ => (),
|
||||
|
@ -287,7 +287,7 @@ impl LateLintPass<'_> for EnumVariantNames {
|
|||
span_lint(
|
||||
cx,
|
||||
MODULE_NAME_REPETITIONS,
|
||||
item.span,
|
||||
item.ident.span,
|
||||
"item name ends with its containing module's name",
|
||||
);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ declare_clippy_lint! {
|
|||
/// let _ = unsafe { Box::from_raw(ptr as *mut usize) };
|
||||
/// ```
|
||||
///
|
||||
#[clippy::version = "1.66.0"]
|
||||
#[clippy::version = "1.67.0"]
|
||||
pub FROM_RAW_WITH_VOID_PTR,
|
||||
suspicious,
|
||||
"creating a `Box` from a void raw pointer"
|
||||
|
|
|
@ -59,7 +59,7 @@ declare_clippy_lint! {
|
|||
///
|
||||
/// [`Duration`]: std::time::Duration
|
||||
/// [`Instant::now()`]: std::time::Instant::now;
|
||||
#[clippy::version = "1.65.0"]
|
||||
#[clippy::version = "1.67.0"]
|
||||
pub UNCHECKED_DURATION_SUBTRACTION,
|
||||
pedantic,
|
||||
"finds unchecked subtraction of a 'Duration' from an 'Instant'"
|
||||
|
|
|
@ -84,7 +84,7 @@ declare_clippy_lint! {
|
|||
/// let _ = foo().await;
|
||||
/// # }
|
||||
/// ```
|
||||
#[clippy::version = "1.66"]
|
||||
#[clippy::version = "1.67.0"]
|
||||
pub LET_UNDERSCORE_FUTURE,
|
||||
suspicious,
|
||||
"non-binding `let` on a future"
|
||||
|
|
|
@ -198,6 +198,7 @@ mod missing_trait_methods;
|
|||
mod mixed_read_write_in_expression;
|
||||
mod module_style;
|
||||
mod multi_assignments;
|
||||
mod multiple_unsafe_ops_per_block;
|
||||
mod mut_key;
|
||||
mod mut_mut;
|
||||
mod mut_reference;
|
||||
|
@ -908,6 +909,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck));
|
||||
store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
|
||||
store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
|
||||
store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock));
|
||||
// add lints here, do not remove this comment, it's used in `new_lint`
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ declare_clippy_lint! {
|
|||
/// 'A'.is_ascii_uppercase();
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.66.0"]
|
||||
#[clippy::version = "1.67.0"]
|
||||
pub MANUAL_IS_ASCII_CHECK,
|
||||
style,
|
||||
"use dedicated method to check ascii range"
|
||||
|
|
|
@ -3102,7 +3102,7 @@ declare_clippy_lint! {
|
|||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.66.0"]
|
||||
#[clippy::version = "1.67.0"]
|
||||
pub SEEK_FROM_CURRENT,
|
||||
complexity,
|
||||
"use dedicated method for seek from current position"
|
||||
|
@ -3133,7 +3133,7 @@ declare_clippy_lint! {
|
|||
/// t.rewind();
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.66.0"]
|
||||
#[clippy::version = "1.67.0"]
|
||||
pub SEEK_TO_START_INSTEAD_OF_REWIND,
|
||||
complexity,
|
||||
"jumping to the start of stream using `seek` method"
|
||||
|
|
|
@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
|
|||
"implement the method",
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
185
clippy_lints/src/multiple_unsafe_ops_per_block.rs
Normal file
185
clippy_lints/src/multiple_unsafe_ops_per_block.rs
Normal file
|
@ -0,0 +1,185 @@
|
|||
use clippy_utils::{
|
||||
diagnostics::span_lint_and_then,
|
||||
visitors::{for_each_expr_with_closures, Descend, Visitable},
|
||||
};
|
||||
use core::ops::ControlFlow::Continue;
|
||||
use hir::{
|
||||
def::{DefKind, Res},
|
||||
BlockCheckMode, ExprKind, QPath, UnOp, Unsafety,
|
||||
};
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for `unsafe` blocks that contain more than one unsafe operation.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Combined with `undocumented_unsafe_blocks`,
|
||||
/// this lint ensures that each unsafe operation must be independently justified.
|
||||
/// Combined with `unused_unsafe`, this lint also ensures
|
||||
/// elimination of unnecessary unsafe blocks through refactoring.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// /// Reads a `char` from the given pointer.
|
||||
/// ///
|
||||
/// /// # Safety
|
||||
/// ///
|
||||
/// /// `ptr` must point to four consecutive, initialized bytes which
|
||||
/// /// form a valid `char` when interpreted in the native byte order.
|
||||
/// fn read_char(ptr: *const u8) -> char {
|
||||
/// // SAFETY: The caller has guaranteed that the value pointed
|
||||
/// // to by `bytes` is a valid `char`.
|
||||
/// unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// /// Reads a `char` from the given pointer.
|
||||
/// ///
|
||||
/// /// # Safety
|
||||
/// ///
|
||||
/// /// - `ptr` must be 4-byte aligned, point to four consecutive
|
||||
/// /// initialized bytes, and be valid for reads of 4 bytes.
|
||||
/// /// - The bytes pointed to by `ptr` must represent a valid
|
||||
/// /// `char` when interpreted in the native byte order.
|
||||
/// fn read_char(ptr: *const u8) -> char {
|
||||
/// // SAFETY: `ptr` is 4-byte aligned, points to four consecutive
|
||||
/// // initialized bytes, and is valid for reads of 4 bytes.
|
||||
/// let int_value = unsafe { *ptr.cast::<u32>() };
|
||||
///
|
||||
/// // SAFETY: The caller has guaranteed that the four bytes
|
||||
/// // pointed to by `bytes` represent a valid `char`.
|
||||
/// unsafe { char::from_u32_unchecked(int_value) }
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.68.0"]
|
||||
pub MULTIPLE_UNSAFE_OPS_PER_BLOCK,
|
||||
restriction,
|
||||
"more than one unsafe operation per `unsafe` block"
|
||||
}
|
||||
declare_lint_pass!(MultipleUnsafeOpsPerBlock => [MULTIPLE_UNSAFE_OPS_PER_BLOCK]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for MultipleUnsafeOpsPerBlock {
|
||||
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
|
||||
if !matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) {
|
||||
return;
|
||||
}
|
||||
let mut unsafe_ops = vec![];
|
||||
collect_unsafe_exprs(cx, block, &mut unsafe_ops);
|
||||
if unsafe_ops.len() > 1 {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
MULTIPLE_UNSAFE_OPS_PER_BLOCK,
|
||||
block.span,
|
||||
&format!(
|
||||
"this `unsafe` block contains {} unsafe operations, expected only one",
|
||||
unsafe_ops.len()
|
||||
),
|
||||
|diag| {
|
||||
for (msg, span) in unsafe_ops {
|
||||
diag.span_note(span, msg);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_unsafe_exprs<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
node: impl Visitable<'tcx>,
|
||||
unsafe_ops: &mut Vec<(&'static str, Span)>,
|
||||
) {
|
||||
for_each_expr_with_closures(cx, node, |expr| {
|
||||
match expr.kind {
|
||||
ExprKind::InlineAsm(_) => unsafe_ops.push(("inline assembly used here", expr.span)),
|
||||
|
||||
ExprKind::Field(e, _) => {
|
||||
if cx.typeck_results().expr_ty(e).is_union() {
|
||||
unsafe_ops.push(("union field access occurs here", expr.span));
|
||||
}
|
||||
},
|
||||
|
||||
ExprKind::Path(QPath::Resolved(
|
||||
_,
|
||||
hir::Path {
|
||||
res: Res::Def(DefKind::Static(Mutability::Mut), _),
|
||||
..
|
||||
},
|
||||
)) => {
|
||||
unsafe_ops.push(("access of a mutable static occurs here", expr.span));
|
||||
},
|
||||
|
||||
ExprKind::Unary(UnOp::Deref, e) if cx.typeck_results().expr_ty_adjusted(e).is_unsafe_ptr() => {
|
||||
unsafe_ops.push(("raw pointer dereference occurs here", expr.span));
|
||||
},
|
||||
|
||||
ExprKind::Call(path_expr, _) => match path_expr.kind {
|
||||
ExprKind::Path(QPath::Resolved(
|
||||
_,
|
||||
hir::Path {
|
||||
res: Res::Def(kind, def_id),
|
||||
..
|
||||
},
|
||||
)) if kind.is_fn_like() => {
|
||||
let sig = cx.tcx.fn_sig(*def_id);
|
||||
if sig.0.unsafety() == Unsafety::Unsafe {
|
||||
unsafe_ops.push(("unsafe function call occurs here", expr.span));
|
||||
}
|
||||
},
|
||||
|
||||
ExprKind::Path(QPath::TypeRelative(..)) => {
|
||||
if let Some(sig) = cx
|
||||
.typeck_results()
|
||||
.type_dependent_def_id(path_expr.hir_id)
|
||||
.map(|def_id| cx.tcx.fn_sig(def_id))
|
||||
{
|
||||
if sig.0.unsafety() == Unsafety::Unsafe {
|
||||
unsafe_ops.push(("unsafe function call occurs here", expr.span));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_ => {},
|
||||
},
|
||||
|
||||
ExprKind::MethodCall(..) => {
|
||||
if let Some(sig) = cx
|
||||
.typeck_results()
|
||||
.type_dependent_def_id(expr.hir_id)
|
||||
.map(|def_id| cx.tcx.fn_sig(def_id))
|
||||
{
|
||||
if sig.0.unsafety() == Unsafety::Unsafe {
|
||||
unsafe_ops.push(("unsafe method call occurs here", expr.span));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ExprKind::AssignOp(_, lhs, rhs) | ExprKind::Assign(lhs, rhs, _) => {
|
||||
if matches!(
|
||||
lhs.kind,
|
||||
ExprKind::Path(QPath::Resolved(
|
||||
_,
|
||||
hir::Path {
|
||||
res: Res::Def(DefKind::Static(Mutability::Mut), _),
|
||||
..
|
||||
}
|
||||
))
|
||||
) {
|
||||
unsafe_ops.push(("modification of a mutable static occurs here", expr.span));
|
||||
collect_unsafe_exprs(cx, rhs, unsafe_ops);
|
||||
return Continue(Descend::No);
|
||||
}
|
||||
},
|
||||
|
||||
_ => {},
|
||||
};
|
||||
|
||||
Continue::<(), _>(Descend::Yes)
|
||||
});
|
||||
}
|
|
@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_hir::hir_id::HirIdMap;
|
||||
use rustc_hir::{Body, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Node, PatKind, TraitItem, TraitItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
||||
use rustc_middle::ty::subst::{EarlyBinder, GenericArgKind, SubstsRef};
|
||||
use rustc_middle::ty::{self, ConstKind};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
|
@ -244,7 +244,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
|
|||
})) => {
|
||||
#[allow(trivial_casts)]
|
||||
if let Some(Node::Item(item)) = get_parent_node(cx.tcx, owner_id.into())
|
||||
&& let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(|t| t.subst_identity())
|
||||
&& let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::subst_identity)
|
||||
&& let Some(trait_item_id) = cx.tcx.associated_item(owner_id).trait_item_def_id
|
||||
{
|
||||
(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
|
||||
use clippy_utils::source::{snippet_opt, snippet_with_context};
|
||||
use clippy_utils::visitors::{for_each_expr, Descend};
|
||||
use clippy_utils::{fn_def_id, path_to_local_id};
|
||||
use clippy_utils::{fn_def_id, path_to_local_id, span_find_starting_semi};
|
||||
use core::ops::ControlFlow;
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -151,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
|
|||
kind: FnKind<'tcx>,
|
||||
_: &'tcx FnDecl<'tcx>,
|
||||
body: &'tcx Body<'tcx>,
|
||||
_: Span,
|
||||
sp: Span,
|
||||
_: HirId,
|
||||
) {
|
||||
match kind {
|
||||
|
@ -166,14 +166,14 @@ impl<'tcx> LateLintPass<'tcx> for Return {
|
|||
check_final_expr(cx, body.value, vec![], replacement);
|
||||
},
|
||||
FnKind::ItemFn(..) | FnKind::Method(..) => {
|
||||
check_block_return(cx, &body.value.kind, vec![]);
|
||||
check_block_return(cx, &body.value.kind, sp, vec![]);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if `expr` is a block, check if there are needless returns in it
|
||||
fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, semi_spans: Vec<Span>) {
|
||||
fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, sp: Span, mut semi_spans: Vec<Span>) {
|
||||
if let ExprKind::Block(block, _) = expr_kind {
|
||||
if let Some(block_expr) = block.expr {
|
||||
check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty);
|
||||
|
@ -183,12 +183,14 @@ fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>,
|
|||
check_final_expr(cx, expr, semi_spans, RetReplacement::Empty);
|
||||
},
|
||||
StmtKind::Semi(semi_expr) => {
|
||||
let mut semi_spans_and_this_one = semi_spans;
|
||||
// we only want the span containing the semicolon so we can remove it later. From `entry.rs:382`
|
||||
if let Some(semicolon_span) = stmt.span.trim_start(semi_expr.span) {
|
||||
semi_spans_and_this_one.push(semicolon_span);
|
||||
check_final_expr(cx, semi_expr, semi_spans_and_this_one, RetReplacement::Empty);
|
||||
// Remove ending semicolons and any whitespace ' ' in between.
|
||||
// Without `return`, the suggestion might not compile if the semicolon is retained
|
||||
if let Some(semi_span) = stmt.span.trim_start(semi_expr.span) {
|
||||
let semi_span_to_remove =
|
||||
span_find_starting_semi(cx.sess().source_map(), semi_span.with_hi(sp.hi()));
|
||||
semi_spans.push(semi_span_to_remove);
|
||||
}
|
||||
check_final_expr(cx, semi_expr, semi_spans, RetReplacement::Empty);
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
@ -231,9 +233,9 @@ fn check_final_expr<'tcx>(
|
|||
emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
|
||||
},
|
||||
ExprKind::If(_, then, else_clause_opt) => {
|
||||
check_block_return(cx, &then.kind, semi_spans.clone());
|
||||
check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone());
|
||||
if let Some(else_clause) = else_clause_opt {
|
||||
check_block_return(cx, &else_clause.kind, semi_spans);
|
||||
check_block_return(cx, &else_clause.kind, peeled_drop_expr.span, semi_spans);
|
||||
}
|
||||
},
|
||||
// a match expr, check all arms
|
||||
|
@ -246,7 +248,7 @@ fn check_final_expr<'tcx>(
|
|||
}
|
||||
},
|
||||
// if it's a whole block, check it
|
||||
other_expr_kind => check_block_return(cx, other_expr_kind, semi_spans),
|
||||
other_expr_kind => check_block_return(cx, other_expr_kind, peeled_drop_expr.span, semi_spans),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ declare_clippy_lint! {
|
|||
/// ### What it does
|
||||
/// Warns for a Bitwise XOR (`^`) operator being probably confused as a powering. It will not trigger if any of the numbers are not in decimal.
|
||||
/// ### Why is this bad?
|
||||
/// It's most probably a typo and may lead to unexpected behaviours.
|
||||
/// It's most probably a typo and may lead to unexpected behaviours.
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// let x = 3_i32 ^ 4_i32;
|
||||
|
@ -18,7 +18,7 @@ declare_clippy_lint! {
|
|||
/// ```rust
|
||||
/// let x = 3_i32.pow(4);
|
||||
/// ```
|
||||
#[clippy::version = "1.66.0"]
|
||||
#[clippy::version = "1.67.0"]
|
||||
pub SUSPICIOUS_XOR_USED_AS_POW,
|
||||
restriction,
|
||||
"XOR (`^`) operator possibly used as exponentiation operator"
|
||||
|
|
|
@ -479,7 +479,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
|
|||
// - char conversions (https://github.com/rust-lang/rust/issues/89259)
|
||||
let const_context = in_constant(cx, e.hir_id);
|
||||
|
||||
let from_ty = cx.typeck_results().expr_ty_adjusted(arg);
|
||||
let (from_ty, from_ty_adjusted) = match cx.typeck_results().expr_adjustments(arg) {
|
||||
[] => (cx.typeck_results().expr_ty(arg), false),
|
||||
[.., a] => (a.target, true),
|
||||
};
|
||||
// Adjustments for `to_ty` happen after the call to `transmute`, so don't use them.
|
||||
let to_ty = cx.typeck_results().expr_ty(e);
|
||||
|
||||
|
@ -506,7 +509,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
|
|||
);
|
||||
|
||||
if !linted {
|
||||
transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, to_ty, arg);
|
||||
transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use super::utils::can_be_expressed_as_pointer_cast;
|
||||
use super::utils::check_cast;
|
||||
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::sugg;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Expr;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::{cast::CastKind, Ty};
|
||||
|
||||
/// Checks for `transmutes_expressible_as_ptr_casts` lint.
|
||||
/// Returns `true` if it's triggered, otherwise returns `false`.
|
||||
|
@ -13,24 +13,40 @@ pub(super) fn check<'tcx>(
|
|||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx Expr<'_>,
|
||||
from_ty: Ty<'tcx>,
|
||||
from_ty_adjusted: bool,
|
||||
to_ty: Ty<'tcx>,
|
||||
arg: &'tcx Expr<'_>,
|
||||
) -> bool {
|
||||
if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
|
||||
e.span,
|
||||
&format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
|
||||
|diag| {
|
||||
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
|
||||
let sugg = arg.as_ty(to_ty.to_string()).to_string();
|
||||
diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable);
|
||||
}
|
||||
},
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let sugg = match check_cast(cx, e, from_ty, to_ty) {
|
||||
Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
|
||||
Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
|
||||
.as_ty(to_ty.to_string())
|
||||
.to_string()
|
||||
},
|
||||
Some(PtrAddrCast) if !from_ty_adjusted => Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
|
||||
.as_ty(to_ty.to_string())
|
||||
.to_string(),
|
||||
|
||||
// The only adjustments here would be ref-to-ptr and unsize coercions. The result of an unsize coercions can't
|
||||
// be transmuted to a usize. For ref-to-ptr coercions, borrows need to be cast to a pointer before being cast to
|
||||
// a usize.
|
||||
Some(PtrAddrCast) => format!(
|
||||
"{} as {to_ty}",
|
||||
Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app).as_ty(from_ty)
|
||||
),
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
|
||||
e.span,
|
||||
&format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
|
||||
"try",
|
||||
sugg,
|
||||
app,
|
||||
);
|
||||
true
|
||||
}
|
||||
|
|
|
@ -20,28 +20,16 @@ pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx
|
|||
}
|
||||
}
|
||||
|
||||
/// Check if the type conversion can be expressed as a pointer cast, instead of
|
||||
/// a transmute. In certain cases, including some invalid casts from array
|
||||
/// references to pointers, this may cause additional errors to be emitted and/or
|
||||
/// ICE error messages. This function will panic if that occurs.
|
||||
pub(super) fn can_be_expressed_as_pointer_cast<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx Expr<'_>,
|
||||
from_ty: Ty<'tcx>,
|
||||
to_ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
|
||||
matches!(
|
||||
check_cast(cx, e, from_ty, to_ty),
|
||||
Some(PtrPtrCast | PtrAddrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast)
|
||||
)
|
||||
}
|
||||
|
||||
/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of
|
||||
/// the cast. In certain cases, including some invalid casts from array references
|
||||
/// to pointers, this may cause additional errors to be emitted and/or ICE error
|
||||
/// messages. This function will panic if that occurs.
|
||||
fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option<CastKind> {
|
||||
pub(super) fn check_cast<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx Expr<'_>,
|
||||
from_ty: Ty<'tcx>,
|
||||
to_ty: Ty<'tcx>,
|
||||
) -> Option<CastKind> {
|
||||
let hir_id = e.hir_id;
|
||||
let local_def_id = hir_id.owner.def_id;
|
||||
|
||||
|
|
|
@ -263,6 +263,18 @@ fn expr_has_unnecessary_safety_comment<'tcx>(
|
|||
expr: &'tcx hir::Expr<'tcx>,
|
||||
comment_pos: BytePos,
|
||||
) -> Option<Span> {
|
||||
if cx.tcx.hir().parent_iter(expr.hir_id).any(|(_, ref node)| {
|
||||
matches!(
|
||||
node,
|
||||
Node::Block(&Block {
|
||||
rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided),
|
||||
..
|
||||
}),
|
||||
)
|
||||
}) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// this should roughly be the reverse of `block_parents_have_safety_comment`
|
||||
if for_each_expr_with_closures(cx, expr, |expr| match expr.kind {
|
||||
hir::ExprKind::Block(
|
||||
|
|
|
@ -219,7 +219,8 @@ define_Conf! {
|
|||
///
|
||||
/// #### Noteworthy
|
||||
///
|
||||
/// A type, say `SomeType`, listed in this configuration has the same behavior of `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
|
||||
/// A type, say `SomeType`, listed in this configuration has the same behavior of
|
||||
/// `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
|
||||
(arithmetic_side_effects_allowed: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
|
||||
/// Lint: ARITHMETIC_SIDE_EFFECTS.
|
||||
///
|
||||
|
|
|
@ -14,6 +14,7 @@ use clippy_utils::diagnostics::span_lint;
|
|||
use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
|
||||
use clippy_utils::{last_path_segment, match_def_path, match_function_call, match_path, paths};
|
||||
use if_chain::if_chain;
|
||||
use itertools::Itertools;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::{
|
||||
|
@ -34,8 +35,10 @@ use std::path::Path;
|
|||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
/// This is the output file of the lint collector.
|
||||
const OUTPUT_FILE: &str = "../util/gh-pages/lints.json";
|
||||
/// This is the json output file of the lint collector.
|
||||
const JSON_OUTPUT_FILE: &str = "../util/gh-pages/lints.json";
|
||||
/// This is the markdown output file of the lint collector.
|
||||
const MARKDOWN_OUTPUT_FILE: &str = "../book/src/lint_configuration.md";
|
||||
/// These lints are excluded from the export.
|
||||
const BLACK_LISTED_LINTS: &[&str] = &["lint_author", "dump_hir", "internal_metadata_collector"];
|
||||
/// These groups will be ignored by the lint group matcher. This is useful for collections like
|
||||
|
@ -176,6 +179,23 @@ This lint has the following configuration variables:
|
|||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn configs_to_markdown(&self, map_fn: fn(&ClippyConfiguration) -> String) -> String {
|
||||
self.config
|
||||
.iter()
|
||||
.filter(|config| config.deprecation_reason.is_none())
|
||||
.filter(|config| !config.lints.is_empty())
|
||||
.map(map_fn)
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
fn get_markdown_docs(&self) -> String {
|
||||
format!(
|
||||
"## Lint Configuration Options\n| <div style=\"width:290px\">Option</div> | Default Value |\n|--|--|\n{}\n\n{}\n",
|
||||
self.configs_to_markdown(ClippyConfiguration::to_markdown_table_entry),
|
||||
self.configs_to_markdown(ClippyConfiguration::to_markdown_paragraph),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MetadataCollector {
|
||||
|
@ -199,12 +219,37 @@ impl Drop for MetadataCollector {
|
|||
|
||||
collect_renames(&mut lints);
|
||||
|
||||
// Outputting
|
||||
if Path::new(OUTPUT_FILE).exists() {
|
||||
fs::remove_file(OUTPUT_FILE).unwrap();
|
||||
// Outputting json
|
||||
if Path::new(JSON_OUTPUT_FILE).exists() {
|
||||
fs::remove_file(JSON_OUTPUT_FILE).unwrap();
|
||||
}
|
||||
let mut file = OpenOptions::new().write(true).create(true).open(OUTPUT_FILE).unwrap();
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(JSON_OUTPUT_FILE)
|
||||
.unwrap();
|
||||
writeln!(file, "{}", serde_json::to_string_pretty(&lints).unwrap()).unwrap();
|
||||
|
||||
// Outputting markdown
|
||||
if Path::new(MARKDOWN_OUTPUT_FILE).exists() {
|
||||
fs::remove_file(MARKDOWN_OUTPUT_FILE).unwrap();
|
||||
}
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(MARKDOWN_OUTPUT_FILE)
|
||||
.unwrap();
|
||||
writeln!(
|
||||
file,
|
||||
"<!--
|
||||
This file is generated by `cargo collect-metadata`.
|
||||
Please use that command to update the file and do not edit it by hand.
|
||||
-->
|
||||
|
||||
{}",
|
||||
self.get_markdown_docs(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -505,6 +550,28 @@ impl ClippyConfiguration {
|
|||
deprecation_reason,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_markdown_paragraph(&self) -> String {
|
||||
format!(
|
||||
"### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
|
||||
self.name,
|
||||
self.doc
|
||||
.lines()
|
||||
.map(|line| line.strip_prefix(" ").unwrap_or(line))
|
||||
.join("\n"),
|
||||
self.default,
|
||||
self.config_type,
|
||||
self.lints
|
||||
.iter()
|
||||
.map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
|
||||
.map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
|
||||
.join("\n"),
|
||||
)
|
||||
}
|
||||
|
||||
fn to_markdown_table_entry(&self) -> String {
|
||||
format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_configs() -> Vec<ClippyConfiguration> {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "clippy_utils"
|
||||
version = "0.1.68"
|
||||
version = "0.1.69"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
|
|
@ -2491,6 +2491,10 @@ pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
|
|||
comments_buf.join("\n")
|
||||
}
|
||||
|
||||
pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
|
||||
sm.span_take_while(span, |&ch| ch == ' ' || ch == ';')
|
||||
}
|
||||
|
||||
macro_rules! op_utils {
|
||||
($($name:ident $assign:ident)*) => {
|
||||
/// Binary operation traits like `LangItem::Add`
|
||||
|
|
|
@ -647,9 +647,12 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
|
|||
Some(ExprFnSig::Closure(decl, subs.as_closure().sig()))
|
||||
},
|
||||
ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.fn_sig(id).subst(cx.tcx, subs), Some(id))),
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
sig_from_bounds(cx, ty, cx.tcx.item_bounds(def_id).subst(cx.tcx, substs), cx.tcx.opt_parent(def_id))
|
||||
},
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => sig_from_bounds(
|
||||
cx,
|
||||
ty,
|
||||
cx.tcx.item_bounds(def_id).subst(cx.tcx, substs),
|
||||
cx.tcx.opt_parent(def_id),
|
||||
),
|
||||
ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
|
||||
ty::Dynamic(bounds, _, _) => {
|
||||
let lang_items = cx.tcx.lang_items();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "declare_clippy_lint"
|
||||
version = "0.1.68"
|
||||
version = "0.1.69"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2023-01-12"
|
||||
channel = "nightly-2023-01-27"
|
||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
|
|
|
@ -28,7 +28,7 @@ with:
|
|||
-D --deny OPT Set lint denied
|
||||
-F --forbid OPT Set lint forbidden
|
||||
|
||||
You can use tool lints to allow or deny lints from your code, eg.:
|
||||
You can use tool lints to allow or deny lints from your code, e.g.:
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
"#;
|
||||
|
|
|
@ -7,14 +7,6 @@ LL | const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
|
|||
= help: convert all references to use `sym::Deref`
|
||||
= note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
|
||||
|
||||
error: hardcoded path to a language item
|
||||
--> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
|
||||
|
|
||||
LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: convert all references to use `LangItem::DerefMut`
|
||||
|
||||
error: hardcoded path to a diagnostic item
|
||||
--> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
|
||||
|
|
||||
|
@ -23,5 +15,13 @@ LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref",
|
|||
|
|
||||
= help: convert all references to use `sym::deref_method`
|
||||
|
||||
error: hardcoded path to a language item
|
||||
--> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
|
||||
|
|
||||
LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: convert all references to use `LangItem::DerefMut`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
161
tests/ui/bool_assert_comparison.fixed
Normal file
161
tests/ui/bool_assert_comparison.fixed
Normal file
|
@ -0,0 +1,161 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(unused, clippy::assertions_on_constants)]
|
||||
#![warn(clippy::bool_assert_comparison)]
|
||||
|
||||
use std::ops::Not;
|
||||
|
||||
macro_rules! a {
|
||||
() => {
|
||||
true
|
||||
};
|
||||
}
|
||||
macro_rules! b {
|
||||
() => {
|
||||
true
|
||||
};
|
||||
}
|
||||
|
||||
// Implements the Not trait but with an output type
|
||||
// that's not bool. Should not suggest a rewrite
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum ImplNotTraitWithoutBool {
|
||||
VariantX(bool),
|
||||
VariantY(u32),
|
||||
}
|
||||
|
||||
impl PartialEq<bool> for ImplNotTraitWithoutBool {
|
||||
fn eq(&self, other: &bool) -> bool {
|
||||
match *self {
|
||||
ImplNotTraitWithoutBool::VariantX(b) => b == *other,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Not for ImplNotTraitWithoutBool {
|
||||
type Output = Self;
|
||||
|
||||
fn not(self) -> Self::Output {
|
||||
match self {
|
||||
ImplNotTraitWithoutBool::VariantX(b) => ImplNotTraitWithoutBool::VariantX(!b),
|
||||
ImplNotTraitWithoutBool::VariantY(0) => ImplNotTraitWithoutBool::VariantY(1),
|
||||
ImplNotTraitWithoutBool::VariantY(_) => ImplNotTraitWithoutBool::VariantY(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This type implements the Not trait with an Output of
|
||||
// type bool. Using assert!(..) must be suggested
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct ImplNotTraitWithBool;
|
||||
|
||||
impl PartialEq<bool> for ImplNotTraitWithBool {
|
||||
fn eq(&self, other: &bool) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Not for ImplNotTraitWithBool {
|
||||
type Output = bool;
|
||||
|
||||
fn not(self) -> Self::Output {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NonCopy;
|
||||
|
||||
impl PartialEq<bool> for NonCopy {
|
||||
fn eq(&self, other: &bool) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Not for NonCopy {
|
||||
type Output = bool;
|
||||
|
||||
fn not(self) -> Self::Output {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = ImplNotTraitWithoutBool::VariantX(true);
|
||||
let b = ImplNotTraitWithBool;
|
||||
|
||||
assert_eq!("a".len(), 1);
|
||||
assert!("a".is_empty());
|
||||
assert!("".is_empty());
|
||||
assert!("".is_empty());
|
||||
assert_eq!(a!(), b!());
|
||||
assert_eq!(a!(), "".is_empty());
|
||||
assert_eq!("".is_empty(), b!());
|
||||
assert_eq!(a, true);
|
||||
assert!(b);
|
||||
|
||||
assert_ne!("a".len(), 1);
|
||||
assert!("a".is_empty());
|
||||
assert!("".is_empty());
|
||||
assert!("".is_empty());
|
||||
assert_ne!(a!(), b!());
|
||||
assert_ne!(a!(), "".is_empty());
|
||||
assert_ne!("".is_empty(), b!());
|
||||
assert_ne!(a, true);
|
||||
assert!(b);
|
||||
|
||||
debug_assert_eq!("a".len(), 1);
|
||||
debug_assert!("a".is_empty());
|
||||
debug_assert!("".is_empty());
|
||||
debug_assert!("".is_empty());
|
||||
debug_assert_eq!(a!(), b!());
|
||||
debug_assert_eq!(a!(), "".is_empty());
|
||||
debug_assert_eq!("".is_empty(), b!());
|
||||
debug_assert_eq!(a, true);
|
||||
debug_assert!(b);
|
||||
|
||||
debug_assert_ne!("a".len(), 1);
|
||||
debug_assert!("a".is_empty());
|
||||
debug_assert!("".is_empty());
|
||||
debug_assert!("".is_empty());
|
||||
debug_assert_ne!(a!(), b!());
|
||||
debug_assert_ne!(a!(), "".is_empty());
|
||||
debug_assert_ne!("".is_empty(), b!());
|
||||
debug_assert_ne!(a, true);
|
||||
debug_assert!(b);
|
||||
|
||||
// assert with error messages
|
||||
assert_eq!("a".len(), 1, "tadam {}", 1);
|
||||
assert_eq!("a".len(), 1, "tadam {}", true);
|
||||
assert!("a".is_empty(), "tadam {}", 1);
|
||||
assert!("a".is_empty(), "tadam {}", true);
|
||||
assert!("a".is_empty(), "tadam {}", true);
|
||||
assert_eq!(a, true, "tadam {}", false);
|
||||
|
||||
debug_assert_eq!("a".len(), 1, "tadam {}", 1);
|
||||
debug_assert_eq!("a".len(), 1, "tadam {}", true);
|
||||
debug_assert!("a".is_empty(), "tadam {}", 1);
|
||||
debug_assert!("a".is_empty(), "tadam {}", true);
|
||||
debug_assert!("a".is_empty(), "tadam {}", true);
|
||||
debug_assert_eq!(a, true, "tadam {}", false);
|
||||
|
||||
assert!(a!());
|
||||
assert!(b!());
|
||||
|
||||
use debug_assert_eq as renamed;
|
||||
renamed!(a, true);
|
||||
debug_assert!(b);
|
||||
|
||||
let non_copy = NonCopy;
|
||||
assert_eq!(non_copy, true);
|
||||
// changing the above to `assert!(non_copy)` would cause a `borrow of moved value`
|
||||
println!("{non_copy:?}");
|
||||
|
||||
macro_rules! in_macro {
|
||||
($v:expr) => {{
|
||||
assert_eq!($v, true);
|
||||
}};
|
||||
}
|
||||
in_macro!(a);
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(unused, clippy::assertions_on_constants)]
|
||||
#![warn(clippy::bool_assert_comparison)]
|
||||
|
||||
use std::ops::Not;
|
||||
|
@ -15,7 +18,7 @@ macro_rules! b {
|
|||
|
||||
// Implements the Not trait but with an output type
|
||||
// that's not bool. Should not suggest a rewrite
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum ImplNotTraitWithoutBool {
|
||||
VariantX(bool),
|
||||
VariantY(u32),
|
||||
|
@ -44,7 +47,7 @@ impl Not for ImplNotTraitWithoutBool {
|
|||
|
||||
// This type implements the Not trait with an Output of
|
||||
// type bool. Using assert!(..) must be suggested
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct ImplNotTraitWithBool;
|
||||
|
||||
impl PartialEq<bool> for ImplNotTraitWithBool {
|
||||
|
@ -61,6 +64,23 @@ impl Not for ImplNotTraitWithBool {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NonCopy;
|
||||
|
||||
impl PartialEq<bool> for NonCopy {
|
||||
fn eq(&self, other: &bool) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Not for NonCopy {
|
||||
type Output = bool;
|
||||
|
||||
fn not(self) -> Self::Output {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = ImplNotTraitWithoutBool::VariantX(true);
|
||||
let b = ImplNotTraitWithBool;
|
||||
|
@ -119,4 +139,23 @@ fn main() {
|
|||
debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||
debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||
debug_assert_eq!(a, true, "tadam {}", false);
|
||||
|
||||
assert_eq!(a!(), true);
|
||||
assert_eq!(true, b!());
|
||||
|
||||
use debug_assert_eq as renamed;
|
||||
renamed!(a, true);
|
||||
renamed!(b, true);
|
||||
|
||||
let non_copy = NonCopy;
|
||||
assert_eq!(non_copy, true);
|
||||
// changing the above to `assert!(non_copy)` would cause a `borrow of moved value`
|
||||
println!("{non_copy:?}");
|
||||
|
||||
macro_rules! in_macro {
|
||||
($v:expr) => {{
|
||||
assert_eq!($v, true);
|
||||
}};
|
||||
}
|
||||
in_macro!(a);
|
||||
}
|
||||
|
|
|
@ -1,136 +1,303 @@
|
|||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:69:5
|
||||
|
|
||||
LL | assert_eq!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
|
||||
= note: `-D clippy::bool-assert-comparison` implied by `-D warnings`
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:70:5
|
||||
|
|
||||
LL | assert_eq!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:71:5
|
||||
|
|
||||
LL | assert_eq!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:76:5
|
||||
|
|
||||
LL | assert_eq!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:79:5
|
||||
|
|
||||
LL | assert_ne!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:80:5
|
||||
|
|
||||
LL | assert_ne!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:81:5
|
||||
|
|
||||
LL | assert_ne!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:86:5
|
||||
|
|
||||
LL | assert_ne!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:89:5
|
||||
|
|
||||
LL | debug_assert_eq!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
LL | assert_eq!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::bool-assert-comparison` implied by `-D warnings`
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!("a".is_empty(), false);
|
||||
LL + assert!("a".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:90:5
|
||||
|
|
||||
LL | debug_assert_eq!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
LL | assert_eq!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!("".is_empty(), true);
|
||||
LL + assert!("".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:91:5
|
||||
|
|
||||
LL | debug_assert_eq!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
LL | assert_eq!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(true, "".is_empty());
|
||||
LL + assert!("".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:96:5
|
||||
|
|
||||
LL | debug_assert_eq!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
LL | assert_eq!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(b, true);
|
||||
LL + assert!(b);
|
||||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:99:5
|
||||
|
|
||||
LL | debug_assert_ne!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
LL | assert_ne!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_ne!("a".is_empty(), false);
|
||||
LL + assert!("a".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:100:5
|
||||
|
|
||||
LL | debug_assert_ne!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
LL | assert_ne!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_ne!("".is_empty(), true);
|
||||
LL + assert!("".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:101:5
|
||||
|
|
||||
LL | debug_assert_ne!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
LL | assert_ne!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_ne!(true, "".is_empty());
|
||||
LL + assert!("".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:106:5
|
||||
|
|
||||
LL | debug_assert_ne!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
LL | assert_ne!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_ne!(b, true);
|
||||
LL + assert!(b);
|
||||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:109:5
|
||||
|
|
||||
LL | debug_assert_eq!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_eq!("a".is_empty(), false);
|
||||
LL + debug_assert!("a".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:110:5
|
||||
|
|
||||
LL | debug_assert_eq!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_eq!("".is_empty(), true);
|
||||
LL + debug_assert!("".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:111:5
|
||||
|
|
||||
LL | assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:112:5
|
||||
LL | debug_assert_eq!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
LL | assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:113:5
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_eq!(true, "".is_empty());
|
||||
LL + debug_assert!("".is_empty());
|
||||
|
|
||||
LL | assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:118:5
|
||||
--> $DIR/bool_assert_comparison.rs:116:5
|
||||
|
|
||||
LL | debug_assert_eq!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_eq!(b, true);
|
||||
LL + debug_assert!(b);
|
||||
|
|
||||
LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:119:5
|
||||
|
|
||||
LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
LL | debug_assert_ne!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_ne!("a".is_empty(), false);
|
||||
LL + debug_assert!("a".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:120:5
|
||||
|
|
||||
LL | debug_assert_ne!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_ne!("".is_empty(), true);
|
||||
LL + debug_assert!("".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:121:5
|
||||
|
|
||||
LL | debug_assert_ne!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_ne!(true, "".is_empty());
|
||||
LL + debug_assert!("".is_empty());
|
||||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:126:5
|
||||
|
|
||||
LL | debug_assert_ne!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_ne!(b, true);
|
||||
LL + debug_assert!(b);
|
||||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:131:5
|
||||
|
|
||||
LL | assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||
LL + assert!("a".is_empty(), "tadam {}", 1);
|
||||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:132:5
|
||||
|
|
||||
LL | assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||
LL + assert!("a".is_empty(), "tadam {}", true);
|
||||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:133:5
|
||||
|
|
||||
LL | assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||
LL + assert!("a".is_empty(), "tadam {}", true);
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:138:5
|
||||
|
|
||||
LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||
LL + debug_assert!("a".is_empty(), "tadam {}", 1);
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:139:5
|
||||
|
|
||||
LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||
LL + debug_assert!("a".is_empty(), "tadam {}", true);
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:140:5
|
||||
|
|
||||
LL | debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||
LL + debug_assert!("a".is_empty(), "tadam {}", true);
|
||||
|
|
||||
|
||||
error: aborting due to 22 previous errors
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:143:5
|
||||
|
|
||||
LL | assert_eq!(a!(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(a!(), true);
|
||||
LL + assert!(a!());
|
||||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:144:5
|
||||
|
|
||||
LL | assert_eq!(true, b!());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(true, b!());
|
||||
LL + assert!(b!());
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> $DIR/bool_assert_comparison.rs:148:5
|
||||
|
|
||||
LL | renamed!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - renamed!(b, true);
|
||||
LL + debug_assert!(b);
|
||||
|
|
||||
|
||||
error: aborting due to 25 previous errors
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ fn main() {
|
|||
1i32 as u8;
|
||||
1f64 as isize;
|
||||
1f64 as usize;
|
||||
1f32 as u32 as u16;
|
||||
// Test clippy::cast_possible_wrap
|
||||
1u8 as i8;
|
||||
1u16 as i16;
|
||||
|
|
|
@ -42,13 +42,24 @@ error: casting `f32` to `i32` may truncate the value
|
|||
LL | 1f32 as i32;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
= note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | i32::try_from(1f32);
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f32` to `u32` may truncate the value
|
||||
--> $DIR/cast.rs:25:5
|
||||
|
|
||||
LL | 1f32 as u32;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | u32::try_from(1f32);
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:25:5
|
||||
|
@ -63,30 +74,60 @@ error: casting `f64` to `f32` may truncate the value
|
|||
|
|
||||
LL | 1f64 as f32;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | f32::try_from(1f64);
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `i32` to `i8` may truncate the value
|
||||
--> $DIR/cast.rs:27:5
|
||||
|
|
||||
LL | 1i32 as i8;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | i8::try_from(1i32);
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `i32` to `u8` may truncate the value
|
||||
--> $DIR/cast.rs:28:5
|
||||
|
|
||||
LL | 1i32 as u8;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | u8::try_from(1i32);
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f64` to `isize` may truncate the value
|
||||
--> $DIR/cast.rs:29:5
|
||||
|
|
||||
LL | 1f64 as isize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | isize::try_from(1f64);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f64` to `usize` may truncate the value
|
||||
--> $DIR/cast.rs:30:5
|
||||
|
|
||||
LL | 1f64 as usize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | usize::try_from(1f64);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f64` to `usize` may lose the sign of the value
|
||||
--> $DIR/cast.rs:30:5
|
||||
|
@ -94,8 +135,38 @@ error: casting `f64` to `usize` may lose the sign of the value
|
|||
LL | 1f64 as usize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: casting `u32` to `u16` may truncate the value
|
||||
--> $DIR/cast.rs:31:5
|
||||
|
|
||||
LL | 1f32 as u32 as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | u16::try_from(1f32 as u32);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f32` to `u32` may truncate the value
|
||||
--> $DIR/cast.rs:31:5
|
||||
|
|
||||
LL | 1f32 as u32 as u16;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | u32::try_from(1f32) as u16;
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:31:5
|
||||
|
|
||||
LL | 1f32 as u32 as u16;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: casting `u8` to `i8` may wrap around the value
|
||||
--> $DIR/cast.rs:32:5
|
||||
--> $DIR/cast.rs:33:5
|
||||
|
|
||||
LL | 1u8 as i8;
|
||||
| ^^^^^^^^^
|
||||
|
@ -103,61 +174,79 @@ LL | 1u8 as i8;
|
|||
= note: `-D clippy::cast-possible-wrap` implied by `-D warnings`
|
||||
|
||||
error: casting `u16` to `i16` may wrap around the value
|
||||
--> $DIR/cast.rs:33:5
|
||||
--> $DIR/cast.rs:34:5
|
||||
|
|
||||
LL | 1u16 as i16;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: casting `u32` to `i32` may wrap around the value
|
||||
--> $DIR/cast.rs:34:5
|
||||
--> $DIR/cast.rs:35:5
|
||||
|
|
||||
LL | 1u32 as i32;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: casting `u64` to `i64` may wrap around the value
|
||||
--> $DIR/cast.rs:35:5
|
||||
--> $DIR/cast.rs:36:5
|
||||
|
|
||||
LL | 1u64 as i64;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: casting `usize` to `isize` may wrap around the value
|
||||
--> $DIR/cast.rs:36:5
|
||||
--> $DIR/cast.rs:37:5
|
||||
|
|
||||
LL | 1usize as isize;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:39:5
|
||||
--> $DIR/cast.rs:40:5
|
||||
|
|
||||
LL | -1i32 as u32;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: casting `isize` to `usize` may lose the sign of the value
|
||||
--> $DIR/cast.rs:41:5
|
||||
--> $DIR/cast.rs:42:5
|
||||
|
|
||||
LL | -1isize as usize;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i64` to `i8` may truncate the value
|
||||
--> $DIR/cast.rs:108:5
|
||||
--> $DIR/cast.rs:109:5
|
||||
|
|
||||
LL | (-99999999999i64).min(1) as i8; // should be linted because signed
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | i8::try_from((-99999999999i64).min(1)); // should be linted because signed
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u64` to `u8` may truncate the value
|
||||
--> $DIR/cast.rs:120:5
|
||||
--> $DIR/cast.rs:121:5
|
||||
|
|
||||
LL | 999999u64.clamp(0, 256) as u8; // should still be linted
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | u8::try_from(999999u64.clamp(0, 256)); // should still be linted
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `main::E2` to `u8` may truncate the value
|
||||
--> $DIR/cast.rs:141:21
|
||||
--> $DIR/cast.rs:142:21
|
||||
|
|
||||
LL | let _ = self as u8;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | let _ = u8::try_from(self);
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `main::E2::B` to `u8` will truncate the value
|
||||
--> $DIR/cast.rs:142:21
|
||||
--> $DIR/cast.rs:143:21
|
||||
|
|
||||
LL | let _ = Self::B as u8;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -165,46 +254,82 @@ LL | let _ = Self::B as u8;
|
|||
= note: `-D clippy::cast-enum-truncation` implied by `-D warnings`
|
||||
|
||||
error: casting `main::E5` to `i8` may truncate the value
|
||||
--> $DIR/cast.rs:178:21
|
||||
--> $DIR/cast.rs:179:21
|
||||
|
|
||||
LL | let _ = self as i8;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | let _ = i8::try_from(self);
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `main::E5::A` to `i8` will truncate the value
|
||||
--> $DIR/cast.rs:179:21
|
||||
--> $DIR/cast.rs:180:21
|
||||
|
|
||||
LL | let _ = Self::A as i8;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: casting `main::E6` to `i16` may truncate the value
|
||||
--> $DIR/cast.rs:193:21
|
||||
--> $DIR/cast.rs:194:21
|
||||
|
|
||||
LL | let _ = self as i16;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | let _ = i16::try_from(self);
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
|
||||
--> $DIR/cast.rs:208:21
|
||||
--> $DIR/cast.rs:209:21
|
||||
|
|
||||
LL | let _ = self as usize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | let _ = usize::try_from(self);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `main::E10` to `u16` may truncate the value
|
||||
--> $DIR/cast.rs:249:21
|
||||
--> $DIR/cast.rs:250:21
|
||||
|
|
||||
LL | let _ = self as u16;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | let _ = u16::try_from(self);
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u32` to `u8` may truncate the value
|
||||
--> $DIR/cast.rs:257:13
|
||||
--> $DIR/cast.rs:258:13
|
||||
|
|
||||
LL | let c = (q >> 16) as u8;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | let c = u8::try_from((q >> 16));
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u32` to `u8` may truncate the value
|
||||
--> $DIR/cast.rs:260:13
|
||||
--> $DIR/cast.rs:261:13
|
||||
|
|
||||
LL | let c = (q / 1000) as u8;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | let c = u8::try_from((q / 1000));
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 33 previous errors
|
||||
error: aborting due to 36 previous errors
|
||||
|
||||
|
|
|
@ -4,7 +4,12 @@ error: casting `isize` to `i8` may truncate the value
|
|||
LL | 1isize as i8;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
= note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | i8::try_from(1isize);
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `isize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`isize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
|
||||
--> $DIR/cast_size.rs:15:5
|
||||
|
@ -37,24 +42,48 @@ error: casting `isize` to `i32` may truncate the value on targets with 64-bit wi
|
|||
|
|
||||
LL | 1isize as i32;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | i32::try_from(1isize);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `isize` to `u32` may truncate the value on targets with 64-bit wide pointers
|
||||
--> $DIR/cast_size.rs:20:5
|
||||
|
|
||||
LL | 1isize as u32;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | u32::try_from(1isize);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers
|
||||
--> $DIR/cast_size.rs:21:5
|
||||
|
|
||||
LL | 1usize as u32;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | u32::try_from(1usize);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
|
||||
--> $DIR/cast_size.rs:22:5
|
||||
|
|
||||
LL | 1usize as i32;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | i32::try_from(1usize);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
|
||||
--> $DIR/cast_size.rs:22:5
|
||||
|
@ -69,18 +98,36 @@ error: casting `i64` to `isize` may truncate the value on targets with 32-bit wi
|
|||
|
|
||||
LL | 1i64 as isize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | isize::try_from(1i64);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
|
||||
--> $DIR/cast_size.rs:25:5
|
||||
|
|
||||
LL | 1i64 as usize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | usize::try_from(1i64);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
|
||||
--> $DIR/cast_size.rs:26:5
|
||||
|
|
||||
LL | 1u64 as isize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | isize::try_from(1u64);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
|
||||
--> $DIR/cast_size.rs:26:5
|
||||
|
@ -93,6 +140,12 @@ error: casting `u64` to `usize` may truncate the value on targets with 32-bit wi
|
|||
|
|
||||
LL | 1u64 as usize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
|
||||
help: ... or use `try_from` and handle the error accordingly
|
||||
|
|
||||
LL | usize::try_from(1u64);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
|
||||
--> $DIR/cast_size.rs:28:5
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
error: item name starts with its containing module's name
|
||||
--> $DIR/module_name_repetitions.rs:8:5
|
||||
--> $DIR/module_name_repetitions.rs:8:12
|
||||
|
|
||||
LL | pub fn foo_bar() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::module-name-repetitions` implied by `-D warnings`
|
||||
|
||||
error: item name ends with its containing module's name
|
||||
--> $DIR/module_name_repetitions.rs:9:5
|
||||
--> $DIR/module_name_repetitions.rs:9:12
|
||||
|
|
||||
LL | pub fn bar_foo() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^
|
||||
|
||||
error: item name starts with its containing module's name
|
||||
--> $DIR/module_name_repetitions.rs:10:5
|
||||
--> $DIR/module_name_repetitions.rs:10:16
|
||||
|
|
||||
LL | pub struct FooCake;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^
|
||||
|
||||
error: item name ends with its containing module's name
|
||||
--> $DIR/module_name_repetitions.rs:11:5
|
||||
--> $DIR/module_name_repetitions.rs:11:14
|
||||
|
|
||||
LL | pub enum CakeFoo {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^
|
||||
|
||||
error: item name starts with its containing module's name
|
||||
--> $DIR/module_name_repetitions.rs:12:5
|
||||
--> $DIR/module_name_repetitions.rs:12:16
|
||||
|
|
||||
LL | pub struct Foo7Bar;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
110
tests/ui/multiple_unsafe_ops_per_block.rs
Normal file
110
tests/ui/multiple_unsafe_ops_per_block.rs
Normal file
|
@ -0,0 +1,110 @@
|
|||
#![allow(unused)]
|
||||
#![allow(deref_nullptr)]
|
||||
#![allow(clippy::unnecessary_operation)]
|
||||
#![allow(clippy::drop_copy)]
|
||||
#![warn(clippy::multiple_unsafe_ops_per_block)]
|
||||
|
||||
use core::arch::asm;
|
||||
|
||||
fn raw_ptr() -> *const () {
|
||||
core::ptr::null()
|
||||
}
|
||||
|
||||
unsafe fn not_very_safe() {}
|
||||
|
||||
struct Sample;
|
||||
|
||||
impl Sample {
|
||||
unsafe fn not_very_safe(&self) {}
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
const sample: Sample = Sample;
|
||||
|
||||
union U {
|
||||
i: i32,
|
||||
u: u32,
|
||||
}
|
||||
|
||||
static mut STATIC: i32 = 0;
|
||||
|
||||
fn test1() {
|
||||
unsafe {
|
||||
STATIC += 1;
|
||||
not_very_safe();
|
||||
}
|
||||
}
|
||||
|
||||
fn test2() {
|
||||
let u = U { i: 0 };
|
||||
|
||||
unsafe {
|
||||
drop(u.u);
|
||||
*raw_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
fn test3() {
|
||||
unsafe {
|
||||
asm!("nop");
|
||||
sample.not_very_safe();
|
||||
STATIC = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn test_all() {
|
||||
let u = U { i: 0 };
|
||||
unsafe {
|
||||
drop(u.u);
|
||||
drop(STATIC);
|
||||
sample.not_very_safe();
|
||||
not_very_safe();
|
||||
*raw_ptr();
|
||||
asm!("nop");
|
||||
}
|
||||
}
|
||||
|
||||
// no lint
|
||||
fn correct1() {
|
||||
unsafe {
|
||||
STATIC += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// no lint
|
||||
fn correct2() {
|
||||
unsafe {
|
||||
STATIC += 1;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
*raw_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
// no lint
|
||||
fn correct3() {
|
||||
let u = U { u: 0 };
|
||||
|
||||
unsafe {
|
||||
not_very_safe();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
drop(u.i);
|
||||
}
|
||||
}
|
||||
|
||||
// tests from the issue (https://github.com/rust-lang/rust-clippy/issues/10064)
|
||||
|
||||
unsafe fn read_char_bad(ptr: *const u8) -> char {
|
||||
unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||
}
|
||||
|
||||
// no lint
|
||||
unsafe fn read_char_good(ptr: *const u8) -> char {
|
||||
let int_value = unsafe { *ptr.cast::<u32>() };
|
||||
unsafe { core::char::from_u32_unchecked(int_value) }
|
||||
}
|
||||
|
||||
fn main() {}
|
129
tests/ui/multiple_unsafe_ops_per_block.stderr
Normal file
129
tests/ui/multiple_unsafe_ops_per_block.stderr
Normal file
|
@ -0,0 +1,129 @@
|
|||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:32:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | | STATIC += 1;
|
||||
LL | | not_very_safe();
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: modification of a mutable static occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:33:9
|
||||
|
|
||||
LL | STATIC += 1;
|
||||
| ^^^^^^^^^^^
|
||||
note: unsafe function call occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:34:9
|
||||
|
|
||||
LL | not_very_safe();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= note: `-D clippy::multiple-unsafe-ops-per-block` implied by `-D warnings`
|
||||
|
||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:41:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | | drop(u.u);
|
||||
LL | | *raw_ptr();
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: union field access occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:42:14
|
||||
|
|
||||
LL | drop(u.u);
|
||||
| ^^^
|
||||
note: raw pointer dereference occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:43:9
|
||||
|
|
||||
LL | *raw_ptr();
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: this `unsafe` block contains 3 unsafe operations, expected only one
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:48:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | | asm!("nop");
|
||||
LL | | sample.not_very_safe();
|
||||
LL | | STATIC = 0;
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: inline assembly used here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:49:9
|
||||
|
|
||||
LL | asm!("nop");
|
||||
| ^^^^^^^^^^^
|
||||
note: unsafe method call occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:50:9
|
||||
|
|
||||
LL | sample.not_very_safe();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: modification of a mutable static occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:51:9
|
||||
|
|
||||
LL | STATIC = 0;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: this `unsafe` block contains 6 unsafe operations, expected only one
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:57:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | | drop(u.u);
|
||||
LL | | drop(STATIC);
|
||||
LL | | sample.not_very_safe();
|
||||
... |
|
||||
LL | | asm!("nop");
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: union field access occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:58:14
|
||||
|
|
||||
LL | drop(u.u);
|
||||
| ^^^
|
||||
note: access of a mutable static occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:59:14
|
||||
|
|
||||
LL | drop(STATIC);
|
||||
| ^^^^^^
|
||||
note: unsafe method call occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:60:9
|
||||
|
|
||||
LL | sample.not_very_safe();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: unsafe function call occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:61:9
|
||||
|
|
||||
LL | not_very_safe();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: raw pointer dereference occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:62:9
|
||||
|
|
||||
LL | *raw_ptr();
|
||||
| ^^^^^^^^^^
|
||||
note: inline assembly used here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:63:9
|
||||
|
|
||||
LL | asm!("nop");
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:101:5
|
||||
|
|
||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: unsafe function call occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:101:14
|
||||
|
|
||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: raw pointer dereference occurs here
|
||||
--> $DIR/multiple_unsafe_ops_per_block.rs:101:39
|
||||
|
|
||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
|
@ -31,6 +31,16 @@ fn test_no_semicolon() -> bool {
|
|||
true
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn test_multiple_semicolon() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn test_multiple_semicolon_with_spaces() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn test_if_block() -> bool {
|
||||
if true {
|
||||
true
|
||||
|
|
|
@ -31,6 +31,16 @@ fn test_no_semicolon() -> bool {
|
|||
return true;
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn test_multiple_semicolon() -> bool {
|
||||
return true;;;
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn test_multiple_semicolon_with_spaces() -> bool {
|
||||
return true;; ; ;
|
||||
}
|
||||
|
||||
fn test_if_block() -> bool {
|
||||
if true {
|
||||
return true;
|
||||
|
|
|
@ -16,7 +16,23 @@ LL | return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:36:9
|
||||
--> $DIR/needless_return.rs:36:5
|
||||
|
|
||||
LL | return true;;;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:41:5
|
||||
|
|
||||
LL | return true;; ; ;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:46:9
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -24,7 +40,7 @@ LL | return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:38:9
|
||||
--> $DIR/needless_return.rs:48:9
|
||||
|
|
||||
LL | return false;
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -32,7 +48,7 @@ LL | return false;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:44:17
|
||||
--> $DIR/needless_return.rs:54:17
|
||||
|
|
||||
LL | true => return false,
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -40,7 +56,7 @@ LL | true => return false,
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:46:13
|
||||
--> $DIR/needless_return.rs:56:13
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -48,7 +64,7 @@ LL | return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:53:9
|
||||
--> $DIR/needless_return.rs:63:9
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -56,7 +72,7 @@ LL | return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:55:16
|
||||
--> $DIR/needless_return.rs:65:16
|
||||
|
|
||||
LL | let _ = || return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -64,7 +80,7 @@ LL | let _ = || return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:59:5
|
||||
--> $DIR/needless_return.rs:69:5
|
||||
|
|
||||
LL | return the_answer!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -72,7 +88,7 @@ LL | return the_answer!();
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:62:21
|
||||
--> $DIR/needless_return.rs:72:21
|
||||
|
|
||||
LL | fn test_void_fun() {
|
||||
| _____________________^
|
||||
|
@ -82,7 +98,7 @@ LL | | return;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:67:11
|
||||
--> $DIR/needless_return.rs:77:11
|
||||
|
|
||||
LL | if b {
|
||||
| ___________^
|
||||
|
@ -92,7 +108,7 @@ LL | | return;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:69:13
|
||||
--> $DIR/needless_return.rs:79:13
|
||||
|
|
||||
LL | } else {
|
||||
| _____________^
|
||||
|
@ -102,7 +118,7 @@ LL | | return;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:77:14
|
||||
--> $DIR/needless_return.rs:87:14
|
||||
|
|
||||
LL | _ => return,
|
||||
| ^^^^^^
|
||||
|
@ -110,7 +126,7 @@ LL | _ => return,
|
|||
= help: replace `return` with a unit value
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:85:24
|
||||
--> $DIR/needless_return.rs:95:24
|
||||
|
|
||||
LL | let _ = 42;
|
||||
| ________________________^
|
||||
|
@ -120,7 +136,7 @@ LL | | return;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:88:14
|
||||
--> $DIR/needless_return.rs:98:14
|
||||
|
|
||||
LL | _ => return,
|
||||
| ^^^^^^
|
||||
|
@ -128,7 +144,7 @@ LL | _ => return,
|
|||
= help: replace `return` with a unit value
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:101:9
|
||||
--> $DIR/needless_return.rs:111:9
|
||||
|
|
||||
LL | return String::from("test");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -136,7 +152,7 @@ LL | return String::from("test");
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:103:9
|
||||
--> $DIR/needless_return.rs:113:9
|
||||
|
|
||||
LL | return String::new();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -144,7 +160,7 @@ LL | return String::new();
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:125:32
|
||||
--> $DIR/needless_return.rs:135:32
|
||||
|
|
||||
LL | bar.unwrap_or_else(|_| return)
|
||||
| ^^^^^^
|
||||
|
@ -152,7 +168,7 @@ LL | bar.unwrap_or_else(|_| return)
|
|||
= help: replace `return` with an empty block
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:129:21
|
||||
--> $DIR/needless_return.rs:139:21
|
||||
|
|
||||
LL | let _ = || {
|
||||
| _____________________^
|
||||
|
@ -162,7 +178,7 @@ LL | | return;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:132:20
|
||||
--> $DIR/needless_return.rs:142:20
|
||||
|
|
||||
LL | let _ = || return;
|
||||
| ^^^^^^
|
||||
|
@ -170,7 +186,7 @@ LL | let _ = || return;
|
|||
= help: replace `return` with an empty block
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:138:32
|
||||
--> $DIR/needless_return.rs:148:32
|
||||
|
|
||||
LL | res.unwrap_or_else(|_| return Foo)
|
||||
| ^^^^^^^^^^
|
||||
|
@ -178,7 +194,7 @@ LL | res.unwrap_or_else(|_| return Foo)
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:147:5
|
||||
--> $DIR/needless_return.rs:157:5
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -186,7 +202,7 @@ LL | return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:151:5
|
||||
--> $DIR/needless_return.rs:161:5
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -194,7 +210,7 @@ LL | return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:156:9
|
||||
--> $DIR/needless_return.rs:166:9
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -202,7 +218,7 @@ LL | return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:158:9
|
||||
--> $DIR/needless_return.rs:168:9
|
||||
|
|
||||
LL | return false;
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -210,7 +226,7 @@ LL | return false;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:164:17
|
||||
--> $DIR/needless_return.rs:174:17
|
||||
|
|
||||
LL | true => return false,
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -218,7 +234,7 @@ LL | true => return false,
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:166:13
|
||||
--> $DIR/needless_return.rs:176:13
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -226,7 +242,7 @@ LL | return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:173:9
|
||||
--> $DIR/needless_return.rs:183:9
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -234,7 +250,7 @@ LL | return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:175:16
|
||||
--> $DIR/needless_return.rs:185:16
|
||||
|
|
||||
LL | let _ = || return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -242,7 +258,7 @@ LL | let _ = || return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:179:5
|
||||
--> $DIR/needless_return.rs:189:5
|
||||
|
|
||||
LL | return the_answer!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -250,7 +266,7 @@ LL | return the_answer!();
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:182:33
|
||||
--> $DIR/needless_return.rs:192:33
|
||||
|
|
||||
LL | async fn async_test_void_fun() {
|
||||
| _________________________________^
|
||||
|
@ -260,7 +276,7 @@ LL | | return;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:187:11
|
||||
--> $DIR/needless_return.rs:197:11
|
||||
|
|
||||
LL | if b {
|
||||
| ___________^
|
||||
|
@ -270,7 +286,7 @@ LL | | return;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:189:13
|
||||
--> $DIR/needless_return.rs:199:13
|
||||
|
|
||||
LL | } else {
|
||||
| _____________^
|
||||
|
@ -280,7 +296,7 @@ LL | | return;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:197:14
|
||||
--> $DIR/needless_return.rs:207:14
|
||||
|
|
||||
LL | _ => return,
|
||||
| ^^^^^^
|
||||
|
@ -288,7 +304,7 @@ LL | _ => return,
|
|||
= help: replace `return` with a unit value
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:210:9
|
||||
--> $DIR/needless_return.rs:220:9
|
||||
|
|
||||
LL | return String::from("test");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -296,7 +312,7 @@ LL | return String::from("test");
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:212:9
|
||||
--> $DIR/needless_return.rs:222:9
|
||||
|
|
||||
LL | return String::new();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -304,7 +320,7 @@ LL | return String::new();
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:228:5
|
||||
--> $DIR/needless_return.rs:238:5
|
||||
|
|
||||
LL | return format!("Hello {}", "world!");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -312,7 +328,7 @@ LL | return format!("Hello {}", "world!");
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:239:9
|
||||
--> $DIR/needless_return.rs:249:9
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -320,7 +336,7 @@ LL | return true;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:241:9
|
||||
--> $DIR/needless_return.rs:251:9
|
||||
|
|
||||
LL | return false;
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -328,7 +344,7 @@ LL | return false;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:248:13
|
||||
--> $DIR/needless_return.rs:258:13
|
||||
|
|
||||
LL | return 10;
|
||||
| ^^^^^^^^^
|
||||
|
@ -336,7 +352,7 @@ LL | return 10;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:251:13
|
||||
--> $DIR/needless_return.rs:261:13
|
||||
|
|
||||
LL | return 100;
|
||||
| ^^^^^^^^^^
|
||||
|
@ -344,7 +360,7 @@ LL | return 100;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:259:9
|
||||
--> $DIR/needless_return.rs:269:9
|
||||
|
|
||||
LL | return 0;
|
||||
| ^^^^^^^^
|
||||
|
@ -352,7 +368,7 @@ LL | return 0;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:266:13
|
||||
--> $DIR/needless_return.rs:276:13
|
||||
|
|
||||
LL | return *(x as *const isize);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -360,7 +376,7 @@ LL | return *(x as *const isize);
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:268:13
|
||||
--> $DIR/needless_return.rs:278:13
|
||||
|
|
||||
LL | return !*(x as *const isize);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -368,7 +384,7 @@ LL | return !*(x as *const isize);
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:275:20
|
||||
--> $DIR/needless_return.rs:285:20
|
||||
|
|
||||
LL | let _ = 42;
|
||||
| ____________________^
|
||||
|
@ -379,7 +395,7 @@ LL | | return;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:282:20
|
||||
--> $DIR/needless_return.rs:292:20
|
||||
|
|
||||
LL | let _ = 42; return;
|
||||
| ^^^^^^^
|
||||
|
@ -387,7 +403,7 @@ LL | let _ = 42; return;
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:294:9
|
||||
--> $DIR/needless_return.rs:304:9
|
||||
|
|
||||
LL | return Ok(format!("ok!"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -395,12 +411,12 @@ LL | return Ok(format!("ok!"));
|
|||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:296:9
|
||||
--> $DIR/needless_return.rs:306:9
|
||||
|
|
||||
LL | return Err(format!("err!"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
|
||||
error: aborting due to 48 previous errors
|
||||
error: aborting due to 50 previous errors
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ fn main() {
|
|||
// e is a function pointer type and U is an integer; fptr-addr-cast
|
||||
let _usize_from_fn_ptr_transmute = unsafe { foo as usize };
|
||||
let _usize_from_fn_ptr = foo as *const usize;
|
||||
|
||||
let _usize_from_ref = unsafe { &1u32 as *const u32 as usize };
|
||||
}
|
||||
|
||||
// If a ref-to-ptr cast of this form where the pointer type points to a type other
|
||||
|
|
|
@ -51,6 +51,8 @@ fn main() {
|
|||
// e is a function pointer type and U is an integer; fptr-addr-cast
|
||||
let _usize_from_fn_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, usize>(foo) };
|
||||
let _usize_from_fn_ptr = foo as *const usize;
|
||||
|
||||
let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) };
|
||||
}
|
||||
|
||||
// If a ref-to-ptr cast of this form where the pointer type points to a type other
|
||||
|
|
|
@ -46,11 +46,17 @@ error: transmute from `fn(usize) -> u8` to `usize` which could be expressed as a
|
|||
LL | let _usize_from_fn_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, usize>(foo) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize`
|
||||
|
||||
error: transmute from `*const u32` to `usize` which could be expressed as a pointer cast instead
|
||||
--> $DIR/transmutes_expressible_as_ptr_casts.rs:55:36
|
||||
|
|
||||
LL | let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&1u32 as *const u32 as usize`
|
||||
|
||||
error: transmute from a reference to a pointer
|
||||
--> $DIR/transmutes_expressible_as_ptr_casts.rs:64:14
|
||||
--> $DIR/transmutes_expressible_as_ptr_casts.rs:66:14
|
||||
|
|
||||
LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
|
@ -48,4 +48,21 @@ fn unnecessary_on_stmt_and_expr() -> u32 {
|
|||
24
|
||||
}
|
||||
|
||||
mod issue_10084 {
|
||||
unsafe fn bar() -> i32 {
|
||||
42
|
||||
}
|
||||
|
||||
macro_rules! foo {
|
||||
() => {
|
||||
// SAFETY: This is necessary
|
||||
unsafe { bar() }
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo!();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
Loading…
Reference in a new issue