mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 07:04:18 +00:00
Merge commit '3ae8faff4d46ad92f194c2a4b941c3152a701b31' into clippyup
This commit is contained in:
parent
91aa821745
commit
6c27482115
189 changed files with 2372 additions and 1310 deletions
|
@ -2493,6 +2493,7 @@ Released 2018-09-13
|
|||
[`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
|
||||
[`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
|
||||
[`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
|
||||
[`manual_str_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat
|
||||
[`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip
|
||||
[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
|
||||
[`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or
|
||||
|
@ -2622,6 +2623,7 @@ Released 2018-09-13
|
|||
[`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate
|
||||
[`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing
|
||||
[`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
|
||||
[`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
|
||||
[`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
|
||||
[`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
|
||||
[`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
|
||||
|
@ -2670,6 +2672,7 @@ Released 2018-09-13
|
|||
[`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map
|
||||
[`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl
|
||||
[`suspicious_operation_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_operation_groupings
|
||||
[`suspicious_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_splitn
|
||||
[`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting
|
||||
[`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments
|
||||
[`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright 2014-2020 The Rust Project Developers
|
||||
Copyright 2014-2021 The Rust Project Developers
|
||||
|
||||
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
|
|
|
@ -33,12 +33,13 @@ tempfile = { version = "3.1.0", optional = true }
|
|||
cargo_metadata = "0.12"
|
||||
compiletest_rs = { version = "0.6.0", features = ["tmp"] }
|
||||
tester = "0.9"
|
||||
clippy-mini-macro-test = { version = "0.2", path = "mini-macro" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
derive-new = "0.5"
|
||||
regex = "1.4"
|
||||
quote = "1"
|
||||
syn = { version = "1", features = ["full"] }
|
||||
# This is used by the `collect-metadata` alias.
|
||||
filetime = "0.2"
|
||||
|
||||
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
|
||||
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
|
||||
|
|
|
@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work.
|
|||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014-2020 The Rust Project Developers
|
||||
Copyright 2014-2021 The Rust Project Developers
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2014-2020 The Rust Project Developers
|
||||
Copyright (c) 2014-2021 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
|
|
|
@ -147,6 +147,7 @@ Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml
|
|||
value` mapping eg.
|
||||
|
||||
```toml
|
||||
avoid-breaking-exported-api = false
|
||||
blacklisted-names = ["toto", "tata", "titi"]
|
||||
cognitive-complexity-threshold = 30
|
||||
```
|
||||
|
@ -236,7 +237,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT
|
|||
|
||||
## License
|
||||
|
||||
Copyright 2014-2020 The Rust Project Developers
|
||||
Copyright 2014-2021 The Rust Project Developers
|
||||
|
||||
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license
|
||||
|
|
2
build.rs
2
build.rs
|
@ -14,6 +14,6 @@ fn main() {
|
|||
);
|
||||
println!(
|
||||
"cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
|
||||
rustc_tools_util::get_channel().unwrap_or_default()
|
||||
rustc_tools_util::get_channel()
|
||||
);
|
||||
}
|
||||
|
|
1
clippy.toml
Normal file
1
clippy.toml
Normal file
|
@ -0,0 +1 @@
|
|||
avoid-breaking-exported-api = false
|
|
@ -3,9 +3,8 @@ use rustc_lint::{LateContext, LateLintPass};
|
|||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
use crate::consts::{constant, Constant};
|
||||
|
||||
use clippy_utils::comparisons::{normalize_comparison, Rel};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::is_isize_or_usize;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::constant_simple;
|
||||
use clippy_utils::consts::constant_simple;
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::{is_direct_expn_of, is_expn_of, match_panic_call};
|
||||
|
@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
|
|||
&format!("`assert!(false, {})` should probably be replaced", panic_message),
|
||||
None,
|
||||
&format!("use `panic!({})` or `unreachable!({})`", panic_message, panic_message),
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
if let Some(debug_assert_span) = is_expn_of(e.span, "debug_assert") {
|
||||
|
|
|
@ -273,7 +273,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
|
|||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
if is_relevant_item(cx, item) {
|
||||
check_attrs(cx, item.span, item.ident.name, attrs)
|
||||
check_attrs(cx, item.span, item.ident.name, attrs);
|
||||
}
|
||||
match item.kind {
|
||||
ItemKind::ExternCrate(..) | ItemKind::Use(..) => {
|
||||
|
@ -343,13 +343,13 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
|
|||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
||||
if is_relevant_impl(cx, item) {
|
||||
check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()))
|
||||
check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
|
||||
if is_relevant_trait(cx, item) {
|
||||
check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()))
|
||||
check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use if_chain::if_chain;
|
||||
|
@ -115,9 +115,9 @@ impl<'tcx> LateLintPass<'tcx> for BitMask {
|
|||
if let ExprKind::Binary(cmp, left, right) = &e.kind {
|
||||
if cmp.node.is_comparison() {
|
||||
if let Some(cmp_opt) = fetch_int_literal(cx, right) {
|
||||
check_compare(cx, left, cmp.node, cmp_opt, e.span)
|
||||
check_compare(cx, left, cmp.node, cmp_opt, e.span);
|
||||
} else if let Some(cmp_val) = fetch_int_literal(cx, left) {
|
||||
check_compare(cx, right, invert_cmp(cmp.node), cmp_val, e.span)
|
||||
check_compare(cx, right, invert_cmp(cmp.node), cmp_val, e.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ fn check_compare(cx: &LateContext<'_>, bit_op: &Expr<'_>, cmp_op: BinOpKind, cmp
|
|||
}
|
||||
fetch_int_literal(cx, right)
|
||||
.or_else(|| fetch_int_literal(cx, left))
|
||||
.map_or((), |mask| check_bit_mask(cx, op.node, cmp_op, mask, cmp_value, span))
|
||||
.map_or((), |mask| check_bit_mask(cx, op.node, cmp_op, mask, cmp_value, span));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool {
|
|||
_: Span,
|
||||
_: HirId,
|
||||
) {
|
||||
NonminimalBoolVisitor { cx }.visit_body(body)
|
||||
NonminimalBoolVisitor { cx }.visit_body(body);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
|
|||
Term(n) => {
|
||||
let terminal = self.terminals[n as usize];
|
||||
if let Some(str) = simplify_not(self.cx, terminal) {
|
||||
self.output.push_str(&str)
|
||||
self.output.push_str(&str);
|
||||
} else {
|
||||
self.output.push('!');
|
||||
let snip = snippet_opt(self.cx, terminal.span)?;
|
||||
|
@ -452,7 +452,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
|
|||
}
|
||||
match &e.kind {
|
||||
ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => {
|
||||
self.bool_expr(e)
|
||||
self.bool_expr(e);
|
||||
},
|
||||
ExprKind::Unary(UnOp::Not, inner) => {
|
||||
if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::{method_chain_args, sext};
|
||||
use if_chain::if_chain;
|
||||
|
|
|
@ -92,7 +92,7 @@ declare_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]);
|
|||
impl EarlyLintPass for CollapsibleIf {
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
|
||||
if !expr.span.from_expansion() {
|
||||
check_if(cx, expr)
|
||||
check_if(cx, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain {
|
|||
"`if` chain can be rewritten with `match`",
|
||||
None,
|
||||
"consider rewriting the `if` chain to use `cmp` and `match`",
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
pub use clippy_utils::consts::*;
|
|
@ -476,7 +476,7 @@ fn emit_branches_sharing_code_lint(
|
|||
}
|
||||
|
||||
suggestions.push(("end", span, suggestion.to_string()));
|
||||
add_expr_note = !cx.typeck_results().expr_ty(if_expr).is_unit()
|
||||
add_expr_note = !cx.typeck_results().expr_ty(if_expr).is_unit();
|
||||
}
|
||||
|
||||
let add_optional_msgs = |diag: &mut DiagnosticBuilder<'_>| {
|
||||
|
|
|
@ -181,9 +181,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
|
|||
match stmt.kind {
|
||||
StmtKind::Local(local) => {
|
||||
if local.ty.is_some() {
|
||||
self.ty_bounds.push(TyBound::Any)
|
||||
self.ty_bounds.push(TyBound::Any);
|
||||
} else {
|
||||
self.ty_bounds.push(TyBound::Nothing)
|
||||
self.ty_bounds.push(TyBound::Nothing);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -141,3 +141,22 @@ declare_deprecated_lint! {
|
|||
pub FILTER_MAP,
|
||||
"this lint has been replaced by `manual_filter_map`, a more specific lint"
|
||||
}
|
||||
|
||||
declare_deprecated_lint! {
|
||||
/// **What it does:** Nothing. This lint has been deprecated.
|
||||
///
|
||||
/// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which
|
||||
/// enables the `enum_variant_names` lint for public items.
|
||||
/// ```
|
||||
pub PUB_ENUM_VARIANT_NAMES,
|
||||
"set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items"
|
||||
}
|
||||
|
||||
declare_deprecated_lint! {
|
||||
/// **What it does:** Nothing. This lint has been deprecated.
|
||||
///
|
||||
/// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which
|
||||
/// enables the `wrong_self_conversion` lint for public items.
|
||||
pub WRONG_PUB_SELF_CONVENTION,
|
||||
"set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items"
|
||||
}
|
||||
|
|
|
@ -70,16 +70,16 @@ impl<'tcx> DoubleComparisons {
|
|||
#[rustfmt::skip]
|
||||
match (op, lkind, rkind) {
|
||||
(BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => {
|
||||
lint_double_comparison!(<=)
|
||||
lint_double_comparison!(<=);
|
||||
},
|
||||
(BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => {
|
||||
lint_double_comparison!(>=)
|
||||
lint_double_comparison!(>=);
|
||||
},
|
||||
(BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => {
|
||||
lint_double_comparison!(!=)
|
||||
lint_double_comparison!(!=);
|
||||
},
|
||||
(BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => {
|
||||
lint_double_comparison!(==)
|
||||
lint_double_comparison!(==);
|
||||
},
|
||||
_ => (),
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc_lint::{LateContext, LateLintPass};
|
|||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::Spanned;
|
||||
|
||||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::paths;
|
||||
|
||||
|
|
|
@ -469,7 +469,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
|
|||
let mut is_map_used = self.is_map_used;
|
||||
for arm in arms {
|
||||
if let Some(Guard::If(guard) | Guard::IfLet(_, guard)) = arm.guard {
|
||||
self.visit_non_tail_expr(guard)
|
||||
self.visit_non_tail_expr(guard);
|
||||
}
|
||||
is_map_used |= self.visit_cond_arm(arm.body);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! lint on C-like enums that are `repr(isize/usize)` and have values that
|
||||
//! don't fit into an `i32`
|
||||
|
||||
use crate::consts::{miri_to_const, Constant};
|
||||
use clippy_utils::consts::{miri_to_const, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
use clippy_utils::camel_case;
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||
use clippy_utils::source::is_present_in_source;
|
||||
use rustc_ast::ast::{EnumDef, Item, ItemKind, VisibilityKind};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
|
||||
use rustc_hir::{EnumDef, Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
@ -39,36 +39,6 @@ declare_clippy_lint! {
|
|||
"enums where all variants share a prefix/postfix"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Detects public enumeration variants that are
|
||||
/// prefixed or suffixed by the same characters.
|
||||
///
|
||||
/// **Why is this bad?** Public enumeration variant names should specify their variant,
|
||||
/// not repeat the enumeration name.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// pub enum Cake {
|
||||
/// BlackForestCake,
|
||||
/// HummingbirdCake,
|
||||
/// BattenbergCake,
|
||||
/// }
|
||||
/// ```
|
||||
/// Could be written as:
|
||||
/// ```rust
|
||||
/// pub enum Cake {
|
||||
/// BlackForest,
|
||||
/// Hummingbird,
|
||||
/// Battenberg,
|
||||
/// }
|
||||
/// ```
|
||||
pub PUB_ENUM_VARIANT_NAMES,
|
||||
pedantic,
|
||||
"public enums where all variants share a prefix/postfix"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Detects type names that are prefixed or suffixed by the
|
||||
/// containing module's name.
|
||||
|
@ -127,21 +97,22 @@ declare_clippy_lint! {
|
|||
pub struct EnumVariantNames {
|
||||
modules: Vec<(Symbol, String)>,
|
||||
threshold: u64,
|
||||
avoid_breaking_exported_api: bool,
|
||||
}
|
||||
|
||||
impl EnumVariantNames {
|
||||
#[must_use]
|
||||
pub fn new(threshold: u64) -> Self {
|
||||
pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self {
|
||||
Self {
|
||||
modules: Vec::new(),
|
||||
threshold,
|
||||
avoid_breaking_exported_api,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(EnumVariantNames => [
|
||||
ENUM_VARIANT_NAMES,
|
||||
PUB_ENUM_VARIANT_NAMES,
|
||||
MODULE_NAME_REPETITIONS,
|
||||
MODULE_INCEPTION
|
||||
]);
|
||||
|
@ -167,33 +138,42 @@ fn partial_rmatch(post: &str, name: &str) -> usize {
|
|||
}
|
||||
|
||||
fn check_variant(
|
||||
cx: &EarlyContext<'_>,
|
||||
cx: &LateContext<'_>,
|
||||
threshold: u64,
|
||||
def: &EnumDef,
|
||||
def: &EnumDef<'_>,
|
||||
item_name: &str,
|
||||
item_name_chars: usize,
|
||||
span: Span,
|
||||
lint: &'static Lint,
|
||||
) {
|
||||
if (def.variants.len() as u64) < threshold {
|
||||
return;
|
||||
}
|
||||
for var in &def.variants {
|
||||
for var in def.variants {
|
||||
let name = var.ident.name.as_str();
|
||||
if partial_match(item_name, &name) == item_name_chars
|
||||
&& name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
|
||||
&& name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
|
||||
{
|
||||
span_lint(cx, lint, var.span, "variant name starts with the enum's name");
|
||||
span_lint(
|
||||
cx,
|
||||
ENUM_VARIANT_NAMES,
|
||||
var.span,
|
||||
"variant name starts with the enum's name",
|
||||
);
|
||||
}
|
||||
if partial_rmatch(item_name, &name) == item_name_chars {
|
||||
span_lint(cx, lint, var.span, "variant name ends with the enum's name");
|
||||
span_lint(
|
||||
cx,
|
||||
ENUM_VARIANT_NAMES,
|
||||
var.span,
|
||||
"variant name ends with the enum's name",
|
||||
);
|
||||
}
|
||||
}
|
||||
let first = &def.variants[0].ident.name.as_str();
|
||||
let mut pre = &first[..camel_case::until(&*first)];
|
||||
let mut post = &first[camel_case::from(&*first)..];
|
||||
for var in &def.variants {
|
||||
for var in def.variants {
|
||||
let name = var.ident.name.as_str();
|
||||
|
||||
let pre_match = partial_match(pre, &name);
|
||||
|
@ -226,7 +206,7 @@ fn check_variant(
|
|||
};
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
lint,
|
||||
ENUM_VARIANT_NAMES,
|
||||
span,
|
||||
&format!("all variants have the same {}fix: `{}`", what, value),
|
||||
None,
|
||||
|
@ -261,14 +241,14 @@ fn to_camel_case(item_name: &str) -> String {
|
|||
s
|
||||
}
|
||||
|
||||
impl EarlyLintPass for EnumVariantNames {
|
||||
fn check_item_post(&mut self, _cx: &EarlyContext<'_>, _item: &Item) {
|
||||
impl LateLintPass<'_> for EnumVariantNames {
|
||||
fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) {
|
||||
let last = self.modules.pop();
|
||||
assert!(last.is_some());
|
||||
}
|
||||
|
||||
#[allow(clippy::similar_names)]
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
let item_name = item.ident.name.as_str();
|
||||
let item_name_chars = item_name.chars().count();
|
||||
let item_camel = to_camel_case(&item_name);
|
||||
|
@ -286,7 +266,7 @@ impl EarlyLintPass for EnumVariantNames {
|
|||
);
|
||||
}
|
||||
}
|
||||
if item.vis.kind.is_pub() {
|
||||
if item.vis.node.is_pub() {
|
||||
let matching = partial_match(mod_camel, &item_camel);
|
||||
let rmatching = partial_rmatch(mod_camel, &item_camel);
|
||||
let nchars = mod_camel.chars().count();
|
||||
|
@ -317,11 +297,9 @@ impl EarlyLintPass for EnumVariantNames {
|
|||
}
|
||||
}
|
||||
if let ItemKind::Enum(ref def, _) = item.kind {
|
||||
let lint = match item.vis.kind {
|
||||
VisibilityKind::Public => PUB_ENUM_VARIANT_NAMES,
|
||||
_ => ENUM_VARIANT_NAMES,
|
||||
};
|
||||
check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span, lint);
|
||||
if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.hir_id())) {
|
||||
check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span);
|
||||
}
|
||||
}
|
||||
self.modules.push((item.ident.name, item_camel));
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
|
|||
vec![(left.span, lsnip), (right.span, rsnip)],
|
||||
);
|
||||
},
|
||||
)
|
||||
);
|
||||
} else if lcpy
|
||||
&& !rcpy
|
||||
&& implements_trait(cx, lty, trait_id, &[cx.typeck_results().expr_ty(right).into()])
|
||||
|
@ -175,7 +175,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
|
|||
Applicability::MaybeIncorrect, // FIXME #2597
|
||||
);
|
||||
},
|
||||
)
|
||||
);
|
||||
} else if !lcpy
|
||||
&& rcpy
|
||||
&& implements_trait(cx, cx.typeck_results().expr_ty(left), trait_id, &[rty.into()])
|
||||
|
@ -194,7 +194,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
|
|||
Applicability::MaybeIncorrect, // FIXME #2597
|
||||
);
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
// &foo == bar
|
||||
|
@ -218,7 +218,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
|
|||
Applicability::MaybeIncorrect, // FIXME #2597
|
||||
);
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
// foo == &bar
|
||||
|
@ -236,7 +236,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
|
|||
rsnip,
|
||||
Applicability::MaybeIncorrect, // FIXME #2597
|
||||
);
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use clippy_utils::consts::{constant_simple, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::Span;
|
||||
|
||||
use crate::consts::{constant_simple, Constant};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for erasing operations, e.g., `x * 0`.
|
||||
///
|
||||
|
|
|
@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
|
|||
for arg in args {
|
||||
// skip `foo(macro!())`
|
||||
if arg.span.ctxt() == expr.span.ctxt() {
|
||||
check_closure(cx, arg)
|
||||
check_closure(cx, arg);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -92,17 +92,19 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
let ex = &body.value;
|
||||
|
||||
if ex.span.ctxt() != expr.span.ctxt() {
|
||||
if let Some(VecArgs::Vec(&[])) = higher::vec_macro(cx, ex) {
|
||||
// replace `|| vec![]` with `Vec::new`
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
REDUNDANT_CLOSURE,
|
||||
expr.span,
|
||||
"redundant closure",
|
||||
"replace the closure with `Vec::new`",
|
||||
"std::vec::Vec::new".into(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if decl.inputs.is_empty() {
|
||||
if let Some(VecArgs::Vec(&[])) = higher::vec_macro(cx, ex) {
|
||||
// replace `|| vec![]` with `Vec::new`
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
REDUNDANT_CLOSURE,
|
||||
expr.span,
|
||||
"redundant closure",
|
||||
"replace the closure with `Vec::new`",
|
||||
"std::vec::Vec::new".into(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
// skip `foo(|| macro!())`
|
||||
return;
|
||||
|
@ -188,9 +190,10 @@ fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_a
|
|||
cx.tcx.impl_of_method(method_def_id).and_then(|_| {
|
||||
//a type may implicitly implement other type's methods (e.g. Deref)
|
||||
if match_types(expected_type_of_self, actual_type_of_self) {
|
||||
return Some(get_type_name(cx, actual_type_of_self));
|
||||
Some(get_type_name(cx, actual_type_of_self))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
|
|||
self.visit_expr(e);
|
||||
for arm in arms {
|
||||
if let Some(Guard::If(if_expr)) = arm.guard {
|
||||
self.visit_expr(if_expr)
|
||||
self.visit_expr(if_expr);
|
||||
}
|
||||
// make sure top level arm expressions aren't linted
|
||||
self.maybe_walk_expr(&*arm.body);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{
|
||||
use clippy_utils::consts::{
|
||||
constant, constant_simple, Constant,
|
||||
Constant::{Int, F32, F64},
|
||||
};
|
||||
|
|
|
@ -240,7 +240,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
|
|||
}
|
||||
},
|
||||
Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => {
|
||||
self.mutates_static |= is_mutated_static(target)
|
||||
self.mutates_static |= is_mutated_static(target);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
|
|||
self.cx,
|
||||
NOT_UNSAFE_PTR_ARG_DEREF,
|
||||
ptr.span,
|
||||
"this public function dereferences a raw pointer but is not marked `unsafe`",
|
||||
"this public function might dereference a raw pointer but is not marked `unsafe`",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use rustc_middle::lint::in_external_macro;
|
|||
use rustc_span::Span;
|
||||
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
|
||||
use super::TOO_MANY_LINES;
|
||||
|
||||
|
@ -13,15 +13,25 @@ pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'
|
|||
return;
|
||||
}
|
||||
|
||||
let code_snippet = snippet(cx, body.value.span, "..");
|
||||
let code_snippet = match snippet_opt(cx, body.value.span) {
|
||||
Some(s) => s,
|
||||
_ => return,
|
||||
};
|
||||
let mut line_count: u64 = 0;
|
||||
let mut in_comment = false;
|
||||
let mut code_in_line;
|
||||
|
||||
// Skip the surrounding function decl.
|
||||
let start_brace_idx = code_snippet.find('{').map_or(0, |i| i + 1);
|
||||
let end_brace_idx = code_snippet.rfind('}').unwrap_or_else(|| code_snippet.len());
|
||||
let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines();
|
||||
let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
|
||||
&& code_snippet.as_bytes().first().copied() == Some(b'{')
|
||||
&& code_snippet.as_bytes().last().copied() == Some(b'}')
|
||||
{
|
||||
// Removing the braces from the enclosing block
|
||||
&code_snippet[1..code_snippet.len() - 1]
|
||||
} else {
|
||||
&code_snippet
|
||||
}
|
||||
.trim() // Remove leading and trailing blank lines
|
||||
.lines();
|
||||
|
||||
for mut line in function_lines {
|
||||
code_in_line = false;
|
||||
|
@ -63,6 +73,6 @@ pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'
|
|||
"this function has too many lines ({}/{})",
|
||||
line_count, too_many_lines_threshold
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|
|||
));
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use rustc_middle::ty;
|
|||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::Span;
|
||||
|
||||
use crate::consts::{constant_simple, Constant};
|
||||
use clippy_utils::consts::{constant_simple, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::{clip, unsext};
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ fn lint_break(cx: &LateContext<'_>, break_span: Span, expr_span: Span) {
|
|||
"change `break` to `return` as shown",
|
||||
format!("return {}", snip),
|
||||
app,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! lint on indexing and slicing operations
|
||||
|
||||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||
use clippy_utils::higher;
|
||||
use rustc_ast::ast::RangeLimits;
|
||||
|
|
|
@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for InfiniteIter {
|
|||
return;
|
||||
},
|
||||
};
|
||||
span_lint(cx, lint, expr.span, msg)
|
||||
span_lint(cx, lint, expr.span, msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
|
|||
use rustc_span::Span;
|
||||
use rustc_target::abi::LayoutOf;
|
||||
|
||||
use crate::consts::{constant, Constant};
|
||||
|
||||
use clippy_utils::comparisons::Rel;
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::{comparisons, sext};
|
||||
|
@ -177,7 +176,7 @@ fn upcast_comparison_bounds_err<'tcx>(
|
|||
},
|
||||
Rel::Eq | Rel::Ne => unreachable!(),
|
||||
} {
|
||||
err_upcast_comparison(cx, span, lhs, true)
|
||||
err_upcast_comparison(cx, span, lhs, true);
|
||||
} else if match rel {
|
||||
Rel::Lt => {
|
||||
if invert {
|
||||
|
@ -195,7 +194,7 @@ fn upcast_comparison_bounds_err<'tcx>(
|
|||
},
|
||||
Rel::Eq | Rel::Ne => unreachable!(),
|
||||
} {
|
||||
err_upcast_comparison(cx, span, lhs, false)
|
||||
err_upcast_comparison(cx, span, lhs, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -380,9 +380,9 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
|
|||
}
|
||||
}
|
||||
|
||||
check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to)
|
||||
check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to);
|
||||
} else {
|
||||
check_empty_expr(cx, span, method, lit, op)
|
||||
check_empty_expr(cx, span, method, lit, op);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
|
|||
None,
|
||||
"consider using an underscore-prefixed named \
|
||||
binding or dropping explicitly with `std::mem::drop`"
|
||||
)
|
||||
);
|
||||
} else if init_ty.needs_drop(cx.tcx, cx.param_env) {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
|
@ -145,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
|
|||
None,
|
||||
"consider using an underscore-prefixed named \
|
||||
binding or dropping explicitly with `std::mem::drop`"
|
||||
)
|
||||
);
|
||||
} else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
|
@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
|
|||
"non-binding let on an expression with `#[must_use]` type",
|
||||
None,
|
||||
"consider explicitly using expression value"
|
||||
)
|
||||
);
|
||||
} else if is_must_use_func_call(cx, init) {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
|
@ -163,7 +163,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
|
|||
"non-binding let on a result of a `#[must_use]` function",
|
||||
None,
|
||||
"consider explicitly using function result"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,9 @@ extern crate rustc_target;
|
|||
extern crate rustc_trait_selection;
|
||||
extern crate rustc_typeck;
|
||||
|
||||
#[macro_use]
|
||||
extern crate clippy_utils;
|
||||
|
||||
use clippy_utils::parse_msrv;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_lint::LintId;
|
||||
|
@ -145,25 +148,9 @@ macro_rules! declare_clippy_lint {
|
|||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! sym {
|
||||
( $($x:tt)* ) => { clippy_utils::sym!($($x)*) }
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! unwrap_cargo_metadata {
|
||||
( $($x:tt)* ) => { clippy_utils::unwrap_cargo_metadata!($($x)*) }
|
||||
}
|
||||
|
||||
macro_rules! extract_msrv_attr {
|
||||
( $($x:tt)* ) => { clippy_utils::extract_msrv_attr!($($x)*); }
|
||||
}
|
||||
|
||||
mod consts;
|
||||
#[macro_use]
|
||||
mod utils;
|
||||
#[cfg(feature = "metadata-collector-lint")]
|
||||
mod deprecated_lints;
|
||||
mod utils;
|
||||
|
||||
// begin lints modules, do not remove this comment, it’s used in `update_lints`
|
||||
mod absurd_extreme_comparisons;
|
||||
|
@ -405,7 +392,6 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn read_conf(sess: &Session) -> Conf {
|
||||
use std::path::Path;
|
||||
let file_name = match utils::conf::lookup_conf_file() {
|
||||
Ok(Some(path)) => path,
|
||||
Ok(None) => return Conf::default(),
|
||||
|
@ -416,16 +402,6 @@ pub fn read_conf(sess: &Session) -> Conf {
|
|||
},
|
||||
};
|
||||
|
||||
let file_name = if file_name.is_relative() {
|
||||
sess.local_crate_source_file
|
||||
.as_deref()
|
||||
.and_then(Path::parent)
|
||||
.unwrap_or_else(|| Path::new(""))
|
||||
.join(file_name)
|
||||
} else {
|
||||
file_name
|
||||
};
|
||||
|
||||
let TryConf { conf, errors } = utils::conf::read(&file_name);
|
||||
// all conf errors are non-fatal, we just use the default conf in case of error
|
||||
for error in errors {
|
||||
|
@ -505,6 +481,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
"clippy::filter_map",
|
||||
"this lint has been replaced by `manual_filter_map`, a more specific lint",
|
||||
);
|
||||
store.register_removed(
|
||||
"clippy::pub_enum_variant_names",
|
||||
"set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items",
|
||||
);
|
||||
store.register_removed(
|
||||
"clippy::wrong_pub_self_convention",
|
||||
"set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items",
|
||||
);
|
||||
// end deprecated lints, do not remove this comment, it’s used in `update_lints`
|
||||
|
||||
// begin register lints, do not remove this comment, it’s used in `update_lints`
|
||||
|
@ -618,7 +602,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
enum_variants::ENUM_VARIANT_NAMES,
|
||||
enum_variants::MODULE_INCEPTION,
|
||||
enum_variants::MODULE_NAME_REPETITIONS,
|
||||
enum_variants::PUB_ENUM_VARIANT_NAMES,
|
||||
eq_op::EQ_OP,
|
||||
eq_op::OP_REF,
|
||||
erasing_op::ERASING_OP,
|
||||
|
@ -779,6 +762,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
methods::MANUAL_FILTER_MAP,
|
||||
methods::MANUAL_FIND_MAP,
|
||||
methods::MANUAL_SATURATING_ARITHMETIC,
|
||||
methods::MANUAL_STR_REPEAT,
|
||||
methods::MAP_COLLECT_RESULT_UNIT,
|
||||
methods::MAP_FLATTEN,
|
||||
methods::MAP_UNWRAP_OR,
|
||||
|
@ -796,13 +780,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
methods::SKIP_WHILE_NEXT,
|
||||
methods::STRING_EXTEND_CHARS,
|
||||
methods::SUSPICIOUS_MAP,
|
||||
methods::SUSPICIOUS_SPLITN,
|
||||
methods::UNINIT_ASSUMED_INIT,
|
||||
methods::UNNECESSARY_FILTER_MAP,
|
||||
methods::UNNECESSARY_FOLD,
|
||||
methods::UNNECESSARY_LAZY_EVALUATIONS,
|
||||
methods::UNWRAP_USED,
|
||||
methods::USELESS_ASREF,
|
||||
methods::WRONG_PUB_SELF_CONVENTION,
|
||||
methods::WRONG_SELF_CONVENTION,
|
||||
methods::ZST_OFFSET,
|
||||
minmax::MIN_MAX,
|
||||
|
@ -841,6 +825,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
needless_bool::BOOL_COMPARISON,
|
||||
needless_bool::NEEDLESS_BOOL,
|
||||
needless_borrow::NEEDLESS_BORROW,
|
||||
needless_borrow::REF_BINDING_TO_REFERENCE,
|
||||
needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
|
||||
needless_continue::NEEDLESS_CONTINUE,
|
||||
needless_for_each::NEEDLESS_FOR_EACH,
|
||||
|
@ -995,291 +980,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
]);
|
||||
// end register lints, do not remove this comment, it’s used in `update_lints`
|
||||
|
||||
// all the internal lints
|
||||
#[cfg(feature = "internal-lints")]
|
||||
{
|
||||
store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal);
|
||||
store.register_early_pass(|| box utils::internal_lints::ProduceIce);
|
||||
store.register_late_pass(|| box utils::inspector::DeepCodeInspector);
|
||||
store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls);
|
||||
store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
|
||||
store.register_late_pass(|| box utils::internal_lints::IfChainStyle);
|
||||
store.register_late_pass(|| box utils::internal_lints::InvalidPaths);
|
||||
store.register_late_pass(|| box utils::internal_lints::InterningDefinedSymbol::default());
|
||||
store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default());
|
||||
store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
|
||||
store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass);
|
||||
}
|
||||
#[cfg(feature = "metadata-collector-lint")]
|
||||
{
|
||||
if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
|
||||
store.register_late_pass(|| box utils::internal_lints::metadata_collector::MetadataCollector::new());
|
||||
}
|
||||
}
|
||||
|
||||
store.register_late_pass(|| box utils::author::Author);
|
||||
store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
|
||||
store.register_late_pass(|| box serde_api::SerdeApi);
|
||||
let vec_box_size_threshold = conf.vec_box_size_threshold;
|
||||
let type_complexity_threshold = conf.type_complexity_threshold;
|
||||
store.register_late_pass(move || box types::Types::new(vec_box_size_threshold, type_complexity_threshold));
|
||||
store.register_late_pass(|| box booleans::NonminimalBool);
|
||||
store.register_late_pass(|| box needless_bitwise_bool::NeedlessBitwiseBool);
|
||||
store.register_late_pass(|| box eq_op::EqOp);
|
||||
store.register_late_pass(|| box enum_clike::UnportableVariant);
|
||||
store.register_late_pass(|| box float_literal::FloatLiteral);
|
||||
let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
|
||||
store.register_late_pass(move || box bit_mask::BitMask::new(verbose_bit_mask_threshold));
|
||||
store.register_late_pass(|| box ptr::Ptr);
|
||||
store.register_late_pass(|| box ptr_eq::PtrEq);
|
||||
store.register_late_pass(|| box needless_bool::NeedlessBool);
|
||||
store.register_late_pass(|| box needless_bool::BoolComparison);
|
||||
store.register_late_pass(|| box needless_for_each::NeedlessForEach);
|
||||
store.register_late_pass(|| box approx_const::ApproxConstant);
|
||||
store.register_late_pass(|| box misc::MiscLints);
|
||||
store.register_late_pass(|| box eta_reduction::EtaReduction);
|
||||
store.register_late_pass(|| box identity_op::IdentityOp);
|
||||
store.register_late_pass(|| box erasing_op::ErasingOp);
|
||||
store.register_late_pass(|| box mut_mut::MutMut);
|
||||
store.register_late_pass(|| box mut_reference::UnnecessaryMutPassed);
|
||||
store.register_late_pass(|| box len_zero::LenZero);
|
||||
store.register_late_pass(|| box attrs::Attributes);
|
||||
store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions);
|
||||
store.register_late_pass(|| box collapsible_match::CollapsibleMatch);
|
||||
store.register_late_pass(|| box unicode::Unicode);
|
||||
store.register_late_pass(|| box unit_return_expecting_ord::UnitReturnExpectingOrd);
|
||||
store.register_late_pass(|| box strings::StringAdd);
|
||||
store.register_late_pass(|| box implicit_return::ImplicitReturn);
|
||||
store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
|
||||
store.register_late_pass(|| box default_numeric_fallback::DefaultNumericFallback);
|
||||
store.register_late_pass(|| box inconsistent_struct_constructor::InconsistentStructConstructor);
|
||||
store.register_late_pass(|| box non_octal_unix_permissions::NonOctalUnixPermissions);
|
||||
store.register_early_pass(|| box unnecessary_self_imports::UnnecessarySelfImports);
|
||||
|
||||
let msrv = conf.msrv.as_ref().and_then(|s| {
|
||||
parse_msrv(s, None, None).or_else(|| {
|
||||
sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s));
|
||||
None
|
||||
})
|
||||
});
|
||||
|
||||
store.register_late_pass(move || box methods::Methods::new(msrv));
|
||||
store.register_late_pass(move || box matches::Matches::new(msrv));
|
||||
store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv));
|
||||
store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv));
|
||||
store.register_early_pass(move || box redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv));
|
||||
store.register_early_pass(move || box redundant_field_names::RedundantFieldNames::new(msrv));
|
||||
store.register_late_pass(move || box checked_conversions::CheckedConversions::new(msrv));
|
||||
store.register_late_pass(move || box mem_replace::MemReplace::new(msrv));
|
||||
store.register_late_pass(move || box ranges::Ranges::new(msrv));
|
||||
store.register_late_pass(move || box from_over_into::FromOverInto::new(msrv));
|
||||
store.register_late_pass(move || box use_self::UseSelf::new(msrv));
|
||||
store.register_late_pass(move || box missing_const_for_fn::MissingConstForFn::new(msrv));
|
||||
store.register_late_pass(move || box needless_question_mark::NeedlessQuestionMark);
|
||||
store.register_late_pass(move || box casts::Casts::new(msrv));
|
||||
store.register_early_pass(move || box unnested_or_patterns::UnnestedOrPatterns::new(msrv));
|
||||
|
||||
store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount);
|
||||
store.register_late_pass(|| box map_clone::MapClone);
|
||||
store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
|
||||
store.register_late_pass(|| box shadow::Shadow);
|
||||
store.register_late_pass(|| box unit_types::UnitTypes);
|
||||
store.register_late_pass(|| box loops::Loops);
|
||||
store.register_late_pass(|| box main_recursion::MainRecursion::default());
|
||||
store.register_late_pass(|| box lifetimes::Lifetimes);
|
||||
store.register_late_pass(|| box entry::HashMapPass);
|
||||
store.register_late_pass(|| box minmax::MinMaxPass);
|
||||
store.register_late_pass(|| box open_options::OpenOptions);
|
||||
store.register_late_pass(|| box zero_div_zero::ZeroDiv);
|
||||
store.register_late_pass(|| box mutex_atomic::Mutex);
|
||||
store.register_late_pass(|| box needless_update::NeedlessUpdate);
|
||||
store.register_late_pass(|| box needless_borrow::NeedlessBorrow::default());
|
||||
store.register_late_pass(|| box needless_borrowed_ref::NeedlessBorrowedRef);
|
||||
store.register_late_pass(|| box no_effect::NoEffect);
|
||||
store.register_late_pass(|| box temporary_assignment::TemporaryAssignment);
|
||||
store.register_late_pass(|| box transmute::Transmute);
|
||||
let cognitive_complexity_threshold = conf.cognitive_complexity_threshold;
|
||||
store.register_late_pass(move || box cognitive_complexity::CognitiveComplexity::new(cognitive_complexity_threshold));
|
||||
let too_large_for_stack = conf.too_large_for_stack;
|
||||
store.register_late_pass(move || box escape::BoxedLocal{too_large_for_stack});
|
||||
store.register_late_pass(move || box vec::UselessVec{too_large_for_stack});
|
||||
store.register_late_pass(|| box panic_unimplemented::PanicUnimplemented);
|
||||
store.register_late_pass(|| box strings::StringLitAsBytes);
|
||||
store.register_late_pass(|| box derive::Derive);
|
||||
store.register_late_pass(|| box get_last_with_len::GetLastWithLen);
|
||||
store.register_late_pass(|| box drop_forget_ref::DropForgetRef);
|
||||
store.register_late_pass(|| box empty_enum::EmptyEnum);
|
||||
store.register_late_pass(|| box absurd_extreme_comparisons::AbsurdExtremeComparisons);
|
||||
store.register_late_pass(|| box invalid_upcast_comparisons::InvalidUpcastComparisons);
|
||||
store.register_late_pass(|| box regex::Regex::default());
|
||||
store.register_late_pass(|| box copies::CopyAndPaste);
|
||||
store.register_late_pass(|| box copy_iterator::CopyIterator);
|
||||
store.register_late_pass(|| box format::UselessFormat);
|
||||
store.register_late_pass(|| box swap::Swap);
|
||||
store.register_late_pass(|| box overflow_check_conditional::OverflowCheckConditional);
|
||||
store.register_late_pass(|| box new_without_default::NewWithoutDefault::default());
|
||||
let blacklisted_names = conf.blacklisted_names.iter().cloned().collect::<FxHashSet<_>>();
|
||||
store.register_late_pass(move || box blacklisted_name::BlacklistedName::new(blacklisted_names.clone()));
|
||||
let too_many_arguments_threshold = conf.too_many_arguments_threshold;
|
||||
let too_many_lines_threshold = conf.too_many_lines_threshold;
|
||||
store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold, too_many_lines_threshold));
|
||||
let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
|
||||
store.register_late_pass(move || box doc::DocMarkdown::new(doc_valid_idents.clone()));
|
||||
store.register_late_pass(|| box neg_multiply::NegMultiply);
|
||||
store.register_late_pass(|| box mem_discriminant::MemDiscriminant);
|
||||
store.register_late_pass(|| box mem_forget::MemForget);
|
||||
store.register_late_pass(|| box arithmetic::Arithmetic::default());
|
||||
store.register_late_pass(|| box assign_ops::AssignOps);
|
||||
store.register_late_pass(|| box let_if_seq::LetIfSeq);
|
||||
store.register_late_pass(|| box eval_order_dependence::EvalOrderDependence);
|
||||
store.register_late_pass(|| box missing_doc::MissingDoc::new());
|
||||
store.register_late_pass(|| box missing_inline::MissingInline);
|
||||
store.register_late_pass(move || box exhaustive_items::ExhaustiveItems);
|
||||
store.register_late_pass(|| box if_let_some_result::OkIfLet);
|
||||
store.register_late_pass(|| box partialeq_ne_impl::PartialEqNeImpl);
|
||||
store.register_late_pass(|| box unused_io_amount::UnusedIoAmount);
|
||||
let enum_variant_size_threshold = conf.enum_variant_size_threshold;
|
||||
store.register_late_pass(move || box large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold));
|
||||
store.register_late_pass(|| box explicit_write::ExplicitWrite);
|
||||
store.register_late_pass(|| box needless_pass_by_value::NeedlessPassByValue);
|
||||
let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new(
|
||||
conf.trivial_copy_size_limit,
|
||||
conf.pass_by_value_size_limit,
|
||||
&sess.target,
|
||||
);
|
||||
store.register_late_pass(move || box pass_by_ref_or_value);
|
||||
store.register_late_pass(|| box ref_option_ref::RefOptionRef);
|
||||
store.register_late_pass(|| box try_err::TryErr);
|
||||
store.register_late_pass(|| box bytecount::ByteCount);
|
||||
store.register_late_pass(|| box infinite_iter::InfiniteIter);
|
||||
store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody);
|
||||
store.register_late_pass(|| box useless_conversion::UselessConversion::default());
|
||||
store.register_late_pass(|| box implicit_hasher::ImplicitHasher);
|
||||
store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom);
|
||||
store.register_late_pass(|| box double_comparison::DoubleComparisons);
|
||||
store.register_late_pass(|| box question_mark::QuestionMark);
|
||||
store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings);
|
||||
store.register_late_pass(|| box suspicious_trait_impl::SuspiciousImpl);
|
||||
store.register_late_pass(|| box map_unit_fn::MapUnit);
|
||||
store.register_late_pass(|| box inherent_impl::MultipleInherentImpl);
|
||||
store.register_late_pass(|| box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd);
|
||||
store.register_late_pass(|| box unwrap::Unwrap);
|
||||
store.register_late_pass(|| box duration_subsec::DurationSubsec);
|
||||
store.register_late_pass(|| box indexing_slicing::IndexingSlicing);
|
||||
store.register_late_pass(|| box non_copy_const::NonCopyConst);
|
||||
store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast);
|
||||
store.register_late_pass(|| box redundant_clone::RedundantClone);
|
||||
store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit);
|
||||
store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy);
|
||||
store.register_late_pass(|| box unnecessary_wraps::UnnecessaryWraps);
|
||||
store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
|
||||
store.register_late_pass(|| box transmuting_null::TransmutingNull);
|
||||
store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite);
|
||||
store.register_late_pass(|| box integer_division::IntegerDivision);
|
||||
store.register_late_pass(|| box inherent_to_string::InherentToString);
|
||||
let max_trait_bounds = conf.max_trait_bounds;
|
||||
store.register_late_pass(move || box trait_bounds::TraitBounds::new(max_trait_bounds));
|
||||
store.register_late_pass(|| box comparison_chain::ComparisonChain);
|
||||
store.register_late_pass(|| box mut_key::MutableKeyType);
|
||||
store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic);
|
||||
store.register_early_pass(|| box reference::DerefAddrOf);
|
||||
store.register_early_pass(|| box reference::RefInDeref);
|
||||
store.register_early_pass(|| box double_parens::DoubleParens);
|
||||
store.register_late_pass(|| box to_string_in_display::ToStringInDisplay::new());
|
||||
store.register_early_pass(|| box unsafe_removed_from_name::UnsafeNameRemoval);
|
||||
store.register_early_pass(|| box if_not_else::IfNotElse);
|
||||
store.register_early_pass(|| box else_if_without_else::ElseIfWithoutElse);
|
||||
store.register_early_pass(|| box int_plus_one::IntPlusOne);
|
||||
store.register_early_pass(|| box formatting::Formatting);
|
||||
store.register_early_pass(|| box misc_early::MiscEarlyLints);
|
||||
store.register_early_pass(|| box redundant_closure_call::RedundantClosureCall);
|
||||
store.register_late_pass(|| box redundant_closure_call::RedundantClosureCall);
|
||||
store.register_early_pass(|| box unused_unit::UnusedUnit);
|
||||
store.register_late_pass(|| box returns::Return);
|
||||
store.register_early_pass(|| box collapsible_if::CollapsibleIf);
|
||||
store.register_early_pass(|| box items_after_statements::ItemsAfterStatements);
|
||||
store.register_early_pass(|| box precedence::Precedence);
|
||||
store.register_early_pass(|| box needless_continue::NeedlessContinue);
|
||||
store.register_early_pass(|| box redundant_else::RedundantElse);
|
||||
store.register_late_pass(|| box create_dir::CreateDir);
|
||||
store.register_early_pass(|| box needless_arbitrary_self_type::NeedlessArbitrarySelfType);
|
||||
let cargo_ignore_publish = conf.cargo_ignore_publish;
|
||||
store.register_late_pass(move || box cargo_common_metadata::CargoCommonMetadata::new(cargo_ignore_publish));
|
||||
store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions);
|
||||
store.register_late_pass(|| box wildcard_dependencies::WildcardDependencies);
|
||||
let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions;
|
||||
store.register_early_pass(move || box literal_representation::LiteralDigitGrouping::new(literal_representation_lint_fraction_readability));
|
||||
let literal_representation_threshold = conf.literal_representation_threshold;
|
||||
store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold));
|
||||
let enum_variant_name_threshold = conf.enum_variant_name_threshold;
|
||||
store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold));
|
||||
store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
|
||||
let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive;
|
||||
store.register_early_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(upper_case_acronyms_aggressive));
|
||||
store.register_late_pass(|| box default::Default::default());
|
||||
store.register_late_pass(|| box unused_self::UnusedSelf);
|
||||
store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall);
|
||||
store.register_late_pass(|| box exit::Exit);
|
||||
store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome);
|
||||
let array_size_threshold = conf.array_size_threshold;
|
||||
store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold));
|
||||
store.register_late_pass(move || box large_const_arrays::LargeConstArrays::new(array_size_threshold));
|
||||
store.register_late_pass(|| box floating_point_arithmetic::FloatingPointArithmetic);
|
||||
store.register_early_pass(|| box as_conversions::AsConversions);
|
||||
store.register_late_pass(|| box let_underscore::LetUnderscore);
|
||||
store.register_late_pass(|| box atomic_ordering::AtomicOrdering);
|
||||
store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports);
|
||||
let max_fn_params_bools = conf.max_fn_params_bools;
|
||||
let max_struct_bools = conf.max_struct_bools;
|
||||
store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools));
|
||||
store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap);
|
||||
let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports;
|
||||
store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports));
|
||||
store.register_late_pass(|| box verbose_file_reads::VerboseFileReads);
|
||||
store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default());
|
||||
store.register_late_pass(|| box unnamed_address::UnnamedAddress);
|
||||
store.register_late_pass(|| box dereference::Dereferencing::default());
|
||||
store.register_late_pass(|| box option_if_let_else::OptionIfLetElse);
|
||||
store.register_late_pass(|| box future_not_send::FutureNotSend);
|
||||
store.register_late_pass(|| box if_let_mutex::IfLetMutex);
|
||||
store.register_late_pass(|| box mut_mutex_lock::MutMutexLock);
|
||||
store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
|
||||
store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
|
||||
store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero);
|
||||
store.register_late_pass(|| box panic_in_result_fn::PanicInResultFn);
|
||||
let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
|
||||
store.register_early_pass(move || box non_expressive_names::NonExpressiveNames {
|
||||
single_char_binding_names_threshold,
|
||||
});
|
||||
store.register_late_pass(|| box macro_use::MacroUseImports::default());
|
||||
store.register_late_pass(|| box map_identity::MapIdentity);
|
||||
store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch);
|
||||
store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive);
|
||||
store.register_late_pass(|| box repeat_once::RepeatOnce);
|
||||
store.register_late_pass(|| box unwrap_in_result::UnwrapInResult);
|
||||
store.register_late_pass(|| box self_assignment::SelfAssignment);
|
||||
store.register_late_pass(|| box manual_unwrap_or::ManualUnwrapOr);
|
||||
store.register_late_pass(|| box manual_ok_or::ManualOkOr);
|
||||
store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs);
|
||||
store.register_late_pass(|| box semicolon_if_nothing_returned::SemicolonIfNothingReturned);
|
||||
store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
|
||||
let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
|
||||
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
|
||||
store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
|
||||
store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
|
||||
store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops);
|
||||
store.register_late_pass(|| box strings::StrToString);
|
||||
store.register_late_pass(|| box strings::StringToString);
|
||||
store.register_late_pass(|| box zero_sized_map_values::ZeroSizedMapValues);
|
||||
store.register_late_pass(|| box vec_init_then_push::VecInitThenPush::default());
|
||||
store.register_late_pass(|| box case_sensitive_file_extension_comparisons::CaseSensitiveFileExtensionComparisons);
|
||||
store.register_late_pass(|| box redundant_slicing::RedundantSlicing);
|
||||
store.register_late_pass(|| box from_str_radix_10::FromStrRadix10);
|
||||
store.register_late_pass(|| box manual_map::ManualMap);
|
||||
store.register_late_pass(move || box if_then_some_else_none::IfThenSomeElseNone::new(msrv));
|
||||
store.register_early_pass(|| box bool_assert_comparison::BoolAssertComparison);
|
||||
store.register_late_pass(|| box unused_async::UnusedAsync);
|
||||
|
||||
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
|
||||
LintId::of(arithmetic::FLOAT_ARITHMETIC),
|
||||
LintId::of(arithmetic::INTEGER_ARITHMETIC),
|
||||
|
@ -1310,7 +1010,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(methods::FILETYPE_IS_FILE),
|
||||
LintId::of(methods::GET_UNWRAP),
|
||||
LintId::of(methods::UNWRAP_USED),
|
||||
LintId::of(methods::WRONG_PUB_SELF_CONVENTION),
|
||||
LintId::of(misc::FLOAT_CMP_CONST),
|
||||
LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
|
||||
LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
|
||||
|
@ -1322,7 +1021,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(panic_unimplemented::UNIMPLEMENTED),
|
||||
LintId::of(panic_unimplemented::UNREACHABLE),
|
||||
LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH),
|
||||
LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
|
||||
LintId::of(shadow::SHADOW_REUSE),
|
||||
LintId::of(shadow::SHADOW_SAME),
|
||||
LintId::of(strings::STRING_ADD),
|
||||
|
@ -1363,7 +1061,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(doc::MISSING_PANICS_DOC),
|
||||
LintId::of(empty_enum::EMPTY_ENUM),
|
||||
LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
|
||||
LintId::of(enum_variants::PUB_ENUM_VARIANT_NAMES),
|
||||
LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
|
||||
LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
|
||||
LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS),
|
||||
|
@ -1401,6 +1098,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
|
||||
LintId::of(mut_mut::MUT_MUT),
|
||||
LintId::of(needless_bitwise_bool::NEEDLESS_BITWISE_BOOL),
|
||||
LintId::of(needless_borrow::REF_BINDING_TO_REFERENCE),
|
||||
LintId::of(needless_continue::NEEDLESS_CONTINUE),
|
||||
LintId::of(needless_for_each::NEEDLESS_FOR_EACH),
|
||||
LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
|
||||
|
@ -1412,6 +1110,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(ranges::RANGE_PLUS_ONE),
|
||||
LintId::of(redundant_else::REDUNDANT_ELSE),
|
||||
LintId::of(ref_option_ref::REF_OPTION_REF),
|
||||
LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
|
||||
LintId::of(shadow::SHADOW_UNRELATED),
|
||||
LintId::of(strings::STRING_ADD_ASSIGN),
|
||||
LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
|
||||
|
@ -1600,6 +1299,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(methods::MANUAL_FILTER_MAP),
|
||||
LintId::of(methods::MANUAL_FIND_MAP),
|
||||
LintId::of(methods::MANUAL_SATURATING_ARITHMETIC),
|
||||
LintId::of(methods::MANUAL_STR_REPEAT),
|
||||
LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
|
||||
LintId::of(methods::NEW_RET_NO_SELF),
|
||||
LintId::of(methods::OK_EXPECT),
|
||||
|
@ -1615,6 +1315,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(methods::SKIP_WHILE_NEXT),
|
||||
LintId::of(methods::STRING_EXTEND_CHARS),
|
||||
LintId::of(methods::SUSPICIOUS_MAP),
|
||||
LintId::of(methods::SUSPICIOUS_SPLITN),
|
||||
LintId::of(methods::UNINIT_ASSUMED_INIT),
|
||||
LintId::of(methods::UNNECESSARY_FILTER_MAP),
|
||||
LintId::of(methods::UNNECESSARY_FOLD),
|
||||
|
@ -1644,6 +1345,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE),
|
||||
LintId::of(needless_bool::BOOL_COMPARISON),
|
||||
LintId::of(needless_bool::NEEDLESS_BOOL),
|
||||
LintId::of(needless_borrow::NEEDLESS_BORROW),
|
||||
LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
|
||||
LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
|
||||
LintId::of(needless_update::NEEDLESS_UPDATE),
|
||||
|
@ -1690,7 +1392,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
|
||||
LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
|
||||
LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
|
||||
LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
|
||||
LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
|
||||
LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
|
||||
LintId::of(swap::ALMOST_SWAPPED),
|
||||
|
@ -1827,6 +1528,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(misc_early::REDUNDANT_PATTERN),
|
||||
LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK),
|
||||
LintId::of(mut_reference::UNNECESSARY_MUT_PASSED),
|
||||
LintId::of(needless_borrow::NEEDLESS_BORROW),
|
||||
LintId::of(neg_multiply::NEG_MULTIPLY),
|
||||
LintId::of(new_without_default::NEW_WITHOUT_DEFAULT),
|
||||
LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
|
||||
|
@ -1843,7 +1545,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(returns::LET_AND_RETURN),
|
||||
LintId::of(returns::NEEDLESS_RETURN),
|
||||
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
|
||||
LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
|
||||
LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
|
||||
LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
|
||||
LintId::of(try_err::TRY_ERR),
|
||||
|
@ -1991,6 +1692,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT),
|
||||
LintId::of(methods::CLONE_DOUBLE_REF),
|
||||
LintId::of(methods::ITERATOR_STEP_BY_ZERO),
|
||||
LintId::of(methods::SUSPICIOUS_SPLITN),
|
||||
LintId::of(methods::UNINIT_ASSUMED_INIT),
|
||||
LintId::of(methods::ZST_OFFSET),
|
||||
LintId::of(minmax::MIN_MAX),
|
||||
|
@ -2035,6 +1737,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(loops::NEEDLESS_COLLECT),
|
||||
LintId::of(methods::EXPECT_FUN_CALL),
|
||||
LintId::of(methods::ITER_NTH),
|
||||
LintId::of(methods::MANUAL_STR_REPEAT),
|
||||
LintId::of(methods::OR_FUN_CALL),
|
||||
LintId::of(methods::SINGLE_CHAR_PATTERN),
|
||||
LintId::of(misc::CMP_OWNED),
|
||||
|
@ -2066,14 +1769,304 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN),
|
||||
LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
|
||||
LintId::of(mutex_atomic::MUTEX_INTEGER),
|
||||
LintId::of(needless_borrow::NEEDLESS_BORROW),
|
||||
LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
|
||||
LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE),
|
||||
LintId::of(regex::TRIVIAL_REGEX),
|
||||
LintId::of(strings::STRING_LIT_AS_BYTES),
|
||||
LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
|
||||
LintId::of(transmute::USELESS_TRANSMUTE),
|
||||
LintId::of(use_self::USE_SELF),
|
||||
]);
|
||||
|
||||
#[cfg(feature = "metadata-collector-lint")]
|
||||
{
|
||||
if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
|
||||
store.register_late_pass(|| box utils::internal_lints::metadata_collector::MetadataCollector::new());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// all the internal lints
|
||||
#[cfg(feature = "internal-lints")]
|
||||
{
|
||||
store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal);
|
||||
store.register_early_pass(|| box utils::internal_lints::ProduceIce);
|
||||
store.register_late_pass(|| box utils::inspector::DeepCodeInspector);
|
||||
store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls);
|
||||
store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
|
||||
store.register_late_pass(|| box utils::internal_lints::IfChainStyle);
|
||||
store.register_late_pass(|| box utils::internal_lints::InvalidPaths);
|
||||
store.register_late_pass(|| box utils::internal_lints::InterningDefinedSymbol::default());
|
||||
store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default());
|
||||
store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
|
||||
store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass);
|
||||
}
|
||||
|
||||
store.register_late_pass(|| box utils::author::Author);
|
||||
store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
|
||||
store.register_late_pass(|| box serde_api::SerdeApi);
|
||||
let vec_box_size_threshold = conf.vec_box_size_threshold;
|
||||
let type_complexity_threshold = conf.type_complexity_threshold;
|
||||
store.register_late_pass(move || box types::Types::new(vec_box_size_threshold, type_complexity_threshold));
|
||||
store.register_late_pass(|| box booleans::NonminimalBool);
|
||||
store.register_late_pass(|| box needless_bitwise_bool::NeedlessBitwiseBool);
|
||||
store.register_late_pass(|| box eq_op::EqOp);
|
||||
store.register_late_pass(|| box enum_clike::UnportableVariant);
|
||||
store.register_late_pass(|| box float_literal::FloatLiteral);
|
||||
let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
|
||||
store.register_late_pass(move || box bit_mask::BitMask::new(verbose_bit_mask_threshold));
|
||||
store.register_late_pass(|| box ptr::Ptr);
|
||||
store.register_late_pass(|| box ptr_eq::PtrEq);
|
||||
store.register_late_pass(|| box needless_bool::NeedlessBool);
|
||||
store.register_late_pass(|| box needless_bool::BoolComparison);
|
||||
store.register_late_pass(|| box needless_for_each::NeedlessForEach);
|
||||
store.register_late_pass(|| box approx_const::ApproxConstant);
|
||||
store.register_late_pass(|| box misc::MiscLints);
|
||||
store.register_late_pass(|| box eta_reduction::EtaReduction);
|
||||
store.register_late_pass(|| box identity_op::IdentityOp);
|
||||
store.register_late_pass(|| box erasing_op::ErasingOp);
|
||||
store.register_late_pass(|| box mut_mut::MutMut);
|
||||
store.register_late_pass(|| box mut_reference::UnnecessaryMutPassed);
|
||||
store.register_late_pass(|| box len_zero::LenZero);
|
||||
store.register_late_pass(|| box attrs::Attributes);
|
||||
store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions);
|
||||
store.register_late_pass(|| box collapsible_match::CollapsibleMatch);
|
||||
store.register_late_pass(|| box unicode::Unicode);
|
||||
store.register_late_pass(|| box unit_return_expecting_ord::UnitReturnExpectingOrd);
|
||||
store.register_late_pass(|| box strings::StringAdd);
|
||||
store.register_late_pass(|| box implicit_return::ImplicitReturn);
|
||||
store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
|
||||
store.register_late_pass(|| box default_numeric_fallback::DefaultNumericFallback);
|
||||
store.register_late_pass(|| box inconsistent_struct_constructor::InconsistentStructConstructor);
|
||||
store.register_late_pass(|| box non_octal_unix_permissions::NonOctalUnixPermissions);
|
||||
store.register_early_pass(|| box unnecessary_self_imports::UnnecessarySelfImports);
|
||||
|
||||
let msrv = conf.msrv.as_ref().and_then(|s| {
|
||||
parse_msrv(s, None, None).or_else(|| {
|
||||
sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s));
|
||||
None
|
||||
})
|
||||
});
|
||||
|
||||
let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
|
||||
store.register_late_pass(move || box methods::Methods::new(avoid_breaking_exported_api, msrv));
|
||||
store.register_late_pass(move || box matches::Matches::new(msrv));
|
||||
store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv));
|
||||
store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv));
|
||||
store.register_early_pass(move || box redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv));
|
||||
store.register_early_pass(move || box redundant_field_names::RedundantFieldNames::new(msrv));
|
||||
store.register_late_pass(move || box checked_conversions::CheckedConversions::new(msrv));
|
||||
store.register_late_pass(move || box mem_replace::MemReplace::new(msrv));
|
||||
store.register_late_pass(move || box ranges::Ranges::new(msrv));
|
||||
store.register_late_pass(move || box from_over_into::FromOverInto::new(msrv));
|
||||
store.register_late_pass(move || box use_self::UseSelf::new(msrv));
|
||||
store.register_late_pass(move || box missing_const_for_fn::MissingConstForFn::new(msrv));
|
||||
store.register_late_pass(move || box needless_question_mark::NeedlessQuestionMark);
|
||||
store.register_late_pass(move || box casts::Casts::new(msrv));
|
||||
store.register_early_pass(move || box unnested_or_patterns::UnnestedOrPatterns::new(msrv));
|
||||
|
||||
store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount);
|
||||
store.register_late_pass(|| box map_clone::MapClone);
|
||||
store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
|
||||
store.register_late_pass(|| box shadow::Shadow);
|
||||
store.register_late_pass(|| box unit_types::UnitTypes);
|
||||
store.register_late_pass(|| box loops::Loops);
|
||||
store.register_late_pass(|| box main_recursion::MainRecursion::default());
|
||||
store.register_late_pass(|| box lifetimes::Lifetimes);
|
||||
store.register_late_pass(|| box entry::HashMapPass);
|
||||
store.register_late_pass(|| box minmax::MinMaxPass);
|
||||
store.register_late_pass(|| box open_options::OpenOptions);
|
||||
store.register_late_pass(|| box zero_div_zero::ZeroDiv);
|
||||
store.register_late_pass(|| box mutex_atomic::Mutex);
|
||||
store.register_late_pass(|| box needless_update::NeedlessUpdate);
|
||||
store.register_late_pass(|| box needless_borrow::NeedlessBorrow::default());
|
||||
store.register_late_pass(|| box needless_borrowed_ref::NeedlessBorrowedRef);
|
||||
store.register_late_pass(|| box no_effect::NoEffect);
|
||||
store.register_late_pass(|| box temporary_assignment::TemporaryAssignment);
|
||||
store.register_late_pass(|| box transmute::Transmute);
|
||||
let cognitive_complexity_threshold = conf.cognitive_complexity_threshold;
|
||||
store.register_late_pass(move || box cognitive_complexity::CognitiveComplexity::new(cognitive_complexity_threshold));
|
||||
let too_large_for_stack = conf.too_large_for_stack;
|
||||
store.register_late_pass(move || box escape::BoxedLocal{too_large_for_stack});
|
||||
store.register_late_pass(move || box vec::UselessVec{too_large_for_stack});
|
||||
store.register_late_pass(|| box panic_unimplemented::PanicUnimplemented);
|
||||
store.register_late_pass(|| box strings::StringLitAsBytes);
|
||||
store.register_late_pass(|| box derive::Derive);
|
||||
store.register_late_pass(|| box get_last_with_len::GetLastWithLen);
|
||||
store.register_late_pass(|| box drop_forget_ref::DropForgetRef);
|
||||
store.register_late_pass(|| box empty_enum::EmptyEnum);
|
||||
store.register_late_pass(|| box absurd_extreme_comparisons::AbsurdExtremeComparisons);
|
||||
store.register_late_pass(|| box invalid_upcast_comparisons::InvalidUpcastComparisons);
|
||||
store.register_late_pass(|| box regex::Regex::default());
|
||||
store.register_late_pass(|| box copies::CopyAndPaste);
|
||||
store.register_late_pass(|| box copy_iterator::CopyIterator);
|
||||
store.register_late_pass(|| box format::UselessFormat);
|
||||
store.register_late_pass(|| box swap::Swap);
|
||||
store.register_late_pass(|| box overflow_check_conditional::OverflowCheckConditional);
|
||||
store.register_late_pass(|| box new_without_default::NewWithoutDefault::default());
|
||||
let blacklisted_names = conf.blacklisted_names.iter().cloned().collect::<FxHashSet<_>>();
|
||||
store.register_late_pass(move || box blacklisted_name::BlacklistedName::new(blacklisted_names.clone()));
|
||||
let too_many_arguments_threshold = conf.too_many_arguments_threshold;
|
||||
let too_many_lines_threshold = conf.too_many_lines_threshold;
|
||||
store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold, too_many_lines_threshold));
|
||||
let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
|
||||
store.register_late_pass(move || box doc::DocMarkdown::new(doc_valid_idents.clone()));
|
||||
store.register_late_pass(|| box neg_multiply::NegMultiply);
|
||||
store.register_late_pass(|| box mem_discriminant::MemDiscriminant);
|
||||
store.register_late_pass(|| box mem_forget::MemForget);
|
||||
store.register_late_pass(|| box arithmetic::Arithmetic::default());
|
||||
store.register_late_pass(|| box assign_ops::AssignOps);
|
||||
store.register_late_pass(|| box let_if_seq::LetIfSeq);
|
||||
store.register_late_pass(|| box eval_order_dependence::EvalOrderDependence);
|
||||
store.register_late_pass(|| box missing_doc::MissingDoc::new());
|
||||
store.register_late_pass(|| box missing_inline::MissingInline);
|
||||
store.register_late_pass(move || box exhaustive_items::ExhaustiveItems);
|
||||
store.register_late_pass(|| box if_let_some_result::OkIfLet);
|
||||
store.register_late_pass(|| box partialeq_ne_impl::PartialEqNeImpl);
|
||||
store.register_late_pass(|| box unused_io_amount::UnusedIoAmount);
|
||||
let enum_variant_size_threshold = conf.enum_variant_size_threshold;
|
||||
store.register_late_pass(move || box large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold));
|
||||
store.register_late_pass(|| box explicit_write::ExplicitWrite);
|
||||
store.register_late_pass(|| box needless_pass_by_value::NeedlessPassByValue);
|
||||
let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new(
|
||||
conf.trivial_copy_size_limit,
|
||||
conf.pass_by_value_size_limit,
|
||||
conf.avoid_breaking_exported_api,
|
||||
&sess.target,
|
||||
);
|
||||
store.register_late_pass(move || box pass_by_ref_or_value);
|
||||
store.register_late_pass(|| box ref_option_ref::RefOptionRef);
|
||||
store.register_late_pass(|| box try_err::TryErr);
|
||||
store.register_late_pass(|| box bytecount::ByteCount);
|
||||
store.register_late_pass(|| box infinite_iter::InfiniteIter);
|
||||
store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody);
|
||||
store.register_late_pass(|| box useless_conversion::UselessConversion::default());
|
||||
store.register_late_pass(|| box implicit_hasher::ImplicitHasher);
|
||||
store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom);
|
||||
store.register_late_pass(|| box double_comparison::DoubleComparisons);
|
||||
store.register_late_pass(|| box question_mark::QuestionMark);
|
||||
store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings);
|
||||
store.register_late_pass(|| box suspicious_trait_impl::SuspiciousImpl);
|
||||
store.register_late_pass(|| box map_unit_fn::MapUnit);
|
||||
store.register_late_pass(|| box inherent_impl::MultipleInherentImpl);
|
||||
store.register_late_pass(|| box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd);
|
||||
store.register_late_pass(|| box unwrap::Unwrap);
|
||||
store.register_late_pass(|| box duration_subsec::DurationSubsec);
|
||||
store.register_late_pass(|| box indexing_slicing::IndexingSlicing);
|
||||
store.register_late_pass(|| box non_copy_const::NonCopyConst);
|
||||
store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast);
|
||||
store.register_late_pass(|| box redundant_clone::RedundantClone);
|
||||
store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit);
|
||||
store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy);
|
||||
store.register_late_pass(move || box unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api));
|
||||
store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
|
||||
store.register_late_pass(|| box transmuting_null::TransmutingNull);
|
||||
store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite);
|
||||
store.register_late_pass(|| box integer_division::IntegerDivision);
|
||||
store.register_late_pass(|| box inherent_to_string::InherentToString);
|
||||
let max_trait_bounds = conf.max_trait_bounds;
|
||||
store.register_late_pass(move || box trait_bounds::TraitBounds::new(max_trait_bounds));
|
||||
store.register_late_pass(|| box comparison_chain::ComparisonChain);
|
||||
store.register_late_pass(|| box mut_key::MutableKeyType);
|
||||
store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic);
|
||||
store.register_early_pass(|| box reference::DerefAddrOf);
|
||||
store.register_early_pass(|| box reference::RefInDeref);
|
||||
store.register_early_pass(|| box double_parens::DoubleParens);
|
||||
store.register_late_pass(|| box to_string_in_display::ToStringInDisplay::new());
|
||||
store.register_early_pass(|| box unsafe_removed_from_name::UnsafeNameRemoval);
|
||||
store.register_early_pass(|| box if_not_else::IfNotElse);
|
||||
store.register_early_pass(|| box else_if_without_else::ElseIfWithoutElse);
|
||||
store.register_early_pass(|| box int_plus_one::IntPlusOne);
|
||||
store.register_early_pass(|| box formatting::Formatting);
|
||||
store.register_early_pass(|| box misc_early::MiscEarlyLints);
|
||||
store.register_early_pass(|| box redundant_closure_call::RedundantClosureCall);
|
||||
store.register_late_pass(|| box redundant_closure_call::RedundantClosureCall);
|
||||
store.register_early_pass(|| box unused_unit::UnusedUnit);
|
||||
store.register_late_pass(|| box returns::Return);
|
||||
store.register_early_pass(|| box collapsible_if::CollapsibleIf);
|
||||
store.register_early_pass(|| box items_after_statements::ItemsAfterStatements);
|
||||
store.register_early_pass(|| box precedence::Precedence);
|
||||
store.register_early_pass(|| box needless_continue::NeedlessContinue);
|
||||
store.register_early_pass(|| box redundant_else::RedundantElse);
|
||||
store.register_late_pass(|| box create_dir::CreateDir);
|
||||
store.register_early_pass(|| box needless_arbitrary_self_type::NeedlessArbitrarySelfType);
|
||||
let cargo_ignore_publish = conf.cargo_ignore_publish;
|
||||
store.register_late_pass(move || box cargo_common_metadata::CargoCommonMetadata::new(cargo_ignore_publish));
|
||||
store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions);
|
||||
store.register_late_pass(|| box wildcard_dependencies::WildcardDependencies);
|
||||
let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions;
|
||||
store.register_early_pass(move || box literal_representation::LiteralDigitGrouping::new(literal_representation_lint_fraction_readability));
|
||||
let literal_representation_threshold = conf.literal_representation_threshold;
|
||||
store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold));
|
||||
let enum_variant_name_threshold = conf.enum_variant_name_threshold;
|
||||
store.register_late_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold, avoid_breaking_exported_api));
|
||||
store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
|
||||
let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive;
|
||||
store.register_late_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(avoid_breaking_exported_api, upper_case_acronyms_aggressive));
|
||||
store.register_late_pass(|| box default::Default::default());
|
||||
store.register_late_pass(|| box unused_self::UnusedSelf);
|
||||
store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall);
|
||||
store.register_late_pass(|| box exit::Exit);
|
||||
store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome);
|
||||
let array_size_threshold = conf.array_size_threshold;
|
||||
store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold));
|
||||
store.register_late_pass(move || box large_const_arrays::LargeConstArrays::new(array_size_threshold));
|
||||
store.register_late_pass(|| box floating_point_arithmetic::FloatingPointArithmetic);
|
||||
store.register_early_pass(|| box as_conversions::AsConversions);
|
||||
store.register_late_pass(|| box let_underscore::LetUnderscore);
|
||||
store.register_late_pass(|| box atomic_ordering::AtomicOrdering);
|
||||
store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports);
|
||||
let max_fn_params_bools = conf.max_fn_params_bools;
|
||||
let max_struct_bools = conf.max_struct_bools;
|
||||
store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools));
|
||||
store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap);
|
||||
let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports;
|
||||
store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports));
|
||||
store.register_late_pass(|| box verbose_file_reads::VerboseFileReads);
|
||||
store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default());
|
||||
store.register_late_pass(|| box unnamed_address::UnnamedAddress);
|
||||
store.register_late_pass(|| box dereference::Dereferencing::default());
|
||||
store.register_late_pass(|| box option_if_let_else::OptionIfLetElse);
|
||||
store.register_late_pass(|| box future_not_send::FutureNotSend);
|
||||
store.register_late_pass(|| box if_let_mutex::IfLetMutex);
|
||||
store.register_late_pass(|| box mut_mutex_lock::MutMutexLock);
|
||||
store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
|
||||
store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
|
||||
store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero);
|
||||
store.register_late_pass(|| box panic_in_result_fn::PanicInResultFn);
|
||||
let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
|
||||
store.register_early_pass(move || box non_expressive_names::NonExpressiveNames {
|
||||
single_char_binding_names_threshold,
|
||||
});
|
||||
store.register_late_pass(|| box macro_use::MacroUseImports::default());
|
||||
store.register_late_pass(|| box map_identity::MapIdentity);
|
||||
store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch);
|
||||
store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive);
|
||||
store.register_late_pass(|| box repeat_once::RepeatOnce);
|
||||
store.register_late_pass(|| box unwrap_in_result::UnwrapInResult);
|
||||
store.register_late_pass(|| box self_assignment::SelfAssignment);
|
||||
store.register_late_pass(|| box manual_unwrap_or::ManualUnwrapOr);
|
||||
store.register_late_pass(|| box manual_ok_or::ManualOkOr);
|
||||
store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs);
|
||||
store.register_late_pass(|| box semicolon_if_nothing_returned::SemicolonIfNothingReturned);
|
||||
store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
|
||||
let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
|
||||
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
|
||||
store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
|
||||
store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
|
||||
store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops);
|
||||
store.register_late_pass(|| box strings::StrToString);
|
||||
store.register_late_pass(|| box strings::StringToString);
|
||||
store.register_late_pass(|| box zero_sized_map_values::ZeroSizedMapValues);
|
||||
store.register_late_pass(|| box vec_init_then_push::VecInitThenPush::default());
|
||||
store.register_late_pass(|| box case_sensitive_file_extension_comparisons::CaseSensitiveFileExtensionComparisons);
|
||||
store.register_late_pass(|| box redundant_slicing::RedundantSlicing);
|
||||
store.register_late_pass(|| box from_str_radix_10::FromStrRadix10);
|
||||
store.register_late_pass(|| box manual_map::ManualMap);
|
||||
store.register_late_pass(move || box if_then_some_else_none::IfThenSomeElseNone::new(msrv));
|
||||
store.register_early_pass(|| box bool_assert_comparison::BoolAssertComparison);
|
||||
store.register_late_pass(|| box unused_async::UnusedAsync);
|
||||
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
|
|
|
@ -205,7 +205,7 @@ fn could_use_elision<'tcx>(
|
|||
output_visitor.visit_ty(ty);
|
||||
}
|
||||
for lt in named_generics {
|
||||
input_visitor.visit_generic_param(lt)
|
||||
input_visitor.visit_generic_param(lt);
|
||||
}
|
||||
|
||||
if input_visitor.abort() || output_visitor.abort() {
|
||||
|
@ -463,7 +463,7 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker {
|
|||
// `'b` in `'a: 'b` is useless unless used elsewhere in
|
||||
// a non-lifetime bound
|
||||
if let GenericParamKind::Type { .. } = param.kind {
|
||||
walk_generic_param(self, param)
|
||||
walk_generic_param(self, param);
|
||||
}
|
||||
}
|
||||
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
||||
|
|
|
@ -231,7 +231,7 @@ impl EarlyLintPass for LiteralDigitGrouping {
|
|||
}
|
||||
|
||||
if let ExprKind::Lit(ref lit) = expr.kind {
|
||||
self.check_lit(cx, lit)
|
||||
self.check_lit(cx, lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ impl LiteralDigitGrouping {
|
|||
}
|
||||
};
|
||||
if should_warn {
|
||||
warning_type.display(num_lit.format(), cx, lit.span)
|
||||
warning_type.display(num_lit.format(), cx, lit.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ impl EarlyLintPass for DecimalLiteralRepresentation {
|
|||
}
|
||||
|
||||
if let ExprKind::Lit(ref lit) = expr.kind {
|
||||
self.check_lit(cx, lit)
|
||||
self.check_lit(cx, lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -446,7 +446,7 @@ impl DecimalLiteralRepresentation {
|
|||
let hex = format!("{:#X}", val);
|
||||
let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
|
||||
let _ = Self::do_lint(num_lit.integer).map_err(|warning_type| {
|
||||
warning_type.display(num_lit.format(), cx, lit.span)
|
||||
warning_type.display(num_lit.format(), cx, lit.span);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, arg: &Expr<'_>, m
|
|||
"to write this more concisely, try",
|
||||
format!("&{}{}", muta, object),
|
||||
applicability,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns `true` if the type of expr is one that provides `IntoIterator` impls
|
||||
|
|
|
@ -88,10 +88,10 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
|
|||
if let ty::BorrowKind::MutBorrow = bk {
|
||||
if let PlaceBase::Local(id) = cmt.place.base {
|
||||
if Some(id) == self.hir_id_low {
|
||||
self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id))
|
||||
self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
|
||||
}
|
||||
if Some(id) == self.hir_id_high {
|
||||
self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id))
|
||||
self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,10 +100,10 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
|
|||
fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
|
||||
if let PlaceBase::Local(id) = cmt.place.base {
|
||||
if Some(id) == self.hir_id_low {
|
||||
self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id))
|
||||
self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
|
||||
}
|
||||
if Some(id) == self.hir_id_high {
|
||||
self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id))
|
||||
self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::NEEDLESS_COLLECT;
|
||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_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::sugg::Sugg;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
|
@ -116,9 +116,10 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
|
|||
// Suggest replacing iter_call with iter_replacement, and removing stmt
|
||||
let mut span = MultiSpan::from_span(collect_span);
|
||||
span.push_span_label(iter_call.span, "the iterator could be used here instead".into());
|
||||
span_lint_and_then(
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
super::NEEDLESS_COLLECT,
|
||||
init_expr.hir_id,
|
||||
span,
|
||||
NEEDLESS_COLLECT_MSG,
|
||||
|diag| {
|
||||
|
|
|
@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(
|
|||
"try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
|
||||
item_str, vec_str, item_str
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if !matches!(pat.kind, PatKind::Wild) {
|
||||
|
|
|
@ -80,10 +80,10 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
|
|||
}
|
||||
},
|
||||
ExprKind::Assign(lhs, _, _) if lhs.hir_id == expr.hir_id => {
|
||||
*state = IncrementVisitorVarState::DontWarn
|
||||
*state = IncrementVisitorVarState::DontWarn;
|
||||
},
|
||||
ExprKind::AddrOf(BorrowKind::Ref, mutability, _) if mutability == Mutability::Mut => {
|
||||
*state = IncrementVisitorVarState::DontWarn
|
||||
*state = IncrementVisitorVarState::DontWarn;
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
|
|||
}
|
||||
},
|
||||
ExprKind::AddrOf(BorrowKind::Ref, mutability, _) if mutability == Mutability::Mut => {
|
||||
self.state = InitializeVisitorState::DontWarn
|
||||
self.state = InitializeVisitorState::DontWarn;
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
|
|||
return;
|
||||
}
|
||||
}
|
||||
walk_pat(self, pat)
|
||||
walk_pat(self, pat);
|
||||
}
|
||||
|
||||
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::WHILE_IMMUTABLE_CONDITION;
|
||||
use crate::consts::constant;
|
||||
use clippy_utils::consts::constant;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::usage::mutated_variables;
|
||||
use if_chain::if_chain;
|
||||
|
|
|
@ -212,9 +212,9 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
|
|||
let mut suggestions = vec![];
|
||||
for ((root, span), path) in used {
|
||||
if path.len() == 1 {
|
||||
suggestions.push((span, format!("{}::{}", root, path[0])))
|
||||
suggestions.push((span, format!("{}::{}", root, path[0])));
|
||||
} else {
|
||||
suggestions.push((span, format!("{}::{{{}}}", root, path.join(", "))))
|
||||
suggestions.push((span, format!("{}::{{{}}}", root, path.join(", "))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
|
|||
"remove the attribute and import the macro directly, try",
|
||||
help,
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::usage::mutated_variables;
|
||||
|
@ -123,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
|
|||
kind_word,
|
||||
snippet(cx, pattern.span, "..")))]
|
||||
.into_iter().chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::constant_simple;
|
||||
use clippy_utils::consts::constant_simple;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
|
|
|
@ -125,7 +125,7 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) {
|
|||
"remove the `map` call",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) {
|
||||
|
@ -142,7 +142,7 @@ fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) {
|
|||
snippet_with_applicability(cx, root, "..", &mut applicability)
|
||||
),
|
||||
applicability,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -155,6 +155,6 @@ fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) {
|
|||
snippet_with_applicability(cx, root, "..", &mut applicability)
|
||||
),
|
||||
applicability,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant, miri_to_const, Constant};
|
||||
use clippy_utils::consts::{constant, miri_to_const, Constant};
|
||||
use clippy_utils::diagnostics::{
|
||||
multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
|
||||
};
|
||||
|
@ -1144,7 +1144,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
|
|||
"try this",
|
||||
suggestions.join(" | "),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1242,7 +1242,7 @@ fn check_match_as_ref(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], exp
|
|||
cast,
|
||||
),
|
||||
applicability,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1494,7 +1494,7 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A
|
|||
"consider using the scrutinee and body instead",
|
||||
sugg,
|
||||
applicability,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -1747,7 +1747,7 @@ mod redundant_pattern_match {
|
|||
match match_source {
|
||||
MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms),
|
||||
MatchSource::IfLetDesugar { contains_else_clause } => {
|
||||
find_sugg_for_if_let(cx, expr, op, &arms[0], "if", *contains_else_clause)
|
||||
find_sugg_for_if_let(cx, expr, op, &arms[0], "if", *contains_else_clause);
|
||||
},
|
||||
MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, &arms[0], "while", false),
|
||||
_ => {},
|
||||
|
@ -1876,7 +1876,7 @@ mod redundant_pattern_match {
|
|||
{
|
||||
self.res = true;
|
||||
} else {
|
||||
self.visit_expr(self_arg)
|
||||
self.visit_expr(self_arg);
|
||||
}
|
||||
}
|
||||
args.iter().for_each(|arg| self.visit_expr(arg));
|
||||
|
|
|
@ -7,7 +7,6 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir::{BorrowKind, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use std::iter;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for calls of `mem::discriminant()` on a non-enum type.
|
||||
|
@ -67,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for MemDiscriminant {
|
|||
}
|
||||
}
|
||||
|
||||
let derefs: String = iter::repeat('*').take(derefs_needed).collect();
|
||||
let derefs = "*".repeat(derefs_needed);
|
||||
diag.span_suggestion(
|
||||
param.span,
|
||||
"try dereferencing",
|
||||
|
|
|
@ -135,7 +135,7 @@ pub(crate) trait BindInsteadOfMap {
|
|||
.into_iter()
|
||||
.map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())),
|
||||
),
|
||||
)
|
||||
);
|
||||
});
|
||||
true
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ use rustc_hir::{BindingAnnotation, Expr, ExprKind, MatchSource, Node, PatKind};
|
|||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, adjustment::Adjust};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use std::iter;
|
||||
|
||||
use super::CLONE_DOUBLE_REF;
|
||||
use super::CLONE_ON_COPY;
|
||||
|
@ -54,8 +53,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol,
|
|||
ty = inner;
|
||||
n += 1;
|
||||
}
|
||||
let refs: String = iter::repeat('&').take(n + 1).collect();
|
||||
let derefs: String = iter::repeat('*').take(n).collect();
|
||||
let refs = "&".repeat(n + 1);
|
||||
let derefs = "*".repeat(n);
|
||||
let explicit = format!("<{}{}>::clone({})", refs, ty, snip);
|
||||
diag.span_suggestion(
|
||||
expr.span,
|
||||
|
|
|
@ -41,5 +41,5 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span,
|
|||
"try",
|
||||
"copied".into(),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -30,5 +30,5 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, arg
|
|||
"try",
|
||||
"filter_map".into(),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,10 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp
|
|||
}
|
||||
|
||||
fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'tcx>) -> String {
|
||||
fn strip_angle_brackets(s: &str) -> Option<&str> {
|
||||
s.strip_prefix('<')?.strip_suffix('>')
|
||||
}
|
||||
|
||||
let call_site = expr.span.source_callsite();
|
||||
if_chain! {
|
||||
if let Ok(snippet) = cx.sess().source_map().span_to_snippet(call_site);
|
||||
|
@ -44,23 +48,32 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'tcx>) -
|
|||
if let Some((_, elements)) = snippet_split.split_last();
|
||||
|
||||
then {
|
||||
// is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`)
|
||||
if let Some(type_specifier) = snippet_split.iter().find(|e| e.starts_with('<') && e.ends_with('>')) {
|
||||
// remove the type specifier from the path elements
|
||||
let without_ts = elements.iter().filter_map(|e| {
|
||||
if e == type_specifier { None } else { Some((*e).to_string()) }
|
||||
}).collect::<Vec<_>>();
|
||||
// join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`)
|
||||
format!("{}{}", without_ts.join("::"), type_specifier)
|
||||
} else {
|
||||
// type is not explicitly specified so wildcards are needed
|
||||
// i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>`
|
||||
let ty_str = ty.to_string();
|
||||
let start = ty_str.find('<').unwrap_or(0);
|
||||
let end = ty_str.find('>').unwrap_or_else(|| ty_str.len());
|
||||
let nb_wildcard = ty_str[start..end].split(',').count();
|
||||
let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1));
|
||||
format!("{}<{}>", elements.join("::"), wildcards)
|
||||
if_chain! {
|
||||
if let [type_specifier, _] = snippet_split.as_slice();
|
||||
if let Some(type_specifier) = strip_angle_brackets(type_specifier);
|
||||
if let Some((type_specifier, ..)) = type_specifier.split_once(" as ");
|
||||
then {
|
||||
type_specifier.to_string()
|
||||
} else {
|
||||
// is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`)
|
||||
if let Some(type_specifier) = snippet_split.iter().find(|e| strip_angle_brackets(e).is_some()) {
|
||||
// remove the type specifier from the path elements
|
||||
let without_ts = elements.iter().filter_map(|e| {
|
||||
if e == type_specifier { None } else { Some((*e).to_string()) }
|
||||
}).collect::<Vec<_>>();
|
||||
// join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`)
|
||||
format!("{}{}", without_ts.join("::"), type_specifier)
|
||||
} else {
|
||||
// type is not explicitly specified so wildcards are needed
|
||||
// i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>`
|
||||
let ty_str = ty.to_string();
|
||||
let start = ty_str.find('<').unwrap_or(0);
|
||||
let end = ty_str.find('>').unwrap_or_else(|| ty_str.len());
|
||||
let nb_wildcard = ty_str[start..end].split(',').count();
|
||||
let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1));
|
||||
format!("{}<{}>", elements.join("::"), wildcards)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ty.to_string()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::is_trait_method;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::is_trait_method;
|
||||
use rustc_hir as hir;
|
||||
|
|
99
clippy_lints/src/methods/manual_str_repeat.rs
Normal file
99
clippy_lints/src/methods/manual_str_repeat.rs
Normal file
|
@ -0,0 +1,99 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item, match_type};
|
||||
use clippy_utils::{is_expr_path_def_path, paths};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, LangItem};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, Ty, TyS};
|
||||
use rustc_span::symbol::sym;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::MANUAL_STR_REPEAT;
|
||||
|
||||
enum RepeatKind {
|
||||
String,
|
||||
Char(char),
|
||||
}
|
||||
|
||||
fn get_ty_param(ty: Ty<'_>) -> Option<Ty<'_>> {
|
||||
if let ty::Adt(_, subs) = ty.kind() {
|
||||
subs.types().next()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<RepeatKind> {
|
||||
if let ExprKind::Lit(lit) = &e.kind {
|
||||
match lit.node {
|
||||
LitKind::Str(..) => Some(RepeatKind::String),
|
||||
LitKind::Char(c) => Some(RepeatKind::Char(c)),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
let ty = cx.typeck_results().expr_ty(e);
|
||||
if is_type_diagnostic_item(cx, ty, sym::string_type)
|
||||
|| (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, TyS::is_str))
|
||||
|| (match_type(cx, ty, &paths::COW) && get_ty_param(ty).map_or(false, TyS::is_str))
|
||||
{
|
||||
Some(RepeatKind::String)
|
||||
} else {
|
||||
let ty = ty.peel_refs();
|
||||
(ty.is_str() || is_type_diagnostic_item(cx, ty, sym::string_type)).then(|| RepeatKind::String)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(
|
||||
cx: &LateContext<'_>,
|
||||
collect_expr: &Expr<'_>,
|
||||
take_expr: &Expr<'_>,
|
||||
take_self_arg: &Expr<'_>,
|
||||
take_arg: &Expr<'_>,
|
||||
) {
|
||||
if_chain! {
|
||||
if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind;
|
||||
if is_expr_path_def_path(cx, repeat_fn, &paths::ITER_REPEAT);
|
||||
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(collect_expr), sym::string_type);
|
||||
if let Some(collect_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id);
|
||||
if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id);
|
||||
if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
|
||||
if cx.tcx.trait_of_item(collect_id) == Some(iter_trait_id);
|
||||
if cx.tcx.trait_of_item(take_id) == Some(iter_trait_id);
|
||||
if let Some(repeat_kind) = parse_repeat_arg(cx, repeat_arg);
|
||||
let ctxt = collect_expr.span.ctxt();
|
||||
if ctxt == take_expr.span.ctxt();
|
||||
if ctxt == take_self_arg.span.ctxt();
|
||||
then {
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let count_snip = snippet_with_context(cx, take_arg.span, ctxt, "..", &mut app).0;
|
||||
|
||||
let val_str = match repeat_kind {
|
||||
RepeatKind::Char(_) if repeat_arg.span.ctxt() != ctxt => return,
|
||||
RepeatKind::Char('\'') => r#""'""#.into(),
|
||||
RepeatKind::Char('"') => r#""\"""#.into(),
|
||||
RepeatKind::Char(_) =>
|
||||
match snippet_with_applicability(cx, repeat_arg.span, "..", &mut app) {
|
||||
Cow::Owned(s) => Cow::Owned(format!("\"{}\"", &s[1..s.len() - 1])),
|
||||
s @ Cow::Borrowed(_) => s,
|
||||
},
|
||||
RepeatKind::String =>
|
||||
Sugg::hir_with_context(cx, repeat_arg, ctxt, "..", &mut app).maybe_par().to_string().into(),
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MANUAL_STR_REPEAT,
|
||||
collect_expr.span,
|
||||
"manual implementation of `str::repeat` using iterators",
|
||||
"try this",
|
||||
format!("{}.repeat({})", val_str, count_snip),
|
||||
app
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ mod iter_nth_zero;
|
|||
mod iter_skip_next;
|
||||
mod iterator_step_by_zero;
|
||||
mod manual_saturating_arithmetic;
|
||||
mod manual_str_repeat;
|
||||
mod map_collect_result_unit;
|
||||
mod map_flatten;
|
||||
mod map_unwrap_or;
|
||||
|
@ -48,6 +49,7 @@ mod single_char_push_string;
|
|||
mod skip_while_next;
|
||||
mod string_extend_chars;
|
||||
mod suspicious_map;
|
||||
mod suspicious_splitn;
|
||||
mod uninit_assumed_init;
|
||||
mod unnecessary_filter_map;
|
||||
mod unnecessary_fold;
|
||||
|
@ -61,7 +63,7 @@ mod zst_offset;
|
|||
use bind_instead_of_map::BindInsteadOfMap;
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||
use clippy_utils::ty::{contains_adt_constructor, contains_ty, implements_trait, is_copy, is_type_diagnostic_item};
|
||||
use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, paths, return_ty};
|
||||
use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, meets_msrv, msrvs, paths, return_ty};
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
|
@ -282,30 +284,6 @@ declare_clippy_lint! {
|
|||
"defining a method named with an established prefix (like \"into_\") that takes `self` with the wrong convention"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** This is the same as
|
||||
/// [`wrong_self_convention`](#wrong_self_convention), but for public items.
|
||||
///
|
||||
/// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention).
|
||||
///
|
||||
/// **Known problems:** Actually *renaming* the function may break clients if
|
||||
/// the function is part of the public interface. In that case, be mindful of
|
||||
/// the stability guarantees you've given your users.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// # struct X;
|
||||
/// impl<'a> X {
|
||||
/// pub fn as_str(self) -> &'a str {
|
||||
/// "foo"
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub WRONG_PUB_SELF_CONVENTION,
|
||||
restriction,
|
||||
"defining a public method named with an established prefix (like \"into_\") that takes `self` with the wrong convention"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for usage of `ok().expect(..)`.
|
||||
///
|
||||
|
@ -1657,14 +1635,69 @@ declare_clippy_lint! {
|
|||
"replace `.iter().count()` with `.len()`"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for calls to [`splitn`]
|
||||
/// (https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and
|
||||
/// related functions with either zero or one splits.
|
||||
///
|
||||
/// **Why is this bad?** These calls don't actually split the value and are
|
||||
/// likely to be intended as a different number.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// // Bad
|
||||
/// let s = "";
|
||||
/// for x in s.splitn(1, ":") {
|
||||
/// // use x
|
||||
/// }
|
||||
///
|
||||
/// // Good
|
||||
/// let s = "";
|
||||
/// for x in s.splitn(2, ":") {
|
||||
/// // use x
|
||||
/// }
|
||||
/// ```
|
||||
pub SUSPICIOUS_SPLITN,
|
||||
correctness,
|
||||
"checks for `.splitn(0, ..)` and `.splitn(1, ..)`"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for manual implementations of `str::repeat`
|
||||
///
|
||||
/// **Why is this bad?** These are both harder to read, as well as less performant.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// // Bad
|
||||
/// let x: String = std::iter::repeat('x').take(10).collect();
|
||||
///
|
||||
/// // Good
|
||||
/// let x: String = "x".repeat(10);
|
||||
/// ```
|
||||
pub MANUAL_STR_REPEAT,
|
||||
perf,
|
||||
"manual implementation of `str::repeat`"
|
||||
}
|
||||
|
||||
pub struct Methods {
|
||||
avoid_breaking_exported_api: bool,
|
||||
msrv: Option<RustcVersion>,
|
||||
}
|
||||
|
||||
impl Methods {
|
||||
#[must_use]
|
||||
pub fn new(msrv: Option<RustcVersion>) -> Self {
|
||||
Self { msrv }
|
||||
pub fn new(avoid_breaking_exported_api: bool, msrv: Option<RustcVersion>) -> Self {
|
||||
Self {
|
||||
avoid_breaking_exported_api,
|
||||
msrv,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1673,7 +1706,6 @@ impl_lint_pass!(Methods => [
|
|||
EXPECT_USED,
|
||||
SHOULD_IMPLEMENT_TRAIT,
|
||||
WRONG_SELF_CONVENTION,
|
||||
WRONG_PUB_SELF_CONVENTION,
|
||||
OK_EXPECT,
|
||||
MAP_UNWRAP_OR,
|
||||
RESULT_MAP_OR_INTO_OPTION,
|
||||
|
@ -1726,7 +1758,9 @@ impl_lint_pass!(Methods => [
|
|||
MAP_COLLECT_RESULT_UNIT,
|
||||
FROM_ITER_INSTEAD_OF_COLLECT,
|
||||
INSPECT_FOR_EACH,
|
||||
IMPLICIT_CLONE
|
||||
IMPLICIT_CLONE,
|
||||
SUSPICIOUS_SPLITN,
|
||||
MANUAL_STR_REPEAT
|
||||
]);
|
||||
|
||||
/// Extracts a method call name, args, and `Span` of the method name.
|
||||
|
@ -1838,11 +1872,13 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
|||
}
|
||||
}
|
||||
|
||||
if sig.decl.implicit_self.has_implicit_self() {
|
||||
if sig.decl.implicit_self.has_implicit_self()
|
||||
&& !(self.avoid_breaking_exported_api
|
||||
&& cx.access_levels.is_exported(impl_item.hir_id()))
|
||||
{
|
||||
wrong_self_convention::check(
|
||||
cx,
|
||||
&name,
|
||||
item.vis.node.is_pub(),
|
||||
self_ty,
|
||||
first_arg_ty,
|
||||
first_arg.pat.span,
|
||||
|
@ -1915,7 +1951,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
|||
wrong_self_convention::check(
|
||||
cx,
|
||||
&item.ident.name.as_str(),
|
||||
false,
|
||||
self_ty,
|
||||
first_arg_ty,
|
||||
first_arg_span,
|
||||
|
@ -1951,7 +1986,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
|
|||
if let Some((name, [recv, args @ ..], span)) = method_call!(expr) {
|
||||
match (name, args) {
|
||||
("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [recv, _]) => {
|
||||
zst_offset::check(cx, expr, recv)
|
||||
zst_offset::check(cx, expr, recv);
|
||||
},
|
||||
("and_then", [arg]) => {
|
||||
let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, recv, arg);
|
||||
|
@ -1969,6 +2004,11 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
|
|||
Some(("map", [m_recv, m_arg], _)) => {
|
||||
map_collect_result_unit::check(cx, expr, m_recv, m_arg, recv);
|
||||
},
|
||||
Some(("take", [take_self_arg, take_arg], _)) => {
|
||||
if meets_msrv(msrv, &msrvs::STR_REPEAT) {
|
||||
manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
},
|
||||
("count", []) => match method_call!(recv) {
|
||||
|
@ -2012,7 +2052,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
|
|||
("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, msrv),
|
||||
("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, msrv),
|
||||
("filter", [f_arg]) => {
|
||||
filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false)
|
||||
filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false);
|
||||
},
|
||||
("find", [f_arg]) => filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, true),
|
||||
_ => {},
|
||||
|
@ -2044,6 +2084,9 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
|
|||
unnecessary_lazy_eval::check(cx, expr, recv, arg, "or");
|
||||
}
|
||||
},
|
||||
("splitn" | "splitn_mut" | "rsplitn" | "rsplitn_mut", [count_arg, _]) => {
|
||||
suspicious_splitn::check(cx, name, expr, recv, count_arg);
|
||||
},
|
||||
("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
|
||||
("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => {
|
||||
implicit_clone::check(cx, name, expr, recv, span);
|
||||
|
@ -2058,7 +2101,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
|
|||
manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]);
|
||||
},
|
||||
Some(("map", [m_recv, m_arg], span)) => {
|
||||
option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span)
|
||||
option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span);
|
||||
},
|
||||
_ => {},
|
||||
},
|
||||
|
@ -2073,7 +2116,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
|
|||
|
||||
fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, is_some: bool) {
|
||||
if let Some((name @ ("find" | "position" | "rposition"), [f_recv, arg], span)) = method_call!(recv) {
|
||||
search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span)
|
||||
search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
56
clippy_lints/src/methods/suspicious_splitn.rs
Normal file
56
clippy_lints/src/methods/suspicious_splitn.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_note;
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::source_map::Spanned;
|
||||
|
||||
use super::SUSPICIOUS_SPLITN;
|
||||
|
||||
pub(super) fn check(
|
||||
cx: &LateContext<'_>,
|
||||
method_name: &str,
|
||||
expr: &Expr<'_>,
|
||||
self_arg: &Expr<'_>,
|
||||
count_arg: &Expr<'_>,
|
||||
) {
|
||||
if_chain! {
|
||||
if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg);
|
||||
if count <= 1;
|
||||
if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
|
||||
if let Some(impl_id) = cx.tcx.impl_of_method(call_id);
|
||||
let lang_items = cx.tcx.lang_items();
|
||||
if lang_items.slice_impl() == Some(impl_id) || lang_items.str_impl() == Some(impl_id);
|
||||
then {
|
||||
// Ignore empty slice and string literals when used with a literal count.
|
||||
if (matches!(self_arg.kind, ExprKind::Array([]))
|
||||
|| matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty())
|
||||
) && matches!(count_arg.kind, ExprKind::Lit(_))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let (msg, note_msg) = if count == 0 {
|
||||
(format!("`{}` called with `0` splits", method_name),
|
||||
"the resulting iterator will always return `None`")
|
||||
} else {
|
||||
(format!("`{}` called with `1` split", method_name),
|
||||
if lang_items.slice_impl() == Some(impl_id) {
|
||||
"the resulting iterator will always return the entire slice followed by `None`"
|
||||
} else {
|
||||
"the resulting iterator will always return the entire string followed by `None`"
|
||||
})
|
||||
};
|
||||
|
||||
span_lint_and_note(
|
||||
cx,
|
||||
SUSPICIOUS_SPLITN,
|
||||
expr.span,
|
||||
&msg,
|
||||
None,
|
||||
note_msg,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -87,7 +87,7 @@ pub(super) fn check(
|
|||
ast::LitKind::Bool(true) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, "all", true),
|
||||
ast::LitKind::Int(0, _) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, "sum", false),
|
||||
ast::LitKind::Int(1, _) => {
|
||||
check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false)
|
||||
check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false);
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ use rustc_middle::ty::TyS;
|
|||
use rustc_span::source_map::Span;
|
||||
use std::fmt;
|
||||
|
||||
use super::WRONG_PUB_SELF_CONVENTION;
|
||||
use super::WRONG_SELF_CONVENTION;
|
||||
|
||||
#[rustfmt::skip]
|
||||
|
@ -21,9 +20,9 @@ const CONVENTIONS: [(&[Convention], &[SelfKind]); 9] = [
|
|||
|
||||
// Conversion using `to_` can use borrowed (non-Copy types) or owned (Copy types).
|
||||
// Source: https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv
|
||||
(&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(false),
|
||||
(&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(false),
|
||||
Convention::IsTraitItem(false), Convention::ImplementsTrait(false)], &[SelfKind::Ref]),
|
||||
(&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(true),
|
||||
(&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(true),
|
||||
Convention::IsTraitItem(false), Convention::ImplementsTrait(false)], &[SelfKind::Value]),
|
||||
];
|
||||
|
||||
|
@ -85,18 +84,12 @@ impl fmt::Display for Convention {
|
|||
pub(super) fn check<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
item_name: &str,
|
||||
is_pub: bool,
|
||||
self_ty: &'tcx TyS<'tcx>,
|
||||
first_arg_ty: &'tcx TyS<'tcx>,
|
||||
first_arg_span: Span,
|
||||
implements_trait: bool,
|
||||
is_trait_item: bool,
|
||||
) {
|
||||
let lint = if is_pub {
|
||||
WRONG_PUB_SELF_CONVENTION
|
||||
} else {
|
||||
WRONG_SELF_CONVENTION
|
||||
};
|
||||
if let Some((conventions, self_kinds)) = &CONVENTIONS.iter().find(|(convs, _)| {
|
||||
convs
|
||||
.iter()
|
||||
|
@ -142,7 +135,7 @@ pub(super) fn check<'tcx>(
|
|||
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
lint,
|
||||
WRONG_SELF_CONVENTION,
|
||||
first_arg_span,
|
||||
&format!(
|
||||
"{} usually take {}",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant_simple, Constant};
|
||||
use clippy_utils::consts::{constant_simple, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::{match_def_path, match_trait_method, paths};
|
||||
use if_chain::if_chain;
|
||||
|
|
|
@ -17,7 +17,7 @@ use rustc_span::hygiene::DesugaringKind;
|
|||
use rustc_span::source_map::{ExpnKind, Span};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::{
|
||||
expr_path_res, get_item_name, get_parent_expr, higher, in_constant, is_diag_trait_item, is_integer_const,
|
||||
|
@ -355,8 +355,10 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
|
|||
if binop.node == BinOpKind::And || binop.node == BinOpKind::Or;
|
||||
if let Some(sugg) = Sugg::hir_opt(cx, a);
|
||||
then {
|
||||
span_lint_and_then(cx,
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
SHORT_CIRCUIT_STATEMENT,
|
||||
expr.hir_id,
|
||||
stmt.span,
|
||||
"boolean short circuit operator in statement may be clearer using an explicit test",
|
||||
|diag| {
|
||||
|
|
|
@ -310,7 +310,7 @@ impl EarlyLintPass for MiscEarlyLints {
|
|||
if in_external_macro(cx.sess(), expr.span) {
|
||||
return;
|
||||
}
|
||||
double_neg::check(cx, expr)
|
||||
double_neg::check(cx, expr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,15 +334,15 @@ impl MiscEarlyLints {
|
|||
};
|
||||
unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
|
||||
if lit_snip.starts_with("0x") {
|
||||
mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip)
|
||||
mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip);
|
||||
} else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") {
|
||||
/* nothing to do */
|
||||
// nothing to do
|
||||
} else if value != 0 && lit_snip.starts_with('0') {
|
||||
zero_prefixed_literal::check(cx, lit, &lit_snip)
|
||||
zero_prefixed_literal::check(cx, lit, &lit_snip);
|
||||
}
|
||||
} else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind {
|
||||
let suffix = float_ty.name_str();
|
||||
unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float")
|
||||
unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,9 +93,9 @@ impl MissingDoc {
|
|||
return;
|
||||
}
|
||||
|
||||
let has_doc = attrs.iter().any(|a| {
|
||||
a.is_doc_comment() || a.doc_str().is_some() || a.value_str().is_some() || Self::has_include(a.meta())
|
||||
});
|
||||
let has_doc = attrs
|
||||
.iter()
|
||||
.any(|a| a.doc_str().is_some() || Self::has_include(a.meta()));
|
||||
if !has_doc {
|
||||
span_lint(
|
||||
cx,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::sext;
|
||||
use if_chain::if_chain;
|
||||
|
|
|
@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
|
|||
let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap();
|
||||
let substs = cx.typeck_results().node_substs(e.hir_id);
|
||||
let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
|
||||
check_arguments(cx, arguments, method_type, &path.ident.as_str(), "method")
|
||||
check_arguments(cx, arguments, method_type, &path.ident.as_str(), "method");
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
|
|||
_ if !self.found => self.expr_span = Some(expr.span),
|
||||
_ => return,
|
||||
}
|
||||
walk_expr(self, expr)
|
||||
walk_expr(self, expr);
|
||||
}
|
||||
|
||||
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
||||
|
|
|
@ -121,7 +121,7 @@ impl EarlyLintPass for NeedlessArbitrarySelfType {
|
|||
match &p.ty.kind {
|
||||
TyKind::Path(None, path) => {
|
||||
if let PatKind::Ident(BindingMode::ByValue(mutbl), _, _) = p.pat.kind {
|
||||
check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl)
|
||||
check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl);
|
||||
}
|
||||
},
|
||||
TyKind::Rptr(lifetime, mut_ty) => {
|
||||
|
@ -129,7 +129,7 @@ impl EarlyLintPass for NeedlessArbitrarySelfType {
|
|||
if let TyKind::Path(None, path) = &mut_ty.ty.kind;
|
||||
if let PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, _) = p.pat.kind;
|
||||
then {
|
||||
check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl)
|
||||
check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
|
|||
}
|
||||
|
||||
if is_else_clause(cx.tcx, e) {
|
||||
snip = snip.blockify()
|
||||
snip = snip.blockify();
|
||||
}
|
||||
|
||||
span_lint_and_sugg(
|
||||
|
@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolComparison {
|
|||
|h: Sugg<'_>| !h,
|
||||
"equality checks against false can be replaced by a negation",
|
||||
));
|
||||
check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal)
|
||||
check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal);
|
||||
},
|
||||
BinOpKind::Ne => {
|
||||
let true_case = Some((
|
||||
|
@ -152,7 +152,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolComparison {
|
|||
"inequality checks against true can be replaced by a negation",
|
||||
));
|
||||
let false_case = Some((|h| h, "inequality checks against false are unnecessary"));
|
||||
check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal)
|
||||
check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal);
|
||||
},
|
||||
BinOpKind::Lt => check_comparison(
|
||||
cx,
|
||||
|
@ -251,22 +251,22 @@ fn check_comparison<'a, 'tcx>(
|
|||
snippet_with_applicability(cx, expression_info.right_span, "..", &mut applicability)
|
||||
),
|
||||
applicability,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
|
||||
(Bool(true), Other) => left_true.map_or((), |(h, m)| {
|
||||
suggest_bool_comparison(cx, e, right_side, applicability, m, h)
|
||||
suggest_bool_comparison(cx, e, right_side, applicability, m, h);
|
||||
}),
|
||||
(Other, Bool(true)) => right_true.map_or((), |(h, m)| {
|
||||
suggest_bool_comparison(cx, e, left_side, applicability, m, h)
|
||||
suggest_bool_comparison(cx, e, left_side, applicability, m, h);
|
||||
}),
|
||||
(Bool(false), Other) => left_false.map_or((), |(h, m)| {
|
||||
suggest_bool_comparison(cx, e, right_side, applicability, m, h)
|
||||
suggest_bool_comparison(cx, e, right_side, applicability, m, h);
|
||||
}),
|
||||
(Other, Bool(false)) => right_false.map_or((), |(h, m)| {
|
||||
suggest_bool_comparison(cx, e, left_side, applicability, m, h)
|
||||
suggest_bool_comparison(cx, e, left_side, applicability, m, h);
|
||||
}),
|
||||
(Other, Other) => no_literal.map_or((), |(h, m)| {
|
||||
let left_side = Sugg::hir_with_applicability(cx, left_side, "..", &mut applicability);
|
||||
|
@ -279,7 +279,7 @@ fn check_comparison<'a, 'tcx>(
|
|||
"try simplifying it as shown",
|
||||
h(left_side, right_side).to_string(),
|
||||
applicability,
|
||||
)
|
||||
);
|
||||
}),
|
||||
_ => (),
|
||||
}
|
||||
|
|
|
@ -3,16 +3,18 @@
|
|||
//! This lint is **warn** by default
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::is_automatically_derived;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::{snippet_opt, snippet_with_applicability, snippet_with_context};
|
||||
use clippy_utils::{get_parent_expr, in_macro, path_to_local};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::util::parser::PREC_POSTFIX;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BindingAnnotation, BorrowKind, Expr, ExprKind, Item, Mutability, Pat, PatKind};
|
||||
use rustc_hir::{BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, PatKind, UnOp};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for address of operations (`&`) that are going to
|
||||
|
@ -32,20 +34,70 @@ declare_clippy_lint! {
|
|||
/// let x: &i32 = &5;
|
||||
/// ```
|
||||
pub NEEDLESS_BORROW,
|
||||
nursery,
|
||||
style,
|
||||
"taking a reference that is going to be automatically dereferenced"
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NeedlessBorrow {
|
||||
derived_item: Option<LocalDefId>,
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for `ref` bindings which create a reference to a reference.
|
||||
///
|
||||
/// **Why is this bad?** The address-of operator at the use site is clearer about the need for a reference.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// // Bad
|
||||
/// let x = Some("");
|
||||
/// if let Some(ref x) = x {
|
||||
/// // use `x` here
|
||||
/// }
|
||||
///
|
||||
/// // Good
|
||||
/// let x = Some("");
|
||||
/// if let Some(x) = x {
|
||||
/// // use `&x` here
|
||||
/// }
|
||||
/// ```
|
||||
pub REF_BINDING_TO_REFERENCE,
|
||||
pedantic,
|
||||
"`ref` binding to a reference"
|
||||
}
|
||||
|
||||
impl_lint_pass!(NeedlessBorrow => [NEEDLESS_BORROW]);
|
||||
impl_lint_pass!(NeedlessBorrow => [NEEDLESS_BORROW, REF_BINDING_TO_REFERENCE]);
|
||||
#[derive(Default)]
|
||||
pub struct NeedlessBorrow {
|
||||
/// The body the first local was found in. Used to emit lints when the traversal of the body has
|
||||
/// been finished. Note we can't lint at the end of every body as they can be nested within each
|
||||
/// other.
|
||||
current_body: Option<BodyId>,
|
||||
/// The list of locals currently being checked by the lint.
|
||||
/// If the value is `None`, then the binding has been seen as a ref pattern, but is not linted.
|
||||
/// This is needed for or patterns where one of the branches can be linted, but another can not
|
||||
/// be.
|
||||
///
|
||||
/// e.g. `m!(x) | Foo::Bar(ref x)`
|
||||
ref_locals: FxIndexMap<HirId, Option<RefPat>>,
|
||||
}
|
||||
|
||||
struct RefPat {
|
||||
/// Whether every usage of the binding is dereferenced.
|
||||
always_deref: bool,
|
||||
/// The spans of all the ref bindings for this local.
|
||||
spans: Vec<Span>,
|
||||
/// The applicability of this suggestion.
|
||||
app: Applicability,
|
||||
/// All the replacements which need to be made.
|
||||
replacements: Vec<(Span, String)>,
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
if e.span.from_expansion() || self.derived_item.is_some() {
|
||||
if let Some(local) = path_to_local(e) {
|
||||
self.check_local_usage(cx, e, local);
|
||||
}
|
||||
|
||||
if e.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = e.kind {
|
||||
|
@ -85,50 +137,131 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
|
||||
if pat.span.from_expansion() || self.derived_item.is_some() {
|
||||
return;
|
||||
}
|
||||
if_chain! {
|
||||
if let PatKind::Binding(BindingAnnotation::Ref, .., name, _) = pat.kind;
|
||||
if let ty::Ref(_, tam, mutbl) = *cx.typeck_results().pat_ty(pat).kind();
|
||||
if mutbl == Mutability::Not;
|
||||
if let ty::Ref(_, _, mutbl) = *tam.kind();
|
||||
// only lint immutable refs, because borrowed `&mut T` cannot be moved out
|
||||
if mutbl == Mutability::Not;
|
||||
then {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
NEEDLESS_BORROW,
|
||||
pat.span,
|
||||
"this pattern creates a reference to a reference",
|
||||
|diag| {
|
||||
if let Some(snippet) = snippet_opt(cx, name.span) {
|
||||
diag.span_suggestion(
|
||||
pat.span,
|
||||
"change this to",
|
||||
snippet,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
if let PatKind::Binding(BindingAnnotation::Ref, id, name, _) = pat.kind {
|
||||
if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) {
|
||||
// This binding id has been seen before. Add this pattern to the list of changes.
|
||||
if let Some(prev_pat) = opt_prev_pat {
|
||||
if in_macro(pat.span) {
|
||||
// Doesn't match the context of the previous pattern. Can't lint here.
|
||||
*opt_prev_pat = None;
|
||||
} else {
|
||||
prev_pat.spans.push(pat.span);
|
||||
prev_pat.replacements.push((
|
||||
pat.span,
|
||||
snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut prev_pat.app)
|
||||
.0
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
if !in_macro(pat.span);
|
||||
if let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind();
|
||||
// only lint immutable refs, because borrowed `&mut T` cannot be moved out
|
||||
if let ty::Ref(_, _, Mutability::Not) = *tam.kind();
|
||||
then {
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let snip = snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut app).0;
|
||||
self.current_body = self.current_body.or(cx.enclosing_body);
|
||||
self.ref_locals.insert(
|
||||
id,
|
||||
Some(RefPat {
|
||||
always_deref: true,
|
||||
spans: vec![pat.span],
|
||||
app,
|
||||
replacements: vec![(pat.span, snip.into())],
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
if is_automatically_derived(attrs) {
|
||||
debug_assert!(self.derived_item.is_none());
|
||||
self.derived_item = Some(item.def_id);
|
||||
fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
|
||||
if Some(body.id()) == self.current_body {
|
||||
for pat in self.ref_locals.drain(..).filter_map(|(_, x)| x) {
|
||||
let replacements = pat.replacements;
|
||||
let app = pat.app;
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
if pat.always_deref {
|
||||
NEEDLESS_BORROW
|
||||
} else {
|
||||
REF_BINDING_TO_REFERENCE
|
||||
},
|
||||
pat.spans,
|
||||
"this pattern creates a reference to a reference",
|
||||
|diag| {
|
||||
diag.multipart_suggestion("try this", replacements, app);
|
||||
},
|
||||
);
|
||||
}
|
||||
self.current_body = None;
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item_post(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let Some(id) = self.derived_item {
|
||||
if item.def_id == id {
|
||||
self.derived_item = None;
|
||||
}
|
||||
impl NeedlessBorrow {
|
||||
fn check_local_usage(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, local: HirId) {
|
||||
if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
|
||||
if let Some(pat) = outer_pat {
|
||||
// Check for auto-deref
|
||||
if !matches!(
|
||||
cx.typeck_results().expr_adjustments(e),
|
||||
[
|
||||
Adjustment {
|
||||
kind: Adjust::Deref(_),
|
||||
..
|
||||
},
|
||||
Adjustment {
|
||||
kind: Adjust::Deref(_),
|
||||
..
|
||||
},
|
||||
..
|
||||
]
|
||||
) {
|
||||
match get_parent_expr(cx, e) {
|
||||
// Field accesses are the same no matter the number of references.
|
||||
Some(Expr {
|
||||
kind: ExprKind::Field(..),
|
||||
..
|
||||
}) => (),
|
||||
Some(&Expr {
|
||||
span,
|
||||
kind: ExprKind::Unary(UnOp::Deref, _),
|
||||
..
|
||||
}) if !in_macro(span) => {
|
||||
// Remove explicit deref.
|
||||
let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0;
|
||||
pat.replacements.push((span, snip.into()));
|
||||
},
|
||||
Some(parent) if !in_macro(parent.span) => {
|
||||
// Double reference might be needed at this point.
|
||||
if parent.precedence().order() == PREC_POSTFIX {
|
||||
// Parentheses would be needed here, don't lint.
|
||||
*outer_pat = None;
|
||||
} else {
|
||||
pat.always_deref = false;
|
||||
let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0;
|
||||
pat.replacements.push((e.span, format!("&{}", snip)));
|
||||
}
|
||||
},
|
||||
_ if !in_macro(e.span) => {
|
||||
// Double reference might be needed at this point.
|
||||
pat.always_deref = false;
|
||||
let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app);
|
||||
pat.replacements.push((e.span, format!("&{}", snip)));
|
||||
},
|
||||
// Edge case for macros. The span of the identifier will usually match the context of the
|
||||
// binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc
|
||||
// macros
|
||||
_ => *outer_pat = None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,10 +142,10 @@ impl<'tcx> Visitor<'tcx> for RetCollector {
|
|||
match expr.kind {
|
||||
ExprKind::Ret(..) => {
|
||||
if self.loop_depth > 0 && !self.ret_in_loop {
|
||||
self.ret_in_loop = true
|
||||
self.ret_in_loop = true;
|
||||
}
|
||||
|
||||
self.spans.push(expr.span)
|
||||
self.spans.push(expr.span);
|
||||
},
|
||||
|
||||
ExprKind::Loop(..) => {
|
||||
|
|
|
@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
|
|||
types produces code that is hard to read and refactor, please \
|
||||
consider using the `partial_cmp` method instead, to make it \
|
||||
clear that the two values could be incomparable"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use clippy_utils::consts::{self, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
|
||||
|
@ -5,8 +6,6 @@ use rustc_lint::{LateContext, LateLintPass};
|
|||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::Span;
|
||||
|
||||
use crate::consts::{self, Constant};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for multiplication by -1 as a form of negation.
|
||||
///
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
|
||||
use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::has_drop;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
|
|||
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
|
||||
if let StmtKind::Semi(expr) = stmt.kind {
|
||||
if has_no_effect(cx, expr) {
|
||||
span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect");
|
||||
span_lint_hir(cx, NO_EFFECT, expr.hir_id, stmt.span, "statement with no effect");
|
||||
} else if let Some(reduced) = reduce_expression(cx, expr) {
|
||||
let mut snippet = String::new();
|
||||
for e in reduced {
|
||||
|
@ -106,14 +106,15 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
|
|||
return;
|
||||
}
|
||||
}
|
||||
span_lint_and_sugg(
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
UNNECESSARY_OPERATION,
|
||||
expr.hir_id,
|
||||
stmt.span,
|
||||
"statement can be reduced",
|
||||
"replace it with",
|
||||
snippet,
|
||||
Applicability::MachineApplicable,
|
||||
|diag| {
|
||||
diag.span_suggestion(stmt.span, "replace it with", snippet, Applicability::MachineApplicable);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,6 +126,7 @@ const ALLOWED_TO_BE_SIMILAR: &[&[&str]] = &[
|
|||
&["args", "arms"],
|
||||
&["qpath", "path"],
|
||||
&["lit", "lint"],
|
||||
&["wparam", "lparam"],
|
||||
];
|
||||
|
||||
struct SimilarNamesNameVisitor<'a, 'tcx, 'b>(&'b mut SimilarNamesLocalVisitor<'a, 'tcx>);
|
||||
|
|
|
@ -123,7 +123,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
|
|||
"the method `create` is called more than once",
|
||||
);
|
||||
} else {
|
||||
create = true
|
||||
create = true;
|
||||
}
|
||||
create_arg = create_arg || (arg == Argument::True);
|
||||
},
|
||||
|
@ -136,7 +136,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
|
|||
"the method `append` is called more than once",
|
||||
);
|
||||
} else {
|
||||
append = true
|
||||
append = true;
|
||||
}
|
||||
append_arg = append_arg || (arg == Argument::True);
|
||||
},
|
||||
|
@ -149,7 +149,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
|
|||
"the method `truncate` is called more than once",
|
||||
);
|
||||
} else {
|
||||
truncate = true
|
||||
truncate = true;
|
||||
}
|
||||
truncate_arg = truncate_arg || (arg == Argument::True);
|
||||
},
|
||||
|
@ -162,7 +162,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
|
|||
"the method `read` is called more than once",
|
||||
);
|
||||
} else {
|
||||
read = true
|
||||
read = true;
|
||||
}
|
||||
read_arg = read_arg || (arg == Argument::True);
|
||||
},
|
||||
|
@ -175,7 +175,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
|
|||
"the method `write` is called more than once",
|
||||
);
|
||||
} else {
|
||||
write = true
|
||||
write = true;
|
||||
}
|
||||
write_arg = write_arg || (arg == Argument::True);
|
||||
},
|
||||
|
|
|
@ -102,10 +102,16 @@ declare_clippy_lint! {
|
|||
pub struct PassByRefOrValue {
|
||||
ref_min_size: u64,
|
||||
value_max_size: u64,
|
||||
avoid_breaking_exported_api: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> PassByRefOrValue {
|
||||
pub fn new(ref_min_size: Option<u64>, value_max_size: u64, target: &Target) -> Self {
|
||||
pub fn new(
|
||||
ref_min_size: Option<u64>,
|
||||
value_max_size: u64,
|
||||
avoid_breaking_exported_api: bool,
|
||||
target: &Target,
|
||||
) -> Self {
|
||||
let ref_min_size = ref_min_size.unwrap_or_else(|| {
|
||||
let bit_width = u64::from(target.pointer_width);
|
||||
// Cap the calculated bit width at 32-bits to reduce
|
||||
|
@ -120,10 +126,14 @@ impl<'tcx> PassByRefOrValue {
|
|||
Self {
|
||||
ref_min_size,
|
||||
value_max_size,
|
||||
avoid_breaking_exported_api,
|
||||
}
|
||||
}
|
||||
|
||||
fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, hir_id: HirId, decl: &FnDecl<'_>, span: Option<Span>) {
|
||||
if self.avoid_breaking_exported_api && cx.access_levels.is_exported(hir_id) {
|
||||
return;
|
||||
}
|
||||
let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
|
||||
|
||||
let fn_sig = cx.tcx.fn_sig(fn_def_id);
|
||||
|
@ -184,7 +194,6 @@ impl<'tcx> PassByRefOrValue {
|
|||
}
|
||||
|
||||
if_chain! {
|
||||
if !cx.access_levels.is_exported(hir_id);
|
||||
if is_copy(cx, ty);
|
||||
if !is_self_ty(input);
|
||||
if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes());
|
||||
|
|
|
@ -211,7 +211,7 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
|||
];
|
||||
|
||||
if_chain! {
|
||||
if let ExprKind::Call(ref fun, ref args) = expr.kind;
|
||||
if let ExprKind::Call(fun, args) = expr.kind;
|
||||
if let ExprKind::Path(ref qpath) = fun.kind;
|
||||
if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
|
||||
let fun_def_path = cx.get_def_path(fun_def_id).into_iter().map(Symbol::to_ident_string).collect::<Vec<_>>();
|
||||
|
|
|
@ -88,7 +88,7 @@ impl QuestionMark {
|
|||
"replace it with",
|
||||
replacement_str,
|
||||
applicability,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ impl QuestionMark {
|
|||
"replace it with",
|
||||
replacement,
|
||||
applicability,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
|
|
|
@ -57,7 +57,7 @@ impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor {
|
|||
self.found_return = true;
|
||||
}
|
||||
|
||||
ast_visit::walk_expr(self, ex)
|
||||
ast_visit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
|
|||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||
use clippy_utils::{match_def_path, paths};
|
||||
use if_chain::if_chain;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{constant_context, Constant};
|
||||
use clippy_utils::consts::{constant_context, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::in_macro;
|
||||
use clippy_utils::source::snippet;
|
||||
|
|
|
@ -139,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
|
|||
} else {
|
||||
RetReplacement::Empty
|
||||
};
|
||||
check_final_expr(cx, &body.value, Some(body.value.span), replacement)
|
||||
check_final_expr(cx, &body.value, Some(body.value.span), replacement);
|
||||
},
|
||||
FnKind::ItemFn(..) | FnKind::Method(..) => {
|
||||
if let ExprKind::Block(block, _) = body.value.kind {
|
||||
|
@ -241,7 +241,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Spa
|
|||
if let Some(snippet) = snippet_opt(cx, inner_span) {
|
||||
diag.span_suggestion(ret_span, "remove `return`", snippet, Applicability::MachineApplicable);
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
None => match replacement {
|
||||
RetReplacement::Empty => {
|
||||
|
|
|
@ -8,11 +8,11 @@ use rustc_lint::{LateContext, LateLintPass};
|
|||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Looks for blocks of expressions and fires if the last expression returns `()`
|
||||
/// but is not followed by a semicolon.
|
||||
/// **What it does:** Looks for blocks of expressions and fires if the last expression returns
|
||||
/// `()` but is not followed by a semicolon.
|
||||
///
|
||||
/// **Why is this bad?** The semicolon might be optional but when
|
||||
/// extending the block with new code, it doesn't require a change in previous last line.
|
||||
/// **Why is this bad?** The semicolon might be optional but when extending the block with new
|
||||
/// code, it doesn't require a change in previous last line.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
|
@ -30,7 +30,7 @@ declare_clippy_lint! {
|
|||
/// }
|
||||
/// ```
|
||||
pub SEMICOLON_IF_NOTHING_RETURNED,
|
||||
restriction,
|
||||
pedantic,
|
||||
"add a semicolon if nothing is returned"
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Bo
|
|||
let mut bindings = Vec::with_capacity(decl.inputs.len());
|
||||
for arg in iter_input_pats(decl, body) {
|
||||
if let PatKind::Binding(.., ident, _) = arg.pat.kind {
|
||||
bindings.push((ident.name, ident.span))
|
||||
bindings.push((ident.name, ident.span));
|
||||
}
|
||||
}
|
||||
check_expr(cx, &body.value, &mut bindings);
|
||||
|
@ -156,7 +156,7 @@ fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &
|
|||
..
|
||||
} = *local;
|
||||
if let Some(t) = *ty {
|
||||
check_ty(cx, t, bindings)
|
||||
check_ty(cx, t, bindings);
|
||||
}
|
||||
if let Some(o) = *init {
|
||||
check_expr(cx, o, bindings);
|
||||
|
@ -324,14 +324,14 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
|
|||
}
|
||||
match expr.kind {
|
||||
ExprKind::Unary(_, e) | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Box(e) => {
|
||||
check_expr(cx, e, bindings)
|
||||
check_expr(cx, e, bindings);
|
||||
},
|
||||
ExprKind::Block(block, _) | ExprKind::Loop(block, ..) => check_block(cx, block, bindings),
|
||||
// ExprKind::Call
|
||||
// ExprKind::MethodCall
|
||||
ExprKind::Array(v) | ExprKind::Tup(v) => {
|
||||
for e in v {
|
||||
check_expr(cx, e, bindings)
|
||||
check_expr(cx, e, bindings);
|
||||
}
|
||||
},
|
||||
ExprKind::If(cond, then, ref otherwise) => {
|
||||
|
@ -374,7 +374,7 @@ fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(
|
|||
TyKind::Ptr(MutTy { ty: mty, .. }) | TyKind::Rptr(_, MutTy { ty: mty, .. }) => check_ty(cx, mty, bindings),
|
||||
TyKind::Tup(tup) => {
|
||||
for t in tup {
|
||||
check_ty(cx, t, bindings)
|
||||
check_ty(cx, t, bindings);
|
||||
}
|
||||
},
|
||||
TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings),
|
||||
|
|
|
@ -70,7 +70,7 @@ fn check_mod(cx: &EarlyContext<'_>, items: &[P<Item>]) {
|
|||
for item in items {
|
||||
track_uses(
|
||||
cx,
|
||||
&item,
|
||||
item,
|
||||
&mut imports_reused_with_self,
|
||||
&mut single_use_usages,
|
||||
&mut macros,
|
||||
|
@ -117,7 +117,7 @@ fn track_uses(
|
|||
|
||||
match &item.kind {
|
||||
ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => {
|
||||
check_mod(cx, &items);
|
||||
check_mod(cx, items);
|
||||
},
|
||||
ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => {
|
||||
macros.push(item.ident.name);
|
||||
|
|
|
@ -158,7 +158,7 @@ impl SlowVectorInit {
|
|||
) {
|
||||
match initialization {
|
||||
InitializationType::Extend(e) | InitializationType::Resize(e) => {
|
||||
Self::emit_lint(cx, e, vec_alloc, "slow zero-filling initialization")
|
||||
Self::emit_lint(cx, e, vec_alloc, "slow zero-filling initialization");
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> {
|
|||
fn visit_block(&mut self, block: &'tcx Block<'_>) {
|
||||
if self.initialization_found {
|
||||
if let Some(s) = block.stmts.get(0) {
|
||||
self.visit_stmt(s)
|
||||
self.visit_stmt(s);
|
||||
}
|
||||
|
||||
self.initialization_found = false;
|
||||
|
|
|
@ -59,7 +59,7 @@ declare_clippy_lint! {
|
|||
/// }
|
||||
/// ```
|
||||
pub SUSPICIOUS_OPERATION_GROUPINGS,
|
||||
style,
|
||||
nursery,
|
||||
"groupings of binary operations that look suspiciously like typos"
|
||||
}
|
||||
|
||||
|
@ -266,7 +266,7 @@ fn emit_suggestion(cx: &EarlyContext<'_>, span: Span, sugg: String, applicabilit
|
|||
"did you mean",
|
||||
sugg,
|
||||
applicability,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
fn ident_swap_sugg(
|
||||
|
@ -475,7 +475,7 @@ impl Add for IdentLocation {
|
|||
|
||||
impl AddAssign for IdentLocation {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
*self = *self + other
|
||||
*self = *self + other;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,7 +506,7 @@ impl Add for IdentDifference {
|
|||
|
||||
impl AddAssign for IdentDifference {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
*self = *self + other
|
||||
*self = *self + other;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
|
|||
use clippy_utils::{in_macro, SpanlessHash};
|
||||
use if_chain::if_chain;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::unhash::UnhashMap;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{def::Res, GenericBound, Generics, ParamName, Path, QPath, TyKind, WherePredicate};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
@ -100,7 +101,7 @@ impl TraitBounds {
|
|||
hasher.hash_ty(ty);
|
||||
hasher.finish()
|
||||
};
|
||||
let mut map = FxHashMap::default();
|
||||
let mut map: UnhashMap<u64, Vec<&GenericBound<'_>>> = UnhashMap::default();
|
||||
let mut applicability = Applicability::MaybeIncorrect;
|
||||
for bound in gen.where_clause.predicates {
|
||||
if_chain! {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue