mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Auto merge of #129531 - Jarcho:clippyup, r=Manishearth
Clippy subtree update r? `@Manishearth`
This commit is contained in:
commit
89103466d7
11
Cargo.lock
11
Cargo.lock
@ -536,6 +536,7 @@ name = "clippy"
|
|||||||
version = "0.1.82"
|
version = "0.1.82"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
|
"cargo_metadata 0.18.1",
|
||||||
"clippy_config",
|
"clippy_config",
|
||||||
"clippy_lints",
|
"clippy_lints",
|
||||||
"clippy_utils",
|
"clippy_utils",
|
||||||
@ -549,6 +550,7 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"rustc_tools_util",
|
"rustc_tools_util",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"syn 2.0.75",
|
"syn 2.0.75",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"termize",
|
"termize",
|
||||||
@ -563,7 +565,6 @@ name = "clippy_config"
|
|||||||
version = "0.1.82"
|
version = "0.1.82"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"rustc-semver",
|
|
||||||
"serde",
|
"serde",
|
||||||
"toml 0.7.8",
|
"toml 0.7.8",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
@ -595,7 +596,6 @@ dependencies = [
|
|||||||
"quine-mc_cluskey",
|
"quine-mc_cluskey",
|
||||||
"regex",
|
"regex",
|
||||||
"regex-syntax 0.8.4",
|
"regex-syntax 0.8.4",
|
||||||
"rustc-semver",
|
|
||||||
"semver",
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -614,7 +614,6 @@ dependencies = [
|
|||||||
"arrayvec",
|
"arrayvec",
|
||||||
"clippy_config",
|
"clippy_config",
|
||||||
"itertools",
|
"itertools",
|
||||||
"rustc-semver",
|
|
||||||
"rustc_apfloat",
|
"rustc_apfloat",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3199,12 +3198,6 @@ dependencies = [
|
|||||||
"num_cpus",
|
"num_cpus",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc-semver"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5be1bdc7edf596692617627bbfeaba522131b18e06ca4df2b6b689e3c5d5ce84"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-stable-hash"
|
name = "rustc-stable-hash"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
[alias]
|
[alias]
|
||||||
|
bless = "test --config env.RUSTC_BLESS='1'"
|
||||||
uitest = "test --test compile-test"
|
uitest = "test --test compile-test"
|
||||||
uibless = "test --test compile-test -- -- --bless"
|
uibless = "bless --test compile-test"
|
||||||
bless = "test -- -- --bless"
|
|
||||||
dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --"
|
dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --"
|
||||||
lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- "
|
lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- "
|
||||||
collect-metadata = "test --test dogfood --features internal -- collect_metadata"
|
collect-metadata = "test --test compile-test --config env.COLLECT_METADATA='1'"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
# -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests
|
# -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests
|
||||||
|
1
src/tools/clippy/.github/deploy.sh
vendored
1
src/tools/clippy/.github/deploy.sh
vendored
@ -10,6 +10,7 @@ mkdir out/master/
|
|||||||
cp util/gh-pages/index.html out/master
|
cp util/gh-pages/index.html out/master
|
||||||
cp util/gh-pages/script.js out/master
|
cp util/gh-pages/script.js out/master
|
||||||
cp util/gh-pages/lints.json out/master
|
cp util/gh-pages/lints.json out/master
|
||||||
|
cp util/gh-pages/style.css out/master
|
||||||
|
|
||||||
if [[ -n $TAG_NAME ]]; then
|
if [[ -n $TAG_NAME ]]; then
|
||||||
echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it"
|
echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it"
|
||||||
|
@ -136,11 +136,6 @@ jobs:
|
|||||||
- name: Test metadata collection
|
- name: Test metadata collection
|
||||||
run: cargo collect-metadata
|
run: cargo collect-metadata
|
||||||
|
|
||||||
- name: Test lint_configuration.md is up-to-date
|
|
||||||
run: |
|
|
||||||
echo "run \`cargo collect-metadata\` if this fails"
|
|
||||||
git update-index --refresh
|
|
||||||
|
|
||||||
integration_build:
|
integration_build:
|
||||||
needs: changelog
|
needs: changelog
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -5914,6 +5914,7 @@ Released 2018-09-13
|
|||||||
[`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args
|
[`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args
|
||||||
[`to_string_trait_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_trait_impl
|
[`to_string_trait_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_trait_impl
|
||||||
[`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo
|
[`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo
|
||||||
|
[`too_long_first_doc_paragraph`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_long_first_doc_paragraph
|
||||||
[`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments
|
[`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments
|
||||||
[`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines
|
[`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines
|
||||||
[`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg
|
[`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg
|
||||||
|
@ -30,8 +30,11 @@ color-print = "0.3.4"
|
|||||||
anstream = "0.6.0"
|
anstream = "0.6.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
cargo_metadata = "0.18.1"
|
||||||
ui_test = "0.25"
|
ui_test = "0.25"
|
||||||
regex = "1.5.5"
|
regex = "1.5.5"
|
||||||
|
serde = { version = "1.0.145", features = ["derive"] }
|
||||||
|
serde_json = "1.0.122"
|
||||||
toml = "0.7.3"
|
toml = "0.7.3"
|
||||||
walkdir = "2.3"
|
walkdir = "2.3"
|
||||||
filetime = "0.2.9"
|
filetime = "0.2.9"
|
||||||
@ -41,7 +44,6 @@ itertools = "0.12"
|
|||||||
clippy_utils = { path = "clippy_utils" }
|
clippy_utils = { path = "clippy_utils" }
|
||||||
if_chain = "1.0"
|
if_chain = "1.0"
|
||||||
quote = "1.0.25"
|
quote = "1.0.25"
|
||||||
serde = { version = "1.0.145", features = ["derive"] }
|
|
||||||
syn = { version = "2.0", features = ["full"] }
|
syn = { version = "2.0", features = ["full"] }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
|
@ -739,7 +739,7 @@ for some users. Adding a configuration is done in the following steps:
|
|||||||
|
|
||||||
5. Update [Lint Configuration](../lint_configuration.md)
|
5. Update [Lint Configuration](../lint_configuration.md)
|
||||||
|
|
||||||
Run `cargo collect-metadata` to generate documentation changes for the book.
|
Run `cargo bless --test config-metadata` to generate documentation changes for the book.
|
||||||
|
|
||||||
[`clippy_config::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_config/src/conf.rs
|
[`clippy_config::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_config/src/conf.rs
|
||||||
[`clippy_lints` lib file]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs
|
[`clippy_lints` lib file]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
This file is generated by `cargo collect-metadata`.
|
This file is generated by `cargo bless --test config-metadata`.
|
||||||
Please use that command to update the file and do not edit it by hand.
|
Please use that command to update the file and do not edit it by hand.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -199,7 +199,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"]`
|
**Default Value:** `["i", "j", "x", "y", "z", "w", "n"]`
|
||||||
|
|
||||||
---
|
---
|
||||||
**Affected lints:**
|
**Affected lints:**
|
||||||
@ -455,7 +455,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 Value:** `["TiB", "CoreGraphics", "CoffeeScript", "TeX", "Direct2D", "PiB", "DirectX", "NetBSD", "OAuth", "NaN", "OpenType", "WebGL2", "WebTransport", "JavaScript", "OpenSSL", "OpenSSH", "EiB", "PureScript", "OpenAL", "MiB", "WebAssembly", "MinGW", "CoreFoundation", "WebGPU", "ClojureScript", "CamelCase", "OpenDNS", "NaNs", "OpenMP", "GitLab", "KiB", "sRGB", "CoreText", "macOS", "TypeScript", "GiB", "OpenExr", "YCbCr", "OpenTelemetry", "OpenBSD", "FreeBSD", "GPLv2", "PostScript", "WebP", "LaTeX", "TensorFlow", "AccessKit", "TrueType", "OpenStreetMap", "OpenGL", "DevOps", "OCaml", "WebRTC", "WebGL", "BibLaTeX", "GitHub", "GraphQL", "iOS", "Direct3D", "BibTeX", "DirectWrite", "GPLv3", "IPv6", "WebSocket", "IPv4", "ECMAScript"]`
|
**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "AccessKit", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]`
|
||||||
|
|
||||||
---
|
---
|
||||||
**Affected lints:**
|
**Affected lints:**
|
||||||
@ -949,5 +949,3 @@ Whether to also emit warnings for unsafe blocks with metavariable expansions in
|
|||||||
---
|
---
|
||||||
**Affected lints:**
|
**Affected lints:**
|
||||||
* [`macro_metavars_in_unsafe`](https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe)
|
* [`macro_metavars_in_unsafe`](https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe)
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
itertools = "0.12"
|
itertools = "0.12"
|
||||||
rustc-semver = "1.1"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
toml = "0.7.3"
|
toml = "0.7.3"
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::msrvs::Msrv;
|
use crate::msrvs::Msrv;
|
||||||
use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename};
|
use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename};
|
||||||
use crate::ClippyConfiguration;
|
use crate::ClippyConfiguration;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::edit_distance::edit_distance;
|
use rustc_span::edit_distance::edit_distance;
|
||||||
@ -218,7 +217,7 @@ macro_rules! define_Conf {
|
|||||||
define_Conf! {
|
define_Conf! {
|
||||||
/// Which crates to allow absolute paths from
|
/// Which crates to allow absolute paths from
|
||||||
#[lints(absolute_paths)]
|
#[lints(absolute_paths)]
|
||||||
absolute_paths_allowed_crates: FxHashSet<String> = FxHashSet::default(),
|
absolute_paths_allowed_crates: Vec<String> = Vec::new(),
|
||||||
/// 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.
|
||||||
#[lints(absolute_paths)]
|
#[lints(absolute_paths)]
|
||||||
@ -280,12 +279,12 @@ define_Conf! {
|
|||||||
allowed_dotfiles: Vec<String> = Vec::default(),
|
allowed_dotfiles: Vec<String> = Vec::default(),
|
||||||
/// A list of crate names to allow duplicates of
|
/// A list of crate names to allow duplicates of
|
||||||
#[lints(multiple_crate_versions)]
|
#[lints(multiple_crate_versions)]
|
||||||
allowed_duplicate_crates: FxHashSet<String> = FxHashSet::default(),
|
allowed_duplicate_crates: Vec<String> = Vec::new(),
|
||||||
/// 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.
|
||||||
#[lints(min_ident_chars)]
|
#[lints(min_ident_chars)]
|
||||||
allowed_idents_below_min_chars: FxHashSet<String> =
|
allowed_idents_below_min_chars: Vec<String> =
|
||||||
DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect(),
|
DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect(),
|
||||||
/// List of prefixes to allow when determining whether an item's name ends with the module's name.
|
/// List of prefixes to allow when determining whether an item's name ends with the module's name.
|
||||||
/// If the rest of an item's name is an allowed prefix (e.g. item `ToFoo` or `to_foo` in module `foo`),
|
/// If the rest of an item's name is an allowed prefix (e.g. item `ToFoo` or `to_foo` in module `foo`),
|
||||||
@ -323,7 +322,7 @@ define_Conf! {
|
|||||||
/// 2. Paths with any segment that containing the word 'prelude'
|
/// 2. Paths with any segment that containing the word 'prelude'
|
||||||
/// are already allowed by default.
|
/// are already allowed by default.
|
||||||
#[lints(wildcard_imports)]
|
#[lints(wildcard_imports)]
|
||||||
allowed_wildcard_imports: FxHashSet<String> = FxHashSet::default(),
|
allowed_wildcard_imports: Vec<String> = Vec::new(),
|
||||||
/// Suppress checking of the passed type names in all types of operations.
|
/// Suppress checking of the passed type names in all types of operations.
|
||||||
///
|
///
|
||||||
/// If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
|
/// If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
|
||||||
@ -355,7 +354,7 @@ define_Conf! {
|
|||||||
/// arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
|
/// arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
|
||||||
/// ```
|
/// ```
|
||||||
#[lints(arithmetic_side_effects)]
|
#[lints(arithmetic_side_effects)]
|
||||||
arithmetic_side_effects_allowed_binary: Vec<[String; 2]> = <_>::default(),
|
arithmetic_side_effects_allowed_binary: Vec<(String, String)> = <_>::default(),
|
||||||
/// Suppress checking of the passed type names in unary operations like "negation" (`-`).
|
/// Suppress checking of the passed type names in unary operations like "negation" (`-`).
|
||||||
///
|
///
|
||||||
/// #### Example
|
/// #### Example
|
||||||
@ -431,7 +430,7 @@ define_Conf! {
|
|||||||
/// * `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.
|
||||||
#[lints(doc_markdown)]
|
#[lints(doc_markdown)]
|
||||||
doc_valid_idents: FxHashSet<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect(),
|
doc_valid_idents: Vec<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect(),
|
||||||
/// 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`.
|
||||||
#[lints(non_send_fields_in_send_ty)]
|
#[lints(non_send_fields_in_send_ty)]
|
||||||
enable_raw_pointer_heuristic_for_send: bool = true,
|
enable_raw_pointer_heuristic_for_send: bool = true,
|
||||||
@ -706,12 +705,12 @@ fn deserialize(file: &SourceFile) -> TryConf {
|
|||||||
DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS,
|
DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS,
|
||||||
);
|
);
|
||||||
// TODO: THIS SHOULD BE TESTED, this comment will be gone soon
|
// TODO: THIS SHOULD BE TESTED, this comment will be gone soon
|
||||||
if conf.conf.allowed_idents_below_min_chars.contains("..") {
|
if conf.conf.allowed_idents_below_min_chars.iter().any(|e| e == "..") {
|
||||||
conf.conf
|
conf.conf
|
||||||
.allowed_idents_below_min_chars
|
.allowed_idents_below_min_chars
|
||||||
.extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string));
|
.extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string));
|
||||||
}
|
}
|
||||||
if conf.conf.doc_valid_idents.contains("..") {
|
if conf.conf.doc_valid_idents.iter().any(|e| e == "..") {
|
||||||
conf.conf
|
conf.conf
|
||||||
.doc_valid_idents
|
.doc_valid_idents
|
||||||
.extend(DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string));
|
.extend(DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string));
|
||||||
@ -890,14 +889,14 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec<usize>) {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
|
||||||
use serde::de::IgnoredAny;
|
use serde::de::IgnoredAny;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn configs_are_tested() {
|
fn configs_are_tested() {
|
||||||
let mut names: FxHashSet<String> = crate::get_configuration_metadata()
|
let mut names: HashSet<String> = crate::get_configuration_metadata()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|meta| meta.name.replace('_', "-"))
|
.map(|meta| meta.name.replace('_', "-"))
|
||||||
.collect();
|
.collect();
|
||||||
@ -910,7 +909,7 @@ mod tests {
|
|||||||
for entry in toml_files {
|
for entry in toml_files {
|
||||||
let file = fs::read_to_string(entry.path()).unwrap();
|
let file = fs::read_to_string(entry.path()).unwrap();
|
||||||
#[allow(clippy::zero_sized_map_values)]
|
#[allow(clippy::zero_sized_map_values)]
|
||||||
if let Ok(map) = toml::from_str::<FxHashMap<String, IgnoredAny>>(&file) {
|
if let Ok(map) = toml::from_str::<HashMap<String, IgnoredAny>>(&file) {
|
||||||
for name in map.keys() {
|
for name in map.keys() {
|
||||||
names.remove(name.as_str());
|
names.remove(name.as_str());
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
)]
|
)]
|
||||||
|
|
||||||
extern crate rustc_ast;
|
extern crate rustc_ast;
|
||||||
extern crate rustc_data_structures;
|
extern crate rustc_attr;
|
||||||
#[allow(unused_extern_crates)]
|
#[allow(unused_extern_crates)]
|
||||||
extern crate rustc_driver;
|
extern crate rustc_driver;
|
||||||
extern crate rustc_errors;
|
extern crate rustc_errors;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rustc_ast::Attribute;
|
use rustc_ast::Attribute;
|
||||||
use rustc_semver::RustcVersion;
|
use rustc_attr::parse_version;
|
||||||
use rustc_session::Session;
|
use rustc_session::{RustcVersion, Session};
|
||||||
use rustc_span::{sym, Symbol};
|
use rustc_span::{sym, Symbol};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -10,7 +10,7 @@ macro_rules! msrv_aliases {
|
|||||||
$($name:ident),* $(,)?
|
$($name:ident),* $(,)?
|
||||||
})*) => {
|
})*) => {
|
||||||
$($(
|
$($(
|
||||||
pub const $name: RustcVersion = RustcVersion::new($major, $minor, $patch);
|
pub const $name: RustcVersion = RustcVersion { major: $major, minor :$minor, patch: $patch };
|
||||||
)*)*
|
)*)*
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -18,6 +18,7 @@ macro_rules! msrv_aliases {
|
|||||||
// names may refer to stabilized feature flags or library items
|
// names may refer to stabilized feature flags or library items
|
||||||
msrv_aliases! {
|
msrv_aliases! {
|
||||||
1,81,0 { LINT_REASONS_STABILIZATION }
|
1,81,0 { LINT_REASONS_STABILIZATION }
|
||||||
|
1,80,0 { BOX_INTO_ITER}
|
||||||
1,77,0 { C_STR_LITERALS }
|
1,77,0 { C_STR_LITERALS }
|
||||||
1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
|
1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
|
||||||
1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
|
1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
|
||||||
@ -81,9 +82,9 @@ impl<'de> Deserialize<'de> for Msrv {
|
|||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let v = String::deserialize(deserializer)?;
|
let v = String::deserialize(deserializer)?;
|
||||||
RustcVersion::parse(&v)
|
parse_version(Symbol::intern(&v))
|
||||||
.map(|v| Msrv { stack: vec![v] })
|
.map(|v| Msrv { stack: vec![v] })
|
||||||
.map_err(|_| serde::de::Error::custom("not a valid Rust version"))
|
.ok_or_else(|| serde::de::Error::custom("not a valid Rust version"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +96,7 @@ impl Msrv {
|
|||||||
pub fn read_cargo(&mut self, sess: &Session) {
|
pub fn read_cargo(&mut self, sess: &Session) {
|
||||||
let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION")
|
let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|v| RustcVersion::parse(&v).ok());
|
.and_then(|v| parse_version(Symbol::intern(&v)));
|
||||||
|
|
||||||
match (self.current(), cargo_msrv) {
|
match (self.current(), cargo_msrv) {
|
||||||
(None, Some(cargo_msrv)) => self.stack = vec![cargo_msrv],
|
(None, Some(cargo_msrv)) => self.stack = vec![cargo_msrv],
|
||||||
@ -115,7 +116,7 @@ impl Msrv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn meets(&self, required: RustcVersion) -> bool {
|
pub fn meets(&self, required: RustcVersion) -> bool {
|
||||||
self.current().map_or(true, |version| version.meets(required))
|
self.current().map_or(true, |msrv| msrv >= required)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> {
|
fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> {
|
||||||
@ -131,7 +132,7 @@ impl Msrv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 Some(version) = parse_version(msrv) {
|
||||||
return Some(version);
|
return Some(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#![feature(rustc_private)]
|
||||||
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||||
|
|
||||||
|
@ -604,7 +604,7 @@ fn gen_declared_lints<'a>(
|
|||||||
details.sort_unstable();
|
details.sort_unstable();
|
||||||
|
|
||||||
let mut output = GENERATED_FILE_COMMENT.to_string();
|
let mut output = GENERATED_FILE_COMMENT.to_string();
|
||||||
output.push_str("pub(crate) static LINTS: &[&crate::LintInfo] = &[\n");
|
output.push_str("pub static LINTS: &[&crate::LintInfo] = &[\n");
|
||||||
|
|
||||||
for (is_public, module_name, lint_name) in details {
|
for (is_public, module_name, lint_name) in details {
|
||||||
if !is_public {
|
if !is_public {
|
||||||
|
@ -25,7 +25,6 @@ regex = { version = "1.5", optional = true }
|
|||||||
unicode-normalization = "0.1"
|
unicode-normalization = "0.1"
|
||||||
unicode-script = { version = "0.5", default-features = false }
|
unicode-script = { version = "0.5", default-features = false }
|
||||||
semver = "1.0"
|
semver = "1.0"
|
||||||
rustc-semver = "1.1"
|
|
||||||
url = "2.2"
|
url = "2.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::is_from_proc_macro;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
|
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||||
@ -8,6 +8,7 @@ use rustc_hir::{HirId, ItemKind, Node, Path};
|
|||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::kw;
|
||||||
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
@ -24,6 +25,13 @@ declare_clippy_lint! {
|
|||||||
/// Note: One exception to this is code from macro expansion - this does not lint such cases, as
|
/// Note: One exception to this is code from macro expansion - this does not lint such cases, as
|
||||||
/// using absolute paths is the proper way of referencing items in one.
|
/// using absolute paths is the proper way of referencing items in one.
|
||||||
///
|
///
|
||||||
|
/// ### Known issues
|
||||||
|
///
|
||||||
|
/// There are currently a few cases which are not caught by this lint:
|
||||||
|
/// * Macro calls. e.g. `path::to::macro!()`
|
||||||
|
/// * Derive macros. e.g. `#[derive(path::to::macro)]`
|
||||||
|
/// * Attribute macros. e.g. `#[path::to::macro]`
|
||||||
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// let x = std::f64::consts::PI;
|
/// let x = std::f64::consts::PI;
|
||||||
@ -48,63 +56,66 @@ impl_lint_pass!(AbsolutePaths => [ABSOLUTE_PATHS]);
|
|||||||
|
|
||||||
pub struct AbsolutePaths {
|
pub struct AbsolutePaths {
|
||||||
pub absolute_paths_max_segments: u64,
|
pub absolute_paths_max_segments: u64,
|
||||||
pub absolute_paths_allowed_crates: &'static FxHashSet<String>,
|
pub absolute_paths_allowed_crates: FxHashSet<Symbol>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbsolutePaths {
|
impl AbsolutePaths {
|
||||||
pub fn new(conf: &'static Conf) -> Self {
|
pub fn new(conf: &'static Conf) -> Self {
|
||||||
Self {
|
Self {
|
||||||
absolute_paths_max_segments: conf.absolute_paths_max_segments,
|
absolute_paths_max_segments: conf.absolute_paths_max_segments,
|
||||||
absolute_paths_allowed_crates: &conf.absolute_paths_allowed_crates,
|
absolute_paths_allowed_crates: conf
|
||||||
|
.absolute_paths_allowed_crates
|
||||||
|
.iter()
|
||||||
|
.map(|x| Symbol::intern(x))
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass<'_> for AbsolutePaths {
|
impl<'tcx> LateLintPass<'tcx> for AbsolutePaths {
|
||||||
// We should only lint `QPath::Resolved`s, but since `Path` is only used in `Resolved` and `UsePath`
|
// We should only lint `QPath::Resolved`s, but since `Path` is only used in `Resolved` and `UsePath`
|
||||||
// we don't need to use a visitor or anything as we can just check if the `Node` for `hir_id` isn't
|
// we don't need to use a visitor or anything as we can just check if the `Node` for `hir_id` isn't
|
||||||
// a `Use`
|
// a `Use`
|
||||||
#[expect(clippy::cast_possible_truncation)]
|
fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, hir_id: HirId) {
|
||||||
fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
|
let segments = match path.segments {
|
||||||
let Self {
|
[] | [_] => return,
|
||||||
absolute_paths_max_segments,
|
// Don't count enum variants and trait items as part of the length.
|
||||||
absolute_paths_allowed_crates,
|
[rest @ .., _]
|
||||||
} = self;
|
if let [.., s] = rest
|
||||||
|
&& matches!(s.res, Res::Def(DefKind::Enum | DefKind::Trait | DefKind::TraitAlias, _)) =>
|
||||||
if !path.span.from_expansion()
|
|
||||||
&& let node = cx.tcx.hir_node(hir_id)
|
|
||||||
&& !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(_, _)))
|
|
||||||
&& let [first, rest @ ..] = path.segments
|
|
||||||
// Handle `::std`
|
|
||||||
&& let (segment, len) = if first.ident.name == kw::PathRoot {
|
|
||||||
// Indexing is fine as `PathRoot` must be followed by another segment. `len() - 1`
|
|
||||||
// is fine here for the same reason
|
|
||||||
(&rest[0], path.segments.len() - 1)
|
|
||||||
} else {
|
|
||||||
(first, path.segments.len())
|
|
||||||
}
|
|
||||||
&& len > *absolute_paths_max_segments as usize
|
|
||||||
&& let Some(segment_snippet) = snippet_opt(cx, segment.ident.span)
|
|
||||||
&& segment_snippet == segment.ident.as_str()
|
|
||||||
{
|
|
||||||
let is_abs_external =
|
|
||||||
matches!(segment.res, Res::Def(DefKind::Mod, DefId { index, .. }) if index == CRATE_DEF_INDEX);
|
|
||||||
let is_abs_crate = segment.ident.name == kw::Crate;
|
|
||||||
|
|
||||||
if is_abs_external && absolute_paths_allowed_crates.contains(segment.ident.name.as_str())
|
|
||||||
|| is_abs_crate && absolute_paths_allowed_crates.contains("crate")
|
|
||||||
{
|
{
|
||||||
|
rest
|
||||||
|
},
|
||||||
|
path => path,
|
||||||
|
};
|
||||||
|
if let [s1, s2, ..] = segments
|
||||||
|
&& let has_root = s1.ident.name == kw::PathRoot
|
||||||
|
&& let first = if has_root { s2 } else { s1 }
|
||||||
|
&& let len = segments.len() - usize::from(has_root)
|
||||||
|
&& len as u64 > self.absolute_paths_max_segments
|
||||||
|
&& let crate_name = if let Res::Def(DefKind::Mod, DefId { index, .. }) = first.res
|
||||||
|
&& index == CRATE_DEF_INDEX
|
||||||
|
{
|
||||||
|
// `other_crate::foo` or `::other_crate::foo`
|
||||||
|
first.ident.name
|
||||||
|
} else if first.ident.name == kw::Crate || has_root {
|
||||||
|
// `::foo` or `crate::foo`
|
||||||
|
kw::Crate
|
||||||
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
&& !path.span.from_expansion()
|
||||||
if is_abs_external || is_abs_crate {
|
&& let node = cx.tcx.hir_node(hir_id)
|
||||||
span_lint(
|
&& !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(..)))
|
||||||
cx,
|
&& !self.absolute_paths_allowed_crates.contains(&crate_name)
|
||||||
ABSOLUTE_PATHS,
|
&& !is_from_proc_macro(cx, path)
|
||||||
path.span,
|
{
|
||||||
"consider bringing this path into scope with the `use` keyword",
|
span_lint(
|
||||||
);
|
cx,
|
||||||
}
|
ABSOLUTE_PATHS,
|
||||||
|
path.span,
|
||||||
|
"consider bringing this path into scope with the `use` keyword",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
|
|||||||
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};
|
||||||
use rustc_semver::RustcVersion;
|
use rustc_session::{impl_lint_pass, RustcVersion};
|
||||||
use rustc_session::impl_lint_pass;
|
|
||||||
use rustc_span::symbol;
|
use rustc_span::symbol;
|
||||||
use std::f64::consts as f64;
|
use std::f64::consts as f64;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use clippy_config::Conf;
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::mir::{enclosing_mir, PossibleBorrowerMap};
|
use clippy_utils::mir::{enclosing_mir, PossibleBorrowerMap};
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::{is_diag_trait_item, last_path_segment, local_is_initialized, path_to_local};
|
use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{self as hir, Expr, ExprKind};
|
use rustc_hir::{self as hir, Expr, ExprKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
@ -118,6 +118,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
&& !clone_source_borrows_from_dest(cx, lhs, rhs.span)
|
&& !clone_source_borrows_from_dest(cx, lhs, rhs.span)
|
||||||
|
&& !is_in_test(cx.tcx, e.hir_id)
|
||||||
{
|
{
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
|
use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use clippy_utils::source::{is_present_in_source, snippet_opt, without_block_comments};
|
use clippy_utils::source::{is_present_in_source, without_block_comments, SpanRangeExt};
|
||||||
use rustc_ast::{AttrKind, AttrStyle};
|
use rustc_ast::{AttrKind, AttrStyle};
|
||||||
use rustc_lint::EarlyContext;
|
use rustc_lint::EarlyContext;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -26,7 +26,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
|
|||||||
item.span.parent(),
|
item.span.parent(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(snippet) = snippet_opt(cx, end_of_attr_to_next_attr_or_item) {
|
if let Some(snippet) = end_of_attr_to_next_attr_or_item.get_source_text(cx) {
|
||||||
let lines = snippet.split('\n').collect::<Vec<_>>();
|
let lines = snippet.split('\n').collect::<Vec<_>>();
|
||||||
let lines = without_block_comments(lines);
|
let lines = without_block_comments(lines);
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! checks for attributes
|
|
||||||
|
|
||||||
mod allow_attributes;
|
mod allow_attributes;
|
||||||
mod allow_attributes_without_reason;
|
mod allow_attributes_without_reason;
|
||||||
mod blanket_clippy_restriction_lints;
|
mod blanket_clippy_restriction_lints;
|
||||||
@ -310,8 +308,8 @@ declare_clippy_lint! {
|
|||||||
/// ```rust,ignore
|
/// ```rust,ignore
|
||||||
/// #[allow(unused_mut)]
|
/// #[allow(unused_mut)]
|
||||||
/// fn foo() -> usize {
|
/// fn foo() -> usize {
|
||||||
/// let mut a = Vec::new();
|
/// let mut a = Vec::new();
|
||||||
/// a.len()
|
/// a.len()
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// Use instead:
|
/// Use instead:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{Attribute, NON_MINIMAL_CFG};
|
use super::{Attribute, NON_MINIMAL_CFG};
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use rustc_ast::{MetaItemKind, NestedMetaItem};
|
use rustc_ast::{MetaItemKind, NestedMetaItem};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_lint::EarlyContext;
|
use rustc_lint::EarlyContext;
|
||||||
@ -29,8 +29,13 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
|
|||||||
meta.span,
|
meta.span,
|
||||||
"unneeded sub `cfg` when there is only one condition",
|
"unneeded sub `cfg` when there is only one condition",
|
||||||
|diag| {
|
|diag| {
|
||||||
if let Some(snippet) = snippet_opt(cx, list[0].span()) {
|
if let Some(snippet) = list[0].span().get_source_text(cx) {
|
||||||
diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect);
|
diag.span_suggestion(
|
||||||
|
meta.span,
|
||||||
|
"try",
|
||||||
|
snippet.to_owned(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::{Attribute, UNNECESSARY_CLIPPY_CFG};
|
use super::{Attribute, UNNECESSARY_CLIPPY_CFG};
|
||||||
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
|
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
|
use itertools::Itertools;
|
||||||
use rustc_ast::AttrStyle;
|
use rustc_ast::AttrStyle;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_lint::{EarlyContext, Level};
|
use rustc_lint::{EarlyContext, Level};
|
||||||
@ -31,7 +32,7 @@ pub(super) fn check(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if nb_items == clippy_lints.len() {
|
if nb_items == clippy_lints.len() {
|
||||||
if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) {
|
if let Some(snippet) = behind_cfg_attr.span.get_source_text(cx) {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
UNNECESSARY_CLIPPY_CFG,
|
UNNECESSARY_CLIPPY_CFG,
|
||||||
@ -47,11 +48,7 @@ pub(super) fn check(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let snippet = clippy_lints
|
let snippet = clippy_lints.iter().filter_map(|sp| sp.get_source_text(cx)).join(",");
|
||||||
.iter()
|
|
||||||
.filter_map(|sp| snippet_opt(cx, *sp))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(",");
|
|
||||||
span_lint_and_note(
|
span_lint_and_note(
|
||||||
cx,
|
cx,
|
||||||
UNNECESSARY_CLIPPY_CFG,
|
UNNECESSARY_CLIPPY_CFG,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::utils::{extract_clippy_lint, is_lint_level, is_word};
|
use super::utils::{extract_clippy_lint, is_lint_level, is_word};
|
||||||
use super::{Attribute, USELESS_ATTRIBUTE};
|
use super::{Attribute, USELESS_ATTRIBUTE};
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::{first_line_of_span, snippet_opt};
|
use clippy_utils::source::{first_line_of_span, SpanRangeExt};
|
||||||
use rustc_ast::NestedMetaItem;
|
use rustc_ast::NestedMetaItem;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Item, ItemKind};
|
use rustc_hir::{Item, ItemKind};
|
||||||
@ -69,14 +69,14 @@ pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute])
|
|||||||
}
|
}
|
||||||
let line_span = first_line_of_span(cx, attr.span);
|
let line_span = first_line_of_span(cx, attr.span);
|
||||||
|
|
||||||
if let Some(mut sugg) = snippet_opt(cx, line_span) {
|
if let Some(src) = line_span.get_source_text(cx) {
|
||||||
if sugg.contains("#[") {
|
if src.contains("#[") {
|
||||||
|
#[expect(clippy::collapsible_span_lint_calls)]
|
||||||
span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| {
|
span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| {
|
||||||
sugg = sugg.replacen("#[", "#![", 1);
|
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
line_span,
|
line_span,
|
||||||
"if you just forgot a `!`, use",
|
"if you just forgot a `!`, use",
|
||||||
sugg,
|
src.replacen("#[", "#![", 1),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
|
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
|
||||||
use clippy_utils::eq_expr_value;
|
use clippy_utils::eq_expr_value;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -134,28 +134,30 @@ fn check_inverted_bool_in_condition(
|
|||||||
|
|
||||||
let suggestion = match (left.kind, right.kind) {
|
let suggestion = match (left.kind, right.kind) {
|
||||||
(ExprKind::Unary(UnOp::Not, left_sub), ExprKind::Unary(UnOp::Not, right_sub)) => {
|
(ExprKind::Unary(UnOp::Not, left_sub), ExprKind::Unary(UnOp::Not, right_sub)) => {
|
||||||
let Some(left) = snippet_opt(cx, left_sub.span) else {
|
let Some(left) = left_sub.span.get_source_text(cx) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(right) = snippet_opt(cx, right_sub.span) else {
|
let Some(right) = right_sub.span.get_source_text(cx) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(op) = bin_op_eq_str(op) else { return };
|
let Some(op) = bin_op_eq_str(op) else { return };
|
||||||
format!("{left} {op} {right}")
|
format!("{left} {op} {right}")
|
||||||
},
|
},
|
||||||
(ExprKind::Unary(UnOp::Not, left_sub), _) => {
|
(ExprKind::Unary(UnOp::Not, left_sub), _) => {
|
||||||
let Some(left) = snippet_opt(cx, left_sub.span) else {
|
let Some(left) = left_sub.span.get_source_text(cx) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(right) = snippet_opt(cx, right.span) else {
|
let Some(right) = right.span.get_source_text(cx) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(op) = inverted_bin_op_eq_str(op) else { return };
|
let Some(op) = inverted_bin_op_eq_str(op) else { return };
|
||||||
format!("{left} {op} {right}")
|
format!("{left} {op} {right}")
|
||||||
},
|
},
|
||||||
(_, ExprKind::Unary(UnOp::Not, right_sub)) => {
|
(_, ExprKind::Unary(UnOp::Not, right_sub)) => {
|
||||||
let Some(left) = snippet_opt(cx, left.span) else { return };
|
let Some(left) = left.span.get_source_text(cx) else {
|
||||||
let Some(right) = snippet_opt(cx, right_sub.span) else {
|
return;
|
||||||
|
};
|
||||||
|
let Some(right) = right_sub.span.get_source_text(cx) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(op) = inverted_bin_op_eq_str(op) else { return };
|
let Some(op) = inverted_bin_op_eq_str(op) else { return };
|
||||||
@ -313,8 +315,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
|
|||||||
self.output.push_str(&str);
|
self.output.push_str(&str);
|
||||||
} else {
|
} else {
|
||||||
self.output.push('!');
|
self.output.push('!');
|
||||||
let snip = snippet_opt(self.cx, terminal.span)?;
|
self.output.push_str(&terminal.span.get_source_text(self.cx)?);
|
||||||
self.output.push_str(&snip);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
True | False | Not(_) => {
|
True | False | Not(_) => {
|
||||||
@ -345,8 +346,12 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
&Term(n) => {
|
&Term(n) => {
|
||||||
let snip = snippet_opt(self.cx, self.terminals[n as usize].span.source_callsite())?;
|
self.output.push_str(
|
||||||
self.output.push_str(&snip);
|
&self.terminals[n as usize]
|
||||||
|
.span
|
||||||
|
.source_callsite()
|
||||||
|
.get_source_text(self.cx)?,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
Some(())
|
Some(())
|
||||||
@ -370,8 +375,8 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
.and_then(|op| {
|
.and_then(|op| {
|
||||||
let lhs_snippet = snippet_opt(cx, lhs.span)?;
|
let lhs_snippet = lhs.span.get_source_text(cx)?;
|
||||||
let rhs_snippet = snippet_opt(cx, rhs.span)?;
|
let rhs_snippet = rhs.span.get_source_text(cx)?;
|
||||||
|
|
||||||
if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')')) {
|
if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')')) {
|
||||||
if let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node) {
|
if let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node) {
|
||||||
@ -399,7 +404,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
|
|||||||
let path: &str = path.ident.name.as_str();
|
let path: &str = path.ident.name.as_str();
|
||||||
a == path
|
a == path
|
||||||
})
|
})
|
||||||
.and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", snippet_opt(cx, receiver.span)?)))
|
.and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", receiver.span.get_source_text(cx)?)))
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::reference::DEREF_ADDROF;
|
use crate::reference::DEREF_ADDROF;
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::ty::implements_trait;
|
use clippy_utils::ty::implements_trait;
|
||||||
use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed};
|
use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -73,6 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
&& !is_from_proc_macro(cx, e)
|
&& !is_from_proc_macro(cx, e)
|
||||||
|
&& let Some(deref_text) = deref_target.span.get_source_text(cx)
|
||||||
{
|
{
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
@ -83,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
|
|||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
e.span,
|
e.span,
|
||||||
"if you would like to reborrow, try removing `&*`",
|
"if you would like to reborrow, try removing `&*`",
|
||||||
snippet_opt(cx, deref_target.span).unwrap(),
|
deref_text.as_str(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -98,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
|
|||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
e.span,
|
e.span,
|
||||||
"if you would like to deref, try using `&**`",
|
"if you would like to deref, try using `&**`",
|
||||||
format!("&**{}", &snippet_opt(cx, deref_target.span).unwrap()),
|
format!("&**{deref_text}"),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! lint on missing cargo common metadata
|
|
||||||
|
|
||||||
use cargo_metadata::Metadata;
|
use cargo_metadata::Metadata;
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
|
@ -205,7 +205,7 @@ declare_clippy_lint! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Cargo {
|
pub struct Cargo {
|
||||||
allowed_duplicate_crates: &'static FxHashSet<String>,
|
allowed_duplicate_crates: FxHashSet<String>,
|
||||||
ignore_publish: bool,
|
ignore_publish: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ impl_lint_pass!(Cargo => [
|
|||||||
impl Cargo {
|
impl Cargo {
|
||||||
pub fn new(conf: &'static Conf) -> Self {
|
pub fn new(conf: &'static Conf) -> Self {
|
||||||
Self {
|
Self {
|
||||||
allowed_duplicate_crates: &conf.allowed_duplicate_crates,
|
allowed_duplicate_crates: conf.allowed_duplicate_crates.iter().cloned().collect(),
|
||||||
ignore_publish: conf.cargo_ignore_publish,
|
ignore_publish: conf.cargo_ignore_publish,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,7 +263,7 @@ impl LateLintPass<'_> for Cargo {
|
|||||||
{
|
{
|
||||||
match MetadataCommand::new().exec() {
|
match MetadataCommand::new().exec() {
|
||||||
Ok(metadata) => {
|
Ok(metadata) => {
|
||||||
multiple_crate_versions::check(cx, &metadata, self.allowed_duplicate_crates);
|
multiple_crate_versions::check(cx, &metadata, &self.allowed_duplicate_crates);
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
for lint in WITH_DEPS_LINTS {
|
for lint in WITH_DEPS_LINTS {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! lint on multiple versions of a crate being used
|
|
||||||
|
|
||||||
use cargo_metadata::{DependencyKind, Metadata, Node, Package, PackageId};
|
use cargo_metadata::{DependencyKind, Metadata, Node, Package, PackageId};
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, ExprKind};
|
use rustc_hir::{Expr, ExprKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
|||||||
&& 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()
|
||||||
&& let Some(recv) = snippet_opt(cx, receiver.span)
|
&& let Some(recv) = receiver.span.get_source_text(cx)
|
||||||
{
|
{
|
||||||
// `as_mut_ptr` might not exist
|
// `as_mut_ptr` might not exist
|
||||||
let applicability = Applicability::MaybeIncorrect;
|
let applicability = Applicability::MaybeIncorrect;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use clippy_config::msrvs::{self, Msrv};
|
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::is_in_const_context;
|
use clippy_utils::is_in_const_context;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::ty::is_isize_or_usize;
|
use clippy_utils::ty::is_isize_or_usize;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -34,7 +34,7 @@ pub(super) fn check(
|
|||||||
diag.help("an `as` cast can become silently lossy if the types change in the future");
|
diag.help("an `as` cast can become silently lossy if the types change in the future");
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let from_sugg = Sugg::hir_with_context(cx, cast_from_expr, expr.span.ctxt(), "<from>", &mut applicability);
|
let from_sugg = Sugg::hir_with_context(cx, cast_from_expr, expr.span.ctxt(), "<from>", &mut applicability);
|
||||||
let Some(ty) = snippet_opt(cx, hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt())) else {
|
let Some(ty) = hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt()).get_source_text(cx) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
match cast_to_hir.kind {
|
match cast_to_hir.kind {
|
||||||
|
@ -4,7 +4,7 @@ use clippy_utils::expr_or_init;
|
|||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
|
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
|
||||||
use rustc_errors::{Applicability, Diag, SuggestionStyle};
|
use rustc_errors::{Applicability, Diag};
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@ -190,12 +190,10 @@ fn offer_suggestion(
|
|||||||
format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, ".."))
|
format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, ".."))
|
||||||
};
|
};
|
||||||
|
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
expr.span,
|
expr.span,
|
||||||
"... or use `try_from` and handle the error accordingly",
|
"... or use `try_from` and handle the error accordingly",
|
||||||
suggestion,
|
suggestion,
|
||||||
Applicability::Unspecified,
|
Applicability::Unspecified,
|
||||||
// always show the suggestion in a separate line
|
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use rustc_errors::{Applicability, SuggestionStyle};
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::Expr;
|
use rustc_hir::Expr;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
@ -24,12 +24,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
|||||||
expr.span,
|
expr.span,
|
||||||
format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
|
format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
|
||||||
|diag| {
|
|diag| {
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
expr.span,
|
expr.span,
|
||||||
"did you mean to invoke the function?",
|
"did you mean to invoke the function?",
|
||||||
format!("{from_snippet}() as {cast_to}"),
|
format!("{from_snippet}() as {cast_to}"),
|
||||||
applicability,
|
applicability,
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::numeric_literal::NumericLiteral;
|
use clippy_utils::numeric_literal::NumericLiteral;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::{snippet_opt, SpanRangeExt};
|
||||||
use clippy_utils::visitors::{for_each_expr_without_closures, Visitable};
|
use clippy_utils::visitors::{for_each_expr_without_closures, Visitable};
|
||||||
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
|
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
|
||||||
use rustc_ast::{LitFloatType, LitIntType, LitKind};
|
use rustc_ast::{LitFloatType, LitIntType, LitKind};
|
||||||
@ -104,7 +104,7 @@ pub(super) fn check<'tcx>(
|
|||||||
let literal_str = &cast_str;
|
let literal_str = &cast_str;
|
||||||
|
|
||||||
if let LitKind::Int(n, _) = lit.node
|
if let LitKind::Int(n, _) = lit.node
|
||||||
&& let Some(src) = snippet_opt(cx, cast_expr.span)
|
&& let Some(src) = cast_expr.span.get_source_text(cx)
|
||||||
&& cast_to.is_floating_point()
|
&& cast_to.is_floating_point()
|
||||||
&& let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
|
&& let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
|
||||||
&& let from_nbits = 128 - n.get().leading_zeros()
|
&& let from_nbits = 128 - n.get().leading_zeros()
|
||||||
@ -131,7 +131,7 @@ pub(super) fn check<'tcx>(
|
|||||||
| LitKind::Float(_, LitFloatType::Suffixed(_))
|
| LitKind::Float(_, LitFloatType::Suffixed(_))
|
||||||
if cast_from.kind() == cast_to.kind() =>
|
if cast_from.kind() == cast_to.kind() =>
|
||||||
{
|
{
|
||||||
if let Some(src) = snippet_opt(cx, cast_expr.span) {
|
if let Some(src) = cast_expr.span.get_source_text(cx) {
|
||||||
if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) {
|
if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) {
|
||||||
lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
|
lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
|
||||||
return true;
|
return true;
|
||||||
@ -253,7 +253,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
|
|||||||
let res = cx.qpath_res(&qpath, expr.hir_id);
|
let res = cx.qpath_res(&qpath, expr.hir_id);
|
||||||
// Function call
|
// Function call
|
||||||
if let Res::Def(DefKind::Fn, def_id) = res {
|
if let Res::Def(DefKind::Fn, def_id) = res {
|
||||||
let Some(snippet) = snippet_opt(cx, cx.tcx.def_span(def_id)) else {
|
let Some(snippet) = cx.tcx.def_span(def_id).get_source_text(cx) else {
|
||||||
return ControlFlow::Continue(());
|
return ControlFlow::Continue(());
|
||||||
};
|
};
|
||||||
// This is the worst part of this entire function. This is the only way I know of to
|
// This is the worst part of this entire function. This is the only way I know of to
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::{is_in_const_context, is_integer_literal, std_or_core};
|
use clippy_utils::{is_in_const_context, is_integer_literal, std_or_core};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, Mutability, Ty, TyKind};
|
use rustc_hir::{Expr, Mutability, Ty, TyKind};
|
||||||
@ -20,7 +20,7 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>
|
|||||||
|
|
||||||
let sugg = if let TyKind::Infer = mut_ty.ty.kind {
|
let sugg = if let TyKind::Infer = mut_ty.ty.kind {
|
||||||
format!("{std_or_core}::{sugg_fn}()")
|
format!("{std_or_core}::{sugg_fn}()")
|
||||||
} else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
|
} else if let Some(mut_ty_snip) = mut_ty.ty.span.get_source_text(cx) {
|
||||||
format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()")
|
format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()")
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -5,7 +5,7 @@ use rustc_session::declare_lint_pass;
|
|||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
/// Checks for usage of `cfg` that excludes code from `test` builds. (i.e., `#{cfg(not(test))]`)
|
/// Checks for usage of `cfg` that excludes code from `test` builds. (i.e., `#[cfg(not(test))]`)
|
||||||
///
|
///
|
||||||
/// ### Why is this bad?
|
/// ### Why is this bad?
|
||||||
/// This may give the false impression that a codebase has 100% coverage, yet actually has untested code.
|
/// This may give the false impression that a codebase has 100% coverage, yet actually has untested code.
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! lint on manually implemented checked conversions that could be transformed into `try_from`
|
|
||||||
|
|
||||||
use clippy_config::msrvs::{self, Msrv};
|
use clippy_config::msrvs::{self, Msrv};
|
||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! calculate cognitive complexity and warn about overly complex functions
|
|
||||||
|
|
||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::diagnostics::span_lint_and_help;
|
use clippy_utils::diagnostics::span_lint_and_help;
|
||||||
use clippy_utils::source::{IntoSpan, SpanRangeExt};
|
use clippy_utils::source::{IntoSpan, SpanRangeExt};
|
||||||
|
@ -1,17 +1,3 @@
|
|||||||
//! Checks for if expressions that contain only an if expression.
|
|
||||||
//!
|
|
||||||
//! For example, the lint would catch:
|
|
||||||
//!
|
|
||||||
//! ```rust,ignore
|
|
||||||
//! if x {
|
|
||||||
//! if y {
|
|
||||||
//! println!("Hello world");
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! This lint is **warn** by default
|
|
||||||
|
|
||||||
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::source::{snippet, snippet_block, snippet_block_with_applicability};
|
use clippy_utils::source::{snippet, snippet_block, snippet_block_with_applicability};
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
|
use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
|
||||||
use clippy_utils::visitors::{for_each_expr, Visitable};
|
use clippy_utils::visitors::{for_each_expr, Visitable};
|
||||||
use clippy_utils::{get_enclosing_block, path_to_local_id};
|
use clippy_utils::{get_enclosing_block, path_to_local_id};
|
||||||
use core::ops::ControlFlow;
|
use core::ops::ControlFlow;
|
||||||
@ -7,7 +7,6 @@ use rustc_hir::{Body, ExprKind, HirId, LangItem, LetStmt, Node, PatKind};
|
|||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Symbol;
|
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
@ -44,24 +43,11 @@ declare_clippy_lint! {
|
|||||||
}
|
}
|
||||||
declare_lint_pass!(CollectionIsNeverRead => [COLLECTION_IS_NEVER_READ]);
|
declare_lint_pass!(CollectionIsNeverRead => [COLLECTION_IS_NEVER_READ]);
|
||||||
|
|
||||||
// Add `String` here when it is added to diagnostic items
|
|
||||||
static COLLECTIONS: [Symbol; 9] = [
|
|
||||||
sym::BTreeMap,
|
|
||||||
sym::BTreeSet,
|
|
||||||
sym::BinaryHeap,
|
|
||||||
sym::HashMap,
|
|
||||||
sym::HashSet,
|
|
||||||
sym::LinkedList,
|
|
||||||
sym::Option,
|
|
||||||
sym::Vec,
|
|
||||||
sym::VecDeque,
|
|
||||||
];
|
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
|
impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
|
||||||
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) {
|
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) {
|
||||||
// Look for local variables whose type is a container. Search surrounding block for read access.
|
// Look for local variables whose type is a container. Search surrounding block for read access.
|
||||||
if let PatKind::Binding(_, local_id, _, _) = local.pat.kind
|
if let PatKind::Binding(_, local_id, _, _) = local.pat.kind
|
||||||
&& match_acceptable_type(cx, local, &COLLECTIONS)
|
&& match_acceptable_type(cx, local)
|
||||||
&& let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id)
|
&& let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id)
|
||||||
&& has_no_read_access(cx, local_id, enclosing_block)
|
&& has_no_read_access(cx, local_id, enclosing_block)
|
||||||
{
|
{
|
||||||
@ -70,11 +56,22 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: &[Symbol]) -> bool {
|
fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool {
|
||||||
let ty = cx.typeck_results().pat_ty(local.pat);
|
let ty = cx.typeck_results().pat_ty(local.pat);
|
||||||
collections.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym))
|
matches!(
|
||||||
// String type is a lang item but not a diagnostic item for now so we need a separate check
|
get_type_diagnostic_name(cx, ty),
|
||||||
|| is_type_lang_item(cx, ty, LangItem::String)
|
Some(
|
||||||
|
sym::BTreeMap
|
||||||
|
| sym::BTreeSet
|
||||||
|
| sym::BinaryHeap
|
||||||
|
| sym::HashMap
|
||||||
|
| sym::HashSet
|
||||||
|
| sym::LinkedList
|
||||||
|
| sym::Option
|
||||||
|
| sym::Vec
|
||||||
|
| sym::VecDeque
|
||||||
|
)
|
||||||
|
) || is_type_lang_item(cx, ty, LangItem::String)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirId, block: T) -> bool {
|
fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirId, block: T) -> bool {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use rustc_errors::{Applicability, SuggestionStyle};
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, ExprKind};
|
use rustc_hir::{Expr, ExprKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
@ -46,7 +46,7 @@ impl LateLintPass<'_> for CreateDir {
|
|||||||
"calling `std::fs::create_dir` where there may be a better way",
|
"calling `std::fs::create_dir` where there may be a better way",
|
||||||
|diag| {
|
|diag| {
|
||||||
let mut app = Applicability::MaybeIncorrect;
|
let mut app = Applicability::MaybeIncorrect;
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
expr.span,
|
expr.span,
|
||||||
"consider calling `std::fs::create_dir_all` instead",
|
"consider calling `std::fs::create_dir_all` instead",
|
||||||
format!(
|
format!(
|
||||||
@ -54,7 +54,6 @@ impl LateLintPass<'_> for CreateDir {
|
|||||||
snippet_with_applicability(cx, arg.span, "..", &mut app)
|
snippet_with_applicability(cx, arg.span, "..", &mut app)
|
||||||
),
|
),
|
||||||
app,
|
app,
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Use that command to update this file and do not edit by hand.
|
// Use that command to update this file and do not edit by hand.
|
||||||
// Manual edits will be overwritten.
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
pub 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")]
|
||||||
@ -22,8 +22,6 @@ 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,
|
||||||
@ -146,6 +144,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||||||
crate::doc::NEEDLESS_DOCTEST_MAIN_INFO,
|
crate::doc::NEEDLESS_DOCTEST_MAIN_INFO,
|
||||||
crate::doc::SUSPICIOUS_DOC_COMMENTS_INFO,
|
crate::doc::SUSPICIOUS_DOC_COMMENTS_INFO,
|
||||||
crate::doc::TEST_ATTR_IN_DOCTEST_INFO,
|
crate::doc::TEST_ATTR_IN_DOCTEST_INFO,
|
||||||
|
crate::doc::TOO_LONG_FIRST_DOC_PARAGRAPH_INFO,
|
||||||
crate::doc::UNNECESSARY_SAFETY_DOC_INFO,
|
crate::doc::UNNECESSARY_SAFETY_DOC_INFO,
|
||||||
crate::double_parens::DOUBLE_PARENS_INFO,
|
crate::double_parens::DOUBLE_PARENS_INFO,
|
||||||
crate::drop_forget_ref::DROP_NON_DROP_INFO,
|
crate::drop_forget_ref::DROP_NON_DROP_INFO,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_errors::{Applicability, SuggestionStyle};
|
use rustc_errors::Applicability;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::{BytePos, Span};
|
use rustc_span::{BytePos, Span};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
@ -59,12 +59,11 @@ pub(super) fn check(
|
|||||||
&& (doc_comment == "///" || doc_comment == "//!")
|
&& (doc_comment == "///" || doc_comment == "//!")
|
||||||
{
|
{
|
||||||
// suggest filling in a blank line
|
// suggest filling in a blank line
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
line_break_span.shrink_to_lo(),
|
line_break_span.shrink_to_lo(),
|
||||||
"if this should be its own paragraph, add a blank doc comment line",
|
"if this should be its own paragraph, add a blank doc comment line",
|
||||||
format!("\n{doc_comment}"),
|
format!("\n{doc_comment}"),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
if ccount > 0 || blockquote_level > 0 {
|
if ccount > 0 || blockquote_level > 0 {
|
||||||
diag.help("if this not intended to be a quote at all, escape it with `\\>`");
|
diag.help("if this not intended to be a quote at all, escape it with `\\>`");
|
||||||
@ -79,12 +78,11 @@ pub(super) fn check(
|
|||||||
if ccount == 0 && blockquote_level == 0 {
|
if ccount == 0 && blockquote_level == 0 {
|
||||||
// simpler suggestion style for indentation
|
// simpler suggestion style for indentation
|
||||||
let indent = list_indentation - lcount;
|
let indent = list_indentation - lcount;
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
span.shrink_to_hi(),
|
span.shrink_to_hi(),
|
||||||
"indent this line",
|
"indent this line",
|
||||||
std::iter::repeat(" ").take(indent).join(""),
|
std::iter::repeat(" ").take(indent).join(""),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
diag.help("if this is supposed to be its own paragraph, add a blank line");
|
diag.help("if this is supposed to be its own paragraph, add a blank line");
|
||||||
return;
|
return;
|
||||||
@ -107,12 +105,11 @@ pub(super) fn check(
|
|||||||
suggested.push_str(text);
|
suggested.push_str(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
"add markers to start of line",
|
"add markers to start of line",
|
||||||
suggested,
|
suggested,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
diag.help("if this not intended to be a quote at all, escape it with `\\>`");
|
diag.help("if this not intended to be a quote at all, escape it with `\\>`");
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
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::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::{Applicability, SuggestionStyle};
|
use rustc_errors::Applicability;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::{BytePos, Pos, Span};
|
use rustc_span::{BytePos, Pos, Span};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@ -92,6 +92,10 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b
|
|||||||
&& matches!(prefix.chars().last(), Some('S' | 'X'))
|
&& matches!(prefix.chars().last(), Some('S' | 'X'))
|
||||||
{
|
{
|
||||||
prefix
|
prefix
|
||||||
|
} else if let Some(prefix) = s.strip_suffix("ified")
|
||||||
|
&& prefix.chars().all(|c| c.is_ascii_uppercase())
|
||||||
|
{
|
||||||
|
prefix
|
||||||
} else {
|
} else {
|
||||||
s.strip_suffix('s').unwrap_or(s)
|
s.strip_suffix('s').unwrap_or(s)
|
||||||
};
|
};
|
||||||
@ -133,24 +137,15 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if has_underscore(word) || word.contains("::") || is_camel_case(word) || word.ends_with("()") {
|
if has_underscore(word) || word.contains("::") || is_camel_case(word) || word.ends_with("()") {
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
|
||||||
|
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
DOC_MARKDOWN,
|
DOC_MARKDOWN,
|
||||||
span,
|
span,
|
||||||
"item in documentation is missing backticks",
|
"item in documentation is missing backticks",
|
||||||
|diag| {
|
|diag| {
|
||||||
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let snippet = snippet_with_applicability(cx, span, "..", &mut applicability);
|
let snippet = snippet_with_applicability(cx, span, "..", &mut applicability);
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(span, "try", format!("`{snippet}`"), applicability);
|
||||||
span,
|
|
||||||
"try",
|
|
||||||
format!("`{snippet}`"),
|
|
||||||
applicability,
|
|
||||||
// always show the suggestion in a separate line, since the
|
|
||||||
// inline presentation adds another pair of backticks
|
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
mod lazy_continuation;
|
mod lazy_continuation;
|
||||||
|
mod too_long_first_doc_paragraph;
|
||||||
|
|
||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::attrs::is_doc_hidden;
|
use clippy_utils::attrs::is_doc_hidden;
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||||
@ -309,7 +311,7 @@ declare_clippy_lint! {
|
|||||||
/// ### Known problems
|
/// ### Known problems
|
||||||
/// Inner doc comments can only appear before items, so there are certain cases where the suggestion
|
/// Inner doc comments can only appear before items, so there are certain cases where the suggestion
|
||||||
/// made by this lint is not valid code. For example:
|
/// made by this lint is not valid code. For example:
|
||||||
/// ```rs
|
/// ```rust
|
||||||
/// fn foo() {}
|
/// fn foo() {}
|
||||||
/// ///!
|
/// ///!
|
||||||
/// fn bar() {}
|
/// fn bar() {}
|
||||||
@ -422,15 +424,47 @@ declare_clippy_lint! {
|
|||||||
"require every line of a paragraph to be indented and marked"
|
"require every line of a paragraph to be indented and marked"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks if the first line in the documentation of items listed in module page is too long.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Documentation will show the first paragraph of the doscstring in the summary page of a
|
||||||
|
/// module, so having a nice, short summary in the first paragraph is part of writing good docs.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```no_run
|
||||||
|
/// /// A very short summary.
|
||||||
|
/// /// A much longer explanation that goes into a lot more detail about
|
||||||
|
/// /// how the thing works, possibly with doclinks and so one,
|
||||||
|
/// /// and probably spanning a many rows.
|
||||||
|
/// struct Foo {}
|
||||||
|
/// ```
|
||||||
|
/// Use instead:
|
||||||
|
/// ```no_run
|
||||||
|
/// /// A very short summary.
|
||||||
|
/// ///
|
||||||
|
/// /// A much longer explanation that goes into a lot more detail about
|
||||||
|
/// /// how the thing works, possibly with doclinks and so one,
|
||||||
|
/// /// and probably spanning a many rows.
|
||||||
|
/// struct Foo {}
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.81.0"]
|
||||||
|
pub TOO_LONG_FIRST_DOC_PARAGRAPH,
|
||||||
|
style,
|
||||||
|
"ensure that the first line of a documentation paragraph isn't too long"
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Documentation {
|
pub struct Documentation {
|
||||||
valid_idents: &'static FxHashSet<String>,
|
valid_idents: FxHashSet<String>,
|
||||||
check_private_items: bool,
|
check_private_items: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Documentation {
|
impl Documentation {
|
||||||
pub fn new(conf: &'static Conf) -> Self {
|
pub fn new(conf: &'static Conf) -> Self {
|
||||||
Self {
|
Self {
|
||||||
valid_idents: &conf.doc_valid_idents,
|
valid_idents: conf.doc_valid_idents.iter().cloned().collect(),
|
||||||
check_private_items: conf.check_private_items,
|
check_private_items: conf.check_private_items,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -448,48 +482,60 @@ impl_lint_pass!(Documentation => [
|
|||||||
SUSPICIOUS_DOC_COMMENTS,
|
SUSPICIOUS_DOC_COMMENTS,
|
||||||
EMPTY_DOCS,
|
EMPTY_DOCS,
|
||||||
DOC_LAZY_CONTINUATION,
|
DOC_LAZY_CONTINUATION,
|
||||||
|
TOO_LONG_FIRST_DOC_PARAGRAPH,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for Documentation {
|
impl<'tcx> LateLintPass<'tcx> for Documentation {
|
||||||
fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
|
fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
|
||||||
let Some(headers) = check_attrs(cx, self.valid_idents, attrs) else {
|
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
match cx.tcx.hir_node(cx.last_node_with_lint_attrs) {
|
match cx.tcx.hir_node(cx.last_node_with_lint_attrs) {
|
||||||
Node::Item(item) => match item.kind {
|
Node::Item(item) => {
|
||||||
ItemKind::Fn(sig, _, body_id) => {
|
too_long_first_doc_paragraph::check(
|
||||||
if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
|
cx,
|
||||||
let body = cx.tcx.hir().body(body_id);
|
item,
|
||||||
|
attrs,
|
||||||
|
headers.first_paragraph_len,
|
||||||
|
self.check_private_items,
|
||||||
|
);
|
||||||
|
match item.kind {
|
||||||
|
ItemKind::Fn(sig, _, body_id) => {
|
||||||
|
if !(is_entrypoint_fn(cx, item.owner_id.to_def_id())
|
||||||
|
|| in_external_macro(cx.tcx.sess, item.span))
|
||||||
|
{
|
||||||
|
let body = cx.tcx.hir().body(body_id);
|
||||||
|
|
||||||
let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
|
let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
|
||||||
missing_headers::check(
|
missing_headers::check(
|
||||||
|
cx,
|
||||||
|
item.owner_id,
|
||||||
|
sig,
|
||||||
|
headers,
|
||||||
|
Some(body_id),
|
||||||
|
panic_info,
|
||||||
|
self.check_private_items,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) {
|
||||||
|
(false, Safety::Unsafe) => span_lint(
|
||||||
cx,
|
cx,
|
||||||
item.owner_id,
|
MISSING_SAFETY_DOC,
|
||||||
sig,
|
cx.tcx.def_span(item.owner_id),
|
||||||
headers,
|
"docs for unsafe trait missing `# Safety` section",
|
||||||
Some(body_id),
|
),
|
||||||
panic_info,
|
(true, Safety::Safe) => span_lint(
|
||||||
self.check_private_items,
|
cx,
|
||||||
);
|
UNNECESSARY_SAFETY_DOC,
|
||||||
}
|
cx.tcx.def_span(item.owner_id),
|
||||||
},
|
"docs for safe trait have unnecessary `# Safety` section",
|
||||||
ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) {
|
),
|
||||||
(false, Safety::Unsafe) => span_lint(
|
_ => (),
|
||||||
cx,
|
},
|
||||||
MISSING_SAFETY_DOC,
|
|
||||||
cx.tcx.def_span(item.owner_id),
|
|
||||||
"docs for unsafe trait missing `# Safety` section",
|
|
||||||
),
|
|
||||||
(true, Safety::Safe) => span_lint(
|
|
||||||
cx,
|
|
||||||
UNNECESSARY_SAFETY_DOC,
|
|
||||||
cx.tcx.def_span(item.owner_id),
|
|
||||||
"docs for safe trait have unnecessary `# Safety` section",
|
|
||||||
),
|
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
}
|
||||||
_ => (),
|
|
||||||
},
|
},
|
||||||
Node::TraitItem(trait_item) => {
|
Node::TraitItem(trait_item) => {
|
||||||
if let TraitItemKind::Fn(sig, ..) = trait_item.kind
|
if let TraitItemKind::Fn(sig, ..) = trait_item.kind
|
||||||
@ -547,6 +593,7 @@ struct DocHeaders {
|
|||||||
safety: bool,
|
safety: bool,
|
||||||
errors: bool,
|
errors: bool,
|
||||||
panics: bool,
|
panics: bool,
|
||||||
|
first_paragraph_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does some pre-processing on raw, desugared `#[doc]` attributes such as parsing them and
|
/// Does some pre-processing on raw, desugared `#[doc]` attributes such as parsing them and
|
||||||
@ -653,6 +700,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
|||||||
let mut paragraph_range = 0..0;
|
let mut paragraph_range = 0..0;
|
||||||
let mut code_level = 0;
|
let mut code_level = 0;
|
||||||
let mut blockquote_level = 0;
|
let mut blockquote_level = 0;
|
||||||
|
let mut is_first_paragraph = true;
|
||||||
|
|
||||||
let mut containers = Vec::new();
|
let mut containers = Vec::new();
|
||||||
|
|
||||||
@ -720,6 +768,10 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
|||||||
}
|
}
|
||||||
ticks_unbalanced = false;
|
ticks_unbalanced = false;
|
||||||
paragraph_range = range;
|
paragraph_range = range;
|
||||||
|
if is_first_paragraph {
|
||||||
|
headers.first_paragraph_len = doc[paragraph_range.clone()].chars().count();
|
||||||
|
is_first_paragraph = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
End(TagEnd::Heading(_) | TagEnd::Paragraph | TagEnd::Item) => {
|
End(TagEnd::Heading(_) | TagEnd::Paragraph | TagEnd::Item) => {
|
||||||
if let End(TagEnd::Heading(_)) = event {
|
if let End(TagEnd::Heading(_)) = event {
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
use rustc_ast::ast::Attribute;
|
||||||
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir::{Item, ItemKind};
|
||||||
|
use rustc_lint::LateContext;
|
||||||
|
|
||||||
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
|
use clippy_utils::is_from_proc_macro;
|
||||||
|
use clippy_utils::source::snippet_opt;
|
||||||
|
|
||||||
|
use super::TOO_LONG_FIRST_DOC_PARAGRAPH;
|
||||||
|
|
||||||
|
pub(super) fn check(
|
||||||
|
cx: &LateContext<'_>,
|
||||||
|
item: &Item<'_>,
|
||||||
|
attrs: &[Attribute],
|
||||||
|
mut first_paragraph_len: usize,
|
||||||
|
check_private_items: bool,
|
||||||
|
) {
|
||||||
|
if !check_private_items && !cx.effective_visibilities.is_exported(item.owner_id.def_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if first_paragraph_len <= 200
|
||||||
|
|| !matches!(
|
||||||
|
item.kind,
|
||||||
|
// This is the list of items which can be documented AND are displayed on the module
|
||||||
|
// page. So associated items or impl blocks are not part of this list.
|
||||||
|
ItemKind::Static(..)
|
||||||
|
| ItemKind::Const(..)
|
||||||
|
| ItemKind::Fn(..)
|
||||||
|
| ItemKind::Macro(..)
|
||||||
|
| ItemKind::Mod(..)
|
||||||
|
| ItemKind::TyAlias(..)
|
||||||
|
| ItemKind::Enum(..)
|
||||||
|
| ItemKind::Struct(..)
|
||||||
|
| ItemKind::Union(..)
|
||||||
|
| ItemKind::Trait(..)
|
||||||
|
| ItemKind::TraitAlias(..)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut spans = Vec::new();
|
||||||
|
let mut should_suggest_empty_doc = false;
|
||||||
|
|
||||||
|
for attr in attrs {
|
||||||
|
if let Some(doc) = attr.doc_str() {
|
||||||
|
spans.push(attr.span);
|
||||||
|
let doc = doc.as_str();
|
||||||
|
let doc = doc.trim();
|
||||||
|
if spans.len() == 1 {
|
||||||
|
// We make this suggestion only if the first doc line ends with a punctuation
|
||||||
|
// because it might just need to add an empty line with `///`.
|
||||||
|
should_suggest_empty_doc = doc.ends_with('.') || doc.ends_with('!') || doc.ends_with('?');
|
||||||
|
}
|
||||||
|
let len = doc.chars().count();
|
||||||
|
if len >= first_paragraph_len {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
first_paragraph_len -= len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let &[first_span, .., last_span] = spans.as_slice() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if is_from_proc_macro(cx, item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
span_lint_and_then(
|
||||||
|
cx,
|
||||||
|
TOO_LONG_FIRST_DOC_PARAGRAPH,
|
||||||
|
first_span.with_hi(last_span.lo()),
|
||||||
|
"first doc comment paragraph is too long",
|
||||||
|
|diag| {
|
||||||
|
if should_suggest_empty_doc
|
||||||
|
&& let Some(second_span) = spans.get(1)
|
||||||
|
&& let new_span = first_span.with_hi(second_span.lo()).with_lo(first_span.hi())
|
||||||
|
&& let Some(snippet) = snippet_opt(cx, new_span)
|
||||||
|
{
|
||||||
|
diag.span_suggestion(
|
||||||
|
new_span,
|
||||||
|
"add an empty line",
|
||||||
|
format!("{snippet}///\n"),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
@ -1,5 +1,3 @@
|
|||||||
//! Lint on if expressions with an else if, but without a final else branch.
|
|
||||||
|
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use rustc_ast::ast::{Expr, ExprKind};
|
use rustc_ast::ast::{Expr, ExprKind};
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! lint when there is an enum with no variants
|
|
||||||
|
|
||||||
use clippy_utils::diagnostics::span_lint_and_help;
|
use clippy_utils::diagnostics::span_lint_and_help;
|
||||||
use rustc_hir::{Item, ItemKind};
|
use rustc_hir::{Item, ItemKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//! lint on C-like enums that are `repr(isize/usize)` and have values that
|
|
||||||
//! don't fit into an `i32`
|
|
||||||
|
|
||||||
use clippy_utils::consts::{mir_to_const, Constant};
|
use clippy_utils::consts::{mir_to_const, Constant};
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use rustc_hir::{Item, ItemKind};
|
use rustc_hir::{Item, ItemKind};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
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::higher::VecArgs;
|
use clippy_utils::higher::VecArgs;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::snippet_opt;
|
||||||
use clippy_utils::ty::type_diagnostic_name;
|
use clippy_utils::ty::get_type_diagnostic_name;
|
||||||
use clippy_utils::usage::{local_used_after_expr, local_used_in};
|
use clippy_utils::usage::{local_used_after_expr, local_used_in};
|
||||||
use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id};
|
use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -139,7 +139,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc
|
|||||||
{
|
{
|
||||||
let callee_ty_raw = typeck.expr_ty(callee);
|
let callee_ty_raw = typeck.expr_ty(callee);
|
||||||
let callee_ty = callee_ty_raw.peel_refs();
|
let callee_ty = callee_ty_raw.peel_refs();
|
||||||
if matches!(type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
|
if matches!(get_type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
|
||||||
|| !check_inputs(typeck, body.params, None, args)
|
|| !check_inputs(typeck, body.params, None, args)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::numeric_literal;
|
use clippy_utils::numeric_literal;
|
||||||
use rustc_ast::ast::{self, LitFloatType, LitKind};
|
use rustc_ast::ast::{self, LitFloatType, LitKind};
|
||||||
use rustc_errors::{Applicability, SuggestionStyle};
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::{self, FloatTy};
|
use rustc_middle::ty::{self, FloatTy};
|
||||||
@ -117,12 +117,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
|
|||||||
if type_suffix.is_none() {
|
if type_suffix.is_none() {
|
||||||
float_str.push_str(".0");
|
float_str.push_str(".0");
|
||||||
}
|
}
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
expr.span,
|
expr.span,
|
||||||
"consider changing the type or replacing it with",
|
"consider changing the type or replacing it with",
|
||||||
numeric_literal::format(&float_str, type_suffix, true),
|
numeric_literal::format(&float_str, type_suffix, true),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -134,12 +133,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
|
|||||||
expr.span,
|
expr.span,
|
||||||
"float has excessive precision",
|
"float has excessive precision",
|
||||||
|diag| {
|
|diag| {
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
expr.span,
|
expr.span,
|
||||||
"consider changing the type or truncating it to",
|
"consider changing the type or truncating it to",
|
||||||
numeric_literal::format(&float_str, type_suffix, true),
|
numeric_literal::format(&float_str, type_suffix, true),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::macros::{find_format_arg_expr, root_macro_call_first_node, FormatArgsStorage};
|
use clippy_utils::macros::{find_format_arg_expr, root_macro_call_first_node, FormatArgsStorage};
|
||||||
use clippy_utils::source::{snippet_opt, snippet_with_context};
|
use clippy_utils::source::{snippet_with_context, SpanRangeExt};
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait};
|
use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -65,7 +65,7 @@ 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 {
|
let Some(snippet) = format_args.span.get_source_text(cx) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let s_expand = snippet.replace("{{", "{").replace("}}", "}");
|
let s_expand = snippet.replace("{{", "{").replace("}}", "}");
|
||||||
@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
|
|||||||
span_useless_format(cx, call_site, sugg, applicability);
|
span_useless_format(cx, call_site, sugg, applicability);
|
||||||
},
|
},
|
||||||
([arg], [piece]) => {
|
([arg], [piece]) => {
|
||||||
if let Ok(value) = find_format_arg_expr(expr, arg)
|
if let Some(value) = find_format_arg_expr(expr, arg)
|
||||||
&& let FormatArgsPiece::Placeholder(placeholder) = piece
|
&& let FormatArgsPiece::Placeholder(placeholder) = piece
|
||||||
&& placeholder.format_trait == FormatTrait::Display
|
&& placeholder.format_trait == FormatTrait::Display
|
||||||
&& placeholder.format_options == FormatOptions::default()
|
&& placeholder.format_options == FormatOptions::default()
|
||||||
|
@ -7,7 +7,7 @@ use clippy_utils::macros::{
|
|||||||
find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro,
|
find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro,
|
||||||
is_panic, matching_root_macro_call, root_macro_call_first_node, FormatArgsStorage, FormatParamUsage, MacroCall,
|
is_panic, matching_root_macro_call, root_macro_call_first_node, FormatArgsStorage, FormatParamUsage, MacroCall,
|
||||||
};
|
};
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::ty::{implements_trait, is_type_lang_item};
|
use clippy_utils::ty::{implements_trait, is_type_lang_item};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
@ -224,13 +224,11 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
|
|||||||
if let FormatArgsPiece::Placeholder(placeholder) = piece
|
if let FormatArgsPiece::Placeholder(placeholder) = piece
|
||||||
&& let Ok(index) = placeholder.argument.index
|
&& let Ok(index) = placeholder.argument.index
|
||||||
&& let Some(arg) = self.format_args.arguments.all_args().get(index)
|
&& let Some(arg) = self.format_args.arguments.all_args().get(index)
|
||||||
|
&& let Some(arg_expr) = find_format_arg_expr(self.expr, arg)
|
||||||
{
|
{
|
||||||
let arg_expr = find_format_arg_expr(self.expr, arg);
|
|
||||||
|
|
||||||
self.check_unused_format_specifier(placeholder, arg_expr);
|
self.check_unused_format_specifier(placeholder, arg_expr);
|
||||||
|
|
||||||
if let Ok(arg_expr) = arg_expr
|
if placeholder.format_trait == FormatTrait::Display
|
||||||
&& placeholder.format_trait == FormatTrait::Display
|
|
||||||
&& placeholder.format_options == FormatOptions::default()
|
&& placeholder.format_options == FormatOptions::default()
|
||||||
&& !self.is_aliased(index)
|
&& !self.is_aliased(index)
|
||||||
{
|
{
|
||||||
@ -242,28 +240,13 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_unused_format_specifier(
|
fn check_unused_format_specifier(&self, placeholder: &FormatPlaceholder, arg: &Expr<'_>) {
|
||||||
&self,
|
|
||||||
placeholder: &FormatPlaceholder,
|
|
||||||
arg_expr: Result<&Expr<'_>, &rustc_ast::Expr>,
|
|
||||||
) {
|
|
||||||
let ty_or_ast_expr = arg_expr.map(|expr| self.cx.typeck_results().expr_ty(expr).peel_refs());
|
|
||||||
|
|
||||||
let is_format_args = match ty_or_ast_expr {
|
|
||||||
Ok(ty) => is_type_lang_item(self.cx, ty, LangItem::FormatArguments),
|
|
||||||
Err(expr) => matches!(expr.peel_parens_and_refs().kind, rustc_ast::ExprKind::FormatArgs(_)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let options = &placeholder.format_options;
|
let options = &placeholder.format_options;
|
||||||
|
|
||||||
let arg_span = match arg_expr {
|
|
||||||
Ok(expr) => expr.span,
|
|
||||||
Err(expr) => expr.span,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(placeholder_span) = placeholder.span
|
if let Some(placeholder_span) = placeholder.span
|
||||||
&& is_format_args
|
|
||||||
&& *options != FormatOptions::default()
|
&& *options != FormatOptions::default()
|
||||||
|
&& let ty = self.cx.typeck_results().expr_ty(arg).peel_refs()
|
||||||
|
&& is_type_lang_item(self.cx, ty, LangItem::FormatArguments)
|
||||||
{
|
{
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
self.cx,
|
self.cx,
|
||||||
@ -274,7 +257,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
|
|||||||
let mut suggest_format = |spec| {
|
let mut suggest_format = |spec| {
|
||||||
let message = format!("for the {spec} to apply consider using `format!()`");
|
let message = format!("for the {spec} to apply consider using `format!()`");
|
||||||
|
|
||||||
if let Some(mac_call) = matching_root_macro_call(self.cx, arg_span, sym::format_args_macro) {
|
if let Some(mac_call) = matching_root_macro_call(self.cx, arg.span, sym::format_args_macro) {
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
self.cx.sess().source_map().span_until_char(mac_call.span, '!'),
|
self.cx.sess().source_map().span_until_char(mac_call.span, '!'),
|
||||||
message,
|
message,
|
||||||
@ -424,7 +407,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
|
|||||||
count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter())
|
count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter())
|
||||||
&& implements_trait(cx, target, display_trait_id, &[])
|
&& implements_trait(cx, target, display_trait_id, &[])
|
||||||
&& let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait()
|
&& let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait()
|
||||||
&& let Some(receiver_snippet) = snippet_opt(cx, receiver.span.source_callsite())
|
&& let Some(receiver_snippet) = receiver.span.source_callsite().get_source_text(cx)
|
||||||
{
|
{
|
||||||
let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]);
|
let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]);
|
||||||
if n_needed_derefs == 0 && !needs_ref {
|
if n_needed_derefs == 0 && !needs_ref {
|
||||||
|
@ -196,7 +196,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> {
|
|||||||
&& trait_name == self.format_trait_impl.name
|
&& trait_name == self.format_trait_impl.name
|
||||||
&& let Ok(index) = placeholder.argument.index
|
&& let Ok(index) = placeholder.argument.index
|
||||||
&& let Some(arg) = format_args.arguments.all_args().get(index)
|
&& let Some(arg) = format_args.arguments.all_args().get(index)
|
||||||
&& let Ok(arg_expr) = find_format_arg_expr(self.expr, arg)
|
&& let Some(arg_expr) = find_format_arg_expr(self.expr, arg)
|
||||||
{
|
{
|
||||||
self.check_format_arg_self(arg_expr);
|
self.check_format_arg_self(arg_expr);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use clippy_config::Conf;
|
|||||||
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::path_def_id;
|
use clippy_utils::path_def_id;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::{walk_path, Visitor};
|
use rustc_hir::intravisit::{walk_path, Visitor};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
@ -178,8 +178,8 @@ fn convert_to_from(
|
|||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let from = snippet_opt(cx, self_ty.span)?;
|
let from = self_ty.span.get_source_text(cx)?;
|
||||||
let into = snippet_opt(cx, target_ty.span)?;
|
let into = target_ty.span.get_source_text(cx)?;
|
||||||
|
|
||||||
let mut suggestions = vec![
|
let mut suggestions = vec![
|
||||||
// impl Into<T> for U -> impl From<T> for U
|
// impl Into<T> for U -> impl From<T> for U
|
||||||
@ -187,10 +187,10 @@ fn convert_to_from(
|
|||||||
(into_trait_seg.ident.span, String::from("From")),
|
(into_trait_seg.ident.span, String::from("From")),
|
||||||
// impl Into<T> for U -> impl Into<U> for U
|
// impl Into<T> for U -> impl Into<U> for U
|
||||||
// ~ ~
|
// ~ ~
|
||||||
(target_ty.span, from.clone()),
|
(target_ty.span, from.to_owned()),
|
||||||
// impl Into<T> for U -> impl Into<T> for T
|
// impl Into<T> for U -> impl Into<T> for T
|
||||||
// ~ ~
|
// ~ ~
|
||||||
(self_ty.span, into),
|
(self_ty.span, into.to_owned()),
|
||||||
// fn into(self) -> T -> fn from(self) -> T
|
// fn into(self) -> T -> fn from(self) -> T
|
||||||
// ~~~~ ~~~~
|
// ~~~~ ~~~~
|
||||||
(impl_item.ident.span, String::from("from")),
|
(impl_item.ident.span, String::from("from")),
|
||||||
@ -223,7 +223,7 @@ fn convert_to_from(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for span in finder.upper {
|
for span in finder.upper {
|
||||||
suggestions.push((span, from.clone()));
|
suggestions.push((span, from.to_owned()));
|
||||||
}
|
}
|
||||||
for span in finder.lower {
|
for span in finder.lower {
|
||||||
suggestions.push((span, String::from("val")));
|
suggestions.push((span, String::from("val")));
|
||||||
|
@ -22,8 +22,8 @@ declare_clippy_lint! {
|
|||||||
///
|
///
|
||||||
/// ### Known problems
|
/// ### Known problems
|
||||||
///
|
///
|
||||||
/// This lint may suggest using (&<expression>).parse() instead of <expression>.parse() directly
|
/// This lint may suggest using `(&<expression>).parse()` instead of `<expression>.parse()`
|
||||||
/// in some cases, which is correct but adds unnecessary complexity to the code.
|
/// directly in some cases, which is correct but adds unnecessary complexity to the code.
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::is_in_test;
|
use clippy_utils::is_in_test;
|
||||||
|
|
||||||
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{Body, GenericParam, Generics, HirId, ImplItem, ImplItemKind, TraitItem, TraitItemKind};
|
use rustc_hir::{Body, GenericParam, Generics, HirId, ImplItem, ImplItemKind, TraitItem, TraitItemKind};
|
||||||
@ -18,20 +19,18 @@ fn report(cx: &LateContext<'_>, param: &GenericParam<'_>, generics: &Generics<'_
|
|||||||
|diag| {
|
|diag| {
|
||||||
if let Some(gen_span) = generics.span_for_param_suggestion() {
|
if let Some(gen_span) = generics.span_for_param_suggestion() {
|
||||||
// If there's already a generic param with the same bound, do not lint **this** suggestion.
|
// If there's already a generic param with the same bound, do not lint **this** suggestion.
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
gen_span,
|
gen_span,
|
||||||
"add a type parameter",
|
"add a type parameter",
|
||||||
format!(", {{ /* Generic name */ }}: {}", ¶m.name.ident().as_str()[5..]),
|
format!(", {{ /* Generic name */ }}: {}", ¶m.name.ident().as_str()[5..]),
|
||||||
rustc_errors::Applicability::HasPlaceholders,
|
Applicability::HasPlaceholders,
|
||||||
rustc_errors::SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
generics.span,
|
generics.span,
|
||||||
"add a type parameter",
|
"add a type parameter",
|
||||||
format!("<{{ /* Generic name */ }}: {}>", ¶m.name.ident().as_str()[5..]),
|
format!("<{{ /* Generic name */ }}: {}>", ¶m.name.ident().as_str()[5..]),
|
||||||
rustc_errors::Applicability::HasPlaceholders,
|
Applicability::HasPlaceholders,
|
||||||
rustc_errors::SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -8,11 +8,11 @@ use rustc_infer::infer::TyCtxtInferExt;
|
|||||||
use rustc_lint::{LateContext, LintContext};
|
use rustc_lint::{LateContext, LintContext};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_span::{sym, Span, Symbol};
|
use rustc_span::{sym, Span};
|
||||||
|
|
||||||
use clippy_utils::attrs::is_proc_macro;
|
use clippy_utils::attrs::is_proc_macro;
|
||||||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
|
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::ty::is_must_use_ty;
|
use clippy_utils::ty::is_must_use_ty;
|
||||||
use clippy_utils::visitors::for_each_expr_without_closures;
|
use clippy_utils::visitors::for_each_expr_without_closures;
|
||||||
use clippy_utils::{return_ty, trait_ref_of_method};
|
use clippy_utils::{return_ty, trait_ref_of_method};
|
||||||
@ -129,9 +129,9 @@ fn check_needless_must_use(
|
|||||||
cx,
|
cx,
|
||||||
DOUBLE_MUST_USE,
|
DOUBLE_MUST_USE,
|
||||||
fn_header_span,
|
fn_header_span,
|
||||||
"this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`",
|
"this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`",
|
||||||
None,
|
None,
|
||||||
"either add some descriptive text or remove the attribute",
|
"either add some descriptive message or remove the attribute",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ fn check_must_use_candidate<'tcx>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| {
|
span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| {
|
||||||
if let Some(snippet) = snippet_opt(cx, fn_span) {
|
if let Some(snippet) = fn_span.get_source_text(cx) {
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
fn_span,
|
fn_span,
|
||||||
"add the attribute",
|
"add the attribute",
|
||||||
@ -193,17 +193,13 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static KNOWN_WRAPPER_TYS: &[Symbol] = &[sym::Rc, sym::Arc];
|
|
||||||
|
|
||||||
fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) -> bool {
|
fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) -> bool {
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
// primitive types are never mutable
|
// primitive types are never mutable
|
||||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
|
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
|
||||||
ty::Adt(adt, args) => {
|
ty::Adt(adt, args) => {
|
||||||
tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env)
|
tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env)
|
||||||
|| KNOWN_WRAPPER_TYS
|
|| matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::Rc | sym::Arc))
|
||||||
.iter()
|
|
||||||
.any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did()))
|
|
||||||
&& args.types().any(|ty| is_mutable_ty(cx, ty, tys))
|
&& args.types().any(|ty| is_mutable_ty(cx, ty, tys))
|
||||||
},
|
},
|
||||||
ty::Tuple(args) => args.iter().any(|ty| is_mutable_ty(cx, ty, tys)),
|
ty::Tuple(args) => args.iter().any(|ty| is_mutable_ty(cx, ty, tys)),
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
|
use clippy_utils::diagnostics::span_lint;
|
||||||
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_lint::{LateContext, LintContext};
|
use rustc_lint::{LateContext, LintContext};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use clippy_utils::diagnostics::span_lint;
|
|
||||||
use clippy_utils::source::snippet_opt;
|
|
||||||
|
|
||||||
use super::TOO_MANY_LINES;
|
use super::TOO_MANY_LINES;
|
||||||
|
|
||||||
pub(super) fn check_fn(
|
pub(super) fn check_fn(
|
||||||
@ -22,57 +21,57 @@ pub(super) fn check_fn(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(code_snippet) = snippet_opt(cx, body.value.span) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let mut line_count: u64 = 0;
|
let mut line_count: u64 = 0;
|
||||||
let mut in_comment = false;
|
let too_many = body.value.span.check_source_text(cx, |src| {
|
||||||
let mut code_in_line;
|
let mut in_comment = false;
|
||||||
|
let mut code_in_line;
|
||||||
|
|
||||||
let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
|
let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
|
||||||
&& code_snippet.as_bytes().first().copied() == Some(b'{')
|
&& src.as_bytes().first().copied() == Some(b'{')
|
||||||
&& code_snippet.as_bytes().last().copied() == Some(b'}')
|
&& src.as_bytes().last().copied() == Some(b'}')
|
||||||
{
|
{
|
||||||
// Removing the braces from the enclosing block
|
// Removing the braces from the enclosing block
|
||||||
&code_snippet[1..code_snippet.len() - 1]
|
&src[1..src.len() - 1]
|
||||||
} else {
|
} else {
|
||||||
&code_snippet
|
src
|
||||||
}
|
}
|
||||||
.trim() // Remove leading and trailing blank lines
|
.trim() // Remove leading and trailing blank lines
|
||||||
.lines();
|
.lines();
|
||||||
|
|
||||||
for mut line in function_lines {
|
for mut line in function_lines {
|
||||||
code_in_line = false;
|
code_in_line = false;
|
||||||
loop {
|
loop {
|
||||||
line = line.trim_start();
|
line = line.trim_start();
|
||||||
if line.is_empty() {
|
if line.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if in_comment {
|
||||||
|
if let Some(i) = line.find("*/") {
|
||||||
|
line = &line[i + 2..];
|
||||||
|
in_comment = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let multi_idx = line.find("/*").unwrap_or(line.len());
|
||||||
|
let single_idx = line.find("//").unwrap_or(line.len());
|
||||||
|
code_in_line |= multi_idx > 0 && single_idx > 0;
|
||||||
|
// Implies multi_idx is below line.len()
|
||||||
|
if multi_idx < single_idx {
|
||||||
|
line = &line[multi_idx + 2..];
|
||||||
|
in_comment = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if in_comment {
|
if code_in_line {
|
||||||
if let Some(i) = line.find("*/") {
|
line_count += 1;
|
||||||
line = &line[i + 2..];
|
|
||||||
in_comment = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let multi_idx = line.find("/*").unwrap_or(line.len());
|
|
||||||
let single_idx = line.find("//").unwrap_or(line.len());
|
|
||||||
code_in_line |= multi_idx > 0 && single_idx > 0;
|
|
||||||
// Implies multi_idx is below line.len()
|
|
||||||
if multi_idx < single_idx {
|
|
||||||
line = &line[multi_idx + 2..];
|
|
||||||
in_comment = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if code_in_line {
|
line_count > too_many_lines_threshold
|
||||||
line_count += 1;
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if line_count > too_many_lines_threshold {
|
if too_many {
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
TOO_MANY_LINES,
|
TOO_MANY_LINES,
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//! lint on if branches that could be swapped so no `!` operation is necessary
|
|
||||||
//! on the condition
|
|
||||||
|
|
||||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
use clippy_utils::consts::{ConstEvalCtxt, 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;
|
||||||
|
@ -3,7 +3,7 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context, wal
|
|||||||
use clippy_utils::visitors::for_each_expr_without_closures;
|
use clippy_utils::visitors::for_each_expr_without_closures;
|
||||||
use clippy_utils::{get_async_fn_body, is_async_fn, is_from_proc_macro};
|
use clippy_utils::{get_async_fn_body, is_async_fn, is_from_proc_macro};
|
||||||
use core::ops::ControlFlow;
|
use core::ops::ControlFlow;
|
||||||
use rustc_errors::{Applicability, SuggestionStyle};
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId};
|
use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
@ -54,13 +54,7 @@ fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) {
|
|||||||
|diag| {
|
|diag| {
|
||||||
let mut app = Applicability::MachineApplicable;
|
let mut app = Applicability::MachineApplicable;
|
||||||
let snip = snippet_with_applicability(cx, span, "..", &mut app);
|
let snip = snippet_with_applicability(cx, span, "..", &mut app);
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(span, "add `return` as shown", format!("return {snip}"), app);
|
||||||
span,
|
|
||||||
"add `return` as shown",
|
|
||||||
format!("return {snip}"),
|
|
||||||
app,
|
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -75,12 +69,11 @@ fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, exp
|
|||||||
|diag| {
|
|diag| {
|
||||||
let mut app = Applicability::MachineApplicable;
|
let mut app = Applicability::MachineApplicable;
|
||||||
let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0;
|
let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0;
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
break_span,
|
break_span,
|
||||||
"change `break` to `return` as shown",
|
"change `break` to `return` as shown",
|
||||||
format!("return {snip}"),
|
format!("return {snip}"),
|
||||||
app,
|
app,
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -7,8 +7,7 @@ use rustc_data_structures::fx::FxHashMap;
|
|||||||
use rustc_hir::{Expr, ExprKind, HirId};
|
use rustc_hir::{Expr, ExprKind, HirId};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_semver::RustcVersion;
|
use rustc_session::{impl_lint_pass, RustcVersion};
|
||||||
use rustc_session::impl_lint_pass;
|
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
use rustc_span::{ExpnKind, Span};
|
use rustc_span::{ExpnKind, Span};
|
||||||
|
|
||||||
@ -65,18 +64,18 @@ impl IncompatibleMsrv {
|
|||||||
StabilityLevel::Stable {
|
StabilityLevel::Stable {
|
||||||
since: StableSince::Version(version),
|
since: StableSince::Version(version),
|
||||||
..
|
..
|
||||||
} => Some(RustcVersion::new(
|
} => Some(version),
|
||||||
version.major.into(),
|
|
||||||
version.minor.into(),
|
|
||||||
version.patch.into(),
|
|
||||||
)),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}) {
|
}) {
|
||||||
version
|
version
|
||||||
} else if let Some(parent_def_id) = tcx.opt_parent(def_id) {
|
} else if let Some(parent_def_id) = tcx.opt_parent(def_id) {
|
||||||
self.get_def_id_version(tcx, parent_def_id)
|
self.get_def_id_version(tcx, parent_def_id)
|
||||||
} else {
|
} else {
|
||||||
RustcVersion::new(1, 0, 0)
|
RustcVersion {
|
||||||
|
major: 1,
|
||||||
|
minor: 0,
|
||||||
|
patch: 0,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
self.is_above_msrv.insert(def_id, version);
|
self.is_above_msrv.insert(def_id, version);
|
||||||
version
|
version
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
|
use clippy_utils::fulfill_or_allowed;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -71,6 +72,8 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
|
|||||||
&& let ty = cx.typeck_results().expr_ty(expr)
|
&& let ty = cx.typeck_results().expr_ty(expr)
|
||||||
&& let Some(adt_def) = ty.ty_adt_def()
|
&& let Some(adt_def) = ty.ty_adt_def()
|
||||||
&& adt_def.is_struct()
|
&& adt_def.is_struct()
|
||||||
|
&& let Some(local_def_id) = adt_def.did().as_local()
|
||||||
|
&& let ty_hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id)
|
||||||
&& let Some(variant) = adt_def.variants().iter().next()
|
&& let Some(variant) = adt_def.variants().iter().next()
|
||||||
{
|
{
|
||||||
let mut def_order_map = FxHashMap::default();
|
let mut def_order_map = FxHashMap::default();
|
||||||
@ -103,15 +106,17 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
|
|||||||
snippet(cx, qpath.span(), ".."),
|
snippet(cx, qpath.span(), ".."),
|
||||||
);
|
);
|
||||||
|
|
||||||
span_lint_and_sugg(
|
if !fulfill_or_allowed(cx, INCONSISTENT_STRUCT_CONSTRUCTOR, Some(ty_hir_id)) {
|
||||||
cx,
|
span_lint_and_sugg(
|
||||||
INCONSISTENT_STRUCT_CONSTRUCTOR,
|
cx,
|
||||||
expr.span,
|
INCONSISTENT_STRUCT_CONSTRUCTOR,
|
||||||
"struct constructor field order is inconsistent with struct definition field order",
|
expr.span,
|
||||||
"try",
|
"struct constructor field order is inconsistent with struct definition field order",
|
||||||
sugg,
|
"try",
|
||||||
Applicability::MachineApplicable,
|
sugg,
|
||||||
);
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! lint on indexing and slicing operations
|
|
||||||
|
|
||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use clippy_utils::higher;
|
use clippy_utils::higher;
|
||||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
use clippy_utils::ty::{get_type_diagnostic_name, implements_trait};
|
||||||
use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
|
use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
@ -210,18 +210,6 @@ const COMPLETING_METHODS: [(&str, usize); 12] = [
|
|||||||
("product", 0),
|
("product", 0),
|
||||||
];
|
];
|
||||||
|
|
||||||
/// the paths of types that are known to be infinitely allocating
|
|
||||||
const INFINITE_COLLECTORS: &[Symbol] = &[
|
|
||||||
sym::BinaryHeap,
|
|
||||||
sym::BTreeMap,
|
|
||||||
sym::BTreeSet,
|
|
||||||
sym::HashMap,
|
|
||||||
sym::HashSet,
|
|
||||||
sym::LinkedList,
|
|
||||||
sym::Vec,
|
|
||||||
sym::VecDeque,
|
|
||||||
];
|
|
||||||
|
|
||||||
fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::MethodCall(method, receiver, args, _) => {
|
ExprKind::MethodCall(method, receiver, args, _) => {
|
||||||
@ -248,10 +236,19 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
|||||||
}
|
}
|
||||||
} else if method.ident.name == sym!(collect) {
|
} else if method.ident.name == sym!(collect) {
|
||||||
let ty = cx.typeck_results().expr_ty(expr);
|
let ty = cx.typeck_results().expr_ty(expr);
|
||||||
if INFINITE_COLLECTORS
|
if matches!(
|
||||||
.iter()
|
get_type_diagnostic_name(cx, ty),
|
||||||
.any(|diag_item| is_type_diagnostic_item(cx, ty, *diag_item))
|
Some(
|
||||||
{
|
sym::BinaryHeap
|
||||||
|
| sym::BTreeMap
|
||||||
|
| sym::BTreeSet
|
||||||
|
| sym::HashMap
|
||||||
|
| sym::HashSet
|
||||||
|
| sym::LinkedList
|
||||||
|
| sym::Vec
|
||||||
|
| sym::VecDeque,
|
||||||
|
)
|
||||||
|
) {
|
||||||
return is_infinite(cx, receiver);
|
return is_infinite(cx, receiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! lint on inherent implementations
|
|
||||||
|
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::is_lint_allowed;
|
use clippy_utils::is_lint_allowed;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! checks for `#[inline]` on trait methods without bodies
|
|
||||||
|
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::sugg::DiagExt;
|
use clippy_utils::sugg::DiagExt;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
//! lint on blocks unnecessarily using >= with a + 1 or - 1
|
|
||||||
|
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind};
|
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind};
|
||||||
use rustc_ast::token;
|
use rustc_ast::token;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -132,8 +130,8 @@ impl IntPlusOne {
|
|||||||
BinOpKind::Le => "<",
|
BinOpKind::Le => "<",
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
if let Some(snippet) = snippet_opt(cx, node.span) {
|
if let Some(snippet) = node.span.get_source_text(cx) {
|
||||||
if let Some(other_side_snippet) = snippet_opt(cx, other_side.span) {
|
if let Some(other_side_snippet) = other_side.span.get_source_text(cx) {
|
||||||
let rec = match side {
|
let rec = match side {
|
||||||
Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")),
|
Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")),
|
||||||
Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")),
|
Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")),
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! lint on enum variants that are prefixed or suffixed by the same characters
|
|
||||||
|
|
||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir};
|
||||||
use clippy_utils::is_bool;
|
use clippy_utils::is_bool;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! lint when items are used after statements
|
|
||||||
|
|
||||||
use clippy_utils::diagnostics::span_lint_hir;
|
use clippy_utils::diagnostics::span_lint_hir;
|
||||||
use rustc_hir::{Block, ItemKind, StmtKind};
|
use rustc_hir::{Block, ItemKind, StmtKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::{fulfill_or_allowed, is_cfg_test, is_from_proc_macro};
|
use clippy_utils::{fulfill_or_allowed, is_cfg_test, is_from_proc_macro};
|
||||||
use rustc_errors::{Applicability, SuggestionStyle};
|
use rustc_errors::{Applicability, SuggestionStyle};
|
||||||
use rustc_hir::{HirId, Item, ItemKind, Mod};
|
use rustc_hir::{HirId, Item, ItemKind, Mod};
|
||||||
@ -93,11 +93,14 @@ impl LateLintPass<'_> for ItemsAfterTestModule {
|
|||||||
if let Some(prev) = mod_pos.checked_sub(1)
|
if let Some(prev) = mod_pos.checked_sub(1)
|
||||||
&& let prev = cx.tcx.hir().item(module.item_ids[prev])
|
&& let prev = cx.tcx.hir().item(module.item_ids[prev])
|
||||||
&& let items_span = last.span.with_lo(test_mod.span.hi())
|
&& let items_span = last.span.with_lo(test_mod.span.hi())
|
||||||
&& let Some(items) = snippet_opt(cx, items_span)
|
&& let Some(items) = items_span.get_source_text(cx)
|
||||||
{
|
{
|
||||||
diag.multipart_suggestion_with_style(
|
diag.multipart_suggestion_with_style(
|
||||||
"move the items to before the test module was defined",
|
"move the items to before the test module was defined",
|
||||||
vec![(prev.span.shrink_to_hi(), items), (items_span, String::new())],
|
vec![
|
||||||
|
(prev.span.shrink_to_hi(), items.to_owned()),
|
||||||
|
(items_span, String::new()),
|
||||||
|
],
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
SuggestionStyle::HideCodeAlways,
|
SuggestionStyle::HideCodeAlways,
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! lint when there is a large size difference between variants on an enum
|
|
||||||
|
|
||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
|
@ -3,7 +3,7 @@ use std::{fmt, ops};
|
|||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::fn_has_unsatisfiable_preds;
|
use clippy_utils::fn_has_unsatisfiable_preds;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{Body, FnDecl};
|
use rustc_hir::{Body, FnDecl};
|
||||||
@ -186,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames {
|
|||||||
// TODO: Is there a cleaner, robust way to ask this question?
|
// TODO: Is there a cleaner, robust way to ask this question?
|
||||||
// The obvious `LocalDecl::is_user_variable()` panics on "unwrapping cross-crate data",
|
// The obvious `LocalDecl::is_user_variable()` panics on "unwrapping cross-crate data",
|
||||||
// and that doesn't get us the true name in scope rather than the span text either.
|
// and that doesn't get us the true name in scope rather than the span text either.
|
||||||
if let Some(name) = snippet_opt(cx, local_span)
|
if let Some(name) = local_span.get_source_text(cx)
|
||||||
&& is_ident(&name)
|
&& is_ident(&name)
|
||||||
{
|
{
|
||||||
// If the local is an ordinary named variable,
|
// If the local is an ordinary named variable,
|
||||||
|
@ -3,7 +3,7 @@ use clippy_config::Conf;
|
|||||||
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
|
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
|
||||||
use clippy_utils::{get_parent_expr, is_from_proc_macro};
|
use clippy_utils::{get_parent_expr, is_from_proc_macro};
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use rustc_errors::{Applicability, SuggestionStyle};
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::{ExprKind, Item, ItemKind, QPath, UseKind};
|
use rustc_hir::{ExprKind, Item, ItemKind, QPath, UseKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
@ -143,12 +143,11 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
|
|||||||
&& !is_from_proc_macro(cx, expr)
|
&& !is_from_proc_macro(cx, expr)
|
||||||
{
|
{
|
||||||
span_lint_hir_and_then(cx, LEGACY_NUMERIC_CONSTANTS, expr.hir_id, span, msg, |diag| {
|
span_lint_hir_and_then(cx, LEGACY_NUMERIC_CONSTANTS, expr.hir_id, span, msg, |diag| {
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
"use the associated constant instead",
|
"use the associated constant instead",
|
||||||
sugg,
|
sugg,
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
|
||||||
use clippy_utils::source::{snippet_opt, snippet_with_context};
|
use clippy_utils::source::{snippet_with_context, SpanRangeExt};
|
||||||
use clippy_utils::sugg::{has_enclosing_paren, Sugg};
|
use clippy_utils::sugg::{has_enclosing_paren, Sugg};
|
||||||
use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
|
use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
@ -216,7 +216,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span {
|
fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span {
|
||||||
let Some(snippet) = snippet_opt(cx, span) else {
|
let Some(snippet) = span.get_source_text(cx) else {
|
||||||
return span;
|
return span;
|
||||||
};
|
};
|
||||||
if has_enclosing_paren(snippet) {
|
if has_enclosing_paren(snippet) {
|
||||||
|
@ -66,8 +66,8 @@ extern crate declare_clippy_lint;
|
|||||||
#[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
|
#[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
mod declared_lints;
|
pub mod declared_lints;
|
||||||
mod deprecated_lints;
|
pub mod deprecated_lints;
|
||||||
|
|
||||||
// begin lints modules, do not remove this comment, it’s used in `update_lints`
|
// begin lints modules, do not remove this comment, it’s used in `update_lints`
|
||||||
mod absolute_paths;
|
mod absolute_paths;
|
||||||
@ -440,7 +440,7 @@ impl RegistrationGroups {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub(crate) enum LintCategory {
|
pub(crate) enum LintCategory {
|
||||||
Cargo,
|
Cargo,
|
||||||
Complexity,
|
Complexity,
|
||||||
@ -479,11 +479,39 @@ impl LintCategory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct LintInfo {
|
pub struct LintInfo {
|
||||||
/// Double reference to maintain pointer equality
|
/// Double reference to maintain pointer equality
|
||||||
lint: &'static &'static Lint,
|
pub lint: &'static &'static Lint,
|
||||||
category: LintCategory,
|
category: LintCategory,
|
||||||
explanation: &'static str,
|
pub explanation: &'static str,
|
||||||
|
/// e.g. `clippy_lints/src/absolute_paths.rs#43`
|
||||||
|
pub location: &'static str,
|
||||||
|
pub version: Option<&'static str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LintInfo {
|
||||||
|
/// Returns the lint name in lowercase without the `clippy::` prefix
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
|
pub fn name_lower(&self) -> String {
|
||||||
|
self.lint.name.strip_prefix("clippy::").unwrap().to_ascii_lowercase()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the name of the lint's category in lowercase (`style`, `pedantic`)
|
||||||
|
pub fn category_str(&self) -> &'static str {
|
||||||
|
match self.category {
|
||||||
|
Cargo => "cargo",
|
||||||
|
Complexity => "complexity",
|
||||||
|
Correctness => "correctness",
|
||||||
|
Nursery => "nursery",
|
||||||
|
Pedantic => "pedantic",
|
||||||
|
Perf => "perf",
|
||||||
|
Restriction => "restriction",
|
||||||
|
Style => "style",
|
||||||
|
Suspicious => "suspicious",
|
||||||
|
#[cfg(feature = "internal")]
|
||||||
|
Internal => "internal",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn explain(name: &str) -> i32 {
|
pub fn explain(name: &str) -> i32 {
|
||||||
@ -538,14 +566,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
|||||||
store.register_removed(name, reason);
|
store.register_removed(name, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "internal")]
|
|
||||||
{
|
|
||||||
if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
|
|
||||||
store.register_late_pass(|_| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let format_args_storage = FormatArgsStorage::default();
|
let format_args_storage = FormatArgsStorage::default();
|
||||||
let format_args = format_args_storage.clone();
|
let format_args = format_args_storage.clone();
|
||||||
store.register_early_pass(move || {
|
store.register_early_pass(move || {
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
//! Lints concerned with the grouping of digits with underscores in integral or
|
|
||||||
//! floating-point literal expressions.
|
|
||||||
|
|
||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::numeric_literal::{NumericLiteral, Radix};
|
use clippy_utils::numeric_literal::{NumericLiteral, Radix};
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use rustc_ast::ast::{Expr, ExprKind, LitKind};
|
use rustc_ast::ast::{Expr, ExprKind, LitKind};
|
||||||
use rustc_ast::token;
|
use rustc_ast::token;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -228,7 +225,7 @@ impl LiteralDigitGrouping {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_lit(&self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
|
fn check_lit(&self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
|
||||||
if let Some(src) = snippet_opt(cx, span)
|
if let Some(src) = span.get_source_text(cx)
|
||||||
&& let Ok(lit_kind) = LitKind::from_token_lit(lit)
|
&& let Ok(lit_kind) = LitKind::from_token_lit(lit)
|
||||||
&& let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind)
|
&& let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind)
|
||||||
{
|
{
|
||||||
@ -442,7 +439,7 @@ impl DecimalLiteralRepresentation {
|
|||||||
// Lint integral literals.
|
// Lint integral literals.
|
||||||
if let Ok(lit_kind) = LitKind::from_token_lit(lit)
|
if let Ok(lit_kind) = LitKind::from_token_lit(lit)
|
||||||
&& let LitKind::Int(val, _) = lit_kind
|
&& let LitKind::Int(val, _) = lit_kind
|
||||||
&& let Some(src) = snippet_opt(cx, span)
|
&& let Some(src) = span.get_source_text(cx)
|
||||||
&& let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind)
|
&& let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind)
|
||||||
&& num_lit.radix == Radix::Decimal
|
&& num_lit.radix == Radix::Decimal
|
||||||
&& val >= u128::from(self.threshold)
|
&& val >= u128::from(self.threshold)
|
||||||
|
@ -3,7 +3,7 @@ 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::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::ty::{
|
use clippy_utils::ty::{
|
||||||
implements_trait, implements_trait_with_env, is_copy, make_normalized_projection,
|
implements_trait, implements_trait_with_env, is_copy, is_type_lang_item, make_normalized_projection,
|
||||||
make_normalized_projection_with_regions, normalize_with_regions,
|
make_normalized_projection_with_regions, normalize_with_regions,
|
||||||
};
|
};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -20,9 +20,10 @@ pub(super) fn check(
|
|||||||
msrv: &Msrv,
|
msrv: &Msrv,
|
||||||
enforce_iter_loop_reborrow: bool,
|
enforce_iter_loop_reborrow: bool,
|
||||||
) {
|
) {
|
||||||
let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow) else {
|
let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow, msrv) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let ty::Array(_, count) = *ty.peel_refs().kind() {
|
if let ty::Array(_, count) = *ty.peel_refs().kind() {
|
||||||
if !ty.is_ref() {
|
if !ty.is_ref() {
|
||||||
if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) {
|
if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) {
|
||||||
@ -109,6 +110,7 @@ fn is_ref_iterable<'tcx>(
|
|||||||
self_arg: &Expr<'_>,
|
self_arg: &Expr<'_>,
|
||||||
call_expr: &Expr<'_>,
|
call_expr: &Expr<'_>,
|
||||||
enforce_iter_loop_reborrow: bool,
|
enforce_iter_loop_reborrow: bool,
|
||||||
|
msrv: &Msrv,
|
||||||
) -> Option<(AdjustKind, Ty<'tcx>)> {
|
) -> Option<(AdjustKind, Ty<'tcx>)> {
|
||||||
let typeck = cx.typeck_results();
|
let typeck = cx.typeck_results();
|
||||||
if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
|
if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
|
||||||
@ -128,6 +130,12 @@ fn is_ref_iterable<'tcx>(
|
|||||||
let self_ty = typeck.expr_ty(self_arg);
|
let self_ty = typeck.expr_ty(self_arg);
|
||||||
let self_is_copy = is_copy(cx, self_ty);
|
let self_is_copy = is_copy(cx, self_ty);
|
||||||
|
|
||||||
|
if !msrv.meets(msrvs::BOX_INTO_ITER)
|
||||||
|
&& is_type_lang_item(cx, self_ty.peel_refs(), rustc_hir::LangItem::OwnedBox)
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
if adjustments.is_empty() && self_is_copy {
|
if adjustments.is_empty() && self_is_copy {
|
||||||
// Exact type match, already checked earlier
|
// Exact type match, already checked earlier
|
||||||
return Some((AdjustKind::None, self_ty));
|
return Some((AdjustKind::None, self_ty));
|
||||||
|
@ -122,8 +122,23 @@ struct BodyVisitor<'a, 'tcx> {
|
|||||||
/// within a relevant macro.
|
/// within a relevant macro.
|
||||||
macro_unsafe_blocks: Vec<HirId>,
|
macro_unsafe_blocks: Vec<HirId>,
|
||||||
/// When this is >0, it means that the node currently being visited is "within" a
|
/// When this is >0, it means that the node currently being visited is "within" a
|
||||||
/// macro definition. This is not necessary for correctness, it merely helps reduce the number
|
/// macro definition.
|
||||||
/// of spans we need to insert into the map, since only spans from macros are relevant.
|
/// This is used to detect if an expression represents a metavariable.
|
||||||
|
///
|
||||||
|
/// For example, the following pre-expansion code that we want to lint
|
||||||
|
/// ```ignore
|
||||||
|
/// macro_rules! m { ($e:expr) => { unsafe { $e; } } }
|
||||||
|
/// m!(1);
|
||||||
|
/// ```
|
||||||
|
/// would look like this post-expansion code:
|
||||||
|
/// ```ignore
|
||||||
|
/// unsafe { /* macro */
|
||||||
|
/// 1 /* root */; /* macro */
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// Visiting the block and the statement will increment the `expn_depth` so that it is >0,
|
||||||
|
/// and visiting the expression with a root context while `expn_depth > 0` tells us
|
||||||
|
/// that it must be a metavariable.
|
||||||
expn_depth: u32,
|
expn_depth: u32,
|
||||||
cx: &'a LateContext<'tcx>,
|
cx: &'a LateContext<'tcx>,
|
||||||
lint: &'a mut ExprMetavarsInUnsafe,
|
lint: &'a mut ExprMetavarsInUnsafe,
|
||||||
@ -157,7 +172,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BodyVisitor<'a, 'tcx> {
|
|||||||
&& (self.lint.warn_unsafe_macro_metavars_in_private_macros || is_public_macro(self.cx, macro_def_id))
|
&& (self.lint.warn_unsafe_macro_metavars_in_private_macros || is_public_macro(self.cx, macro_def_id))
|
||||||
{
|
{
|
||||||
self.macro_unsafe_blocks.push(block.hir_id);
|
self.macro_unsafe_blocks.push(block.hir_id);
|
||||||
|
self.expn_depth += 1;
|
||||||
walk_block(self, block);
|
walk_block(self, block);
|
||||||
|
self.expn_depth -= 1;
|
||||||
self.macro_unsafe_blocks.pop();
|
self.macro_unsafe_blocks.pop();
|
||||||
} else if ctxt.is_root() && self.expn_depth > 0 {
|
} else if ctxt.is_root() && self.expn_depth > 0 {
|
||||||
let unsafe_block = self.macro_unsafe_blocks.last().copied();
|
let unsafe_block = self.macro_unsafe_blocks.last().copied();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
|
use clippy_utils::source::{position_before_rarrow, snippet_block, SpanRangeExt};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
@ -68,8 +68,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
|
|||||||
header_span,
|
header_span,
|
||||||
"this function can be simplified using the `async fn` syntax",
|
"this function can be simplified using the `async fn` syntax",
|
||||||
|diag| {
|
|diag| {
|
||||||
if let Some(vis_snip) = snippet_opt(cx, *vis_span)
|
if let Some(vis_snip) = vis_span.get_source_text(cx)
|
||||||
&& let Some(header_snip) = snippet_opt(cx, header_span)
|
&& let Some(header_snip) = header_span.get_source_text(cx)
|
||||||
&& let Some(ret_pos) = position_before_rarrow(&header_snip)
|
&& let Some(ret_pos) = position_before_rarrow(&header_snip)
|
||||||
&& let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output)
|
&& let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output)
|
||||||
{
|
{
|
||||||
@ -190,6 +190,6 @@ fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str,
|
|||||||
Some((sugg, String::new()))
|
Some((sugg, String::new()))
|
||||||
} else {
|
} else {
|
||||||
let sugg = "return the output of the future directly";
|
let sugg = "return the output of the future directly";
|
||||||
snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}")))
|
output.span.get_source_text(cx).map(|src| (sugg, format!(" -> {src}")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::{is_from_proc_macro, path_to_local};
|
use clippy_utils::{is_from_proc_macro, path_to_local};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{BinOpKind, Constness, Expr, ExprKind};
|
use rustc_hir::{BinOpKind, Constness, Expr, ExprKind};
|
||||||
@ -103,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
|
|||||||
// case somebody does that for some reason
|
// case somebody does that for some reason
|
||||||
&& (is_infinity(&const_1) && is_neg_infinity(&const_2)
|
&& (is_infinity(&const_1) && is_neg_infinity(&const_2)
|
||||||
|| is_neg_infinity(&const_1) && is_infinity(&const_2))
|
|| is_neg_infinity(&const_1) && is_infinity(&const_2))
|
||||||
&& let Some(local_snippet) = snippet_opt(cx, first.span)
|
&& let Some(local_snippet) = first.span.get_source_text(cx)
|
||||||
{
|
{
|
||||||
let variant = match (kind.node, lhs_kind.node, rhs_kind.node) {
|
let variant = match (kind.node, lhs_kind.node, rhs_kind.node) {
|
||||||
(BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => Variant::ManualIsInfinite,
|
(BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => Variant::ManualIsInfinite,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use clippy_config::msrvs::{self, Msrv};
|
use clippy_config::msrvs::{self, Msrv};
|
||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::visitors::{is_local_used, local_used_once};
|
use clippy_utils::visitors::{is_local_used, local_used_once};
|
||||||
use clippy_utils::{is_trait_method, path_to_local_id};
|
use clippy_utils::{is_trait_method, path_to_local_id};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -107,8 +107,8 @@ impl LateLintPass<'_> for ManualHashOne {
|
|||||||
finish_expr.span,
|
finish_expr.span,
|
||||||
"manual implementation of `BuildHasher::hash_one`",
|
"manual implementation of `BuildHasher::hash_one`",
|
||||||
|diag| {
|
|diag| {
|
||||||
if let Some(build_hasher) = snippet_opt(cx, build_hasher.span)
|
if let Some(build_hasher) = build_hasher.span.get_source_text(cx)
|
||||||
&& let Some(hashed_value) = snippet_opt(cx, hashed_value.span)
|
&& let Some(hashed_value) = hashed_value.span.get_source_text(cx)
|
||||||
{
|
{
|
||||||
diag.multipart_suggestion(
|
diag.multipart_suggestion(
|
||||||
"try",
|
"try",
|
||||||
|
@ -2,7 +2,7 @@ use clippy_config::msrvs::{self, Msrv};
|
|||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
|
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
|
||||||
use clippy_utils::is_doc_hidden;
|
use clippy_utils::is_doc_hidden;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use rustc_ast::ast::{self, VisibilityKind};
|
use rustc_ast::ast::{self, VisibilityKind};
|
||||||
use rustc_ast::attr;
|
use rustc_ast::attr;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
@ -124,7 +124,7 @@ impl EarlyLintPass for ManualNonExhaustiveStruct {
|
|||||||
|diag| {
|
|diag| {
|
||||||
if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive))
|
if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive))
|
||||||
&& let header_span = cx.sess().source_map().span_until_char(item.span, delimiter)
|
&& let header_span = cx.sess().source_map().span_until_char(item.span, delimiter)
|
||||||
&& let Some(snippet) = snippet_opt(cx, header_span)
|
&& let Some(snippet) = header_span.get_source_text(cx)
|
||||||
{
|
{
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
header_span,
|
header_span,
|
||||||
@ -194,7 +194,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
|
|||||||
"this seems like a manual implementation of the non-exhaustive pattern",
|
"this seems like a manual implementation of the non-exhaustive pattern",
|
||||||
|diag| {
|
|diag| {
|
||||||
let header_span = cx.sess().source_map().span_until_char(enum_span, '{');
|
let header_span = cx.sess().source_map().span_until_char(enum_span, '{');
|
||||||
if let Some(snippet) = snippet_opt(cx, header_span) {
|
if let Some(snippet) = header_span.get_source_text(cx) {
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
header_span,
|
header_span,
|
||||||
"add the attribute",
|
"add the attribute",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use rustc_ast::LitKind;
|
use rustc_ast::LitKind;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -143,8 +143,8 @@ impl LateLintPass<'_> for ManualRangePatterns {
|
|||||||
pat.span,
|
pat.span,
|
||||||
"this OR pattern can be rewritten using a range",
|
"this OR pattern can be rewritten using a range",
|
||||||
|diag| {
|
|diag| {
|
||||||
if let Some(min) = snippet_opt(cx, min.span)
|
if let Some(min) = min.span.get_source_text(cx)
|
||||||
&& let Some(max) = snippet_opt(cx, max.span)
|
&& let Some(max) = max.span.get_source_text(cx)
|
||||||
{
|
{
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
pat.span,
|
pat.span,
|
||||||
|
@ -2,14 +2,13 @@ use clippy_config::msrvs::{self, Msrv};
|
|||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
|
use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
|
||||||
use clippy_utils::{match_def_path, paths, SpanlessEq};
|
use clippy_utils::{match_def_path, paths, SpanlessEq};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::ExprKind::Assign;
|
use rustc_hir::ExprKind::Assign;
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_semver::RustcVersion;
|
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -21,16 +20,6 @@ const ACCEPTABLE_METHODS: [&[&str]; 5] = [
|
|||||||
&paths::SLICE_INTO,
|
&paths::SLICE_INTO,
|
||||||
&paths::VEC_DEQUE_ITER,
|
&paths::VEC_DEQUE_ITER,
|
||||||
];
|
];
|
||||||
const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 7] = [
|
|
||||||
(sym::BinaryHeap, Some(msrvs::BINARY_HEAP_RETAIN)),
|
|
||||||
(sym::BTreeSet, Some(msrvs::BTREE_SET_RETAIN)),
|
|
||||||
(sym::BTreeMap, Some(msrvs::BTREE_MAP_RETAIN)),
|
|
||||||
(sym::HashSet, Some(msrvs::HASH_SET_RETAIN)),
|
|
||||||
(sym::HashMap, Some(msrvs::HASH_MAP_RETAIN)),
|
|
||||||
(sym::Vec, None),
|
|
||||||
(sym::VecDeque, None),
|
|
||||||
];
|
|
||||||
const MAP_TYPES: [rustc_span::Symbol; 2] = [sym::BTreeMap, sym::HashMap];
|
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
@ -265,16 +254,22 @@ fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool {
|
fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool {
|
||||||
let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
|
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
|
||||||
ACCEPTABLE_TYPES.iter().any(|(ty, acceptable_msrv)| {
|
let required = match get_type_diagnostic_name(cx, ty) {
|
||||||
is_type_diagnostic_item(cx, expr_ty, *ty)
|
Some(sym::BinaryHeap) => msrvs::BINARY_HEAP_RETAIN,
|
||||||
&& acceptable_msrv.map_or(true, |acceptable_msrv| msrv.meets(acceptable_msrv))
|
Some(sym::BTreeSet) => msrvs::BTREE_SET_RETAIN,
|
||||||
})
|
Some(sym::BTreeMap) => msrvs::BTREE_MAP_RETAIN,
|
||||||
|
Some(sym::HashSet) => msrvs::HASH_SET_RETAIN,
|
||||||
|
Some(sym::HashMap) => msrvs::HASH_MAP_RETAIN,
|
||||||
|
Some(sym::Vec | sym::VecDeque) => return true,
|
||||||
|
_ => return false,
|
||||||
|
};
|
||||||
|
msrv.meets(required)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_map_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
|
fn match_map_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
|
||||||
let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
|
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
|
||||||
MAP_TYPES.iter().any(|ty| is_type_diagnostic_item(cx, expr_ty, *ty))
|
matches!(get_type_diagnostic_name(cx, ty), Some(sym::BTreeMap | sym::HashMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_span_lint_and_sugg(cx: &LateContext<'_>, span: Span, sugg: String) {
|
fn make_span_lint_and_sugg(cx: &LateContext<'_>, span: Span, sugg: String) {
|
||||||
|
@ -96,7 +96,7 @@ fn check_arm<'tcx>(
|
|||||||
// collapsing patterns need an explicit field name in struct pattern matching
|
// collapsing patterns need an explicit field name in struct pattern matching
|
||||||
// ex: Struct {x: Some(1)}
|
// ex: Struct {x: Some(1)}
|
||||||
let replace_msg = if is_innermost_parent_pat_struct {
|
let replace_msg = if is_innermost_parent_pat_struct {
|
||||||
format!(", prefixed by {}:", snippet(cx, binding_span, "their field name"))
|
format!(", prefixed by `{}`:", snippet(cx, binding_span, "their field name"))
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::consts::ConstEvalCtxt;
|
use clippy_utils::consts::ConstEvalCtxt;
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
|
use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::usage::contains_return_break_continue_macro;
|
use clippy_utils::usage::contains_return_break_continue_macro;
|
||||||
use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg};
|
use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg};
|
||||||
@ -67,11 +67,11 @@ fn check_and_lint<'tcx>(
|
|||||||
&& path_to_local_id(peel_blocks(then_expr), binding_hir_id)
|
&& path_to_local_id(peel_blocks(then_expr), binding_hir_id)
|
||||||
&& cx.typeck_results().expr_adjustments(then_expr).is_empty()
|
&& cx.typeck_results().expr_adjustments(then_expr).is_empty()
|
||||||
&& let Some(ty_name) = find_type_name(cx, ty)
|
&& let Some(ty_name) = find_type_name(cx, ty)
|
||||||
&& let Some(or_body_snippet) = snippet_opt(cx, else_expr.span)
|
&& let Some(or_body_snippet) = else_expr.span.get_source_text(cx)
|
||||||
&& let Some(indent) = indent_of(cx, expr.span)
|
&& let Some(indent) = indent_of(cx, expr.span)
|
||||||
&& ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some()
|
&& ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some()
|
||||||
{
|
{
|
||||||
lint(cx, expr, let_expr, ty_name, or_body_snippet, indent);
|
lint(cx, expr, let_expr, ty_name, &or_body_snippet, indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ fn lint<'tcx>(
|
|||||||
expr: &Expr<'tcx>,
|
expr: &Expr<'tcx>,
|
||||||
scrutinee: &'tcx Expr<'_>,
|
scrutinee: &'tcx Expr<'_>,
|
||||||
ty_name: &str,
|
ty_name: &str,
|
||||||
or_body_snippet: String,
|
or_body_snippet: &str,
|
||||||
indent: usize,
|
indent: usize,
|
||||||
) {
|
) {
|
||||||
let reindented_or_body = reindent_multiline(or_body_snippet.into(), true, Some(indent));
|
let reindented_or_body = reindent_multiline(or_body_snippet.into(), true, Some(indent));
|
||||||
|
@ -22,7 +22,7 @@ use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
|
|||||||
/// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty
|
/// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty
|
||||||
/// match arms.
|
/// match arms.
|
||||||
fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool {
|
fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool {
|
||||||
if let Some(ff) = span.get_source_text(cx)
|
if let Some(ff) = span.get_source_range(cx)
|
||||||
&& let Some(text) = ff.as_str()
|
&& let Some(text) = ff.as_str()
|
||||||
{
|
{
|
||||||
text.as_bytes().windows(2).any(|w| w == b"//" || w == b"/*")
|
text.as_bytes().windows(2).any(|w| w == b"//" || w == b"/*")
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
|
use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
|
||||||
use clippy_utils::ty::is_type_lang_item;
|
use clippy_utils::ty::is_type_lang_item;
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -49,10 +49,12 @@ pub(super) fn check<'tcx>(
|
|||||||
"case-sensitive file extension comparison",
|
"case-sensitive file extension comparison",
|
||||||
|diag| {
|
|diag| {
|
||||||
diag.help("consider using a case-insensitive comparison instead");
|
diag.help("consider using a case-insensitive comparison instead");
|
||||||
if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
|
if let Some(recv_source) = recv.span.get_source_text(cx) {
|
||||||
if !cx.typeck_results().expr_ty(recv).is_ref() {
|
let recv_source = if cx.typeck_results().expr_ty(recv).is_ref() {
|
||||||
recv_source = format!("&{recv_source}");
|
recv_source.to_owned()
|
||||||
}
|
} else {
|
||||||
|
format!("&{recv_source}")
|
||||||
|
};
|
||||||
|
|
||||||
let suggestion_source = reindent_multiline(
|
let suggestion_source = reindent_multiline(
|
||||||
format!(
|
format!(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::FILTER_MAP_BOOL_THEN;
|
use super::FILTER_MAP_BOOL_THEN;
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::paths::BOOL_THEN;
|
use clippy_utils::paths::BOOL_THEN;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::ty::is_copy;
|
use clippy_utils::ty::is_copy;
|
||||||
use clippy_utils::{is_from_proc_macro, is_trait_method, match_def_path, peel_blocks};
|
use clippy_utils::{is_from_proc_macro, is_trait_method, match_def_path, peel_blocks};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -42,9 +42,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
|
|||||||
.iter()
|
.iter()
|
||||||
.filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
|
.filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
|
||||||
.count()
|
.count()
|
||||||
&& let Some(param_snippet) = snippet_opt(cx, param.span)
|
&& let Some(param_snippet) = param.span.get_source_text(cx)
|
||||||
&& let Some(filter) = snippet_opt(cx, recv.span)
|
&& let Some(filter) = recv.span.get_source_text(cx)
|
||||||
&& let Some(map) = snippet_opt(cx, then_body.span)
|
&& let Some(map) = then_body.span.get_source_text(cx)
|
||||||
{
|
{
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::ty::implements_trait;
|
use clippy_utils::ty::implements_trait;
|
||||||
use clippy_utils::{is_path_diagnostic_item, sugg};
|
use clippy_utils::{is_path_diagnostic_item, sugg};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -39,7 +39,7 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
let call_site = expr.span.source_callsite();
|
let call_site = expr.span.source_callsite();
|
||||||
if let Some(snippet) = snippet_opt(cx, call_site)
|
if let Some(snippet) = call_site.get_source_text(cx)
|
||||||
&& let snippet_split = snippet.split("::").collect::<Vec<_>>()
|
&& let snippet_split = snippet.split("::").collect::<Vec<_>>()
|
||||||
&& let Some((_, elements)) = snippet_split.split_last()
|
&& let Some((_, elements)) = snippet_split.split_last()
|
||||||
{
|
{
|
||||||
|
@ -74,7 +74,7 @@ pub(super) fn check<'tcx>(
|
|||||||
"&"
|
"&"
|
||||||
};
|
};
|
||||||
|
|
||||||
diag.span_suggestion_with_style(
|
diag.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
"using `[]` is clearer and more concise",
|
"using `[]` is clearer and more concise",
|
||||||
format!(
|
format!(
|
||||||
@ -82,7 +82,6 @@ pub(super) fn check<'tcx>(
|
|||||||
snippet_with_applicability(cx, recv.span, "..", &mut applicability)
|
snippet_with_applicability(cx, recv.span, "..", &mut applicability)
|
||||||
),
|
),
|
||||||
applicability,
|
applicability,
|
||||||
rustc_errors::SuggestionStyle::ShowAlways,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! Lint for `c.is_digit(10)`
|
|
||||||
|
|
||||||
use super::IS_DIGIT_ASCII_RADIX;
|
use super::IS_DIGIT_ASCII_RADIX;
|
||||||
use clippy_config::msrvs::{self, Msrv};
|
use clippy_config::msrvs::{self, Msrv};
|
||||||
use clippy_utils::consts::{ConstEvalCtxt, FullInt};
|
use clippy_utils::consts::{ConstEvalCtxt, FullInt};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::expr_or_init;
|
use clippy_utils::expr_or_init;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a
|
|||||||
join_arg.span,
|
join_arg.span,
|
||||||
"argument to `Path::join` starts with a path separator",
|
"argument to `Path::join` starts with a path separator",
|
||||||
|diag| {
|
|diag| {
|
||||||
let arg_str = snippet_opt(cx, spanned.span).unwrap_or_else(|| "..".to_string());
|
let arg_str = snippet(cx, spanned.span, "..");
|
||||||
|
|
||||||
let no_separator = if sym_str.starts_with('/') {
|
let no_separator = if sym_str.starts_with('/') {
|
||||||
arg_str.replacen('/', "", 1)
|
arg_str.replacen('/', "", 1)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
|
use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
|
use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -23,11 +23,11 @@ pub(super) fn check<'tcx>(
|
|||||||
&& let ExprKind::Call(err_path, [err_arg]) = or_expr.kind
|
&& let ExprKind::Call(err_path, [err_arg]) = or_expr.kind
|
||||||
&& is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr)
|
&& is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr)
|
||||||
&& is_ok_wrapping(cx, map_expr)
|
&& is_ok_wrapping(cx, map_expr)
|
||||||
&& let Some(recv_snippet) = snippet_opt(cx, recv.span)
|
&& let Some(recv_snippet) = recv.span.get_source_text(cx)
|
||||||
&& let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span)
|
&& let Some(err_arg_snippet) = err_arg.span.get_source_text(cx)
|
||||||
&& let Some(indent) = indent_of(cx, expr.span)
|
&& let Some(indent) = indent_of(cx, expr.span)
|
||||||
{
|
{
|
||||||
let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.into(), true, Some(indent + 4));
|
let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.as_str().into(), true, Some(indent + 4));
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
MANUAL_OK_OR,
|
MANUAL_OK_OR,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_config::msrvs::{self, Msrv};
|
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::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::ty::implements_trait;
|
use clippy_utils::ty::implements_trait;
|
||||||
use clippy_utils::{is_from_proc_macro, is_trait_method};
|
use clippy_utils::{is_from_proc_macro, is_trait_method};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -31,13 +31,15 @@ pub(super) fn check<'tcx>(
|
|||||||
&& let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id)
|
&& let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id)
|
||||||
&& let ExprKind::Closure(closure) = acc.kind
|
&& let ExprKind::Closure(closure) = acc.kind
|
||||||
&& !is_from_proc_macro(cx, expr)
|
&& !is_from_proc_macro(cx, expr)
|
||||||
&& let Some(args_snip) = closure.fn_arg_span.and_then(|fn_arg_span| snippet_opt(cx, fn_arg_span))
|
&& let Some(args_snip) = closure
|
||||||
|
.fn_arg_span
|
||||||
|
.and_then(|fn_arg_span| fn_arg_span.get_source_text(cx))
|
||||||
{
|
{
|
||||||
let init_snip = rest
|
let init_snip = rest
|
||||||
.is_empty()
|
.is_empty()
|
||||||
.then_some(first.span)
|
.then_some(first.span)
|
||||||
.and_then(|span| snippet_opt(cx, span))
|
.and_then(|span| span.get_source_text(cx))
|
||||||
.unwrap_or("...".to_owned());
|
.map_or_else(|| "...".to_owned(), |src| src.to_owned());
|
||||||
|
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
|
@ -2702,10 +2702,10 @@ declare_clippy_lint! {
|
|||||||
/// }
|
/// }
|
||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// After:
|
/// After:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use std::{fmt, num::ParseIntError};
|
/// use std::{fmt, num::ParseIntError};
|
||||||
///
|
///
|
||||||
/// #[derive(Debug)]
|
/// #[derive(Debug)]
|
||||||
|
@ -7,7 +7,7 @@ use rustc_span::Span;
|
|||||||
use super::utils::get_last_chain_binding_hir_id;
|
use super::utils::get_last_chain_binding_hir_id;
|
||||||
use super::NEEDLESS_CHARACTER_ITERATION;
|
use super::NEEDLESS_CHARACTER_ITERATION;
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::{match_def_path, path_to_local_id, peel_blocks};
|
use clippy_utils::{match_def_path, path_to_local_id, peel_blocks};
|
||||||
|
|
||||||
fn peels_expr_ref<'a, 'tcx>(mut expr: &'a Expr<'tcx>) -> &'a Expr<'tcx> {
|
fn peels_expr_ref<'a, 'tcx>(mut expr: &'a Expr<'tcx>) -> &'a Expr<'tcx> {
|
||||||
@ -35,7 +35,7 @@ fn handle_expr(
|
|||||||
&& path_to_local_id(receiver, first_param)
|
&& path_to_local_id(receiver, first_param)
|
||||||
&& let char_arg_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs()
|
&& let char_arg_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs()
|
||||||
&& *char_arg_ty.kind() == ty::Char
|
&& *char_arg_ty.kind() == ty::Char
|
||||||
&& let Some(snippet) = snippet_opt(cx, before_chars)
|
&& let Some(snippet) = before_chars.get_source_text(cx)
|
||||||
{
|
{
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
@ -79,7 +79,7 @@ fn handle_expr(
|
|||||||
&& let Some(fn_def_id) = cx.qpath_res(&path, fn_path.hir_id).opt_def_id()
|
&& let Some(fn_def_id) = cx.qpath_res(&path, fn_path.hir_id).opt_def_id()
|
||||||
&& match_def_path(cx, fn_def_id, &["core", "char", "methods", "<impl char>", "is_ascii"])
|
&& match_def_path(cx, fn_def_id, &["core", "char", "methods", "<impl char>", "is_ascii"])
|
||||||
&& path_to_local_id(peels_expr_ref(arg), first_param)
|
&& path_to_local_id(peels_expr_ref(arg), first_param)
|
||||||
&& let Some(snippet) = snippet_opt(cx, before_chars)
|
&& let Some(snippet) = before_chars.get_source_text(cx)
|
||||||
{
|
{
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
|
@ -2,7 +2,7 @@ use super::NEEDLESS_COLLECT;
|
|||||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
|
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
|
||||||
use clippy_utils::source::{snippet, snippet_with_applicability};
|
use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection};
|
use clippy_utils::ty::{get_type_diagnostic_name, make_normalized_projection, make_projection};
|
||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local, path_to_local_id,
|
can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local, path_to_local_id,
|
||||||
CaptureKind,
|
CaptureKind,
|
||||||
@ -88,9 +88,10 @@ pub(super) fn check<'tcx>(
|
|||||||
Node::LetStmt(l) => {
|
Node::LetStmt(l) => {
|
||||||
if let PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None) = l.pat.kind
|
if let PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None) = l.pat.kind
|
||||||
&& let ty = cx.typeck_results().expr_ty(collect_expr)
|
&& let ty = cx.typeck_results().expr_ty(collect_expr)
|
||||||
&& [sym::Vec, sym::VecDeque, sym::BinaryHeap, sym::LinkedList]
|
&& matches!(
|
||||||
.into_iter()
|
get_type_diagnostic_name(cx, ty),
|
||||||
.any(|item| is_type_diagnostic_item(cx, ty, item))
|
Some(sym::Vec | sym::VecDeque | sym::BinaryHeap | sym::LinkedList)
|
||||||
|
)
|
||||||
&& let iter_ty = cx.typeck_results().expr_ty(iter_expr)
|
&& let iter_ty = cx.typeck_results().expr_ty(iter_expr)
|
||||||
&& let Some(block) = get_enclosing_block(cx, l.hir_id)
|
&& let Some(block) = get_enclosing_block(cx, l.hir_id)
|
||||||
&& let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty))
|
&& let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty))
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::path_res;
|
use clippy_utils::path_res;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::usage::local_used_after_expr;
|
use clippy_utils::usage::local_used_after_expr;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -32,7 +32,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, name
|
|||||||
expr.span,
|
expr.span,
|
||||||
"derefed type is same as origin",
|
"derefed type is same as origin",
|
||||||
"try",
|
"try",
|
||||||
snippet_opt(cx, recv.span).unwrap(),
|
recv.span.get_source_text(cx).unwrap().to_owned(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_config::msrvs::{self, Msrv};
|
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::source::snippet_opt;
|
use clippy_utils::source::SpanRangeExt;
|
||||||
use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local};
|
use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_ast::LitKind;
|
use rustc_ast::LitKind;
|
||||||
@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(
|
|||||||
_ => return,
|
_ => return,
|
||||||
}
|
}
|
||||||
&& !is_from_proc_macro(cx, expr)
|
&& !is_from_proc_macro(cx, expr)
|
||||||
&& let Some(scrutinee_snip) = snippet_opt(cx, scrutinee.span)
|
&& let Some(scrutinee_snip) = scrutinee.span.get_source_text(cx)
|
||||||
{
|
{
|
||||||
// Normalize the char using `map` so `join` doesn't use `Display`, if we don't then
|
// Normalize the char using `map` so `join` doesn't use `Display`, if we don't then
|
||||||
// something like `r"\"` will become `'\'`, which is of course invalid
|
// something like `r"\"` will become `'\'`, which is of course invalid
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user