Merge commit '09ac14c901abc43bd0d617ae4a44e8a4fed98d9c' into clippyup

This commit is contained in:
Philipp Krones 2023-11-02 17:35:56 +01:00
parent aae86ccc47
commit 77c1e3aaa1
418 changed files with 4900 additions and 3588 deletions

View File

@ -60,7 +60,7 @@ jobs:
working-directory: clippy_lints working-directory: clippy_lints
- name: Test clippy_utils - name: Test clippy_utils
run: cargo test --features deny-warnings,internal run: cargo test --features deny-warnings
working-directory: clippy_utils working-directory: clippy_utils
- name: Test rustc_tools_util - name: Test rustc_tools_util

View File

@ -120,9 +120,13 @@ jobs:
working-directory: clippy_lints working-directory: clippy_lints
- name: Test clippy_utils - name: Test clippy_utils
run: cargo test --features deny-warnings,internal run: cargo test --features deny-warnings
working-directory: clippy_utils working-directory: clippy_utils
- name: Test clippy_config
run: cargo test --features deny-warnings
working-directory: clippy_config
- name: Test rustc_tools_util - name: Test rustc_tools_util
run: cargo test --features deny-warnings run: cargo test --features deny-warnings
working-directory: rustc_tools_util working-directory: rustc_tools_util

View File

@ -5528,6 +5528,7 @@ Released 2018-09-13
[`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints [`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints
[`unnecessary_box_returns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns [`unnecessary_box_returns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns
[`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
[`unnecessary_fallible_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions
[`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
[`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_find_map [`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_find_map
[`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold
@ -5560,6 +5561,7 @@ Released 2018-09-13
[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice [`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice
[`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async [`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect [`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
[`unused_enumerate_index`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_enumerate_index
[`unused_format_specs`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_format_specs [`unused_format_specs`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_format_specs
[`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount [`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount
[`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label [`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label
@ -5589,6 +5591,7 @@ Released 2018-09-13
[`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask [`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask
[`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads [`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads
[`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons [`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons
[`waker_clone_wake`]: https://rust-lang.github.io/rust-clippy/master/index.html#waker_clone_wake
[`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition
[`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop
[`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator

View File

@ -21,11 +21,12 @@ name = "clippy-driver"
path = "src/driver.rs" path = "src/driver.rs"
[dependencies] [dependencies]
clippy_config = { path = "clippy_config" }
clippy_lints = { path = "clippy_lints" } clippy_lints = { path = "clippy_lints" }
rustc_tools_util = "0.3.0" rustc_tools_util = "0.3.0"
tempfile = { version = "3.2", optional = true } tempfile = { version = "3.2", optional = true }
termize = "0.1" termize = "0.1"
color-print = "0.3.4" # Sync version with Cargo color-print = "0.3.4"
anstream = "0.5.0" anstream = "0.5.0"
[dev-dependencies] [dev-dependencies]

View File

@ -26,7 +26,7 @@ arithmetic-side-effects-allowed = ["SomeType", "AnotherType"]
A type, say `SomeType`, listed in this configuration has the same behavior of A type, say `SomeType`, listed in this configuration has the same behavior of
`["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`. `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -49,7 +49,7 @@ Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the
arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]] arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
``` ```
**Default Value:** `[]` (`Vec<[String; 2]>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -65,7 +65,7 @@ Suppress checking of the passed type names in unary operations like "negation" (
arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
``` ```
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -75,7 +75,7 @@ arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
## `avoid-breaking-exported-api` ## `avoid-breaking-exported-api`
Suppress lints whenever the suggested change would cause breakage for other crates. Suppress lints whenever the suggested change would cause breakage for other crates.
**Default Value:** `true` (`bool`) **Default Value:** `true`
--- ---
**Affected lints:** **Affected lints:**
@ -98,9 +98,7 @@ Suppress lints whenever the suggested change would cause breakage for other crat
## `msrv` ## `msrv`
The minimum rust version that the project supports The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
**Default Value:** `Msrv { stack: [] }` (`crate::Msrv`)
--- ---
**Affected lints:** **Affected lints:**
@ -157,7 +155,7 @@ The minimum rust version that the project supports
## `cognitive-complexity-threshold` ## `cognitive-complexity-threshold`
The maximum cognitive complexity a function can have The maximum cognitive complexity a function can have
**Default Value:** `25` (`u64`) **Default Value:** `25`
--- ---
**Affected lints:** **Affected lints:**
@ -167,7 +165,7 @@ The maximum cognitive complexity a function can have
## `excessive-nesting-threshold` ## `excessive-nesting-threshold`
The maximum amount of nesting a block can reside in The maximum amount of nesting a block can reside in
**Default Value:** `0` (`u64`) **Default Value:** `0`
--- ---
**Affected lints:** **Affected lints:**
@ -179,7 +177,7 @@ The list of disallowed names to lint about. NB: `bar` is not here since it has l
`".."` can be used as part of the list to indicate that the configured values should be appended to the `".."` 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 configuration of Clippy. By default, any configuration will replace the default value.
**Default Value:** `["foo", "baz", "quux"]` (`Vec<String>`) **Default Value:** `["foo", "baz", "quux"]`
--- ---
**Affected lints:** **Affected lints:**
@ -189,7 +187,7 @@ default configuration of Clippy. By default, any configuration will replace the
## `semicolon-inside-block-ignore-singleline` ## `semicolon-inside-block-ignore-singleline`
Whether to lint only if it's multiline. Whether to lint only if it's multiline.
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -199,7 +197,7 @@ Whether to lint only if it's multiline.
## `semicolon-outside-block-ignore-multiline` ## `semicolon-outside-block-ignore-multiline`
Whether to lint only if it's singleline. Whether to lint only if it's singleline.
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -213,9 +211,7 @@ default configuration of Clippy. By default, any configuration will replace the
* `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
* `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. * `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", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]`
**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "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>`)
--- ---
**Affected lints:** **Affected lints:**
@ -225,7 +221,7 @@ Default list:
## `too-many-arguments-threshold` ## `too-many-arguments-threshold`
The maximum number of argument a function or method can have The maximum number of argument a function or method can have
**Default Value:** `7` (`u64`) **Default Value:** `7`
--- ---
**Affected lints:** **Affected lints:**
@ -235,7 +231,7 @@ The maximum number of argument a function or method can have
## `type-complexity-threshold` ## `type-complexity-threshold`
The maximum complexity a type can have The maximum complexity a type can have
**Default Value:** `250` (`u64`) **Default Value:** `250`
--- ---
**Affected lints:** **Affected lints:**
@ -245,7 +241,7 @@ The maximum complexity a type can have
## `single-char-binding-names-threshold` ## `single-char-binding-names-threshold`
The maximum number of single char bindings a scope may have The maximum number of single char bindings a scope may have
**Default Value:** `4` (`u64`) **Default Value:** `4`
--- ---
**Affected lints:** **Affected lints:**
@ -255,7 +251,7 @@ The maximum number of single char bindings a scope may have
## `too-large-for-stack` ## `too-large-for-stack`
The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
**Default Value:** `200` (`u64`) **Default Value:** `200`
--- ---
**Affected lints:** **Affected lints:**
@ -266,7 +262,7 @@ The maximum size of objects (in bytes) that will be linted. Larger objects are o
## `enum-variant-name-threshold` ## `enum-variant-name-threshold`
The minimum number of enum variants for the lints about variant names to trigger The minimum number of enum variants for the lints about variant names to trigger
**Default Value:** `3` (`u64`) **Default Value:** `3`
--- ---
**Affected lints:** **Affected lints:**
@ -276,7 +272,7 @@ The minimum number of enum variants for the lints about variant names to trigger
## `struct-field-name-threshold` ## `struct-field-name-threshold`
The minimum number of struct fields for the lints about field names to trigger The minimum number of struct fields for the lints about field names to trigger
**Default Value:** `3` (`u64`) **Default Value:** `3`
--- ---
**Affected lints:** **Affected lints:**
@ -286,7 +282,7 @@ The minimum number of struct fields for the lints about field names to trigger
## `enum-variant-size-threshold` ## `enum-variant-size-threshold`
The maximum size of an enum's variant to avoid box suggestion The maximum size of an enum's variant to avoid box suggestion
**Default Value:** `200` (`u64`) **Default Value:** `200`
--- ---
**Affected lints:** **Affected lints:**
@ -296,7 +292,7 @@ The maximum size of an enum's variant to avoid box suggestion
## `verbose-bit-mask-threshold` ## `verbose-bit-mask-threshold`
The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
**Default Value:** `1` (`u64`) **Default Value:** `1`
--- ---
**Affected lints:** **Affected lints:**
@ -306,7 +302,7 @@ The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
## `literal-representation-threshold` ## `literal-representation-threshold`
The lower bound for linting decimal literals The lower bound for linting decimal literals
**Default Value:** `16384` (`u64`) **Default Value:** `16384`
--- ---
**Affected lints:** **Affected lints:**
@ -314,9 +310,8 @@ The lower bound for linting decimal literals
## `trivial-copy-size-limit` ## `trivial-copy-size-limit`
The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference. The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
reference. By default there is no limit
**Default Value:** `None` (`Option<u64>`)
--- ---
**Affected lints:** **Affected lints:**
@ -326,7 +321,7 @@ The maximum size (in bytes) to consider a `Copy` type for passing by value inste
## `pass-by-value-size-limit` ## `pass-by-value-size-limit`
The minimum size (in bytes) to consider a type for passing by reference instead of by value. The minimum size (in bytes) to consider a type for passing by reference instead of by value.
**Default Value:** `256` (`u64`) **Default Value:** `256`
--- ---
**Affected lints:** **Affected lints:**
@ -336,7 +331,7 @@ The minimum size (in bytes) to consider a type for passing by reference instead
## `too-many-lines-threshold` ## `too-many-lines-threshold`
The maximum number of lines a function or method can have The maximum number of lines a function or method can have
**Default Value:** `100` (`u64`) **Default Value:** `100`
--- ---
**Affected lints:** **Affected lints:**
@ -346,7 +341,7 @@ The maximum number of lines a function or method can have
## `array-size-threshold` ## `array-size-threshold`
The maximum allowed size for arrays on the stack The maximum allowed size for arrays on the stack
**Default Value:** `512000` (`u64`) **Default Value:** `512000`
--- ---
**Affected lints:** **Affected lints:**
@ -357,7 +352,7 @@ The maximum allowed size for arrays on the stack
## `stack-size-threshold` ## `stack-size-threshold`
The maximum allowed stack size for functions in bytes The maximum allowed stack size for functions in bytes
**Default Value:** `512000` (`u64`) **Default Value:** `512000`
--- ---
**Affected lints:** **Affected lints:**
@ -367,7 +362,7 @@ The maximum allowed stack size for functions in bytes
## `vec-box-size-threshold` ## `vec-box-size-threshold`
The size of the boxed type in bytes, where boxing in a `Vec` is allowed The size of the boxed type in bytes, where boxing in a `Vec` is allowed
**Default Value:** `4096` (`u64`) **Default Value:** `4096`
--- ---
**Affected lints:** **Affected lints:**
@ -377,7 +372,7 @@ The size of the boxed type in bytes, where boxing in a `Vec` is allowed
## `max-trait-bounds` ## `max-trait-bounds`
The maximum number of bounds a trait can have to be linted The maximum number of bounds a trait can have to be linted
**Default Value:** `3` (`u64`) **Default Value:** `3`
--- ---
**Affected lints:** **Affected lints:**
@ -387,7 +382,7 @@ The maximum number of bounds a trait can have to be linted
## `max-struct-bools` ## `max-struct-bools`
The maximum number of bool fields a struct can have The maximum number of bool fields a struct can have
**Default Value:** `3` (`u64`) **Default Value:** `3`
--- ---
**Affected lints:** **Affected lints:**
@ -397,7 +392,7 @@ The maximum number of bool fields a struct can have
## `max-fn-params-bools` ## `max-fn-params-bools`
The maximum number of bool parameters a function can have The maximum number of bool parameters a function can have
**Default Value:** `3` (`u64`) **Default Value:** `3`
--- ---
**Affected lints:** **Affected lints:**
@ -407,7 +402,7 @@ The maximum number of bool parameters a function can have
## `warn-on-all-wildcard-imports` ## `warn-on-all-wildcard-imports`
Whether to allow certain wildcard imports (prelude, super in tests). Whether to allow certain wildcard imports (prelude, super in tests).
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -417,7 +412,7 @@ Whether to allow certain wildcard imports (prelude, super in tests).
## `disallowed-macros` ## `disallowed-macros`
The list of disallowed macros, written as fully qualified paths. The list of disallowed macros, written as fully qualified paths.
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -427,7 +422,7 @@ The list of disallowed macros, written as fully qualified paths.
## `disallowed-methods` ## `disallowed-methods`
The list of disallowed methods, written as fully qualified paths. The list of disallowed methods, written as fully qualified paths.
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -437,7 +432,7 @@ The list of disallowed methods, written as fully qualified paths.
## `disallowed-types` ## `disallowed-types`
The list of disallowed types, written as fully qualified paths. The list of disallowed types, written as fully qualified paths.
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -447,7 +442,7 @@ The list of disallowed types, written as fully qualified paths.
## `unreadable-literal-lint-fractions` ## `unreadable-literal-lint-fractions`
Should the fraction of a decimal be linted to include separators. Should the fraction of a decimal be linted to include separators.
**Default Value:** `true` (`bool`) **Default Value:** `true`
--- ---
**Affected lints:** **Affected lints:**
@ -457,7 +452,7 @@ Should the fraction of a decimal be linted to include separators.
## `upper-case-acronyms-aggressive` ## `upper-case-acronyms-aggressive`
Enables verbose mode. Triggers if there is more than one uppercase char next to each other Enables verbose mode. Triggers if there is more than one uppercase char next to each other
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -468,7 +463,7 @@ Enables verbose mode. Triggers if there is more than one uppercase char next to
Whether the matches should be considered by the lint, and whether there should Whether the matches should be considered by the lint, and whether there should
be filtering for common types. be filtering for common types.
**Default Value:** `WellKnownTypes` (`crate::manual_let_else::MatchLintBehaviour`) **Default Value:** `"WellKnownTypes"`
--- ---
**Affected lints:** **Affected lints:**
@ -478,11 +473,11 @@ be filtering for common types.
## `cargo-ignore-publish` ## `cargo-ignore-publish`
For internal testing only, ignores the current `publish` settings in the Cargo manifest. For internal testing only, ignores the current `publish` settings in the Cargo manifest.
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
* [`_cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#_cargo_common_metadata) * [`cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata)
## `standard-macro-braces` ## `standard-macro-braces`
@ -492,7 +487,7 @@ A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If
could be used with a full path two `MacroMatcher`s have to be added one with the full path 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. `crate_name::macro_name` and one with just the macro name.
**Default Value:** `[]` (`Vec<crate::nonstandard_macro_braces::MacroMatcher>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -502,7 +497,7 @@ could be used with a full path two `MacroMatcher`s have to be added one with the
## `enforced-import-renames` ## `enforced-import-renames`
The list of imports to always rename, a fully qualified path followed by the rename. The list of imports to always rename, a fully qualified path followed by the rename.
**Default Value:** `[]` (`Vec<crate::utils::conf::Rename>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -512,7 +507,7 @@ The list of imports to always rename, a fully qualified path followed by the ren
## `allowed-scripts` ## `allowed-scripts`
The list of unicode scripts allowed to be used in the scope. The list of unicode scripts allowed to be used in the scope.
**Default Value:** `["Latin"]` (`Vec<String>`) **Default Value:** `["Latin"]`
--- ---
**Affected lints:** **Affected lints:**
@ -522,7 +517,7 @@ The list of unicode scripts allowed to be used in the scope.
## `enable-raw-pointer-heuristic-for-send` ## `enable-raw-pointer-heuristic-for-send`
Whether to apply the raw pointer heuristic to determine if a type is `Send`. Whether to apply the raw pointer heuristic to determine if a type is `Send`.
**Default Value:** `true` (`bool`) **Default Value:** `true`
--- ---
**Affected lints:** **Affected lints:**
@ -534,7 +529,7 @@ When Clippy suggests using a slice pattern, this is the maximum number of elemen
the slice pattern that is suggested. If more elements are necessary, the lint is suppressed. the slice pattern that is suggested. If more elements are necessary, the lint is suppressed.
For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
**Default Value:** `3` (`u64`) **Default Value:** `3`
--- ---
**Affected lints:** **Affected lints:**
@ -544,7 +539,7 @@ For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
## `await-holding-invalid-types` ## `await-holding-invalid-types`
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -554,7 +549,7 @@ For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
## `max-include-file-size` ## `max-include-file-size`
The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
**Default Value:** `1000000` (`u64`) **Default Value:** `1000000`
--- ---
**Affected lints:** **Affected lints:**
@ -564,7 +559,7 @@ The maximum size of a file included via `include_bytes!()` or `include_str!()`,
## `allow-expect-in-tests` ## `allow-expect-in-tests`
Whether `expect` should be allowed in test functions or `#[cfg(test)]` Whether `expect` should be allowed in test functions or `#[cfg(test)]`
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -574,7 +569,7 @@ Whether `expect` should be allowed in test functions or `#[cfg(test)]`
## `allow-unwrap-in-tests` ## `allow-unwrap-in-tests`
Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -584,7 +579,7 @@ Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
## `allow-dbg-in-tests` ## `allow-dbg-in-tests`
Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -594,7 +589,7 @@ Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
## `allow-print-in-tests` ## `allow-print-in-tests`
Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]` Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -605,7 +600,7 @@ Whether print macros (ex. `println!`) should be allowed in test functions or `#[
## `large-error-threshold` ## `large-error-threshold`
The maximum size of the `Err`-variant in a `Result` returned from a function The maximum size of the `Err`-variant in a `Result` returned from a function
**Default Value:** `128` (`u64`) **Default Value:** `128`
--- ---
**Affected lints:** **Affected lints:**
@ -616,7 +611,7 @@ The maximum size of the `Err`-variant in a `Result` returned from a function
A list of paths to types that should be treated like `Arc`, i.e. ignored but A list of paths to types that should be treated like `Arc`, i.e. ignored but
for the generic parameters for determining interior mutability for the generic parameters for determining interior mutability
**Default Value:** `["bytes::Bytes"]` (`Vec<String>`) **Default Value:** `["bytes::Bytes"]`
--- ---
**Affected lints:** **Affected lints:**
@ -627,7 +622,7 @@ for the generic parameters for determining interior mutability
## `allow-mixed-uninlined-format-args` ## `allow-mixed-uninlined-format-args`
Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)` Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
**Default Value:** `true` (`bool`) **Default Value:** `true`
--- ---
**Affected lints:** **Affected lints:**
@ -641,7 +636,7 @@ suggested counterparts are unavailable in constant code. This
configuration will cause restriction lints to trigger even configuration will cause restriction lints to trigger even
if no suggestion can be made. if no suggestion can be made.
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -652,7 +647,7 @@ if no suggestion can be made.
Whether to **only** check for missing documentation in items visible within the current Whether to **only** check for missing documentation in items visible within the current
crate. For example, `pub(crate)` items. crate. For example, `pub(crate)` items.
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -662,7 +657,7 @@ crate. For example, `pub(crate)` items.
## `future-size-threshold` ## `future-size-threshold`
The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
**Default Value:** `16384` (`u64`) **Default Value:** `16384`
--- ---
**Affected lints:** **Affected lints:**
@ -672,7 +667,7 @@ The maximum byte size a `Future` can have, before it triggers the `clippy::large
## `unnecessary-box-size` ## `unnecessary-box-size`
The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
**Default Value:** `128` (`u64`) **Default Value:** `128`
--- ---
**Affected lints:** **Affected lints:**
@ -682,7 +677,7 @@ The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::u
## `allow-private-module-inception` ## `allow-private-module-inception`
Whether to allow module inception if it's not public. Whether to allow module inception if it's not public.
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -694,7 +689,7 @@ Allowed names below the minimum allowed characters. The value `".."` can be used
the list to indicate, that the configured values should be appended to the default 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. configuration of Clippy. By default, any configuration will replace the default value.
**Default Value:** `{"j", "z", "i", "y", "n", "x", "w"}` (`rustc_data_structures::fx::FxHashSet<String>`) **Default Value:** `["j", "z", "i", "y", "n", "x", "w"]`
--- ---
**Affected lints:** **Affected lints:**
@ -704,7 +699,7 @@ configuration of Clippy. By default, any configuration will replace the default
## `min-ident-chars-threshold` ## `min-ident-chars-threshold`
Minimum chars an ident can have, anything below or equal to this will be linted. Minimum chars an ident can have, anything below or equal to this will be linted.
**Default Value:** `1` (`u64`) **Default Value:** `1`
--- ---
**Affected lints:** **Affected lints:**
@ -714,7 +709,7 @@ Minimum chars an ident can have, anything below or equal to this will be linted.
## `accept-comment-above-statement` ## `accept-comment-above-statement`
Whether to accept a safety comment to be placed above the statement containing the `unsafe` block Whether to accept a safety comment to be placed above the statement containing the `unsafe` block
**Default Value:** `true` (`bool`) **Default Value:** `true`
--- ---
**Affected lints:** **Affected lints:**
@ -724,7 +719,7 @@ Whether to accept a safety comment to be placed above the statement containing t
## `accept-comment-above-attributes` ## `accept-comment-above-attributes`
Whether to accept a safety comment to be placed above the attributes for the `unsafe` block Whether to accept a safety comment to be placed above the attributes for the `unsafe` block
**Default Value:** `true` (`bool`) **Default Value:** `true`
--- ---
**Affected lints:** **Affected lints:**
@ -734,7 +729,7 @@ Whether to accept a safety comment to be placed above the attributes for the `un
## `allow-one-hash-in-raw-strings` ## `allow-one-hash-in-raw-strings`
Whether to allow `r#""#` when `r""` can be used Whether to allow `r#""#` when `r""` can be used
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**
@ -745,7 +740,7 @@ Whether to allow `r#""#` when `r""` can be used
The maximum number of segments a path can have before being linted, anything above this will The maximum number of segments a path can have before being linted, anything above this will
be linted. be linted.
**Default Value:** `2` (`u64`) **Default Value:** `2`
--- ---
**Affected lints:** **Affected lints:**
@ -755,7 +750,7 @@ be linted.
## `absolute-paths-allowed-crates` ## `absolute-paths-allowed-crates`
Which crates to allow absolute paths from Which crates to allow absolute paths from
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -765,7 +760,7 @@ Which crates to allow absolute paths from
## `allowed-dotfiles` ## `allowed-dotfiles`
Additional dotfiles (files or directories starting with a dot) to allow Additional dotfiles (files or directories starting with a dot) to allow
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`) **Default Value:** `[]`
--- ---
**Affected lints:** **Affected lints:**
@ -774,7 +769,7 @@ Additional dotfiles (files or directories starting with a dot) to allow
## `enforce-iter-loop-reborrow` ## `enforce-iter-loop-reborrow`
#### Example #### Example
``` ```no_run
let mut vec = vec![1, 2, 3]; let mut vec = vec![1, 2, 3];
let rmvec = &mut vec; let rmvec = &mut vec;
for _ in rmvec.iter() {} for _ in rmvec.iter() {}
@ -782,14 +777,14 @@ for _ in rmvec.iter_mut() {}
``` ```
Use instead: Use instead:
``` ```no_run
let mut vec = vec![1, 2, 3]; let mut vec = vec![1, 2, 3];
let rmvec = &mut vec; let rmvec = &mut vec;
for _ in &*rmvec {} for _ in &*rmvec {}
for _ in &mut *rmvec {} for _ in &mut *rmvec {}
``` ```
**Default Value:** `false` (`bool`) **Default Value:** `false`
--- ---
**Affected lints:** **Affected lints:**

21
clippy_config/Cargo.toml Normal file
View File

@ -0,0 +1,21 @@
[package]
name = "clippy_config"
version = "0.1.75"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rustc-semver = "1.1"
serde = { version = "1.0", features = ["derive"] }
toml = "0.7.3"
[dev-dependencies]
walkdir = "2.3"
[features]
deny-warnings = []
[package.metadata.rust-analyzer]
# This crate uses #[feature(rustc_private)]
rustc_private = true

View File

@ -1,11 +1,11 @@
//! Read configurations files. use crate::msrvs::Msrv;
use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, Rename};
#![allow(clippy::module_name_repetitions)] use crate::ClippyConfiguration;
use rustc_data_structures::fx::FxHashSet;
use rustc_session::Session; use rustc_session::Session;
use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext}; use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext};
use serde::de::{Deserializer, IgnoredAny, IntoDeserializer, MapAccess, Visitor}; use serde::de::{IgnoredAny, IntoDeserializer, MapAccess, Visitor};
use serde::Deserialize; use serde::{Deserialize, Deserializer, Serialize};
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use std::ops::Range; use std::ops::Range;
use std::path::PathBuf; use std::path::PathBuf;
@ -38,43 +38,12 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"]; const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"];
const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"]; const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"];
/// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint.
#[derive(Clone, Debug, Deserialize)]
pub struct Rename {
pub path: String,
pub rename: String,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum DisallowedPath {
Simple(String),
WithReason { path: String, reason: Option<String> },
}
impl DisallowedPath {
pub fn path(&self) -> &str {
let (Self::Simple(path) | Self::WithReason { path, .. }) = self;
path
}
pub fn reason(&self) -> Option<String> {
match self {
Self::WithReason {
reason: Some(reason), ..
} => Some(format!("{reason} (from clippy.toml)")),
_ => None,
}
}
}
/// Conf with parse errors /// Conf with parse errors
#[derive(Default)] #[derive(Default)]
pub struct TryConf { struct TryConf {
pub conf: Conf, conf: Conf,
pub errors: Vec<ConfError>, errors: Vec<ConfError>,
pub warnings: Vec<ConfError>, warnings: Vec<ConfError>,
} }
impl TryConf { impl TryConf {
@ -88,9 +57,9 @@ impl TryConf {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct ConfError { struct ConfError {
pub message: String, message: String,
pub span: Span, span: Span,
} }
impl ConfError { impl ConfError {
@ -112,10 +81,31 @@ impl ConfError {
} }
} }
macro_rules! wrap_option {
() => {
None
};
($x:literal) => {
Some($x)
};
}
macro_rules! default_text {
($value:expr) => {{
let mut text = String::new();
$value.serialize(toml::ser::ValueSerializer::new(&mut text)).unwrap();
text
}};
($value:expr, $override:expr) => {
$override.to_string()
};
}
macro_rules! define_Conf { macro_rules! define_Conf {
($( ($(
$(#[doc = $doc:literal])+ $(#[doc = $doc:literal])+
$(#[conf_deprecated($dep:literal, $new_conf:ident)])? $(#[conf_deprecated($dep:literal, $new_conf:ident)])?
$(#[default_text = $default_text:expr])?
($name:ident: $ty:ty = $default:expr), ($name:ident: $ty:ty = $default:expr),
)*) => { )*) => {
/// Clippy lint configuration /// Clippy lint configuration
@ -124,6 +114,7 @@ macro_rules! define_Conf {
} }
mod defaults { mod defaults {
use super::*;
$(pub fn $name() -> $ty { $default })* $(pub fn $name() -> $ty { $default })*
} }
@ -190,31 +181,21 @@ macro_rules! define_Conf {
} }
} }
pub mod metadata { pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
use crate::utils::ClippyConfiguration; vec![
$(
{
let deprecation_reason = wrap_option!($($dep)?);
macro_rules! wrap_option { ClippyConfiguration::new(
() => (None); stringify!($name),
($x:literal) => (Some($x)); default_text!(defaults::$name() $(, $default_text)?),
} concat!($($doc, '\n',)*),
deprecation_reason,
pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> { )
vec![ },
$( )+
{ ]
let deprecation_reason = wrap_option!($($dep)?);
ClippyConfiguration::new(
stringify!($name),
stringify!($ty),
format!("{:?}", super::defaults::$name()),
concat!($($doc, '\n',)*),
deprecation_reason,
)
},
)+
]
}
} }
}; };
} }
@ -236,7 +217,7 @@ define_Conf! {
/// ///
/// A type, say `SomeType`, listed in this configuration has the same behavior of /// A type, say `SomeType`, listed in this configuration has the same behavior of
/// `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`. /// `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
(arithmetic_side_effects_allowed: rustc_data_structures::fx::FxHashSet<String> = <_>::default()), (arithmetic_side_effects_allowed: FxHashSet<String> = <_>::default()),
/// Lint: ARITHMETIC_SIDE_EFFECTS. /// Lint: ARITHMETIC_SIDE_EFFECTS.
/// ///
/// Suppress checking of the passed type pair names in binary operations like addition or /// Suppress checking of the passed type pair names in binary operations like addition or
@ -263,15 +244,16 @@ define_Conf! {
/// ```toml /// ```toml
/// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
/// ``` /// ```
(arithmetic_side_effects_allowed_unary: rustc_data_structures::fx::FxHashSet<String> = <_>::default()), (arithmetic_side_effects_allowed_unary: FxHashSet<String> = <_>::default()),
/// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS, SINGLE_CALL_FN. /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS, SINGLE_CALL_FN.
/// ///
/// Suppress lints whenever the suggested change would cause breakage for other crates. /// Suppress lints whenever the suggested change would cause breakage for other crates.
(avoid_breaking_exported_api: bool = true), (avoid_breaking_exported_api: bool = true),
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE. /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE.
/// ///
/// The minimum rust version that the project supports /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
(msrv: crate::Msrv = crate::Msrv::empty()), #[default_text = ""]
(msrv: Msrv = Msrv::empty()),
/// DEPRECATED LINT: BLACKLISTED_NAME. /// DEPRECATED LINT: BLACKLISTED_NAME.
/// ///
/// Use the Disallowed Names lint instead /// Use the Disallowed Names lint instead
@ -295,7 +277,7 @@ define_Conf! {
/// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value /// 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 /// `".."` 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 configuration of Clippy. By default, any configuration will replace the default value.
(disallowed_names: Vec<String> = super::DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()), (disallowed_names: Vec<String> = DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()),
/// Lint: SEMICOLON_INSIDE_BLOCK. /// Lint: SEMICOLON_INSIDE_BLOCK.
/// ///
/// Whether to lint only if it's multiline. /// Whether to lint only if it's multiline.
@ -311,9 +293,7 @@ define_Conf! {
/// default configuration of Clippy. By default, any configuration will replace the default value. For example: /// default configuration of Clippy. By default, any configuration will replace the default value. For example:
/// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
/// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
/// (doc_valid_idents: Vec<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect()),
/// Default list:
(doc_valid_idents: Vec<String> = super::DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect()),
/// Lint: TOO_MANY_ARGUMENTS. /// Lint: TOO_MANY_ARGUMENTS.
/// ///
/// The maximum number of argument a function or method can have /// The maximum number of argument a function or method can have
@ -352,7 +332,9 @@ define_Conf! {
(literal_representation_threshold: u64 = 16384), (literal_representation_threshold: u64 = 16384),
/// Lint: TRIVIALLY_COPY_PASS_BY_REF. /// Lint: TRIVIALLY_COPY_PASS_BY_REF.
/// ///
/// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference. /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
/// reference. By default there is no limit
#[default_text = ""]
(trivial_copy_size_limit: Option<u64> = None), (trivial_copy_size_limit: Option<u64> = None),
/// Lint: LARGE_TYPES_PASSED_BY_VALUE. /// Lint: LARGE_TYPES_PASSED_BY_VALUE.
/// ///
@ -393,15 +375,15 @@ define_Conf! {
/// Lint: DISALLOWED_MACROS. /// Lint: DISALLOWED_MACROS.
/// ///
/// The list of disallowed macros, written as fully qualified paths. /// The list of disallowed macros, written as fully qualified paths.
(disallowed_macros: Vec<crate::utils::conf::DisallowedPath> = Vec::new()), (disallowed_macros: Vec<DisallowedPath> = Vec::new()),
/// Lint: DISALLOWED_METHODS. /// Lint: DISALLOWED_METHODS.
/// ///
/// The list of disallowed methods, written as fully qualified paths. /// The list of disallowed methods, written as fully qualified paths.
(disallowed_methods: Vec<crate::utils::conf::DisallowedPath> = Vec::new()), (disallowed_methods: Vec<DisallowedPath> = Vec::new()),
/// Lint: DISALLOWED_TYPES. /// Lint: DISALLOWED_TYPES.
/// ///
/// The list of disallowed types, written as fully qualified paths. /// The list of disallowed types, written as fully qualified paths.
(disallowed_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()), (disallowed_types: Vec<DisallowedPath> = Vec::new()),
/// Lint: UNREADABLE_LITERAL. /// Lint: UNREADABLE_LITERAL.
/// ///
/// Should the fraction of a decimal be linted to include separators. /// Should the fraction of a decimal be linted to include separators.
@ -414,9 +396,8 @@ define_Conf! {
/// ///
/// Whether the matches should be considered by the lint, and whether there should /// Whether the matches should be considered by the lint, and whether there should
/// be filtering for common types. /// be filtering for common types.
(matches_for_let_else: crate::manual_let_else::MatchLintBehaviour = (matches_for_let_else: MatchLintBehaviour = MatchLintBehaviour::WellKnownTypes),
crate::manual_let_else::MatchLintBehaviour::WellKnownTypes), /// Lint: CARGO_COMMON_METADATA.
/// Lint: _CARGO_COMMON_METADATA.
/// ///
/// For internal testing only, ignores the current `publish` settings in the Cargo manifest. /// For internal testing only, ignores the current `publish` settings in the Cargo manifest.
(cargo_ignore_publish: bool = false), (cargo_ignore_publish: bool = false),
@ -427,11 +408,11 @@ define_Conf! {
/// A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro /// A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
/// could be used with a full path two `MacroMatcher`s have to be added one with the full path /// 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. /// `crate_name::macro_name` and one with just the macro name.
(standard_macro_braces: Vec<crate::nonstandard_macro_braces::MacroMatcher> = Vec::new()), (standard_macro_braces: Vec<MacroMatcher> = Vec::new()),
/// Lint: MISSING_ENFORCED_IMPORT_RENAMES. /// Lint: MISSING_ENFORCED_IMPORT_RENAMES.
/// ///
/// The list of imports to always rename, a fully qualified path followed by the rename. /// The list of imports to always rename, a fully qualified path followed by the rename.
(enforced_import_renames: Vec<crate::utils::conf::Rename> = Vec::new()), (enforced_import_renames: Vec<Rename> = Vec::new()),
/// Lint: DISALLOWED_SCRIPT_IDENTS. /// Lint: DISALLOWED_SCRIPT_IDENTS.
/// ///
/// The list of unicode scripts allowed to be used in the scope. /// The list of unicode scripts allowed to be used in the scope.
@ -447,7 +428,7 @@ define_Conf! {
/// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. /// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
(max_suggested_slice_pattern_length: u64 = 3), (max_suggested_slice_pattern_length: u64 = 3),
/// Lint: AWAIT_HOLDING_INVALID_TYPE. /// Lint: AWAIT_HOLDING_INVALID_TYPE.
(await_holding_invalid_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()), (await_holding_invalid_types: Vec<DisallowedPath> = Vec::new()),
/// Lint: LARGE_INCLUDE_FILE. /// Lint: LARGE_INCLUDE_FILE.
/// ///
/// The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes /// The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
@ -511,8 +492,8 @@ define_Conf! {
/// Allowed names below the minimum allowed characters. The value `".."` can be used as part of /// Allowed names below the minimum allowed characters. The value `".."` can be used as part of
/// the list to indicate, that the configured values should be appended to the default /// 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. /// configuration of Clippy. By default, any configuration will replace the default value.
(allowed_idents_below_min_chars: rustc_data_structures::fx::FxHashSet<String> = (allowed_idents_below_min_chars: FxHashSet<String> =
super::DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect()), DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect()),
/// Lint: MIN_IDENT_CHARS. /// Lint: MIN_IDENT_CHARS.
/// ///
/// Minimum chars an ident can have, anything below or equal to this will be linted. /// Minimum chars an ident can have, anything below or equal to this will be linted.
@ -537,19 +518,17 @@ define_Conf! {
/// Lint: ABSOLUTE_PATHS. /// Lint: ABSOLUTE_PATHS.
/// ///
/// Which crates to allow absolute paths from /// Which crates to allow absolute paths from
(absolute_paths_allowed_crates: rustc_data_structures::fx::FxHashSet<String> = (absolute_paths_allowed_crates: FxHashSet<String> = FxHashSet::default()),
rustc_data_structures::fx::FxHashSet::default()),
/// Lint: PATH_ENDS_WITH_EXT. /// Lint: PATH_ENDS_WITH_EXT.
/// ///
/// Additional dotfiles (files or directories starting with a dot) to allow /// Additional dotfiles (files or directories starting with a dot) to allow
(allowed_dotfiles: rustc_data_structures::fx::FxHashSet<String> = (allowed_dotfiles: FxHashSet<String> = FxHashSet::default()),
rustc_data_structures::fx::FxHashSet::default()),
/// Lint: EXPLICIT_ITER_LOOP /// Lint: EXPLICIT_ITER_LOOP
/// ///
/// Whether to recommend using implicit into iter for reborrowed values. /// Whether to recommend using implicit into iter for reborrowed values.
/// ///
/// #### Example /// #### Example
/// ``` /// ```no_run
/// let mut vec = vec![1, 2, 3]; /// let mut vec = vec![1, 2, 3];
/// let rmvec = &mut vec; /// let rmvec = &mut vec;
/// for _ in rmvec.iter() {} /// for _ in rmvec.iter() {}
@ -557,7 +536,7 @@ define_Conf! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ``` /// ```no_run
/// let mut vec = vec![1, 2, 3]; /// let mut vec = vec![1, 2, 3];
/// let rmvec = &mut vec; /// let rmvec = &mut vec;
/// for _ in &*rmvec {} /// for _ in &*rmvec {}
@ -779,7 +758,7 @@ mod tests {
#[test] #[test]
fn configs_are_tested() { fn configs_are_tested() {
let mut names: FxHashSet<String> = super::metadata::get_configuration_metadata() let mut names: FxHashSet<String> = crate::get_configuration_metadata()
.into_iter() .into_iter()
.map(|meta| meta.name.replace('_', "-")) .map(|meta| meta.name.replace('_', "-"))
.collect(); .collect();

23
clippy_config/src/lib.rs Normal file
View File

@ -0,0 +1,23 @@
#![feature(rustc_private, let_chains)]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
#![allow(
clippy::must_use_candidate,
clippy::missing_panics_doc,
rustc::untranslatable_diagnostic_trivial
)]
extern crate rustc_ast;
extern crate rustc_data_structures;
#[allow(unused_extern_crates)]
extern crate rustc_driver;
extern crate rustc_session;
extern crate rustc_span;
mod conf;
mod metadata;
pub mod msrvs;
pub mod types;
pub use conf::{get_configuration_metadata, lookup_conf_file, Conf};
pub use metadata::ClippyConfiguration;

View File

@ -0,0 +1,116 @@
use std::fmt::{self, Write};
#[derive(Debug, Clone, Default)]
pub struct ClippyConfiguration {
pub name: String,
pub default: String,
pub lints: Vec<String>,
pub doc: String,
pub deprecation_reason: Option<&'static str>,
}
impl fmt::Display for ClippyConfiguration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "- `{}`: {}", self.name, self.doc)?;
if !self.default.is_empty() {
write!(f, " (default: `{}`)", self.default)?;
}
Ok(())
}
}
impl ClippyConfiguration {
pub fn new(
name: &'static str,
default: String,
doc_comment: &'static str,
deprecation_reason: Option<&'static str>,
) -> Self {
let (lints, doc) = parse_config_field_doc(doc_comment)
.unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
Self {
name: to_kebab(name),
lints,
doc,
default,
deprecation_reason,
}
}
pub fn to_markdown_paragraph(&self) -> String {
let mut out = format!(
"## `{}`\n{}\n\n",
self.name,
self.doc
.lines()
.map(|line| line.strip_prefix(" ").unwrap_or(line))
.collect::<Vec<_>>()
.join("\n"),
);
if !self.default.is_empty() {
write!(out, "**Default Value:** `{}`\n\n", self.default).unwrap();
}
write!(
out,
"---\n**Affected lints:**\n{}\n\n",
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})"))
.collect::<Vec<_>>()
.join("\n"),
)
.unwrap();
out
}
pub fn to_markdown_link(&self) -> String {
const BOOK_CONFIGS_PATH: &str = "https://doc.rust-lang.org/clippy/lint_configuration.html";
format!("[`{}`]: {BOOK_CONFIGS_PATH}#{}", self.name, self.name)
}
}
/// This parses the field documentation of the config struct.
///
/// ```rust, ignore
/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
/// ```
///
/// Would yield:
/// ```rust, ignore
/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
/// ```
fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
const DOC_START: &str = " Lint: ";
if doc_comment.starts_with(DOC_START)
&& let Some(split_pos) = doc_comment.find('.')
{
let mut doc_comment = doc_comment.to_string();
let mut documentation = doc_comment.split_off(split_pos);
// Extract lints
doc_comment.make_ascii_lowercase();
let lints: Vec<String> = doc_comment
.split_off(DOC_START.len())
.split(", ")
.map(str::to_string)
.collect();
// Format documentation correctly
// split off leading `.` from lint name list and indent for correct formatting
documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n ");
Some((lints, documentation))
} else {
None
}
}
/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
fn to_kebab(config_name: &str) -> String {
config_name.replace('_', "-")
}

View File

@ -1,10 +1,9 @@
use rustc_ast::Attribute; use rustc_ast::Attribute;
use rustc_semver::RustcVersion; use rustc_semver::RustcVersion;
use rustc_session::Session; use rustc_session::Session;
use rustc_span::{sym, Symbol};
use serde::Deserialize; use serde::Deserialize;
use crate::attrs::get_unique_attr;
macro_rules! msrv_aliases { macro_rules! msrv_aliases {
($($major:literal,$minor:literal,$patch:literal { ($($major:literal,$minor:literal,$patch:literal {
$($name:ident),* $(,)? $($name:ident),* $(,)?
@ -101,7 +100,16 @@ impl Msrv {
} }
fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> { fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> {
if let Some(msrv_attr) = get_unique_attr(sess, attrs, "msrv") { let sym_msrv = Symbol::intern("msrv");
let mut msrv_attrs = attrs.iter().filter(|attr| attr.path_matches(&[sym::clippy, sym_msrv]));
if let Some(msrv_attr) = msrv_attrs.next() {
if let Some(duplicate) = msrv_attrs.last() {
sess.struct_span_err(duplicate.span, "`clippy::msrv` is defined multiple times")
.span_note(msrv_attr.span, "first definition found here")
.emit();
}
if let Some(msrv) = msrv_attr.value_str() { if let Some(msrv) = msrv_attr.value_str() {
if let Ok(version) = RustcVersion::parse(msrv.as_str()) { if let Ok(version) = RustcVersion::parse(msrv.as_str()) {
return Some(version); return Some(version);

142
clippy_config/src/types.rs Normal file
View File

@ -0,0 +1,142 @@
use serde::de::{self, Deserializer, Visitor};
use serde::{ser, Deserialize, Serialize};
use std::fmt;
use std::hash::{Hash, Hasher};
#[derive(Clone, Debug, Deserialize)]
pub struct Rename {
pub path: String,
pub rename: String,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum DisallowedPath {
Simple(String),
WithReason { path: String, reason: Option<String> },
}
impl DisallowedPath {
pub fn path(&self) -> &str {
let (Self::Simple(path) | Self::WithReason { path, .. }) = self;
path
}
pub fn reason(&self) -> Option<String> {
match self {
Self::WithReason {
reason: Some(reason), ..
} => Some(format!("{reason} (from clippy.toml)")),
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub enum MatchLintBehaviour {
AllTypes,
WellKnownTypes,
Never,
}
#[derive(Clone, Debug)]
pub struct MacroMatcher {
pub name: String,
pub braces: (String, String),
}
impl Hash for MacroMatcher {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl PartialEq for MacroMatcher {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Eq for MacroMatcher {}
impl<'de> Deserialize<'de> for MacroMatcher {
fn deserialize<D>(deser: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum Field {
Name,
Brace,
}
struct MacVisitor;
impl<'de> Visitor<'de> for MacVisitor {
type Value = MacroMatcher;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("struct MacroMatcher")
}
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where
V: de::MapAccess<'de>,
{
let mut name = None;
let mut brace: Option<String> = None;
while let Some(key) = map.next_key()? {
match key {
Field::Name => {
if name.is_some() {
return Err(de::Error::duplicate_field("name"));
}
name = Some(map.next_value()?);
},
Field::Brace => {
if brace.is_some() {
return Err(de::Error::duplicate_field("brace"));
}
brace = Some(map.next_value()?);
},
}
}
let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
let brace = brace.ok_or_else(|| de::Error::missing_field("brace"))?;
Ok(MacroMatcher {
name,
braces: [("(", ")"), ("{", "}"), ("[", "]")]
.into_iter()
.find(|b| b.0 == brace)
.map(|(o, c)| (o.to_owned(), c.to_owned()))
.ok_or_else(|| de::Error::custom(format!("expected one of `(`, `{{`, `[` found `{brace}`")))?,
})
}
}
const FIELDS: &[&str] = &["name", "brace"];
deser.deserialize_struct("MacroMatcher", FIELDS, MacVisitor)
}
}
// these impls are never actually called but are used by the various config options that default to
// empty lists
macro_rules! unimplemented_serialize {
($($t:ty,)*) => {
$(
impl Serialize for $t {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
Err(ser::Error::custom("unimplemented"))
}
}
)*
}
}
unimplemented_serialize! {
DisallowedPath,
Rename,
MacroMatcher,
}

View File

@ -199,7 +199,6 @@ fn get_clap_config() -> ArgMatches {
"cargo", "cargo",
"nursery", "nursery",
"internal", "internal",
"internal_warn",
]), ]),
Arg::new("type").long("type").help("What directory the lint belongs in"), Arg::new("type").long("type").help("What directory the lint belongs in"),
Arg::new("msrv") Arg::new("msrv")

View File

@ -346,11 +346,11 @@ fn get_lint_declaration(name_upper: &str, category: &str) -> String {
/// ### Why is this bad? /// ### Why is this bad?
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// // example code where clippy issues a warning /// // example code where clippy issues a warning
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// // example code which does not raise clippy warning /// // example code which does not raise clippy warning
/// ``` /// ```
#[clippy::version = "{}"] #[clippy::version = "{}"]

View File

@ -588,7 +588,7 @@ impl Lint {
.collect() .collect()
} }
/// Returns all internal lints (not `internal_warn` lints) /// Returns all internal lints
#[must_use] #[must_use]
fn internal_lints(lints: &[Self]) -> Vec<Self> { fn internal_lints(lints: &[Self]) -> Vec<Self> {
lints.iter().filter(|l| l.group == "internal").cloned().collect() lints.iter().filter(|l| l.group == "internal").cloned().collect()

View File

@ -11,6 +11,7 @@ edition = "2021"
[dependencies] [dependencies]
arrayvec = { version = "0.7", default-features = false } arrayvec = { version = "0.7", default-features = false }
cargo_metadata = "0.15.3" cargo_metadata = "0.15.3"
clippy_config = { path = "../clippy_config" }
clippy_utils = { path = "../clippy_utils" } clippy_utils = { path = "../clippy_utils" }
declare_clippy_lint = { path = "../declare_clippy_lint" } declare_clippy_lint = { path = "../declare_clippy_lint" }
if_chain = "1.0" if_chain = "1.0"
@ -32,9 +33,9 @@ url = "2.2"
walkdir = "2.3" walkdir = "2.3"
[features] [features]
deny-warnings = ["clippy_utils/deny-warnings"] deny-warnings = ["clippy_config/deny-warnings", "clippy_utils/deny-warnings"]
# build clippy with internal lints enabled, off by default # build clippy with internal lints enabled, off by default
internal = ["clippy_utils/internal", "serde_json", "tempfile", "regex"] internal = ["serde_json", "tempfile", "regex"]
[package.metadata.rust-analyzer] [package.metadata.rust-analyzer]
# This crate uses #[feature(rustc_private)] # This crate uses #[feature(rustc_private)]

View File

@ -24,11 +24,11 @@ declare_clippy_lint! {
/// using absolute paths is the proper way of referencing items in one. /// using absolute paths is the proper way of referencing items in one.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let x = std::f64::consts::PI; /// let x = std::f64::consts::PI;
/// ``` /// ```
/// Use any of the below instead, or anything else: /// Use any of the below instead, or anything else:
/// ```rust /// ```no_run
/// use std::f64; /// use std::f64;
/// use std::f64::consts; /// use std::f64::consts;
/// use std::f64::consts::PI; /// use std::f64::consts::PI;

View File

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{trim_span, walk_span_to_context}; use clippy_utils::source::{trim_span, walk_span_to_context};
use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits}; use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -17,11 +17,11 @@ declare_clippy_lint! {
/// This (`'a'..'z'`) is almost certainly a typo meant to include all letters. /// This (`'a'..'z'`) is almost certainly a typo meant to include all letters.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let _ = 'a'..'z'; /// let _ = 'a'..'z';
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let _ = 'a'..='z'; /// let _ = 'a'..='z';
/// ``` /// ```
#[clippy::version = "1.68.0"] #[clippy::version = "1.68.0"]
@ -82,33 +82,20 @@ fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg
( (
Ok(LitKind::Byte(b'a') | LitKind::Char('a')), Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
Ok(LitKind::Byte(b'z') | LitKind::Char('z')) Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
) ) | (
| (
Ok(LitKind::Byte(b'A') | LitKind::Char('A')), Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')), Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
) ) | (
| (
Ok(LitKind::Byte(b'0') | LitKind::Char('0')), Ok(LitKind::Byte(b'0') | LitKind::Char('0')),
Ok(LitKind::Byte(b'9') | LitKind::Char('9')), Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
) )
) )
&& !in_external_macro(cx.sess(), span) && !in_external_macro(cx.sess(), span)
{ {
span_lint_and_then( span_lint_and_then(cx, ALMOST_COMPLETE_RANGE, span, "almost complete ascii range", |diag| {
cx, if let Some((span, sugg)) = sugg {
ALMOST_COMPLETE_RANGE, diag.span_suggestion(span, "use an inclusive range", sugg, Applicability::MaybeIncorrect);
span,
"almost complete ascii range",
|diag| {
if let Some((span, sugg)) = sugg {
diag.span_suggestion(
span,
"use an inclusive range",
sugg,
Applicability::MaybeIncorrect,
);
}
} }
); });
} }
} }

View File

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::msrvs::{self, Msrv};
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
@ -24,12 +24,12 @@ declare_clippy_lint! {
/// issue](https://github.com/rust-lang/rust/issues). /// issue](https://github.com/rust-lang/rust/issues).
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let x = 3.14; /// let x = 3.14;
/// let y = 1_f64 / x; /// let y = 1_f64 / x;
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let x = std::f32::consts::PI; /// let x = std::f32::consts::PI;
/// let y = std::f64::consts::FRAC_1_PI; /// let y = std::f64::consts::FRAC_1_PI;
/// ``` /// ```

View File

@ -18,7 +18,7 @@ declare_clippy_lint! {
/// either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc` /// either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc`
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::cell::RefCell; /// # use std::cell::RefCell;
/// # use std::sync::Arc; /// # use std::sync::Arc;
/// ///
@ -62,19 +62,21 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
ARC_WITH_NON_SEND_SYNC, ARC_WITH_NON_SEND_SYNC,
expr.span, expr.span,
"usage of an `Arc` that is not `Send` or `Sync`", "usage of an `Arc` that is not `Send` or `Sync`",
|diag| with_forced_trimmed_paths!({ |diag| {
if !is_send { with_forced_trimmed_paths!({
diag.note(format!("the trait `Send` is not implemented for `{arg_ty}`")); if !is_send {
} diag.note(format!("the trait `Send` is not implemented for `{arg_ty}`"));
if !is_sync { }
diag.note(format!("the trait `Sync` is not implemented for `{arg_ty}`")); if !is_sync {
} diag.note(format!("the trait `Sync` is not implemented for `{arg_ty}`"));
}
diag.note(format!("required for `{ty}` to implement `Send` and `Sync`")); diag.note(format!("required for `{ty}` to implement `Send` and `Sync`"));
diag.help("consider using an `Rc` instead or wrapping the inner type with a `Mutex`"); diag.help("consider using an `Rc` instead or wrapping the inner type with a `Mutex`");
} });
)); },
);
} }
} }
} }

View File

@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
return; return;
} }
} }
let semicolon = if is_expr_final_block_expr(cx.tcx, e) {";"} else {""}; let semicolon = if is_expr_final_block_expr(cx.tcx, e) { ";" } else { "" };
let mut app = Applicability::MachineApplicable; let mut app = Applicability::MachineApplicable;
match method_segment.ident.as_str() { match method_segment.ident.as_str() {
"is_ok" if type_suitable_to_unwrap(cx, args.type_at(1)) => { "is_ok" if type_suitable_to_unwrap(cx, args.type_at(1)) => {
@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
), ),
app, app,
); );
} },
"is_err" if type_suitable_to_unwrap(cx, args.type_at(0)) => { "is_err" if type_suitable_to_unwrap(cx, args.type_at(0)) => {
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
), ),
app, app,
); );
} },
_ => (), _ => (),
}; };
} }

View File

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use clippy_utils::ty::implements_trait; use clippy_utils::ty::implements_trait;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{CoroutineSource, Body, BodyId, CoroutineKind, ExprKind, QPath}; use rustc_hir::{Body, BodyId, CoroutineKind, CoroutineSource, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -15,7 +15,7 @@ declare_clippy_lint! {
/// An await is likely missing. /// An await is likely missing.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// async fn foo() {} /// async fn foo() {}
/// ///
/// fn bar() { /// fn bar() {
@ -26,7 +26,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// async fn foo() {} /// async fn foo() {}
/// ///
/// fn bar() { /// fn bar() {

View File

@ -1,9 +1,9 @@
//! checks for attributes //! checks for attributes
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::is_from_proc_macro; use clippy_utils::is_from_proc_macro;
use clippy_utils::macros::{is_panic, macro_backtrace}; use clippy_utils::macros::{is_panic, macro_backtrace};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments}; use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_ast::token::{Token, TokenKind}; use rustc_ast::token::{Token, TokenKind};
@ -129,7 +129,7 @@ declare_clippy_lint! {
/// a valid semver. Failing that, the contained information is useless. /// a valid semver. Failing that, the contained information is useless.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// #[deprecated(since = "forever")] /// #[deprecated(since = "forever")]
/// fn something_else() { /* ... */ } /// fn something_else() { /* ... */ }
/// ``` /// ```
@ -156,14 +156,14 @@ declare_clippy_lint! {
/// currently works for basic cases but is not perfect. /// currently works for basic cases but is not perfect.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// #[allow(dead_code)] /// #[allow(dead_code)]
/// ///
/// fn not_quite_good_code() { } /// fn not_quite_good_code() { }
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// // Good (as inner attribute) /// // Good (as inner attribute)
/// #![allow(dead_code)] /// #![allow(dead_code)]
/// ///
@ -198,25 +198,25 @@ declare_clippy_lint! {
/// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`). /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`).
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// /// Some doc comment with a blank line after it. /// /// Some doc comment with a blank line after it.
/// ///
/// fn not_quite_good_code() { } /// fn not_quite_good_code() { }
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// /// Good (no blank line) /// /// Good (no blank line)
/// fn this_is_fine() { } /// fn this_is_fine() { }
/// ``` /// ```
/// ///
/// ```rust /// ```no_run
/// // Good (convert to a regular comment) /// // Good (convert to a regular comment)
/// ///
/// fn this_is_fine_too() { } /// fn this_is_fine_too() { }
/// ``` /// ```
/// ///
/// ```rust /// ```no_run
/// //! Good (convert to a comment on an inner attribute) /// //! Good (convert to a comment on an inner attribute)
/// ///
/// fn this_is_fine_as_well() { } /// fn this_is_fine_as_well() { }
@ -236,12 +236,12 @@ declare_clippy_lint! {
/// These lints should only be enabled on a lint-by-lint basis and with careful consideration. /// These lints should only be enabled on a lint-by-lint basis and with careful consideration.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// #![deny(clippy::restriction)] /// #![deny(clippy::restriction)]
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #![deny(clippy::as_conversions)] /// #![deny(clippy::as_conversions)]
/// ``` /// ```
#[clippy::version = "1.47.0"] #[clippy::version = "1.47.0"]
@ -265,13 +265,13 @@ declare_clippy_lint! {
/// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765) /// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765)
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// #[cfg_attr(rustfmt, rustfmt_skip)] /// #[cfg_attr(rustfmt, rustfmt_skip)]
/// fn main() { } /// fn main() { }
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #[rustfmt::skip] /// #[rustfmt::skip]
/// fn main() { } /// fn main() { }
/// ``` /// ```
@ -290,13 +290,13 @@ declare_clippy_lint! {
/// by the conditional compilation engine. /// by the conditional compilation engine.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// #[cfg(linux)] /// #[cfg(linux)]
/// fn conditional() { } /// fn conditional() { }
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # mod hidden { /// # mod hidden {
/// #[cfg(target_os = "linux")] /// #[cfg(target_os = "linux")]
/// fn conditional() { } /// fn conditional() { }
@ -325,14 +325,14 @@ declare_clippy_lint! {
/// ensure that others understand the reasoning /// ensure that others understand the reasoning
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// #![feature(lint_reasons)] /// #![feature(lint_reasons)]
/// ///
/// #![allow(clippy::some_lint)] /// #![allow(clippy::some_lint)]
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #![feature(lint_reasons)] /// #![feature(lint_reasons)]
/// ///
/// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")] /// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")]
@ -352,7 +352,7 @@ declare_clippy_lint! {
/// panicking with the expected message, and not another unrelated panic. /// panicking with the expected message, and not another unrelated panic.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn random() -> i32 { 0 } /// fn random() -> i32 { 0 }
/// ///
/// #[should_panic] /// #[should_panic]
@ -363,7 +363,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// fn random() -> i32 { 0 } /// fn random() -> i32 { 0 }
/// ///
/// #[should_panic = "attempt to divide by zero"] /// #[should_panic = "attempt to divide by zero"]
@ -386,13 +386,13 @@ declare_clippy_lint! {
/// If there is only one condition, no need to wrap it into `any` or `all` combinators. /// If there is only one condition, no need to wrap it into `any` or `all` combinators.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// #[cfg(any(unix))] /// #[cfg(any(unix))]
/// pub struct Bar; /// pub struct Bar;
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #[cfg(unix)] /// #[cfg(unix)]
/// pub struct Bar; /// pub struct Bar;
/// ``` /// ```
@ -409,16 +409,16 @@ declare_clippy_lint! {
/// ///
/// ### Why is this bad? /// ### Why is this bad?
/// Misspelling `feature` as `features` can be sometimes hard to spot. It /// Misspelling `feature` as `features` can be sometimes hard to spot. It
/// may cause conditional compilation not work quitely. /// may cause conditional compilation not work quietly.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// #[cfg(features = "some-feature")] /// #[cfg(features = "some-feature")]
/// fn conditional() { } /// fn conditional() { }
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #[cfg(feature = "some-feature")] /// #[cfg(feature = "some-feature")]
/// fn conditional() { } /// fn conditional() { }
/// ``` /// ```
@ -602,9 +602,26 @@ fn check_should_panic_reason(cx: &LateContext<'_>, attr: &Attribute) {
if let AttrArgs::Delimited(args) = &normal_attr.item.args if let AttrArgs::Delimited(args) = &normal_attr.item.args
&& let mut tt_iter = args.tokens.trees() && let mut tt_iter = args.tokens.trees()
&& let Some(TokenTree::Token(Token { kind: TokenKind::Ident(sym::expected, _), .. }, _)) = tt_iter.next() && let Some(TokenTree::Token(
&& let Some(TokenTree::Token(Token { kind: TokenKind::Eq, .. }, _)) = tt_iter.next() Token {
&& let Some(TokenTree::Token(Token { kind: TokenKind::Literal(_), .. }, _)) = tt_iter.next() kind: TokenKind::Ident(sym::expected, _),
..
},
_,
)) = tt_iter.next()
&& let Some(TokenTree::Token(
Token {
kind: TokenKind::Eq, ..
},
_,
)) = tt_iter.next()
&& let Some(TokenTree::Token(
Token {
kind: TokenKind::Literal(_),
..
},
_,
)) = tt_iter.next()
{ {
// `#[should_panic(expected = "..")]` found, good // `#[should_panic(expected = "..")]` found, good
return; return;
@ -914,7 +931,9 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
for item in items { for item in items {
if let NestedMetaItem::MetaItem(meta) = item { if let NestedMetaItem::MetaItem(meta) = item {
if meta.has_name(sym!(features)) && let Some(val) = meta.value_str() { if meta.has_name(sym!(features))
&& let Some(val) = meta.value_str()
{
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
MAYBE_MISUSED_CFG, MAYBE_MISUSED_CFG,
@ -933,16 +952,16 @@ fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
} }
fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) { fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
if attr.has_name(sym::cfg) && if attr.has_name(sym::cfg)
let Some(items) = attr.meta_item_list() && let Some(items) = attr.meta_item_list()
{ {
check_nested_cfg(cx, &items); check_nested_cfg(cx, &items);
} }
} }
fn check_misused_cfg(cx: &EarlyContext<'_>, attr: &Attribute) { fn check_misused_cfg(cx: &EarlyContext<'_>, attr: &Attribute) {
if attr.has_name(sym::cfg) && if attr.has_name(sym::cfg)
let Some(items) = attr.meta_item_list() && let Some(items) = attr.meta_item_list()
{ {
check_nested_misused_cfg(cx, &items); check_nested_misused_cfg(cx, &items);
} }

View File

@ -1,15 +1,14 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{match_def_path, paths}; use clippy_utils::{match_def_path, paths};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{CoroutineSource, Body, CoroutineKind}; use rustc_hir::{Body, CoroutineKind, CoroutineSource};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::CoroutineLayout; use rustc_middle::mir::CoroutineLayout;
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{sym, Span}; use rustc_span::{sym, Span};
use crate::utils::conf::DisallowedPath;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
/// Checks for calls to await while holding a non-async-aware MutexGuard. /// Checks for calls to await while holding a non-async-aware MutexGuard.
@ -29,7 +28,7 @@ declare_clippy_lint! {
/// to wrap the `.lock()` call in a block instead of explicitly dropping the guard. /// to wrap the `.lock()` call in a block instead of explicitly dropping the guard.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::sync::Mutex; /// # use std::sync::Mutex;
/// # async fn baz() {} /// # async fn baz() {}
/// async fn foo(x: &Mutex<u32>) { /// async fn foo(x: &Mutex<u32>) {
@ -47,7 +46,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # use std::sync::Mutex; /// # use std::sync::Mutex;
/// # async fn baz() {} /// # async fn baz() {}
/// async fn foo(x: &Mutex<u32>) { /// async fn foo(x: &Mutex<u32>) {
@ -87,7 +86,7 @@ declare_clippy_lint! {
/// to wrap the `.borrow[_mut]()` call in a block instead of explicitly dropping the ref. /// to wrap the `.borrow[_mut]()` call in a block instead of explicitly dropping the ref.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::cell::RefCell; /// # use std::cell::RefCell;
/// # async fn baz() {} /// # async fn baz() {}
/// async fn foo(x: &RefCell<u32>) { /// async fn foo(x: &RefCell<u32>) {
@ -105,7 +104,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # use std::cell::RefCell; /// # use std::cell::RefCell;
/// # async fn baz() {} /// # async fn baz() {}
/// async fn foo(x: &RefCell<u32>) { /// async fn foo(x: &RefCell<u32>) {
@ -151,7 +150,7 @@ declare_clippy_lint! {
/// ] /// ]
/// ``` /// ```
/// ///
/// ```rust /// ```no_run
/// # async fn baz() {} /// # async fn baz() {}
/// struct CustomLockType; /// struct CustomLockType;
/// struct OtherCustomLockType; /// struct OtherCustomLockType;

View File

@ -21,7 +21,7 @@ declare_clippy_lint! {
/// Style, using blocks in the condition makes it hard to read. /// Style, using blocks in the condition makes it hard to read.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
/// # fn somefunc() -> bool { true }; /// # fn somefunc() -> bool { true };
/// if { true } { /* ... */ } /// if { true } { /* ... */ }
/// ///
@ -29,7 +29,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # fn somefunc() -> bool { true }; /// # fn somefunc() -> bool { true };
/// if true { /* ... */ } /// if true { /* ... */ }
/// ///

View File

@ -18,13 +18,13 @@ declare_clippy_lint! {
/// It is shorter to use the equivalent. /// It is shorter to use the equivalent.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// assert_eq!("a".is_empty(), false); /// assert_eq!("a".is_empty(), false);
/// assert_ne!("a".is_empty(), true); /// assert_ne!("a".is_empty(), true);
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// assert!(!"a".is_empty()); /// assert!(!"a".is_empty());
/// ``` /// ```
#[clippy::version = "1.53.0"] #[clippy::version = "1.53.0"]

View File

@ -21,7 +21,7 @@ declare_clippy_lint! {
/// See https://doc.rust-lang.org/std/primitive.bool.html#impl-From%3Cbool%3E /// See https://doc.rust-lang.org/std/primitive.bool.html#impl-From%3Cbool%3E
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # let condition = false; /// # let condition = false;
/// if condition { /// if condition {
/// 1_i64 /// 1_i64
@ -30,12 +30,12 @@ declare_clippy_lint! {
/// }; /// };
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # let condition = false; /// # let condition = false;
/// i64::from(condition); /// i64::from(condition);
/// ``` /// ```
/// or /// or
/// ```rust /// ```no_run
/// # let condition = false; /// # let condition = false;
/// condition as i64; /// condition as i64;
/// ``` /// ```
@ -55,7 +55,11 @@ impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf {
} }
fn check_if_else<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { fn check_if_else<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
if let Some(If { cond, then, r#else: Some(r#else) }) = If::hir(expr) if let Some(If {
cond,
then,
r#else: Some(r#else),
}) = If::hir(expr)
&& let Some(then_lit) = int_literal(then) && let Some(then_lit) = int_literal(then)
&& let Some(else_lit) = int_literal(r#else) && let Some(else_lit) = int_literal(r#else)
{ {
@ -90,19 +94,18 @@ fn check_if_else<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>
let into_snippet = snippet.clone().maybe_par(); let into_snippet = snippet.clone().maybe_par();
let as_snippet = snippet.as_ty(ty); let as_snippet = snippet.as_ty(ty);
span_lint_and_then(cx, span_lint_and_then(
cx,
BOOL_TO_INT_WITH_IF, BOOL_TO_INT_WITH_IF,
expr.span, expr.span,
"boolean to int conversion using if", "boolean to int conversion using if",
|diag| { |diag| {
diag.span_suggestion( diag.span_suggestion(expr.span, "replace with from", suggestion, applicability);
expr.span, diag.note(format!(
"replace with from", "`{as_snippet}` or `{into_snippet}.into()` can also be valid options"
suggestion, ));
applicability, },
); );
diag.note(format!("`{as_snippet}` or `{into_snippet}.into()` can also be valid options"));
});
}; };
} }
@ -110,7 +113,7 @@ fn check_if_else<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>
fn int_literal<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>) -> Option<&'tcx rustc_hir::Expr<'tcx>> { fn int_literal<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>) -> Option<&'tcx rustc_hir::Expr<'tcx>> {
if let ExprKind::Block(block, _) = expr.kind if let ExprKind::Block(block, _) = expr.kind
&& let Block { && let Block {
stmts: [], // Shouldn't lint if statements with side effects stmts: [], // Shouldn't lint if statements with side effects
expr: Some(expr), expr: Some(expr),
.. ..
} = block } = block

View File

@ -472,8 +472,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
self.bool_expr(e); self.bool_expr(e);
}, },
ExprKind::Unary(UnOp::Not, inner) => { ExprKind::Unary(UnOp::Not, inner) => {
if let ExprKind::Unary(UnOp::Not, ex) = inner.kind && if let ExprKind::Unary(UnOp::Not, ex) = inner.kind
!self.cx.typeck_results().node_types()[ex.hir_id].is_bool() { && !self.cx.typeck_results().node_types()[ex.hir_id].is_bool()
{
return; return;
} }
if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() { if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() {
@ -500,10 +501,10 @@ struct NotSimplificationVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind && if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind
!inner.span.from_expansion() && && !inner.span.from_expansion()
let Some(suggestion) = simplify_not(self.cx, inner) && let Some(suggestion) = simplify_not(self.cx, inner)
&& self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow && self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow
{ {
span_lint_and_sugg( span_lint_and_sugg(
self.cx, self.cx,

View File

@ -19,7 +19,7 @@ declare_clippy_lint! {
/// ///
/// ### Known problems /// ### Known problems
/// False negative on such code: /// False negative on such code:
/// ``` /// ```no_run
/// let x = &12; /// let x = &12;
/// let addr_x = &x as *const _ as usize; /// let addr_x = &x as *const _ as usize;
/// let addr_y = &&*x as *const _ as usize; // assert ok now, and lint triggered. /// let addr_y = &&*x as *const _ as usize; // assert ok now, and lint triggered.
@ -28,14 +28,14 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let s = &String::new(); /// let s = &String::new();
/// ///
/// let a: &String = &* s; /// let a: &String = &* s;
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # let s = &String::new(); /// # let s = &String::new();
/// let a: &String = s; /// let a: &String = s;
/// ``` /// ```

View File

@ -24,11 +24,11 @@ declare_clippy_lint! {
/// [in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box). /// [in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box).
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let x: Box<String> = Box::new(Default::default()); /// let x: Box<String> = Box::new(Default::default());
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let x: Box<String> = Box::default(); /// let x: Box<String> = Box::default();
/// ``` /// ```
#[clippy::version = "1.66.0"] #[clippy::version = "1.66.0"]
@ -61,9 +61,9 @@ impl LateLintPass<'_> for BoxDefault {
} else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) { } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) {
with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()")) with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
} else { } else {
return return;
}, },
Applicability::MachineApplicable Applicability::MachineApplicable,
); );
} }
} }
@ -110,7 +110,8 @@ fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
Node::Expr(Expr { Node::Expr(Expr {
kind: ExprKind::Call(path, args), kind: ExprKind::Call(path, args),
.. ..
}) | Node::Block(Block { })
| Node::Block(Block {
expr: expr:
Some(Expr { Some(Expr {
kind: ExprKind::Call(path, args), kind: ExprKind::Call(path, args),
@ -119,10 +120,10 @@ fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
.. ..
}), }),
) => { ) => {
if let Some(index) = args.iter().position(|arg| arg.hir_id == expr.hir_id) && if let Some(index) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
let Some(sig) = expr_sig(cx, path) && && let Some(sig) = expr_sig(cx, path)
let Some(input) = sig.input(index) && && let Some(input) = sig.input(index)
!cx.typeck_results().expr_ty_adjusted(expr).boxed_ty().is_trait() && !cx.typeck_results().expr_ty_adjusted(expr).boxed_ty().is_trait()
{ {
input.no_bound_vars().is_some() input.no_bound_vars().is_some()
} else { } else {

View File

@ -9,12 +9,19 @@ use rustc_middle::ty::{self, Ty, TypeAndMut};
use super::AS_PTR_CAST_MUT; use super::AS_PTR_CAST_MUT;
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>) { pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>) {
if let ty::RawPtr(ptrty @ TypeAndMut { mutbl: Mutability::Mut, .. }) = cast_to.kind() if let ty::RawPtr(
&& let ty::RawPtr(TypeAndMut { mutbl: Mutability::Not, .. }) = ptrty @ TypeAndMut {
cx.typeck_results().node_type(cast_expr.hir_id).kind() mutbl: Mutability::Mut, ..
},
) = cast_to.kind()
&& let ty::RawPtr(TypeAndMut {
mutbl: Mutability::Not, ..
}) = cx.typeck_results().node_type(cast_expr.hir_id).kind()
&& let ExprKind::MethodCall(method_name, receiver, [], _) = cast_expr.peel_blocks().kind && let ExprKind::MethodCall(method_name, receiver, [], _) = cast_expr.peel_blocks().kind
&& method_name.ident.name == rustc_span::sym::as_ptr && method_name.ident.name == rustc_span::sym::as_ptr
&& let Some(as_ptr_did) = cx.typeck_results().type_dependent_def_id(cast_expr.peel_blocks().hir_id) && let Some(as_ptr_did) = cx
.typeck_results()
.type_dependent_def_id(cast_expr.peel_blocks().hir_id)
&& let as_ptr_sig = cx.tcx.fn_sig(as_ptr_did).instantiate_identity() && let as_ptr_sig = cx.tcx.fn_sig(as_ptr_did).instantiate_identity()
&& let Some(first_param_ty) = as_ptr_sig.skip_binder().inputs().iter().next() && let Some(first_param_ty) = as_ptr_sig.skip_binder().inputs().iter().next()
&& let ty::Ref(_, _, Mutability::Not) = first_param_ty.kind() && let ty::Ref(_, _, Mutability::Not) = first_param_ty.kind()
@ -30,7 +37,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
&format!("casting the result of `as_ptr` to *{ptrty}"), &format!("casting the result of `as_ptr` to *{ptrty}"),
"replace with", "replace with",
format!("{recv}.as_mut_ptr()"), format!("{recv}.as_mut_ptr()"),
applicability applicability,
); );
} }
} }

View File

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::sugg::Sugg; use clippy_utils::sugg::Sugg;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};

View File

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::in_constant; use clippy_utils::in_constant;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_isize_or_usize; use clippy_utils::ty::is_isize_or_usize;
use rustc_errors::Applicability; use rustc_errors::Applicability;

View File

@ -26,8 +26,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
// There probably is no obvious reason to do this, just to be consistent with `as` cases. // There probably is no obvious reason to do this, just to be consistent with `as` cases.
&& !is_hir_ty_cfg_dependant(cx, cast_to) && !is_hir_ty_cfg_dependant(cx, cast_to)
{ {
let (cast_from, cast_to) = let (cast_from, cast_to) = (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr));
(cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr));
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
} }
} }
@ -81,9 +80,9 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
cx.tcx.get_diagnostic_name(def_id), cx.tcx.get_diagnostic_name(def_id),
Some( Some(
sym::ptr_write_unaligned sym::ptr_write_unaligned
| sym::ptr_read_unaligned | sym::ptr_read_unaligned
| sym::intrinsics_unaligned_volatile_load | sym::intrinsics_unaligned_volatile_load
| sym::intrinsics_unaligned_volatile_store | sym::intrinsics_unaligned_volatile_store
) )
) )
{ {

View File

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source; use clippy_utils::source;
use if_chain::if_chain; use if_chain::if_chain;
use rustc_ast::Mutability; use rustc_ast::Mutability;

View File

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context; use clippy_utils::source::snippet_with_context;
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;

View File

@ -22,8 +22,8 @@ mod unnecessary_cast;
mod utils; mod utils;
mod zero_ptr; mod zero_ptr;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::is_hir_ty_cfg_dependant; use clippy_utils::is_hir_ty_cfg_dependant;
use clippy_utils::msrvs::{self, Msrv};
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
@ -45,7 +45,7 @@ declare_clippy_lint! {
/// those places in the code. /// those places in the code.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let x = u64::MAX; /// let x = u64::MAX;
/// x as f64; /// x as f64;
/// ``` /// ```
@ -67,7 +67,7 @@ declare_clippy_lint! {
/// as a one-time check to see where numerical wrapping can arise. /// as a one-time check to see where numerical wrapping can arise.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let y: i8 = -1; /// let y: i8 = -1;
/// y as u128; // will return 18446744073709551615 /// y as u128; // will return 18446744073709551615
/// ``` /// ```
@ -90,13 +90,13 @@ declare_clippy_lint! {
/// checks could be beneficial. /// checks could be beneficial.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn as_u8(x: u64) -> u8 { /// fn as_u8(x: u64) -> u8 {
/// x as u8 /// x as u8
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ``` /// ```no_run
/// fn as_u8(x: u64) -> u8 { /// fn as_u8(x: u64) -> u8 {
/// if let Ok(x) = u8::try_from(x) { /// if let Ok(x) = u8::try_from(x) {
/// x /// x
@ -132,7 +132,7 @@ declare_clippy_lint! {
/// example below. /// example below.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// u32::MAX as i32; // will yield a value of `-1` /// u32::MAX as i32; // will yield a value of `-1`
/// ``` /// ```
#[clippy::version = "pre 1.29.0"] #[clippy::version = "pre 1.29.0"]
@ -155,7 +155,7 @@ declare_clippy_lint! {
/// people reading the code to know that the conversion is lossless. /// people reading the code to know that the conversion is lossless.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn as_u64(x: u8) -> u64 { /// fn as_u64(x: u8) -> u64 {
/// x as u64 /// x as u64
/// } /// }
@ -163,7 +163,7 @@ declare_clippy_lint! {
/// ///
/// Using `::from` would look like this: /// Using `::from` would look like this:
/// ///
/// ```rust /// ```no_run
/// fn as_u64(x: u8) -> u64 { /// fn as_u64(x: u8) -> u64 {
/// u64::from(x) /// u64::from(x)
/// } /// }
@ -191,14 +191,14 @@ declare_clippy_lint! {
/// intermediate references, raw pointers and trait objects may or may not work. /// intermediate references, raw pointers and trait objects may or may not work.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let _ = 2i32 as i32; /// let _ = 2i32 as i32;
/// let _ = 0.5 as f32; /// let _ = 0.5 as f32;
/// ``` /// ```
/// ///
/// Better: /// Better:
/// ///
/// ```rust /// ```no_run
/// let _ = 2_i32; /// let _ = 2_i32;
/// let _ = 0.5_f32; /// let _ = 0.5_f32;
/// ``` /// ```
@ -223,7 +223,7 @@ declare_clippy_lint! {
/// u64-> u8 -> u16 can be fine. Miri is able to do a more in-depth analysis. /// u64-> u8 -> u16 can be fine. Miri is able to do a more in-depth analysis.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let _ = (&1u8 as *const u8) as *const u16; /// let _ = (&1u8 as *const u8) as *const u16;
/// let _ = (&mut 1u8 as *mut u8) as *mut u16; /// let _ = (&mut 1u8 as *mut u8) as *mut u16;
/// ///
@ -249,13 +249,13 @@ declare_clippy_lint! {
/// Casting to isize also doesn't make sense since there are no signed addresses. /// Casting to isize also doesn't make sense since there are no signed addresses.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn fun() -> i32 { 1 } /// fn fun() -> i32 { 1 }
/// let _ = fun as i64; /// let _ = fun as i64;
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # fn fun() -> i32 { 1 } /// # fn fun() -> i32 { 1 }
/// let _ = fun as usize; /// let _ = fun as usize;
/// ``` /// ```
@ -276,7 +276,7 @@ declare_clippy_lint! {
/// a comment) to perform the truncation. /// a comment) to perform the truncation.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn fn1() -> i16 { /// fn fn1() -> i16 {
/// 1 /// 1
/// }; /// };
@ -284,7 +284,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// // Cast to usize first, then comment with the reason for the truncation /// // Cast to usize first, then comment with the reason for the truncation
/// fn fn1() -> i16 { /// fn fn1() -> i16 {
/// 1 /// 1
@ -310,7 +310,7 @@ declare_clippy_lint! {
/// pointer casts in your code. /// pointer casts in your code.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// // fn1 is cast as `usize` /// // fn1 is cast as `usize`
/// fn fn1() -> u16 { /// fn fn1() -> u16 {
/// 1 /// 1
@ -319,7 +319,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// // maybe you intended to call the function? /// // maybe you intended to call the function?
/// fn fn2() -> u16 { /// fn fn2() -> u16 {
/// 1 /// 1
@ -378,14 +378,14 @@ declare_clippy_lint! {
/// it cannot accidentally change the pointer's mutability nor cast the pointer to other types like `usize`. /// it cannot accidentally change the pointer's mutability nor cast the pointer to other types like `usize`.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let ptr: *const u32 = &42_u32; /// let ptr: *const u32 = &42_u32;
/// let mut_ptr: *mut u32 = &mut 42_u32; /// let mut_ptr: *mut u32 = &mut 42_u32;
/// let _ = ptr as *const i32; /// let _ = ptr as *const i32;
/// let _ = mut_ptr as *mut i32; /// let _ = mut_ptr as *mut i32;
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let ptr: *const u32 = &42_u32; /// let ptr: *const u32 = &42_u32;
/// let mut_ptr: *mut u32 = &mut 42_u32; /// let mut_ptr: *mut u32 = &mut 42_u32;
/// let _ = ptr.cast::<i32>(); /// let _ = ptr.cast::<i32>();
@ -408,13 +408,13 @@ declare_clippy_lint! {
/// type. /// type.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let ptr: *const u32 = &42_u32; /// let ptr: *const u32 = &42_u32;
/// let mut_ptr = ptr as *mut u32; /// let mut_ptr = ptr as *mut u32;
/// let ptr = mut_ptr as *const u32; /// let ptr = mut_ptr as *const u32;
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let ptr: *const u32 = &42_u32; /// let ptr: *const u32 = &42_u32;
/// let mut_ptr = ptr.cast_mut(); /// let mut_ptr = ptr.cast_mut();
/// let ptr = mut_ptr.cast_const(); /// let ptr = mut_ptr.cast_const();
@ -434,7 +434,7 @@ declare_clippy_lint! {
/// The resulting integral value will not match the value of the variant it came from. /// The resulting integral value will not match the value of the variant it came from.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// enum E { X = 256 }; /// enum E { X = 256 };
/// let _ = E::X as u8; /// let _ = E::X as u8;
/// ``` /// ```
@ -457,7 +457,7 @@ declare_clippy_lint! {
/// ///
/// ### Example /// ### Example
/// // Missing data /// // Missing data
/// ```rust /// ```no_run
/// let a = [1_i32, 2, 3, 4]; /// let a = [1_i32, 2, 3, 4];
/// let p = &a as *const [i32] as *const [u8]; /// let p = &a as *const [i32] as *const [u8];
/// unsafe { /// unsafe {
@ -465,7 +465,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// // Undefined Behavior (note: also potential alignment issues) /// // Undefined Behavior (note: also potential alignment issues)
/// ```rust /// ```no_run
/// let a = [1_u8, 2, 3, 4]; /// let a = [1_u8, 2, 3, 4];
/// let p = &a as *const [u8] as *const [u32]; /// let p = &a as *const [u8] as *const [u32];
/// unsafe { /// unsafe {
@ -473,7 +473,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Instead use `ptr::slice_from_raw_parts` to construct a slice from a data pointer and the correct length /// Instead use `ptr::slice_from_raw_parts` to construct a slice from a data pointer and the correct length
/// ```rust /// ```no_run
/// let a = [1_i32, 2, 3, 4]; /// let a = [1_i32, 2, 3, 4];
/// let old_ptr = &a as *const [i32]; /// let old_ptr = &a as *const [i32];
/// // The data pointer is cast to a pointer to the target `u8` not `[u8]` /// // The data pointer is cast to a pointer to the target `u8` not `[u8]`
@ -497,7 +497,7 @@ declare_clippy_lint! {
/// The cast is easily confused with casting a c-like enum value to an integer. /// The cast is easily confused with casting a c-like enum value to an integer.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// enum E { X(i32) }; /// enum E { X(i32) };
/// let _ = E::X as usize; /// let _ = E::X as usize;
/// ``` /// ```
@ -515,12 +515,12 @@ declare_clippy_lint! {
/// The `unsigned_abs()` method avoids panic when called on the MIN value. /// The `unsigned_abs()` method avoids panic when called on the MIN value.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let x: i32 = -42; /// let x: i32 = -42;
/// let y: u32 = x.abs() as u32; /// let y: u32 = x.abs() as u32;
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let x: i32 = -42; /// let x: i32 = -42;
/// let y: u32 = x.unsigned_abs(); /// let y: u32 = x.unsigned_abs();
/// ``` /// ```
@ -541,13 +541,13 @@ declare_clippy_lint! {
/// The lint is allowed by default as using `_` is less wordy than always specifying the type. /// The lint is allowed by default as using `_` is less wordy than always specifying the type.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn foo(n: usize) {} /// fn foo(n: usize) {}
/// let n: u16 = 256; /// let n: u16 = 256;
/// foo(n as _); /// foo(n as _);
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// fn foo(n: usize) {} /// fn foo(n: usize) {}
/// let n: u16 = 256; /// let n: u16 = 256;
/// foo(n as usize); /// foo(n as usize);
@ -570,7 +570,7 @@ declare_clippy_lint! {
/// Read the `ptr::addr_of` docs for more information. /// Read the `ptr::addr_of` docs for more information.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let val = 1; /// let val = 1;
/// let p = &val as *const i32; /// let p = &val as *const i32;
/// ///
@ -578,7 +578,7 @@ declare_clippy_lint! {
/// let p_mut = &mut val_mut as *mut i32; /// let p_mut = &mut val_mut as *mut i32;
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let val = 1; /// let val = 1;
/// let p = std::ptr::addr_of!(val); /// let p = std::ptr::addr_of!(val);
/// ///
@ -627,13 +627,13 @@ declare_clippy_lint! {
/// mutability is used, making it unlikely that having it as a mutable pointer is correct. /// mutability is used, making it unlikely that having it as a mutable pointer is correct.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let mut vec = Vec::<u8>::with_capacity(1); /// let mut vec = Vec::<u8>::with_capacity(1);
/// let ptr = vec.as_ptr() as *mut u8; /// let ptr = vec.as_ptr() as *mut u8;
/// unsafe { ptr.write(4) }; // UNDEFINED BEHAVIOUR /// unsafe { ptr.write(4) }; // UNDEFINED BEHAVIOUR
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let mut vec = Vec::<u8>::with_capacity(1); /// let mut vec = Vec::<u8>::with_capacity(1);
/// let ptr = vec.as_mut_ptr(); /// let ptr = vec.as_mut_ptr();
/// unsafe { ptr.write(4) }; /// unsafe { ptr.write(4) };
@ -675,12 +675,12 @@ declare_clippy_lint! {
/// {`std`, `core`}`::ptr::`{`null`, `null_mut`}. /// {`std`, `core`}`::ptr::`{`null`, `null_mut`}.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let a = 0 as *const u32; /// let a = 0 as *const u32;
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let a = std::ptr::null::<u32>(); /// let a = std::ptr::null::<u32>();
/// ``` /// ```
#[clippy::version = "pre 1.29.0"] #[clippy::version = "pre 1.29.0"]

View File

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability; use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg; use clippy_utils::sugg::Sugg;
use rustc_errors::Applicability; use rustc_errors::Applicability;

View File

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{Msrv, POINTER_CAST_CONSTNESS};
use clippy_utils::sugg::Sugg; use clippy_utils::sugg::Sugg;
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -18,7 +18,7 @@ pub(super) fn check<'tcx>(
msrv: &Msrv, msrv: &Msrv,
) { ) {
if_chain! { if_chain! {
if msrv.meets(POINTER_CAST_CONSTNESS); if msrv.meets(msrvs::POINTER_CAST_CONSTNESS);
if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, ty: from_ty }) = cast_from.kind(); if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, ty: from_ty }) = cast_from.kind();
if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, ty: to_ty }) = cast_to.kind(); if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, ty: to_ty }) = cast_to.kind();
if matches!((from_mutbl, to_mutbl), if matches!((from_mutbl, to_mutbl),

View File

@ -97,7 +97,9 @@ pub(super) fn check<'tcx>(
} }
// skip cast of fn call that returns type alias // skip cast of fn call that returns type alias
if let ExprKind::Cast(inner, ..) = expr.kind && is_cast_from_ty_alias(cx, inner, cast_from) { if let ExprKind::Cast(inner, ..) = expr.kind
&& is_cast_from_ty_alias(cx, inner, cast_from)
{
return false; return false;
} }
@ -189,11 +191,10 @@ fn lint_unnecessary_cast(
let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr) let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr)
&& let ExprKind::MethodCall(..) = parent_expr.kind && let ExprKind::MethodCall(..) = parent_expr.kind
&& literal_str.starts_with('-') && literal_str.starts_with('-')
{ {
format!("({literal_str}_{cast_to})") format!("({literal_str}_{cast_to})")
} else {
} else { format!("{literal_str}_{cast_to}")
format!("{literal_str}_{cast_to}")
}; };
span_lint_and_sugg( span_lint_and_sugg(
@ -269,7 +270,9 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
&& let Some(parent) = get_parent_node(cx.tcx, hir_id) && let Some(parent) = get_parent_node(cx.tcx, hir_id)
&& let Node::Local(l) = parent && let Node::Local(l) = parent
{ {
if let Some(e) = l.init && is_cast_from_ty_alias(cx, e, cast_from) { if let Some(e) = l.init
&& is_cast_from_ty_alias(cx, e, cast_from)
{
return ControlFlow::Break::<()>(()); return ControlFlow::Break::<()>(());
} }

View File

@ -1,7 +1,7 @@
//! lint on manually implemented checked conversions that could be transformed into `try_from` //! lint on manually implemented checked conversions that could be transformed into `try_from`
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability; use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{in_constant, is_integer_literal, SpanlessEq}; use clippy_utils::{in_constant, is_integer_literal, SpanlessEq};
use if_chain::if_chain; use if_chain::if_chain;
@ -19,13 +19,13 @@ declare_clippy_lint! {
/// Reduces the readability of statements & is error prone. /// Reduces the readability of statements & is error prone.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # let foo: u32 = 5; /// # let foo: u32 = 5;
/// foo <= i32::MAX as u32; /// foo <= i32::MAX as u32;
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # let foo = 1; /// # let foo = 1;
/// # #[allow(unused)] /// # #[allow(unused)]
/// i32::try_from(foo).is_ok(); /// i32::try_from(foo).is_ok();

View File

@ -32,7 +32,7 @@ declare_clippy_lint! {
/// makes code look more complex than it really is. /// makes code look more complex than it really is.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # let (x, y) = (true, true); /// # let (x, y) = (true, true);
/// if x { /// if x {
/// if y { /// if y {
@ -42,7 +42,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # let (x, y) = (true, true); /// # let (x, y) = (true, true);
/// if x && y { /// if x && y {
/// // … /// // …

View File

@ -20,7 +20,7 @@ declare_clippy_lint! {
/// instead. /// instead.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # let samples = vec![3, 1, 2]; /// # let samples = vec![3, 1, 2];
/// let mut sorted_samples = samples.clone(); /// let mut sorted_samples = samples.clone();
/// sorted_samples.sort(); /// sorted_samples.sort();
@ -29,7 +29,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # let samples = vec![3, 1, 2]; /// # let samples = vec![3, 1, 2];
/// let mut sorted_samples = samples.clone(); /// let mut sorted_samples = samples.clone();
/// sorted_samples.sort(); /// sorted_samples.sort();

View File

@ -18,7 +18,7 @@ declare_clippy_lint! {
/// https://doc.rust-lang.org/reference/macros-by-example.html#hygiene /// https://doc.rust-lang.org/reference/macros-by-example.html#hygiene
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// #[macro_export] /// #[macro_export]
/// macro_rules! print_message { /// macro_rules! print_message {
/// () => { /// () => {
@ -28,7 +28,7 @@ declare_clippy_lint! {
/// pub const MESSAGE: &str = "Hello!"; /// pub const MESSAGE: &str = "Hello!";
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #[macro_export] /// #[macro_export]
/// macro_rules! print_message { /// macro_rules! print_message {
/// () => { /// () => {

View File

@ -6,8 +6,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO, crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO,
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
crate::utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS_INFO, crate::utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS_INFO,
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
crate::utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS_INFO, crate::utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS_INFO,
@ -30,6 +28,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
crate::utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE_INFO, crate::utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE_INFO,
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
crate::utils::internal_lints::metadata_collector::METADATA_COLLECTOR_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL_INFO, crate::utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL_INFO,
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
crate::utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA_INFO, crate::utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA_INFO,
@ -37,6 +37,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO, crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO, crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS_INFO,
crate::absolute_paths::ABSOLUTE_PATHS_INFO, crate::absolute_paths::ABSOLUTE_PATHS_INFO,
crate::allow_attributes::ALLOW_ATTRIBUTES_INFO, crate::allow_attributes::ALLOW_ATTRIBUTES_INFO,
crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO, crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
@ -272,6 +274,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::loops::NEVER_LOOP_INFO, crate::loops::NEVER_LOOP_INFO,
crate::loops::SAME_ITEM_PUSH_INFO, crate::loops::SAME_ITEM_PUSH_INFO,
crate::loops::SINGLE_ELEMENT_LOOP_INFO, crate::loops::SINGLE_ELEMENT_LOOP_INFO,
crate::loops::UNUSED_ENUMERATE_INDEX_INFO,
crate::loops::WHILE_IMMUTABLE_CONDITION_INFO, crate::loops::WHILE_IMMUTABLE_CONDITION_INFO,
crate::loops::WHILE_LET_LOOP_INFO, crate::loops::WHILE_LET_LOOP_INFO,
crate::loops::WHILE_LET_ON_ITERATOR_INFO, crate::loops::WHILE_LET_ON_ITERATOR_INFO,
@ -428,6 +431,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::methods::TYPE_ID_ON_BOX_INFO, crate::methods::TYPE_ID_ON_BOX_INFO,
crate::methods::UNINIT_ASSUMED_INIT_INFO, crate::methods::UNINIT_ASSUMED_INIT_INFO,
crate::methods::UNIT_HASH_INFO, crate::methods::UNIT_HASH_INFO,
crate::methods::UNNECESSARY_FALLIBLE_CONVERSIONS_INFO,
crate::methods::UNNECESSARY_FILTER_MAP_INFO, crate::methods::UNNECESSARY_FILTER_MAP_INFO,
crate::methods::UNNECESSARY_FIND_MAP_INFO, crate::methods::UNNECESSARY_FIND_MAP_INFO,
crate::methods::UNNECESSARY_FOLD_INFO, crate::methods::UNNECESSARY_FOLD_INFO,
@ -441,6 +445,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::methods::USELESS_ASREF_INFO, crate::methods::USELESS_ASREF_INFO,
crate::methods::VEC_RESIZE_TO_ZERO_INFO, crate::methods::VEC_RESIZE_TO_ZERO_INFO,
crate::methods::VERBOSE_FILE_READS_INFO, crate::methods::VERBOSE_FILE_READS_INFO,
crate::methods::WAKER_CLONE_WAKE_INFO,
crate::methods::WRONG_SELF_CONVENTION_INFO, crate::methods::WRONG_SELF_CONVENTION_INFO,
crate::methods::ZST_OFFSET_INFO, crate::methods::ZST_OFFSET_INFO,
crate::min_ident_chars::MIN_IDENT_CHARS_INFO, crate::min_ident_chars::MIN_IDENT_CHARS_INFO,

View File

@ -23,12 +23,12 @@ declare_clippy_lint! {
/// generic `Default`. /// generic `Default`.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let s: String = Default::default(); /// let s: String = Default::default();
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let s = String::default(); /// let s = String::default();
/// ``` /// ```
#[clippy::version = "pre 1.29.0"] #[clippy::version = "pre 1.29.0"]
@ -49,7 +49,7 @@ declare_clippy_lint! {
/// Assignments to patterns that are of tuple type are not linted. /// Assignments to patterns that are of tuple type are not linted.
/// ///
/// ### Example /// ### Example
/// ``` /// ```no_run
/// # #[derive(Default)] /// # #[derive(Default)]
/// # struct A { i: i32 } /// # struct A { i: i32 }
/// let mut a: A = Default::default(); /// let mut a: A = Default::default();
@ -57,7 +57,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ``` /// ```no_run
/// # #[derive(Default)] /// # #[derive(Default)]
/// # struct A { i: i32 } /// # struct A { i: i32 }
/// let a = A { /// let a = A {

View File

@ -17,7 +17,7 @@ declare_clippy_lint! {
/// This adds code complexity and an unnecessary function call. /// This adds code complexity and an unnecessary function call.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
/// #[derive(Default)] /// #[derive(Default)]
/// struct S<T> { /// struct S<T> {
@ -29,7 +29,7 @@ declare_clippy_lint! {
/// }; /// };
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
/// struct S<T> { /// struct S<T> {
/// _marker: PhantomData<T> /// _marker: PhantomData<T>

View File

@ -14,12 +14,12 @@ declare_clippy_lint! {
/// ### Why is this bad? /// ### Why is this bad?
/// `std::iter::empty()` is the more idiomatic way. /// `std::iter::empty()` is the more idiomatic way.
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let _ = std::iter::Empty::<usize>::default(); /// let _ = std::iter::Empty::<usize>::default();
/// let iter: std::iter::Empty<usize> = std::iter::Empty::default(); /// let iter: std::iter::Empty<usize> = std::iter::Empty::default();
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let _ = std::iter::empty::<usize>(); /// let _ = std::iter::empty::<usize>();
/// let iter: std::iter::Empty<usize> = std::iter::empty(); /// let iter: std::iter::Empty<usize> = std::iter::empty();
/// ``` /// ```
@ -68,7 +68,10 @@ fn make_sugg(
_ => None, _ => None,
}) })
{ {
format!("std::iter::empty::<{}>()", snippet_with_context(cx, iter_ty.span, ctxt, "..", applicability).0) format!(
"std::iter::empty::<{}>()",
snippet_with_context(cx, iter_ty.span, ctxt, "..", applicability).0
)
} else { } else {
"std::iter::empty()".to_owned() "std::iter::empty()".to_owned()
} }

View File

@ -31,13 +31,13 @@ declare_clippy_lint! {
/// This lint can only be allowed at the function level or above. /// This lint can only be allowed at the function level or above.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let i = 10; /// let i = 10;
/// let f = 1.23; /// let f = 1.23;
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let i = 10i32; /// let i = 10i32;
/// let f = 1.23f64; /// let f = 1.23f64;
/// ``` /// ```

View File

@ -17,7 +17,7 @@ declare_clippy_lint! {
/// specified layout. These cases may lead to undefined behavior in unsafe blocks. /// specified layout. These cases may lead to undefined behavior in unsafe blocks.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// union Foo { /// union Foo {
/// a: i32, /// a: i32,
/// b: u32, /// b: u32,
@ -30,7 +30,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #[repr(C)] /// #[repr(C)]
/// union Foo { /// union Foo {
/// a: i32, /// a: i32,

View File

@ -29,14 +29,14 @@ declare_clippy_lint! {
/// when not part of a method chain. /// when not part of a method chain.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// use std::ops::Deref; /// use std::ops::Deref;
/// let a: &mut String = &mut String::from("foo"); /// let a: &mut String = &mut String::from("foo");
/// let b: &str = a.deref(); /// let b: &str = a.deref();
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let a: &mut String = &mut String::from("foo"); /// let a: &mut String = &mut String::from("foo");
/// let b = &*a; /// let b = &*a;
/// ``` /// ```
@ -68,7 +68,7 @@ declare_clippy_lint! {
/// in such a case can change the semantics of the code. /// in such a case can change the semantics of the code.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn fun(_a: &i32) {} /// fn fun(_a: &i32) {}
/// ///
/// let x: &i32 = &&&&&&5; /// let x: &i32 = &&&&&&5;
@ -76,7 +76,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # fn fun(_a: &i32) {} /// # fn fun(_a: &i32) {}
/// let x: &i32 = &5; /// let x: &i32 = &5;
/// fun(x); /// fun(x);
@ -95,7 +95,7 @@ declare_clippy_lint! {
/// The address-of operator at the use site is clearer about the need for a reference. /// The address-of operator at the use site is clearer about the need for a reference.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let x = Some(""); /// let x = Some("");
/// if let Some(ref x) = x { /// if let Some(ref x) = x {
/// // use `x` here /// // use `x` here
@ -103,7 +103,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let x = Some(""); /// let x = Some("");
/// if let Some(x) = x { /// if let Some(x) = x {
/// // use `&x` here /// // use `&x` here
@ -123,12 +123,12 @@ declare_clippy_lint! {
/// This unnecessarily complicates the code. /// This unnecessarily complicates the code.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let x = String::new(); /// let x = String::new();
/// let y: &str = &*x; /// let y: &str = &*x;
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let x = String::new(); /// let x = String::new();
/// let y: &str = &x; /// let y: &str = &x;
/// ``` /// ```
@ -353,23 +353,26 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
// priority. // priority.
if let Some(fn_id) = typeck.type_dependent_def_id(hir_id) if let Some(fn_id) = typeck.type_dependent_def_id(hir_id)
&& let Some(trait_id) = cx.tcx.trait_of_item(fn_id) && let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
&& let arg_ty && let arg_ty = cx
= cx.tcx.erase_regions(use_cx.adjustments.last().map_or(expr_ty, |a| a.target)) .tcx
.erase_regions(use_cx.adjustments.last().map_or(expr_ty, |a| a.target))
&& let ty::Ref(_, sub_ty, _) = *arg_ty.kind() && let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
&& let args = cx && let args = cx
.typeck_results() .typeck_results()
.node_args_opt(hir_id).map(|args| &args[1..]).unwrap_or_default() .node_args_opt(hir_id)
&& let impl_ty = if cx.tcx.fn_sig(fn_id) .map(|args| &args[1..])
.instantiate_identity() .unwrap_or_default()
.skip_binder() && let impl_ty =
.inputs()[0].is_ref() if cx.tcx.fn_sig(fn_id).instantiate_identity().skip_binder().inputs()[0]
{ .is_ref()
// Trait methods taking `&self` {
sub_ty // Trait methods taking `&self`
} else { sub_ty
// Trait methods taking `self` } else {
arg_ty // Trait methods taking `self`
} && impl_ty.is_ref() arg_ty
}
&& impl_ty.is_ref()
&& implements_trait( && implements_trait(
cx, cx,
impl_ty, impl_ty,
@ -414,9 +417,9 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
let (required_refs, msg) = if can_auto_borrow { let (required_refs, msg) = if can_auto_borrow {
(1, if deref_count == 1 { borrow_msg } else { deref_msg }) (1, if deref_count == 1 { borrow_msg } else { deref_msg })
} else if let Some(&Adjustment { } else if let Some(&Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(_, mutability)), kind: Adjust::Borrow(AutoBorrow::Ref(_, mutability)),
.. ..
}) = next_adjust }) = next_adjust
&& matches!(mutability, AutoBorrowMutability::Mut { .. }) && matches!(mutability, AutoBorrowMutability::Mut { .. })
&& !stability.is_reborrow_stable() && !stability.is_reborrow_stable()
{ {
@ -705,9 +708,11 @@ fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> boo
{ {
match parent.kind { match parent.kind {
ExprKind::Call(child, _) | ExprKind::MethodCall(_, child, _, _) | ExprKind::Index(child, _, _) ExprKind::Call(child, _) | ExprKind::MethodCall(_, child, _, _) | ExprKind::Index(child, _, _)
if child.hir_id == e.hir_id => true, if child.hir_id == e.hir_id =>
ExprKind::Match(.., MatchSource::TryDesugar(_) | MatchSource::AwaitDesugar) {
| ExprKind::Field(_, _) => true, true
},
ExprKind::Match(.., MatchSource::TryDesugar(_) | MatchSource::AwaitDesugar) | ExprKind::Field(_, _) => true,
_ => false, _ => false,
} }
} else { } else {

View File

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::indent_of; use clippy_utils::source::indent_of;
use clippy_utils::{is_default_equivalent, peel_blocks}; use clippy_utils::{is_default_equivalent, peel_blocks};
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -21,7 +21,7 @@ declare_clippy_lint! {
/// It is less concise. /// It is less concise.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct Foo { /// struct Foo {
/// bar: bool /// bar: bool
/// } /// }
@ -36,7 +36,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #[derive(Default)] /// #[derive(Default)]
/// struct Foo { /// struct Foo {
/// bar: bool /// bar: bool

View File

@ -173,7 +173,7 @@ declare_clippy_lint! {
/// `Eq` themselves. /// `Eq` themselves.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// #[derive(PartialEq)] /// #[derive(PartialEq)]
/// struct Foo { /// struct Foo {
/// i_am_eq: i32, /// i_am_eq: i32,
@ -181,7 +181,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #[derive(PartialEq, Eq)] /// #[derive(PartialEq, Eq)]
/// struct Foo { /// struct Foo {
/// i_am_eq: i32, /// i_am_eq: i32,

View File

@ -1,3 +1,4 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::macro_backtrace; use clippy_utils::macros::macro_backtrace;
use rustc_ast::Attribute; use rustc_ast::Attribute;
@ -8,8 +9,6 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{ExpnId, Span}; use rustc_span::{ExpnId, Span};
use crate::utils::conf;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
/// Denies the configured macros in clippy.toml /// Denies the configured macros in clippy.toml
@ -35,7 +34,7 @@ declare_clippy_lint! {
/// { path = "serde::Serialize", reason = "no serializing" }, /// { path = "serde::Serialize", reason = "no serializing" },
/// ] /// ]
/// ``` /// ```
/// ``` /// ```no_run
/// use serde::Serialize; /// use serde::Serialize;
/// ///
/// // Example code where clippy issues a warning /// // Example code where clippy issues a warning
@ -55,13 +54,13 @@ declare_clippy_lint! {
} }
pub struct DisallowedMacros { pub struct DisallowedMacros {
conf_disallowed: Vec<conf::DisallowedPath>, conf_disallowed: Vec<DisallowedPath>,
disallowed: DefIdMap<usize>, disallowed: DefIdMap<usize>,
seen: FxHashSet<ExpnId>, seen: FxHashSet<ExpnId>,
} }
impl DisallowedMacros { impl DisallowedMacros {
pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self { pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
Self { Self {
conf_disallowed, conf_disallowed,
disallowed: DefIdMap::default(), disallowed: DefIdMap::default(),

View File

@ -1,13 +1,11 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{fn_def_id, get_parent_expr, path_def_id}; use clippy_utils::{fn_def_id, get_parent_expr, path_def_id};
use rustc_hir::def_id::DefIdMap; use rustc_hir::def_id::DefIdMap;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use crate::utils::conf;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
/// Denies the configured methods and functions in clippy.toml /// Denies the configured methods and functions in clippy.toml
@ -59,12 +57,12 @@ declare_clippy_lint! {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DisallowedMethods { pub struct DisallowedMethods {
conf_disallowed: Vec<conf::DisallowedPath>, conf_disallowed: Vec<DisallowedPath>,
disallowed: DefIdMap<usize>, disallowed: DefIdMap<usize>,
} }
impl DisallowedMethods { impl DisallowedMethods {
pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self { pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
Self { Self {
conf_disallowed, conf_disallowed,
disallowed: DefIdMap::default(), disallowed: DefIdMap::default(),

View File

@ -15,7 +15,7 @@ declare_clippy_lint! {
/// avoided. /// avoided.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let foo = 3.14; /// let foo = 3.14;
/// ``` /// ```
#[clippy::version = "pre 1.29.0"] #[clippy::version = "pre 1.29.0"]

View File

@ -30,7 +30,7 @@ declare_clippy_lint! {
/// [`non_ascii_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#non-ascii-idents /// [`non_ascii_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#non-ascii-idents
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// // Assuming that `clippy.toml` contains the following line: /// // Assuming that `clippy.toml` contains the following line:
/// // allowed-scripts = ["Latin", "Cyrillic"] /// // allowed-scripts = ["Latin", "Cyrillic"]
/// let counter = 10; // OK, latin is allowed. /// let counter = 10; // OK, latin is allowed.

View File

@ -1,5 +1,5 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -8,8 +8,6 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span; use rustc_span::Span;
use crate::utils::conf;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
/// Denies the configured types in clippy.toml. /// Denies the configured types in clippy.toml.
@ -50,15 +48,16 @@ declare_clippy_lint! {
style, style,
"use of disallowed types" "use of disallowed types"
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DisallowedTypes { pub struct DisallowedTypes {
conf_disallowed: Vec<conf::DisallowedPath>, conf_disallowed: Vec<DisallowedPath>,
def_ids: FxHashMap<DefId, usize>, def_ids: FxHashMap<DefId, usize>,
prim_tys: FxHashMap<PrimTy, usize>, prim_tys: FxHashMap<PrimTy, usize>,
} }
impl DisallowedTypes { impl DisallowedTypes {
pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self { pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
Self { Self {
conf_disallowed, conf_disallowed,
def_ids: FxHashMap::default(), def_ids: FxHashMap::default(),
@ -123,7 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
} }
} }
fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &conf::DisallowedPath) { fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &DisallowedPath) {
span_lint_and_then( span_lint_and_then(
cx, cx,
DISALLOWED_TYPES, DISALLOWED_TYPES,

View File

@ -58,14 +58,14 @@ declare_clippy_lint! {
/// would fail. /// would fail.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
/// /// Do something with the foo_bar parameter. See also /// /// Do something with the foo_bar parameter. See also
/// /// that::other::module::foo. /// /// that::other::module::foo.
/// // ^ `foo_bar` and `that::other::module::foo` should be ticked. /// // ^ `foo_bar` and `that::other::module::foo` should be ticked.
/// fn doit(foo_bar: usize) {} /// fn doit(foo_bar: usize) {}
/// ``` /// ```
/// ///
/// ```rust /// ```no_run
/// // Link text with `[]` brackets should be written as following: /// // Link text with `[]` brackets should be written as following:
/// /// Consume the array and return the inner /// /// Consume the array and return the inner
/// /// [`SmallVec<[T; INLINE_CAPACITY]>`][SmallVec]. /// /// [`SmallVec<[T; INLINE_CAPACITY]>`][SmallVec].
@ -88,7 +88,7 @@ declare_clippy_lint! {
/// preconditions, so that users can be sure they are using them safely. /// preconditions, so that users can be sure they are using them safely.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
///# type Universe = (); ///# type Universe = ();
/// /// This function should really be documented /// /// This function should really be documented
/// pub unsafe fn start_apocalypse(u: &mut Universe) { /// pub unsafe fn start_apocalypse(u: &mut Universe) {
@ -98,7 +98,7 @@ declare_clippy_lint! {
/// ///
/// At least write a line about safety: /// At least write a line about safety:
/// ///
/// ```rust /// ```no_run
///# type Universe = (); ///# type Universe = ();
/// /// # Safety /// /// # Safety
/// /// /// ///
@ -126,7 +126,7 @@ declare_clippy_lint! {
/// Since the following function returns a `Result` it has an `# Errors` section in /// Since the following function returns a `Result` it has an `# Errors` section in
/// its doc comment: /// its doc comment:
/// ///
/// ```rust /// ```no_run
///# use std::io; ///# use std::io;
/// /// # Errors /// /// # Errors
/// /// /// ///
@ -155,7 +155,7 @@ declare_clippy_lint! {
/// Since the following function may panic it has a `# Panics` section in /// Since the following function may panic it has a `# Panics` section in
/// its doc comment: /// its doc comment:
/// ///
/// ```rust /// ```no_run
/// /// # Panics /// /// # Panics
/// /// /// ///
/// /// Will panic if y is 0 /// /// Will panic if y is 0
@ -182,7 +182,7 @@ declare_clippy_lint! {
/// if the `fn main()` is left implicit. /// if the `fn main()` is left implicit.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
/// /// An example of a doctest with a `main()` function /// /// An example of a doctest with a `main()` function
/// /// /// ///
/// /// # Examples /// /// # Examples
@ -210,12 +210,12 @@ declare_clippy_lint! {
/// It is likely a typo when defining an intra-doc link /// It is likely a typo when defining an intra-doc link
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// /// See also: ['foo'] /// /// See also: ['foo']
/// fn bar() {} /// fn bar() {}
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// /// See also: [`foo`] /// /// See also: [`foo`]
/// fn bar() {} /// fn bar() {}
/// ``` /// ```
@ -235,7 +235,7 @@ declare_clippy_lint! {
/// need to describe safety preconditions that users are required to uphold. /// need to describe safety preconditions that users are required to uphold.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
///# type Universe = (); ///# type Universe = ();
/// /// # Safety /// /// # Safety
/// /// /// ///
@ -248,7 +248,7 @@ declare_clippy_lint! {
/// The function is safe, so there shouldn't be any preconditions /// The function is safe, so there shouldn't be any preconditions
/// that have to be explained for safety reasons. /// that have to be explained for safety reasons.
/// ///
/// ```rust /// ```no_run
///# type Universe = (); ///# type Universe = ();
/// /// This function should really be documented /// /// This function should really be documented
/// pub fn start_apocalypse(u: &mut Universe) { /// pub fn start_apocalypse(u: &mut Universe) {
@ -569,9 +569,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
if let End(Heading(_, _, _)) = event { if let End(Heading(_, _, _)) = event {
in_heading = false; in_heading = false;
} }
if ticks_unbalanced if ticks_unbalanced && let Some(span) = fragments.span(cx, paragraph_range.clone()) {
&& let Some(span) = fragments.span(cx, paragraph_range.clone())
{
span_lint_and_help( span_lint_and_help(
cx, cx,
DOC_MARKDOWN, DOC_MARKDOWN,
@ -617,8 +615,9 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
check_link_quotes(cx, trimmed_text, range.clone(), fragments); check_link_quotes(cx, trimmed_text, range.clone(), fragments);
} }
if let Some(link) = in_link.as_ref() if let Some(link) = in_link.as_ref()
&& let Ok(url) = Url::parse(link) && let Ok(url) = Url::parse(link)
&& (url.scheme() == "https" || url.scheme() == "http") { && (url.scheme() == "https" || url.scheme() == "http")
{
// Don't check the text associated with external URLs // Don't check the text associated with external URLs
continue; continue;
} }
@ -716,7 +715,9 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, range: Range<u
// Because of the global session, we need to create a new session in a different thread with // Because of the global session, we need to create a new session in a different thread with
// the edition we need. // the edition we need.
let text = text.to_owned(); let text = text.to_owned();
if thread::spawn(move || has_needless_main(text, edition)).join().expect("thread::spawn failed") if thread::spawn(move || has_needless_main(text, edition))
.join()
.expect("thread::spawn failed")
&& let Some(span) = fragments.span(cx, range.start..range.end - trailing_whitespace) && let Some(span) = fragments.span(cx, range.start..range.end - trailing_whitespace)
{ {
span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest"); span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest");
@ -756,11 +757,12 @@ fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str
} }
fn check_word(cx: &LateContext<'_>, word: &str, span: Span) { fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
/// Checks if a string is camel-case, i.e., contains at least two uppercase /// Checks if a string is upper-camel-case, i.e., starts with an uppercase and
/// letters (`Clippy` is ok) and one lower-case letter (`NASA` is ok). /// contains at least two uppercase letters (`Clippy` is ok) and one lower-case
/// letter (`NASA` is ok).
/// Plurals are also excluded (`IDs` is ok). /// Plurals are also excluded (`IDs` is ok).
fn is_camel_case(s: &str) -> bool { fn is_camel_case(s: &str) -> bool {
if s.starts_with(|c: char| c.is_ascii_digit()) { if s.starts_with(|c: char| c.is_ascii_digit() | c.is_ascii_lowercase()) {
return false; return false;
} }

View File

@ -12,7 +12,7 @@ declare_clippy_lint! {
/// mistake. /// mistake.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn simple_double_parens() -> i32 { /// fn simple_double_parens() -> i32 {
/// ((0)) /// ((0))
/// } /// }
@ -22,7 +22,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// fn simple_no_parens() -> i32 { /// fn simple_no_parens() -> i32 {
/// 0 /// 0
/// } /// }

View File

@ -16,7 +16,7 @@ declare_clippy_lint! {
/// have been intended. /// have been intended.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct Foo; /// struct Foo;
/// let x = Foo; /// let x = Foo;
/// std::mem::drop(x); /// std::mem::drop(x);
@ -36,7 +36,7 @@ declare_clippy_lint! {
/// have been intended. /// have been intended.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct Foo; /// struct Foo;
/// let x = Foo; /// let x = Foo;
/// std::mem::forget(x); /// std::mem::forget(x);
@ -57,7 +57,7 @@ declare_clippy_lint! {
/// destructor, possibly causing leaks. /// destructor, possibly causing leaks.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::mem; /// # use std::mem;
/// # use std::rc::Rc; /// # use std::rc::Rc;
/// mem::forget(Rc::new(55)) /// mem::forget(Rc::new(55))
@ -90,7 +90,8 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
let is_copy = is_copy(cx, arg_ty); let is_copy = is_copy(cx, arg_ty);
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
let (lint, msg, note_span) = match fn_name { let (lint, msg, note_span) = match fn_name {
// early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references, forgetting_copy_types // early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references,
// forgetting_copy_types
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return, sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return,
sym::mem_forget if arg_ty.is_ref() => return, sym::mem_forget if arg_ty.is_ref() => return,
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => return, sym::mem_drop if is_copy && !drop_is_single_call_in_arm => return,
@ -100,8 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
if !(arg_ty.needs_drop(cx.tcx, cx.param_env) if !(arg_ty.needs_drop(cx.tcx, cx.param_env)
|| is_must_use_func_call(cx, arg) || is_must_use_func_call(cx, arg)
|| is_must_use_ty(cx, arg_ty) || is_must_use_ty(cx, arg_ty)
|| drop_is_single_call_in_arm || drop_is_single_call_in_arm) =>
) =>
{ {
(DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span)) (DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span))
}, },
@ -122,7 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
} else { } else {
(FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY.into(), Some(arg.span)) (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY.into(), Some(arg.span))
} }
} },
_ => return, _ => return,
}; };
span_lint_and_note( span_lint_and_note(

View File

@ -15,7 +15,7 @@ declare_clippy_lint! {
/// Some coding guidelines require this (e.g., MISRA-C:2004 Rule 14.10). /// Some coding guidelines require this (e.g., MISRA-C:2004 Rule 14.10).
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # fn a() {} /// # fn a() {}
/// # fn b() {} /// # fn b() {}
/// # let x: i32 = 1; /// # let x: i32 = 1;
@ -28,7 +28,7 @@ declare_clippy_lint! {
/// ///
/// Use instead: /// Use instead:
/// ///
/// ```rust /// ```no_run
/// # fn a() {} /// # fn a() {}
/// # fn b() {} /// # fn b() {}
/// # let x: i32 = 1; /// # let x: i32 = 1;

View File

@ -16,7 +16,7 @@ declare_clippy_lint! {
/// destructured, which might be the intention behind adding the implementation as a marker. /// destructured, which might be the intention behind adding the implementation as a marker.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct S; /// struct S;
/// ///
/// impl Drop for S { /// impl Drop for S {
@ -24,7 +24,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// struct S; /// struct S;
/// ``` /// ```
#[clippy::version = "1.62.0"] #[clippy::version = "1.62.0"]

View File

@ -23,12 +23,12 @@ declare_clippy_lint! {
/// ///
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// enum Test {} /// enum Test {}
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #![feature(never_type)] /// #![feature(never_type)]
/// ///
/// struct Test(!); /// struct Test(!);

View File

@ -15,11 +15,11 @@ declare_clippy_lint! {
/// Empty brackets after a struct declaration can be omitted. /// Empty brackets after a struct declaration can be omitted.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct Cookie {} /// struct Cookie {}
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// struct Cookie; /// struct Cookie;
/// ``` /// ```
#[clippy::version = "1.62.0"] #[clippy::version = "1.62.0"]
@ -35,7 +35,8 @@ impl EarlyLintPass for EmptyStructsWithBrackets {
if let ItemKind::Struct(var_data, _) = &item.kind if let ItemKind::Struct(var_data, _) = &item.kind
&& has_brackets(var_data) && has_brackets(var_data)
&& has_no_fields(cx, var_data, span_after_ident) { && has_no_fields(cx, var_data, span_after_ident)
{
span_lint_and_then( span_lint_and_then(
cx, cx,
EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_STRUCTS_WITH_BRACKETS,
@ -46,8 +47,9 @@ impl EarlyLintPass for EmptyStructsWithBrackets {
span_after_ident, span_after_ident,
"remove the brackets", "remove the brackets",
";", ";",
Applicability::Unspecified); Applicability::Unspecified,
}, );
},
); );
} }
} }

View File

@ -23,7 +23,7 @@ declare_clippy_lint! {
/// ///
/// ### Known problems /// ### Known problems
/// The suggestion may have type inference errors in some cases. e.g. /// The suggestion may have type inference errors in some cases. e.g.
/// ```rust /// ```no_run
/// let mut map = std::collections::HashMap::new(); /// let mut map = std::collections::HashMap::new();
/// let _ = if !map.contains_key(&0) { /// let _ = if !map.contains_key(&0) {
/// map.insert(0, 0) /// map.insert(0, 0)
@ -33,7 +33,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::collections::HashMap; /// # use std::collections::HashMap;
/// # let mut map = HashMap::new(); /// # let mut map = HashMap::new();
/// # let k = 1; /// # let k = 1;
@ -43,7 +43,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # use std::collections::HashMap; /// # use std::collections::HashMap;
/// # let mut map = HashMap::new(); /// # let mut map = HashMap::new();
/// # let k = 1; /// # let k = 1;

View File

@ -19,7 +19,7 @@ declare_clippy_lint! {
/// architectures, but works fine on 64 bit. /// architectures, but works fine on 64 bit.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # #[cfg(target_pointer_width = "64")] /// # #[cfg(target_pointer_width = "64")]
/// #[repr(usize)] /// #[repr(usize)]
/// enum NonPortable { /// enum NonPortable {

View File

@ -68,7 +68,8 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if !in_external_macro(cx.sess(), expr.span) if !in_external_macro(cx.sess(), expr.span)
&& let ExprKind::Let(let_expr) = expr.kind && let ExprKind::Let(let_expr) = expr.kind
&& unary_pattern(let_expr.pat) { && unary_pattern(let_expr.pat)
{
let exp_ty = cx.typeck_results().expr_ty(let_expr.init); let exp_ty = cx.typeck_results().expr_ty(let_expr.init);
let pat_ty = cx.typeck_results().pat_ty(let_expr.pat); let pat_ty = cx.typeck_results().pat_ty(let_expr.pat);
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
@ -79,7 +80,9 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
"({})", "({})",
snippet_with_context(cx, let_expr.pat.span, expr.span.ctxt(), "..", &mut applicability).0, snippet_with_context(cx, let_expr.pat.span, expr.span.ctxt(), "..", &mut applicability).0,
), ),
_ => snippet_with_context(cx, let_expr.pat.span, expr.span.ctxt(), "..", &mut applicability).0.to_string(), _ => snippet_with_context(cx, let_expr.pat.span, expr.span.ctxt(), "..", &mut applicability)
.0
.to_string(),
}; };
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,

View File

@ -41,10 +41,11 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
}; };
match item.kind { match item.kind {
ItemKind::TyAlias(..) if item.ident.name == sym::Error ItemKind::TyAlias(..)
&& is_visible_outside_module(cx, item.owner_id.def_id) if item.ident.name == sym::Error
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && is_visible_outside_module(cx, item.owner_id.def_id)
&& implements_trait(cx, ty, error_def_id, &[]) => && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& implements_trait(cx, ty, error_def_id, &[]) =>
{ {
span_lint( span_lint(
cx, cx,
@ -53,13 +54,14 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
"exported type alias named `Error` that implements `Error`", "exported type alias named `Error` that implements `Error`",
); );
}, },
ItemKind::Impl(imp) if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_def_id()) ItemKind::Impl(imp)
&& error_def_id == trait_def_id if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_def_id())
&& let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local) && error_def_id == trait_def_id
&& let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id) && let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local)
&& let Some(ident) = cx.tcx.opt_item_ident(def_id.to_def_id()) && let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id)
&& ident.name == sym::Error && let Some(ident) = cx.tcx.opt_item_ident(def_id.to_def_id())
&& is_visible_outside_module(cx, def_id) => && ident.name == sym::Error
&& is_visible_outside_module(cx, def_id) =>
{ {
span_lint_hir_and_then( span_lint_hir_and_then(
cx, cx,
@ -69,9 +71,9 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
"exported type named `Error` that implements `Error`", "exported type named `Error` that implements `Error`",
|diag| { |diag| {
diag.span_note(item.span, "`Error` was implemented here"); diag.span_note(item.span, "`Error` was implemented here");
} },
); );
} },
_ => {}, _ => {},
} }
} }

View File

@ -28,12 +28,12 @@ declare_clippy_lint! {
/// into something. /// into something.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn foo(x: Box<u32>) {} /// fn foo(x: Box<u32>) {}
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// fn foo(x: u32) {} /// fn foo(x: u32) {}
/// ``` /// ```
#[clippy::version = "pre 1.29.0"] #[clippy::version = "pre 1.29.0"]

View File

@ -119,19 +119,21 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
match body.value.kind { match body.value.kind {
ExprKind::Call(callee, args) ExprKind::Call(callee, args)
if matches!(callee.kind, ExprKind::Path(QPath::Resolved(..) | QPath::TypeRelative(..))) => if matches!(
callee.kind,
ExprKind::Path(QPath::Resolved(..) | QPath::TypeRelative(..))
) =>
{ {
let callee_ty = typeck.expr_ty(callee).peel_refs(); let callee_ty = typeck.expr_ty(callee).peel_refs();
if matches!( if matches!(type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
type_diagnostic_name(cx, callee_ty), || !check_inputs(typeck, body.params, None, args)
Some(sym::Arc | sym::Rc) {
) || !check_inputs(typeck, body.params, None, args) {
return; return;
} }
let callee_ty_adjusted = typeck.expr_adjustments(callee).last().map_or( let callee_ty_adjusted = typeck
callee_ty, .expr_adjustments(callee)
|a| a.target.peel_refs(), .last()
); .map_or(callee_ty, |a| a.target.peel_refs());
let sig = match callee_ty_adjusted.kind() { let sig = match callee_ty_adjusted.kind() {
ty::FnDef(def, _) => cx.tcx.fn_sig(def).skip_binder().skip_binder(), ty::FnDef(def, _) => cx.tcx.fn_sig(def).skip_binder().skip_binder(),
@ -160,36 +162,26 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
// For now ignore all callee types which reference a type parameter. // For now ignore all callee types which reference a type parameter.
&& !generic_args.types().any(|t| matches!(t.kind(), ty::Param(_))) && !generic_args.types().any(|t| matches!(t.kind(), ty::Param(_)))
{ {
span_lint_and_then( span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
cx, if let Some(mut snippet) = snippet_opt(cx, callee.span) {
REDUNDANT_CLOSURE, if let Ok((ClosureKind::FnMut, _)) = cx.tcx.infer_ctxt().build().type_implements_fn_trait(
expr.span, cx.param_env,
"redundant closure", Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
|diag| { ImplPolarity::Positive,
if let Some(mut snippet) = snippet_opt(cx, callee.span) { ) && path_to_local(callee).map_or(false, |l| {
if let Ok((ClosureKind::FnMut, _)) local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
= cx.tcx.infer_ctxt().build().type_implements_fn_trait( }) {
cx.param_env, // Mutable closure is used after current expr; we cannot consume it.
Binder::bind_with_vars(callee_ty_adjusted, List::empty()), snippet = format!("&mut {snippet}");
ImplPolarity::Positive,
) && path_to_local(callee)
.map_or(
false,
|l| local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr),
)
{
// Mutable closure is used after current expr; we cannot consume it.
snippet = format!("&mut {snippet}");
}
diag.span_suggestion(
expr.span,
"replace the closure with the function itself",
snippet,
Applicability::MachineApplicable,
);
} }
diag.span_suggestion(
expr.span,
"replace the closure with the function itself",
snippet,
Applicability::MachineApplicable,
);
} }
); });
} }
}, },
ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => { ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => {

View File

@ -22,7 +22,7 @@ declare_clippy_lint! {
/// readability and API. /// readability and API.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct S { /// struct S {
/// is_pending: bool, /// is_pending: bool,
/// is_processing: bool, /// is_processing: bool,
@ -31,7 +31,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// enum S { /// enum S {
/// Pending, /// Pending,
/// Processing, /// Processing,
@ -157,7 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
// functions with a body are already checked by `check_fn` // functions with a body are already checked by `check_fn`
if let TraitItemKind::Fn(fn_sig, TraitFn::Required(_)) = &trait_item.kind if let TraitItemKind::Fn(fn_sig, TraitFn::Required(_)) = &trait_item.kind
&& fn_sig.header.abi == Abi::Rust && fn_sig.header.abi == Abi::Rust
{ {
self.check_fn_sig(cx, fn_sig.decl, fn_sig.span); self.check_fn_sig(cx, fn_sig.decl, fn_sig.span);
} }
} }
@ -174,11 +174,8 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
if let Some(fn_header) = fn_kind.header() if let Some(fn_header) = fn_kind.header()
&& fn_header.abi == Abi::Rust && fn_header.abi == Abi::Rust
&& get_parent_as_impl(cx.tcx, hir_id) && get_parent_as_impl(cx.tcx, hir_id).map_or(true, |impl_item| impl_item.of_trait.is_none())
.map_or(true, {
|impl_item| impl_item.of_trait.is_none()
)
{
self.check_fn_sig(cx, fn_decl, span); self.check_fn_sig(cx, fn_decl, span);
} }
} }

View File

@ -17,14 +17,14 @@ declare_clippy_lint! {
/// disable them by default. /// disable them by default.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// enum Foo { /// enum Foo {
/// Bar, /// Bar,
/// Baz /// Baz
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #[non_exhaustive] /// #[non_exhaustive]
/// enum Foo { /// enum Foo {
/// Bar, /// Bar,
@ -47,14 +47,14 @@ declare_clippy_lint! {
/// disable them by default. /// disable them by default.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct Foo { /// struct Foo {
/// bar: u8, /// bar: u8,
/// baz: String, /// baz: String,
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// #[non_exhaustive] /// #[non_exhaustive]
/// struct Foo { /// struct Foo {
/// bar: u8, /// bar: u8,

View File

@ -17,7 +17,7 @@ declare_clippy_lint! {
/// the main function. /// the main function.
/// ///
/// ### Example /// ### Example
/// ``` /// ```no_run
/// std::process::exit(0) /// std::process::exit(0)
/// ``` /// ```
/// ///

View File

@ -19,7 +19,7 @@ declare_clippy_lint! {
/// Using `(e)println! is clearer and more concise /// Using `(e)println! is clearer and more concise
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::io::Write; /// # use std::io::Write;
/// # let bar = "furchtbar"; /// # let bar = "furchtbar";
/// writeln!(&mut std::io::stderr(), "foo: {:?}", bar).unwrap(); /// writeln!(&mut std::io::stderr(), "foo: {:?}", bar).unwrap();
@ -27,7 +27,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # use std::io::Write; /// # use std::io::Write;
/// # let bar = "furchtbar"; /// # let bar = "furchtbar";
/// eprintln!("foo: {:?}", bar); /// eprintln!("foo: {:?}", bar);
@ -58,7 +58,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
Some(sym::io_stderr) => ("stderr", "e"), Some(sym::io_stderr) => ("stderr", "e"),
_ => return, _ => return,
}; };
let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root()) else { return; }; let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root()) else {
return;
};
// ordering is important here, since `writeln!` uses `write!` internally // ordering is important here, since `writeln!` uses `write!` internally
let calling_macro = if is_expn_of(write_call.span, "writeln").is_some() { let calling_macro = if is_expn_of(write_call.span, "writeln").is_some() {
@ -78,18 +80,11 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
macro_name.replace("write", "print"), macro_name.replace("write", "print"),
) )
} else { } else {
( (format!("{dest_name}().write_fmt(...)"), "print".into())
format!("{dest_name}().write_fmt(...)"),
"print".into(),
)
}; };
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
let inputs_snippet = snippet_with_applicability( let inputs_snippet =
cx, snippet_with_applicability(cx, format_args_inputs_span(&format_args), "..", &mut applicability);
format_args_inputs_span(&format_args),
"..",
&mut applicability,
);
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
EXPLICIT_WRITE, EXPLICIT_WRITE,

View File

@ -23,13 +23,13 @@ declare_clippy_lint! {
/// requires using a turbofish, which serves no purpose but to satisfy the compiler. /// requires using a turbofish, which serves no purpose but to satisfy the compiler.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn unused_ty<T>(x: u8) { /// fn unused_ty<T>(x: u8) {
/// // .. /// // ..
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// fn no_unused_ty(x: u8) { /// fn no_unused_ty(x: u8) {
/// // .. /// // ..
/// } /// }
@ -177,20 +177,22 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
.iter() .iter()
.rev() .rev()
.map(|(idx, param)| { .map(|(idx, param)| {
if let Some(next) = explicit_params.get(idx + 1) && end != Some(next.def_id) { if let Some(next) = explicit_params.get(idx + 1)
// Extend the current span forward, up until the next param in the list. && end != Some(next.def_id)
param.span.until(next.span) {
} else { // Extend the current span forward, up until the next param in the list.
// Extend the current span back to include the comma following the previous param.span.until(next.span)
// param. If the span of the next param in the list has already been } else {
// extended, we continue the chain. This is why we're iterating in reverse. // Extend the current span back to include the comma following the previous
end = Some(param.def_id); // param. If the span of the next param in the list has already been
// extended, we continue the chain. This is why we're iterating in reverse.
end = Some(param.def_id);
// idx will never be 0, else we'd be removing the entire list of generics // idx will never be 0, else we'd be removing the entire list of generics
let prev = explicit_params[idx - 1]; let prev = explicit_params[idx - 1];
let prev_span = self.get_bound_span(prev); let prev_span = self.get_bound_span(prev);
self.get_bound_span(param).with_lo(prev_span.hi()) self.get_bound_span(param).with_lo(prev_span.hi())
} }
}) })
.collect() .collect()
}; };

View File

@ -17,7 +17,7 @@ declare_clippy_lint! {
/// `TryFrom` should be used if there's a possibility of failure. /// `TryFrom` should be used if there's a possibility of failure.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct Foo(i32); /// struct Foo(i32);
/// ///
/// impl From<String> for Foo { /// impl From<String> for Foo {
@ -28,7 +28,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// struct Foo(i32); /// struct Foo(i32);
/// ///
/// impl TryFrom<String> for Foo { /// impl TryFrom<String> for Foo {

View File

@ -18,13 +18,13 @@ declare_clippy_lint! {
/// Rust will truncate the literal silently. /// Rust will truncate the literal silently.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let v: f32 = 0.123_456_789_9; /// let v: f32 = 0.123_456_789_9;
/// println!("{}", v); // 0.123_456_789 /// println!("{}", v); // 0.123_456_789
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let v: f64 = 0.123_456_789_9; /// let v: f64 = 0.123_456_789_9;
/// println!("{}", v); // 0.123_456_789_9 /// println!("{}", v); // 0.123_456_789_9
/// ``` /// ```
@ -44,12 +44,12 @@ declare_clippy_lint! {
/// conversion to a float. /// conversion to a float.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let _: f32 = 16_777_217.0; // 16_777_216.0 /// let _: f32 = 16_777_217.0; // 16_777_216.0
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let _: f32 = 16_777_216.0; /// let _: f32 = 16_777_216.0;
/// let _: f64 = 16_777_217.0; /// let _: f64 = 16_777_217.0;
/// ``` /// ```

View File

@ -27,7 +27,7 @@ declare_clippy_lint! {
/// Negatively impacts accuracy. /// Negatively impacts accuracy.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let a = 3f32; /// let a = 3f32;
/// let _ = a.powf(1.0 / 3.0); /// let _ = a.powf(1.0 / 3.0);
/// let _ = (1.0 + a).ln(); /// let _ = (1.0 + a).ln();
@ -35,7 +35,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let a = 3f32; /// let a = 3f32;
/// let _ = a.cbrt(); /// let _ = a.cbrt();
/// let _ = a.ln_1p(); /// let _ = a.ln_1p();
@ -57,7 +57,7 @@ declare_clippy_lint! {
/// Negatively impacts accuracy and performance. /// Negatively impacts accuracy and performance.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// use std::f32::consts::E; /// use std::f32::consts::E;
/// ///
/// let a = 3f32; /// let a = 3f32;
@ -83,7 +83,7 @@ declare_clippy_lint! {
/// ///
/// is better expressed as /// is better expressed as
/// ///
/// ```rust /// ```no_run
/// use std::f32::consts::E; /// use std::f32::consts::E;
/// ///
/// let a = 3f32; /// let a = 3f32;
@ -323,9 +323,9 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
let maybe_neg_sugg = |expr, hir_id| { let maybe_neg_sugg = |expr, hir_id| {
let sugg = Sugg::hir(cx, expr, ".."); let sugg = Sugg::hir(cx, expr, "..");
if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id { if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id {
format!("-{}", sugg.maybe_par()) -sugg
} else { } else {
sugg.to_string() sugg
} }
}; };
@ -470,25 +470,13 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
let maybe_neg_sugg = |expr| { let maybe_neg_sugg = |expr| {
let sugg = Sugg::hir(cx, expr, ".."); let sugg = Sugg::hir(cx, expr, "..");
if let BinOpKind::Sub = op { if let BinOpKind::Sub = op { -sugg } else { sugg }
format!("-{sugg}")
} else {
sugg.to_string()
}
}; };
let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) { let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) {
( (inner_lhs, Sugg::hir(cx, inner_rhs, ".."), maybe_neg_sugg(rhs))
inner_lhs,
Sugg::hir(cx, inner_rhs, "..").to_string(),
maybe_neg_sugg(rhs),
)
} else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) { } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) {
( (inner_lhs, maybe_neg_sugg(inner_rhs), Sugg::hir(cx, lhs, ".."))
inner_lhs,
maybe_neg_sugg(inner_rhs),
Sugg::hir(cx, lhs, "..").to_string(),
)
} else { } else {
return; return;
}; };

View File

@ -23,13 +23,13 @@ declare_clippy_lint! {
/// if `foo: &str`. /// if `foo: &str`.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
/// let foo = "foo"; /// let foo = "foo";
/// format!("{}", foo); /// format!("{}", foo);
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let foo = "foo"; /// let foo = "foo";
/// foo.to_owned(); /// foo.to_owned();
/// ``` /// ```
@ -54,7 +54,9 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability), ([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability),
([], [_]) => { ([], [_]) => {
// Simulate macro expansion, converting {{ and }} to { and }. // Simulate macro expansion, converting {{ and }} to { and }.
let Some(snippet) = snippet_opt(cx, format_args.span) else { return }; let Some(snippet) = snippet_opt(cx, format_args.span) else {
return;
};
let s_expand = snippet.replace("{{", "{").replace("}}", "}"); let s_expand = snippet.replace("{{", "{").replace("}}", "}");
let sugg = format!("{s_expand}.to_string()"); let sugg = format!("{s_expand}.to_string()");
span_useless_format(cx, call_site, sugg, applicability); span_useless_format(cx, call_site, sugg, applicability);
@ -76,13 +78,14 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
_ => false, _ => false,
}; };
let sugg = if is_new_string { let sugg = if is_new_string {
snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability).0.into_owned() snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability)
.0
.into_owned()
} else { } else {
let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "<arg>", &mut applicability); let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "<arg>", &mut applicability);
format!("{}.to_string()", sugg.maybe_par()) format!("{}.to_string()", sugg.maybe_par())
}; };
span_useless_format(cx, call_site, sugg, applicability); span_useless_format(cx, call_site, sugg, applicability);
} }
}, },
_ => {}, _ => {},

View File

@ -1,11 +1,11 @@
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::is_diag_trait_item; use clippy_utils::is_diag_trait_item;
use clippy_utils::macros::{ use clippy_utils::macros::{
find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro,
is_format_macro, is_panic, root_macro_call, root_macro_call_first_node, FormatParamUsage, is_format_macro, is_panic, root_macro_call, root_macro_call_first_node, FormatParamUsage,
}; };
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_type_lang_item}; use clippy_utils::ty::{implements_trait, is_type_lang_item};
use if_chain::if_chain; use if_chain::if_chain;
@ -35,12 +35,12 @@ declare_clippy_lint! {
/// The recommended code is both shorter and avoids a temporary allocation. /// The recommended code is both shorter and avoids a temporary allocation.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::panic::Location; /// # use std::panic::Location;
/// println!("error: {}", format!("something failed at {}", Location::caller())); /// println!("error: {}", format!("something failed at {}", Location::caller()));
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # use std::panic::Location; /// # use std::panic::Location;
/// println!("error: something failed at {}", Location::caller()); /// println!("error: something failed at {}", Location::caller());
/// ``` /// ```
@ -61,12 +61,12 @@ declare_clippy_lint! {
/// unnecessary. /// unnecessary.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::panic::Location; /// # use std::panic::Location;
/// println!("error: something failed at {}", Location::caller().to_string()); /// println!("error: something failed at {}", Location::caller().to_string());
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # use std::panic::Location; /// # use std::panic::Location;
/// println!("error: something failed at {}", Location::caller()); /// println!("error: something failed at {}", Location::caller());
/// ``` /// ```
@ -87,7 +87,7 @@ declare_clippy_lint! {
/// The inlined syntax, where allowed, is simpler. /// The inlined syntax, where allowed, is simpler.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # let var = 42; /// # let var = 42;
/// # let width = 1; /// # let width = 1;
/// # let prec = 2; /// # let prec = 2;
@ -98,7 +98,7 @@ declare_clippy_lint! {
/// format!("{:.*}", prec, var); /// format!("{:.*}", prec, var);
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # let var = 42; /// # let var = 42;
/// # let width = 1; /// # let width = 1;
/// # let prec = 2; /// # let prec = 2;
@ -111,12 +111,12 @@ declare_clippy_lint! {
/// ///
/// If allow-mixed-uninlined-format-args is set to false in clippy.toml, /// If allow-mixed-uninlined-format-args is set to false in clippy.toml,
/// the following code will also trigger the lint: /// the following code will also trigger the lint:
/// ```rust /// ```no_run
/// # let var = 42; /// # let var = 42;
/// format!("{} {}", var, 1+2); /// format!("{} {}", var, 1+2);
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # let var = 42; /// # let var = 42;
/// format!("{var} {}", 1+2); /// format!("{var} {}", 1+2);
/// ``` /// ```
@ -141,13 +141,13 @@ declare_clippy_lint! {
/// an expected formatting operation such as adding padding isn't happening. /// an expected formatting operation such as adding padding isn't happening.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// println!("{:.}", 1.0); /// println!("{:.}", 1.0);
/// ///
/// println!("not padded: {:5}", format_args!("...")); /// println!("not padded: {:5}", format_args!("..."));
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// println!("{}", 1.0); /// println!("{}", 1.0);
/// ///
/// println!("not padded: {}", format_args!("...")); /// println!("not padded: {}", format_args!("..."));
@ -370,7 +370,7 @@ fn check_one_arg(
}; };
fixes.push((pos_span, replacement)); fixes.push((pos_span, replacement));
fixes.push((arg_span, String::new())); fixes.push((arg_span, String::new()));
true // successful inlining, continue checking true // successful inlining, continue checking
} else { } else {
// Do not continue inlining (return false) in case // Do not continue inlining (return false) in case
// * if we can't inline a numbered argument, e.g. `print!("{0} ...", foo.bar, ...)` // * if we can't inline a numbered argument, e.g. `print!("{0} ...", foo.bar, ...)`

View File

@ -21,7 +21,7 @@ declare_clippy_lint! {
/// ///
/// ### Example /// ### Example
/// ///
/// ```rust /// ```no_run
/// use std::fmt; /// use std::fmt;
/// ///
/// struct Structure(i32); /// struct Structure(i32);
@ -33,7 +33,7 @@ declare_clippy_lint! {
/// ///
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// use std::fmt; /// use std::fmt;
/// ///
/// struct Structure(i32); /// struct Structure(i32);
@ -59,7 +59,7 @@ declare_clippy_lint! {
/// should write to the `Formatter`, not stdout/stderr. /// should write to the `Formatter`, not stdout/stderr.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// use std::fmt::{Display, Error, Formatter}; /// use std::fmt::{Display, Error, Formatter};
/// ///
/// struct S; /// struct S;
@ -72,7 +72,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// use std::fmt::{Display, Error, Formatter}; /// use std::fmt::{Display, Error, Formatter};
/// ///
/// struct S; /// struct S;

View File

@ -21,13 +21,13 @@ declare_clippy_lint! {
/// While using `write!` in the suggested way should never fail, this isn't necessarily clear to the programmer. /// While using `write!` in the suggested way should never fail, this isn't necessarily clear to the programmer.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let mut s = String::new(); /// let mut s = String::new();
/// s += &format!("0x{:X}", 1024); /// s += &format!("0x{:X}", 1024);
/// s.push_str(&format!("0x{:X}", 1024)); /// s.push_str(&format!("0x{:X}", 1024));
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// use std::fmt::Write as _; // import without risk of name clashing /// use std::fmt::Write as _; // import without risk of name clashing
/// ///
/// let mut s = String::new(); /// let mut s = String::new();
@ -58,7 +58,7 @@ fn is_format(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
arms.iter().any(|arm| is_format(cx, arm.body)) arms.iter().any(|arm| is_format(cx, arm.body))
}, },
Some(higher::IfLetOrMatch::IfLet(_, _, then, r#else)) => { Some(higher::IfLetOrMatch::IfLet(_, _, then, r#else)) => {
is_format(cx, then) ||r#else.is_some_and(|e| is_format(cx, e)) is_format(cx, then) || r#else.is_some_and(|e| is_format(cx, e))
}, },
_ => false, _ => false,
} }
@ -69,17 +69,15 @@ impl<'tcx> LateLintPass<'tcx> for FormatPushString {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let arg = match expr.kind { let arg = match expr.kind {
ExprKind::MethodCall(_, _, [arg], _) => { ExprKind::MethodCall(_, _, [arg], _) => {
if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) && if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
match_def_path(cx, fn_def_id, &paths::PUSH_STR) { && match_def_path(cx, fn_def_id, &paths::PUSH_STR)
{
arg arg
} else { } else {
return; return;
} }
}
ExprKind::AssignOp(op, left, arg)
if op.node == BinOpKind::Add && is_string(cx, left) => {
arg
}, },
ExprKind::AssignOp(op, left, arg) if op.node == BinOpKind::Add && is_string(cx, left) => arg,
_ => return, _ => return,
}; };
if is_format(cx, arg) { if is_format(cx, arg) {

View File

@ -37,7 +37,7 @@ declare_clippy_lint! {
/// This is either a typo in the binary operator or confusing. /// This is either a typo in the binary operator or confusing.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # let foo = true; /// # let foo = true;
/// # let bar = false; /// # let bar = false;
/// // &&! looks like a different operator /// // &&! looks like a different operator
@ -45,7 +45,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # let foo = true; /// # let foo = true;
/// # let bar = false; /// # let bar = false;
/// if foo && !bar {} /// if foo && !bar {}

View File

@ -14,7 +14,7 @@ declare_clippy_lint! {
/// comment. /// comment.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// //// My amazing data structure /// //// My amazing data structure
/// pub struct Foo { /// pub struct Foo {
/// // ... /// // ...
@ -22,7 +22,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// /// My amazing data structure /// /// My amazing data structure
/// pub struct Foo { /// pub struct Foo {
/// // ... /// // ...

View File

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::span_is_local; use clippy_utils::macros::span_is_local;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::path_def_id; use clippy_utils::path_def_id;
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -24,7 +24,7 @@ declare_clippy_lint! {
/// According the std docs implementing `From<..>` is preferred since it gives you `Into<..>` for free where the reverse isn't true. /// According the std docs implementing `From<..>` is preferred since it gives you `Into<..>` for free where the reverse isn't true.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct StringWrapper(String); /// struct StringWrapper(String);
/// ///
/// impl Into<StringWrapper> for String { /// impl Into<StringWrapper> for String {
@ -34,7 +34,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// struct StringWrapper(String); /// struct StringWrapper(String);
/// ///
/// impl From<String> for StringWrapper { /// impl From<String> for StringWrapper {
@ -88,7 +88,8 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
cx.tcx.sess.source_map().guess_head_span(item.span), cx.tcx.sess.source_map().guess_head_span(item.span),
"an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true", "an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true",
|diag| { |diag| {
// If the target type is likely foreign mention the orphan rules as it's a common source of confusion // If the target type is likely foreign mention the orphan rules as it's a common source of
// confusion
if path_def_id(cx, target_ty.peel_refs()).map_or(true, |id| !id.is_local()) { if path_def_id(cx, target_ty.peel_refs()).map_or(true, |id| !id.is_local()) {
diag.help( diag.help(
"`impl From<Local> for Foreign` is allowed by the orphan rules, for more information see\n\ "`impl From<Local> for Foreign` is allowed by the orphan rules, for more information see\n\
@ -96,7 +97,10 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
); );
} }
let message = format!("replace the `Into` implementation with `From<{}>`", middle_trait_ref.self_ty()); let message = format!(
"replace the `Into` implementation with `From<{}>`",
middle_trait_ref.self_ty()
);
if let Some(suggestions) = convert_to_from(cx, into_trait_seg, target_ty, self_ty, impl_item_ref) { if let Some(suggestions) = convert_to_from(cx, into_trait_seg, target_ty, self_ty, impl_item_ref) {
diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable); diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable);
} else { } else {
@ -110,12 +114,12 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
extract_msrv_attr!(LateContext); extract_msrv_attr!(LateContext);
} }
/// Finds the occurences of `Self` and `self` /// Finds the occurrences of `Self` and `self`
struct SelfFinder<'a, 'tcx> { struct SelfFinder<'a, 'tcx> {
cx: &'a LateContext<'tcx>, cx: &'a LateContext<'tcx>,
/// Occurences of `Self` /// Occurrences of `Self`
upper: Vec<Span>, upper: Vec<Span>,
/// Occurences of `self` /// Occurrences of `self`
lower: Vec<Span>, lower: Vec<Span>,
/// If any of the `self`/`Self` usages were from an expansion, or the body contained a binding /// If any of the `self`/`Self` usages were from an expansion, or the body contained a binding
/// already named `val` /// already named `val`

View File

@ -18,13 +18,13 @@ declare_clippy_lint! {
/// For this to be safe, `c_void` would need to have the same memory layout as the original type, which is often not the case. /// For this to be safe, `c_void` would need to have the same memory layout as the original type, which is often not the case.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::ffi::c_void; /// # use std::ffi::c_void;
/// let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void; /// let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
/// let _ = unsafe { Box::from_raw(ptr) }; /// let _ = unsafe { Box::from_raw(ptr) };
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # use std::ffi::c_void; /// # use std::ffi::c_void;
/// # let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void; /// # let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
/// let _ = unsafe { Box::from_raw(ptr as *mut usize) }; /// let _ = unsafe { Box::from_raw(ptr as *mut usize) };
@ -40,14 +40,22 @@ declare_lint_pass!(FromRawWithVoidPtr => [FROM_RAW_WITH_VOID_PTR]);
impl LateLintPass<'_> for FromRawWithVoidPtr { impl LateLintPass<'_> for FromRawWithVoidPtr {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::Call(box_from_raw, [arg]) = expr.kind if let ExprKind::Call(box_from_raw, [arg]) = expr.kind
&& let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_from_raw.kind && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_from_raw.kind
&& seg.ident.name == sym!(from_raw) && seg.ident.name == sym!(from_raw)
&& let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id)) && let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id))
&& let arg_kind = cx.typeck_results().expr_ty(arg).kind() && let arg_kind = cx.typeck_results().expr_ty(arg).kind()
&& let RawPtr(TypeAndMut { ty, .. }) = arg_kind && let RawPtr(TypeAndMut { ty, .. }) = arg_kind
&& is_c_void(cx, *ty) { && is_c_void(cx, *ty)
{
let msg = format!("creating a `{type_str}` from a void raw pointer"); let msg = format!("creating a `{type_str}` from a void raw pointer");
span_lint_and_help(cx, FROM_RAW_WITH_VOID_PTR, expr.span, &msg, Some(arg.span), "cast this to a pointer of the appropriate type"); span_lint_and_help(
cx,
FROM_RAW_WITH_VOID_PTR,
expr.span,
&msg,
Some(arg.span),
"cast this to a pointer of the appropriate type",
);
} }
} }
} }

View File

@ -23,7 +23,7 @@ declare_clippy_lint! {
/// grouping some parameters into a new type. /// grouping some parameters into a new type.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # struct Color; /// # struct Color;
/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) { /// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) {
/// // .. /// // ..
@ -46,7 +46,7 @@ declare_clippy_lint! {
/// multiple functions. /// multiple functions.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn im_too_long() { /// fn im_too_long() {
/// println!(""); /// println!("");
/// // ... 100 more LoC /// // ... 100 more LoC
@ -129,7 +129,7 @@ declare_clippy_lint! {
/// a remnant of a refactoring that removed the return type. /// a remnant of a refactoring that removed the return type.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
/// #[must_use] /// #[must_use]
/// fn useless() { } /// fn useless() { }
/// ``` /// ```
@ -151,7 +151,7 @@ declare_clippy_lint! {
/// attribute to improve the lint message. /// attribute to improve the lint message.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
/// #[must_use] /// #[must_use]
/// fn double_must_use() -> Result<(), ()> { /// fn double_must_use() -> Result<(), ()> {
/// unimplemented!(); /// unimplemented!();
@ -183,7 +183,7 @@ declare_clippy_lint! {
/// `#[must_use]`. /// `#[must_use]`.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
/// // this could be annotated with `#[must_use]`. /// // this could be annotated with `#[must_use]`.
/// pub fn id<T>(t: T) -> T { t } /// pub fn id<T>(t: T) -> T { t }
/// ``` /// ```
@ -211,7 +211,7 @@ declare_clippy_lint! {
/// instead. /// instead.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
/// pub fn read_u8() -> Result<u8, ()> { Err(()) } /// pub fn read_u8() -> Result<u8, ()> { Err(()) }
/// ``` /// ```
/// should become /// should become
@ -262,7 +262,7 @@ declare_clippy_lint! {
/// The size determined by Clippy is platform-dependent. /// The size determined by Clippy is platform-dependent.
/// ///
/// ### Examples /// ### Examples
/// ```rust /// ```no_run
/// pub enum ParseError { /// pub enum ParseError {
/// UnparsedBytes([u8; 512]), /// UnparsedBytes([u8; 512]),
/// UnexpectedEof, /// UnexpectedEof,
@ -274,7 +274,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// should be /// should be
/// ``` /// ```no_run
/// pub enum ParseError { /// pub enum ParseError {
/// UnparsedBytes(Box<[u8; 512]>), /// UnparsedBytes(Box<[u8; 512]>),
/// UnexpectedEof, /// UnexpectedEof,
@ -301,7 +301,7 @@ declare_clippy_lint! {
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct A { /// struct A {
/// a: String, /// a: String,
/// b: String, /// b: String,
@ -315,7 +315,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// struct A { /// struct A {
/// a: String, /// a: String,
/// b: String, /// b: String,
@ -340,14 +340,14 @@ declare_clippy_lint! {
/// Turbofish syntax (`::<>`) cannot be used when `impl Trait` is being used, making `impl Trait` less powerful. Readability may also be a factor. /// Turbofish syntax (`::<>`) cannot be used when `impl Trait` is being used, making `impl Trait` less powerful. Readability may also be a factor.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// trait MyTrait {} /// trait MyTrait {}
/// fn foo(a: impl MyTrait) { /// fn foo(a: impl MyTrait) {
/// // [...] /// // [...]
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// trait MyTrait {} /// trait MyTrait {}
/// fn foo<T: MyTrait>(a: T) { /// fn foo<T: MyTrait>(a: T) {
/// // [...] /// // [...]

View File

@ -118,9 +118,10 @@ fn check_needless_must_use(
if sig.header.is_async() { if sig.header.is_async() {
let infcx = cx.tcx.infer_ctxt().build(); let infcx = cx.tcx.infer_ctxt().build();
if let Some(future_ty) = infcx.get_impl_future_output_ty(return_ty(cx, item_id)) if let Some(future_ty) = infcx.get_impl_future_output_ty(return_ty(cx, item_id))
&& !is_must_use_ty(cx, future_ty) { && !is_must_use_ty(cx, future_ty)
return; {
} return;
}
} }
span_lint_and_help( span_lint_and_help(

View File

@ -21,7 +21,9 @@ fn result_err_ty<'tcx>(
) -> Option<(&'tcx hir::Ty<'tcx>, Ty<'tcx>)> { ) -> Option<(&'tcx hir::Ty<'tcx>, Ty<'tcx>)> {
if !in_external_macro(cx.sess(), item_span) if !in_external_macro(cx.sess(), item_span)
&& let hir::FnRetTy::Return(hir_ty) = decl.output && let hir::FnRetTy::Return(hir_ty) = decl.output
&& let ty = cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).instantiate_identity().output()) && let ty = cx
.tcx
.erase_late_bound_regions(cx.tcx.fn_sig(id).instantiate_identity().output())
&& is_type_diagnostic_item(cx, ty, sym::Result) && is_type_diagnostic_item(cx, ty, sym::Result)
&& let ty::Adt(_, args) = ty.kind() && let ty::Adt(_, args) = ty.kind()
{ {

View File

@ -34,11 +34,11 @@ declare_clippy_lint! {
/// produced. /// produced.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// async fn not_send(bytes: std::rc::Rc<[u8]>) {} /// async fn not_send(bytes: std::rc::Rc<[u8]>) {}
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// async fn is_send(bytes: std::sync::Arc<[u8]>) {} /// async fn is_send(bytes: std::sync::Arc<[u8]>) {}
/// ``` /// ```
#[clippy::version = "1.44.0"] #[clippy::version = "1.44.0"]

View File

@ -1,6 +1,7 @@
//! lint on if branches that could be swapped so no `!` operation is necessary //! lint on if branches that could be swapped so no `!` operation is necessary
//! on the condition //! on the condition
use clippy_utils::consts::{constant_simple, Constant};
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_else_clause; use clippy_utils::is_else_clause;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
@ -16,7 +17,7 @@ declare_clippy_lint! {
/// Negations reduce the readability of statements. /// Negations reduce the readability of statements.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # let v: Vec<usize> = vec![]; /// # let v: Vec<usize> = vec![];
/// # fn a() {} /// # fn a() {}
/// # fn b() {} /// # fn b() {}
@ -29,7 +30,7 @@ declare_clippy_lint! {
/// ///
/// Could be written: /// Could be written:
/// ///
/// ```rust /// ```no_run
/// # let v: Vec<usize> = vec![]; /// # let v: Vec<usize> = vec![];
/// # fn a() {} /// # fn a() {}
/// # fn b() {} /// # fn b() {}
@ -47,6 +48,13 @@ declare_clippy_lint! {
declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]); declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]);
fn is_zero_const(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
if let Some(value) = constant_simple(cx, cx.typeck_results(), expr) {
return Constant::Int(0) == value;
}
false
}
impl LateLintPass<'_> for IfNotElse { impl LateLintPass<'_> for IfNotElse {
fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
// While loops will be desugared to ExprKind::If. This will cause the lint to fire. // While loops will be desugared to ExprKind::If. This will cause the lint to fire.
@ -72,7 +80,9 @@ impl LateLintPass<'_> for IfNotElse {
"remove the `!` and swap the blocks of the `if`/`else`", "remove the `!` and swap the blocks of the `if`/`else`",
); );
}, },
ExprKind::Binary(ref kind, _, _) if kind.node == BinOpKind::Ne => { ExprKind::Binary(ref kind, _, lhs) if kind.node == BinOpKind::Ne && !is_zero_const(lhs, cx) => {
// Disable firing the lint on `… != 0`, as these are likely to be bit tests.
// For example, `if foo & 0x0F00 != 0 { … } else { … }` already is in the "proper" order.
span_lint_and_help( span_lint_and_help(
cx, cx,
IF_NOT_ELSE, IF_NOT_ELSE,

View File

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::eager_or_lazy::switch_to_eager_eval; use clippy_utils::eager_or_lazy::switch_to_eager_eval;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context; use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::Sugg; use clippy_utils::sugg::Sugg;
use clippy_utils::{contains_return, higher, is_else_clause, is_res_lang_ctor, path_res, peel_blocks}; use clippy_utils::{contains_return, higher, is_else_clause, is_res_lang_ctor, path_res, peel_blocks};
@ -21,7 +21,7 @@ declare_clippy_lint! {
/// in comparison to `bool::then`. /// in comparison to `bool::then`.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # let v = vec![0]; /// # let v = vec![0];
/// let a = if v.is_empty() { /// let a = if v.is_empty() {
/// println!("true!"); /// println!("true!");
@ -33,7 +33,7 @@ declare_clippy_lint! {
/// ///
/// Could be written: /// Could be written:
/// ///
/// ```rust /// ```no_run
/// # let v = vec![0]; /// # let v = vec![0];
/// let a = v.is_empty().then(|| { /// let a = v.is_empty().then(|| {
/// println!("true!"); /// println!("true!");
@ -76,7 +76,11 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
let ctxt = expr.span.ctxt(); let ctxt = expr.span.ctxt();
if let Some(higher::If { cond, then, r#else: Some(els) }) = higher::If::hir(expr) if let Some(higher::If {
cond,
then,
r#else: Some(els),
}) = higher::If::hir(expr)
&& let ExprKind::Block(then_block, _) = then.kind && let ExprKind::Block(then_block, _) = then.kind
&& let Some(then_expr) = then_block.expr && let Some(then_expr) = then_block.expr
&& let ExprKind::Call(then_call, [then_arg]) = then_expr.kind && let ExprKind::Call(then_call, [then_arg]) = then_expr.kind
@ -86,7 +90,9 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
&& !contains_return(then_block.stmts) && !contains_return(then_block.stmts)
{ {
let mut app = Applicability::Unspecified; let mut app = Applicability::Unspecified;
let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app).maybe_par().to_string(); let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app)
.maybe_par()
.to_string();
let arg_snip = snippet_with_context(cx, then_arg.span, ctxt, "[body]", &mut app).0; let arg_snip = snippet_with_context(cx, then_arg.span, ctxt, "[body]", &mut app).0;
let mut method_body = if then_block.stmts.is_empty() { let mut method_body = if then_block.stmts.is_empty() {
arg_snip.into_owned() arg_snip.into_owned()
@ -100,9 +106,8 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
"then" "then"
}; };
let help = format!( let help =
"consider using `bool::{method_name}` like: `{cond_snip}.{method_name}({method_body})`", format!("consider using `bool::{method_name}` like: `{cond_snip}.{method_name}({method_body})`",);
);
span_lint_and_help( span_lint_and_help(
cx, cx,
IF_THEN_SOME_ELSE_NONE, IF_THEN_SOME_ELSE_NONE,

View File

@ -15,14 +15,14 @@ declare_clippy_lint! {
/// would detect a type change that `_` would ignore. /// would detect a type change that `_` would ignore.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// match std::fs::create_dir("tmp-work-dir") { /// match std::fs::create_dir("tmp-work-dir") {
/// Ok(_) => println!("Working directory created"), /// Ok(_) => println!("Working directory created"),
/// Err(s) => eprintln!("Could not create directory: {s}"), /// Err(s) => eprintln!("Could not create directory: {s}"),
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// match std::fs::create_dir("tmp-work-dir") { /// match std::fs::create_dir("tmp-work-dir") {
/// Ok(()) => println!("Working directory created"), /// Ok(()) => println!("Working directory created"),
/// Err(s) => eprintln!("Could not create directory: {s}"), /// Err(s) => eprintln!("Could not create directory: {s}"),
@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for IgnoredUnitPatterns {
}, },
_ => {}, _ => {},
} }
if matches!(pat.kind, PatKind::Wild) && cx.typeck_results().pat_ty(pat).is_unit() { if matches!(pat.kind, PatKind::Wild) && cx.typeck_results().pat_ty(pat).peel_refs().is_unit() {
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
IGNORED_UNIT_PATTERNS, IGNORED_UNIT_PATTERNS,

View File

@ -35,7 +35,7 @@ declare_clippy_lint! {
/// pieces of code, possibly including external crates. /// pieces of code, possibly including external crates.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::collections::HashMap; /// # use std::collections::HashMap;
/// # use std::hash::{Hash, BuildHasher}; /// # use std::hash::{Hash, BuildHasher};
/// # trait Serialize {}; /// # trait Serialize {};
@ -44,7 +44,7 @@ declare_clippy_lint! {
/// pub fn foo(map: &mut HashMap<i32, i32>) { } /// pub fn foo(map: &mut HashMap<i32, i32>) { }
/// ``` /// ```
/// could be rewritten as /// could be rewritten as
/// ```rust /// ```no_run
/// # use std::collections::HashMap; /// # use std::collections::HashMap;
/// # use std::hash::{Hash, BuildHasher}; /// # use std::hash::{Hash, BuildHasher};
/// # trait Serialize {}; /// # trait Serialize {};

View File

@ -24,13 +24,13 @@ declare_clippy_lint! {
/// corresponding statements. /// corresponding statements.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// fn foo(x: usize) -> usize { /// fn foo(x: usize) -> usize {
/// x /// x
/// } /// }
/// ``` /// ```
/// add return /// add return
/// ```rust /// ```no_run
/// fn foo(x: usize) -> usize { /// fn foo(x: usize) -> usize {
/// return x; /// return x;
/// } /// }

View File

@ -18,7 +18,7 @@ declare_clippy_lint! {
/// The built-in function is more readable and may be faster. /// The built-in function is more readable and may be faster.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
///let mut u:u32 = 7000; ///let mut u:u32 = 7000;
/// ///
/// if u != u32::MAX { /// if u != u32::MAX {
@ -26,7 +26,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
///let mut u:u32 = 7000; ///let mut u:u32 = 7000;
/// ///
/// u = u.saturating_add(1); /// u = u.saturating_add(1);
@ -82,18 +82,18 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
fn get_int_max(ty: Ty<'_>) -> Option<u128> { fn get_int_max(ty: Ty<'_>) -> Option<u128> {
match ty.peel_refs().kind() { match ty.peel_refs().kind() {
Int(IntTy::I8) => i8::max_value().try_into().ok(), Int(IntTy::I8) => i8::MAX.try_into().ok(),
Int(IntTy::I16) => i16::max_value().try_into().ok(), Int(IntTy::I16) => i16::MAX.try_into().ok(),
Int(IntTy::I32) => i32::max_value().try_into().ok(), Int(IntTy::I32) => i32::MAX.try_into().ok(),
Int(IntTy::I64) => i64::max_value().try_into().ok(), Int(IntTy::I64) => i64::MAX.try_into().ok(),
Int(IntTy::I128) => i128::max_value().try_into().ok(), Int(IntTy::I128) => i128::MAX.try_into().ok(),
Int(IntTy::Isize) => isize::max_value().try_into().ok(), Int(IntTy::Isize) => isize::MAX.try_into().ok(),
Uint(UintTy::U8) => u8::max_value().try_into().ok(), Uint(UintTy::U8) => Some(u8::MAX.into()),
Uint(UintTy::U16) => u16::max_value().try_into().ok(), Uint(UintTy::U16) => Some(u16::MAX.into()),
Uint(UintTy::U32) => u32::max_value().try_into().ok(), Uint(UintTy::U32) => Some(u32::MAX.into()),
Uint(UintTy::U64) => u64::max_value().try_into().ok(), Uint(UintTy::U64) => Some(u64::MAX.into()),
Uint(UintTy::U128) => Some(u128::max_value()), Uint(UintTy::U128) => Some(u128::MAX),
Uint(UintTy::Usize) => usize::max_value().try_into().ok(), Uint(UintTy::Usize) => usize::MAX.try_into().ok(),
_ => None, _ => None,
} }
} }

View File

@ -15,7 +15,7 @@ declare_clippy_lint! {
/// Simplicity and readability. Instead we can easily use an builtin function. /// Simplicity and readability. Instead we can easily use an builtin function.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # let end: u32 = 10; /// # let end: u32 = 10;
/// # let start: u32 = 5; /// # let start: u32 = 5;
/// let mut i: u32 = end - start; /// let mut i: u32 = end - start;
@ -26,7 +26,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # let end: u32 = 10; /// # let end: u32 = 10;
/// # let start: u32 = 5; /// # let start: u32 = 5;
/// let mut i: u32 = end - start; /// let mut i: u32 = end - start;

View File

@ -29,7 +29,7 @@ declare_clippy_lint! {
/// (e.g. `trait A {} trait B: A {} trait C: B {}`, then having an `fn() -> impl A + C`) /// (e.g. `trait A {} trait B: A {} trait C: B {}`, then having an `fn() -> impl A + C`)
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// # use std::ops::{Deref,DerefMut}; /// # use std::ops::{Deref,DerefMut};
/// fn f() -> impl Deref<Target = i32> + DerefMut<Target = i32> { /// fn f() -> impl Deref<Target = i32> + DerefMut<Target = i32> {
/// // ^^^^^^^^^^^^^^^^^^^ unnecessary bound, already implied by the `DerefMut` trait bound /// // ^^^^^^^^^^^^^^^^^^^ unnecessary bound, already implied by the `DerefMut` trait bound
@ -37,7 +37,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # use std::ops::{Deref,DerefMut}; /// # use std::ops::{Deref,DerefMut};
/// fn f() -> impl DerefMut<Target = i32> { /// fn f() -> impl DerefMut<Target = i32> {
/// Box::new(123) /// Box::new(123)
@ -230,19 +230,24 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
// Example: // Example:
// `impl Deref<Target = i32> + DerefMut<Target = u32>` is not allowed. // `impl Deref<Target = i32> + DerefMut<Target = u32>` is not allowed.
// `DerefMut::Target` needs to match `Deref::Target`. // `DerefMut::Target` needs to match `Deref::Target`.
let implied_bounds: Vec<_> = opaque_ty.bounds.iter().filter_map(|bound| { let implied_bounds: Vec<_> = opaque_ty
if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound .bounds
&& let [.., path] = poly_trait.trait_ref.path.segments .iter()
&& poly_trait.bound_generic_params.is_empty() .filter_map(|bound| {
&& let Some(trait_def_id) = path.res.opt_def_id() if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound
&& let predicates = cx.tcx.super_predicates_of(trait_def_id).predicates && let [.., path] = poly_trait.trait_ref.path.segments
&& !predicates.is_empty() // If the trait has no supertrait, there is nothing to add. && poly_trait.bound_generic_params.is_empty()
{ && let Some(trait_def_id) = path.res.opt_def_id()
Some((bound.span(), path, predicates, trait_def_id)) && let predicates = cx.tcx.super_predicates_of(trait_def_id).predicates
} else { && !predicates.is_empty()
None // If the trait has no supertrait, there is nothing to add.
} {
}).collect(); Some((bound.span(), path, predicates, trait_def_id))
} else {
None
}
})
.collect();
// Lint all bounds in the `impl Trait` type that are also in the `implied_bounds` vec. // Lint all bounds in the `impl Trait` type that are also in the `implied_bounds` vec.
// This involves some extra logic when generic arguments are present, since // This involves some extra logic when generic arguments are present, since
@ -253,30 +258,31 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
&& let implied_args = path.args.map_or([].as_slice(), |a| a.args) && let implied_args = path.args.map_or([].as_slice(), |a| a.args)
&& let implied_bindings = path.args.map_or([].as_slice(), |a| a.bindings) && let implied_bindings = path.args.map_or([].as_slice(), |a| a.bindings)
&& let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id() && let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id()
&& let Some((implied_by_span, implied_by_args, implied_by_bindings)) = implied_bounds && let Some((implied_by_span, implied_by_args, implied_by_bindings)) =
.iter() implied_bounds
.find_map(|&(span, implied_by_path, preds, implied_by_def_id)| { .iter()
let implied_by_args = implied_by_path.args.map_or([].as_slice(), |a| a.args); .find_map(|&(span, implied_by_path, preds, implied_by_def_id)| {
let implied_by_bindings = implied_by_path.args.map_or([].as_slice(), |a| a.bindings); let implied_by_args = implied_by_path.args.map_or([].as_slice(), |a| a.args);
let implied_by_bindings = implied_by_path.args.map_or([].as_slice(), |a| a.bindings);
preds.iter().find_map(|(clause, _)| { preds.iter().find_map(|(clause, _)| {
if let ClauseKind::Trait(tr) = clause.kind().skip_binder() if let ClauseKind::Trait(tr) = clause.kind().skip_binder()
&& tr.def_id() == def_id && tr.def_id() == def_id
&& is_same_generics( && is_same_generics(
cx.tcx, cx.tcx,
tr.trait_ref.args, tr.trait_ref.args,
implied_by_args, implied_by_args,
implied_args, implied_args,
implied_by_def_id, implied_by_def_id,
def_id, def_id,
) )
{ {
Some((span, implied_by_args, implied_by_bindings)) Some((span, implied_by_args, implied_by_bindings))
} else { } else {
None None
} }
})
}) })
})
{ {
emit_lint( emit_lint(
cx, cx,
@ -286,7 +292,7 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
implied_bindings, implied_bindings,
implied_by_bindings, implied_by_bindings,
implied_by_args, implied_by_args,
implied_by_span implied_by_span,
); );
} }
} }

View File

@ -19,7 +19,7 @@ declare_clippy_lint! {
/// Since the order of fields in a constructor doesn't affect the /// Since the order of fields in a constructor doesn't affect the
/// resulted instance as the below example indicates, /// resulted instance as the below example indicates,
/// ///
/// ```rust /// ```no_run
/// #[derive(Debug, PartialEq, Eq)] /// #[derive(Debug, PartialEq, Eq)]
/// struct Foo { /// struct Foo {
/// x: i32, /// x: i32,
@ -35,7 +35,7 @@ declare_clippy_lint! {
/// inconsistent order can be confusing and decreases readability and consistency. /// inconsistent order can be confusing and decreases readability and consistency.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// struct Foo { /// struct Foo {
/// x: i32, /// x: i32,
/// y: i32, /// y: i32,
@ -47,7 +47,7 @@ declare_clippy_lint! {
/// ``` /// ```
/// ///
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// # struct Foo { /// # struct Foo {
/// # x: i32, /// # x: i32,
/// # y: i32, /// # y: i32,

View File

@ -1,7 +1,7 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{constant, Constant}; use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLet; use clippy_utils::higher::IfLet;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::is_copy; use clippy_utils::ty::is_copy;
use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local}; use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
use if_chain::if_chain; use if_chain::if_chain;
@ -31,7 +31,7 @@ declare_clippy_lint! {
/// patterns. /// patterns.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```no_run
/// let slice: Option<&[u32]> = Some(&[1, 2, 3]); /// let slice: Option<&[u32]> = Some(&[1, 2, 3]);
/// ///
/// if let Some(slice) = slice { /// if let Some(slice) = slice {
@ -39,7 +39,7 @@ declare_clippy_lint! {
/// } /// }
/// ``` /// ```
/// Use instead: /// Use instead:
/// ```rust /// ```no_run
/// let slice: Option<&[u32]> = Some(&[1, 2, 3]); /// let slice: Option<&[u32]> = Some(&[1, 2, 3]);
/// ///
/// if let Some(&[first, ..]) = slice { /// if let Some(&[first, ..]) = slice {

Some files were not shown because too many files have changed in this diff Show More