Merge commit '3ae8faff4d46ad92f194c2a4b941c3152a701b31' into clippyup

This commit is contained in:
flip1995 2021-06-03 08:41:37 +02:00
parent 91aa821745
commit 6c27482115
189 changed files with 2372 additions and 1310 deletions

View File

@ -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

View File

@ -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

View File

@ -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`

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -0,0 +1 @@
avoid-breaking-exported-api = false

View File

@ -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;

View File

@ -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};

View File

@ -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") {

View File

@ -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()));
}
}
}

View File

@ -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));
}
}

View File

@ -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() {

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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`",
)
);
}
}

View File

@ -1 +0,0 @@
pub use clippy_utils::consts::*;

View File

@ -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<'_>| {

View File

@ -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);
}
},

View File

@ -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"
}

View File

@ -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!(==);
},
_ => (),
};

View File

@ -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;

View File

@ -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);
}

View File

@ -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};

View File

@ -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));
}

View File

@ -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
);
})
});
}
},
_ => {},

View File

@ -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`.
///

View File

@ -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
})
}

View File

@ -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);

View File

@ -1,4 +1,4 @@
use crate::consts::{
use clippy_utils::consts::{
constant, constant_simple, Constant,
Constant::{Int, F32, F64},
};

View File

@ -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);
},
_ => {},
}

View File

@ -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`",
);
}
}

View File

@ -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
),
)
);
}
}

View File

@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
));
}
}
})
});
},
);
}

View File

@ -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};

View File

@ -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)]

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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"
)
);
}
}
}

View File

@ -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, its 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, its used in `update_lints`
// begin register lints, do not remove this comment, its 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, its 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]

View File

@ -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> {

View File

@ -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);
});
}
}

View File

@ -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

View File

@ -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));
}
}
}

View File

@ -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| {

View File

@ -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) {

View File

@ -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> {

View File

@ -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;

View File

@ -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,
)
);
}
}
}

View File

@ -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()))),
)
);
});
}
}

View File

@ -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;

View File

@ -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,
)
);
}
}

View File

@ -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));

View File

@ -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",

View File

@ -135,7 +135,7 @@ pub(crate) trait BindInsteadOfMap {
.into_iter()
.map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())),
),
)
);
});
true
}

View File

@ -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,

View File

@ -41,5 +41,5 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span,
"try",
"copied".into(),
Applicability::MachineApplicable,
)
);
}

View File

@ -30,5 +30,5 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, arg
"try",
"filter_map".into(),
Applicability::MachineApplicable,
)
);
}

View File

@ -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()

View File

@ -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;

View File

@ -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;

View 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
)
}
}
}

View File

@ -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);
}
}

View 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,
);
}
}
}

View File

@ -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);
},
_ => (),
}

View File

@ -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 {}",

View File

@ -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;

View File

@ -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| {

View File

@ -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");
}
}
}

View File

@ -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,

View File

@ -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;

View File

@ -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");
},
_ => (),
}

View File

@ -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> {

View File

@ -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);
}
}
},

View File

@ -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,
)
);
}),
_ => (),
}

View File

@ -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,
}
}
}
}
}

View File

@ -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(..) => {

View File

@ -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"
)
);
}
}
}

View File

@ -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.
///

View File

@ -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);
},
);
}
}

View File

@ -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>);

View File

@ -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);
},

View File

@ -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());

View File

@ -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<_>>();

View File

@ -88,7 +88,7 @@ impl QuestionMark {
"replace it with",
replacement_str,
applicability,
)
);
}
}
}
@ -129,7 +129,7 @@ impl QuestionMark {
"replace it with",
replacement,
applicability,
)
);
}
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
Applicability::MachineApplicable,
);
},
)
);
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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 => {

View File

@ -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"
}

View File

@ -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),

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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