Apply collapsible_if to Clippy itself
Since Clippy uses the `let_chains` feature, there are many occasions to collapse `if` and `if let` statements.
This commit is contained in:
parent
cd70152470
commit
79c69112dc
135 changed files with 1870 additions and 1913 deletions
|
|
@ -192,10 +192,10 @@ impl BindInsteadOfMap {
|
|||
}
|
||||
|
||||
fn is_variant(&self, cx: &LateContext<'_>, res: Res) -> bool {
|
||||
if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
|
||||
if let Some(variant_id) = cx.tcx.lang_items().get(self.variant_lang_item) {
|
||||
return cx.tcx.parent(id) == variant_id;
|
||||
}
|
||||
if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res
|
||||
&& let Some(variant_id) = cx.tcx.lang_items().get(self.variant_lang_item)
|
||||
{
|
||||
return cx.tcx.parent(id) == variant_id;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ pub(super) fn check<'tcx>(
|
|||
arg: &'tcx Expr<'_>,
|
||||
msrv: Msrv,
|
||||
) {
|
||||
if let ExprKind::MethodCall(path_segment, ..) = recv.kind {
|
||||
if matches!(
|
||||
if let ExprKind::MethodCall(path_segment, ..) = recv.kind
|
||||
&& matches!(
|
||||
path_segment.ident.name.as_str(),
|
||||
"to_lowercase" | "to_uppercase" | "to_ascii_lowercase" | "to_ascii_uppercase"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ pub(super) fn check(
|
|||
.map_or_else(|| cx.typeck_results().expr_ty(arg), |a| a.target);
|
||||
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if let ty::Ref(_, inner, _) = arg_ty.kind() {
|
||||
if let ty::Ref(..) = inner.kind() {
|
||||
return; // don't report clone_on_copy
|
||||
}
|
||||
if let ty::Ref(_, inner, _) = arg_ty.kind()
|
||||
&& let ty::Ref(..) = inner.kind()
|
||||
{
|
||||
return; // don't report clone_on_copy
|
||||
}
|
||||
|
||||
if is_copy(cx, ty) {
|
||||
|
|
|
|||
|
|
@ -54,10 +54,11 @@ pub(super) fn check<'tcx>(
|
|||
if is_type_lang_item(cx, arg_ty, hir::LangItem::String) {
|
||||
return false;
|
||||
}
|
||||
if let ty::Ref(_, ty, ..) = arg_ty.kind() {
|
||||
if ty.is_str() && can_be_static_str(cx, arg) {
|
||||
return false;
|
||||
}
|
||||
if let ty::Ref(_, ty, ..) = arg_ty.kind()
|
||||
&& ty.is_str()
|
||||
&& can_be_static_str(cx, arg)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,15 +14,13 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
|
|||
if expr.span.in_external_macro(cx.sess().source_map()) || !receiver.span.eq_ctxt(expr.span) {
|
||||
return;
|
||||
}
|
||||
if let Some(parent) = get_parent_expr(cx, expr) {
|
||||
if let Some(parent) = get_parent_expr(cx, parent) {
|
||||
if is_inside_always_const_context(cx.tcx, expr.hir_id)
|
||||
&& let Some(macro_call) = root_macro_call(parent.span)
|
||||
&& is_assert_macro(cx, macro_call.def_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if let Some(parent) = get_parent_expr(cx, expr)
|
||||
&& let Some(parent) = get_parent_expr(cx, parent)
|
||||
&& is_inside_always_const_context(cx.tcx, expr.hir_id)
|
||||
&& let Some(macro_call) = root_macro_call(parent.span)
|
||||
&& is_assert_macro(cx, macro_call.def_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
let init_expr = expr_or_init(cx, receiver);
|
||||
if !receiver.span.eq_ctxt(init_expr.span) {
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ use rustc_span::sym;
|
|||
use super::ITERATOR_STEP_BY_ZERO;
|
||||
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) {
|
||||
if is_trait_method(cx, expr, sym::Iterator) {
|
||||
if let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg) {
|
||||
span_lint(
|
||||
cx,
|
||||
ITERATOR_STEP_BY_ZERO,
|
||||
expr.span,
|
||||
"`Iterator::step_by(0)` will panic at runtime",
|
||||
);
|
||||
}
|
||||
if is_trait_method(cx, expr, sym::Iterator)
|
||||
&& let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg)
|
||||
{
|
||||
span_lint(
|
||||
cx,
|
||||
ITERATOR_STEP_BY_ZERO,
|
||||
expr.span,
|
||||
"`Iterator::step_by(0)` will panic at runtime",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,15 +106,15 @@ fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<MinMax> {
|
|||
};
|
||||
|
||||
let check_lit = |expr: &hir::Expr<'_>, check_min: bool| {
|
||||
if let hir::ExprKind::Lit(lit) = &expr.kind {
|
||||
if let ast::LitKind::Int(value, _) = lit.node {
|
||||
if value == maxval {
|
||||
return Some(MinMax::Max);
|
||||
}
|
||||
if let hir::ExprKind::Lit(lit) = &expr.kind
|
||||
&& let ast::LitKind::Int(value, _) = lit.node
|
||||
{
|
||||
if value == maxval {
|
||||
return Some(MinMax::Max);
|
||||
}
|
||||
|
||||
if check_min && value == minval {
|
||||
return Some(MinMax::Min);
|
||||
}
|
||||
if check_min && value == minval {
|
||||
return Some(MinMax::Min);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,10 +125,10 @@ fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<MinMax> {
|
|||
return r;
|
||||
}
|
||||
|
||||
if ty.is_signed() {
|
||||
if let hir::ExprKind::Unary(hir::UnOp::Neg, val) = &expr.kind {
|
||||
return check_lit(val, true);
|
||||
}
|
||||
if ty.is_signed()
|
||||
&& let hir::ExprKind::Unary(hir::UnOp::Neg, val) = &expr.kind
|
||||
{
|
||||
return check_lit(val, true);
|
||||
}
|
||||
|
||||
None
|
||||
|
|
|
|||
|
|
@ -51,19 +51,19 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
|
|||
let closure_expr = peel_blocks(closure_body.value);
|
||||
match closure_body.params[0].pat.kind {
|
||||
hir::PatKind::Ref(inner, Mutability::Not) => {
|
||||
if let hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) = inner.kind {
|
||||
if ident_eq(name, closure_expr) {
|
||||
lint_explicit_closure(cx, e.span, recv.span, true, msrv);
|
||||
}
|
||||
if let hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) = inner.kind
|
||||
&& ident_eq(name, closure_expr)
|
||||
{
|
||||
lint_explicit_closure(cx, e.span, recv.span, true, msrv);
|
||||
}
|
||||
},
|
||||
hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) => {
|
||||
match closure_expr.kind {
|
||||
hir::ExprKind::Unary(hir::UnOp::Deref, inner) => {
|
||||
if ident_eq(name, inner) {
|
||||
if let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() {
|
||||
lint_explicit_closure(cx, e.span, recv.span, true, msrv);
|
||||
}
|
||||
if ident_eq(name, inner)
|
||||
&& let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind()
|
||||
{
|
||||
lint_explicit_closure(cx, e.span, recv.span, true, msrv);
|
||||
}
|
||||
},
|
||||
hir::ExprKind::MethodCall(method, obj, [], _) => {
|
||||
|
|
|
|||
|
|
@ -4667,11 +4667,12 @@ impl_lint_pass!(Methods => [
|
|||
pub fn method_call<'tcx>(
|
||||
recv: &'tcx Expr<'tcx>,
|
||||
) -> Option<(&'tcx str, &'tcx Expr<'tcx>, &'tcx [Expr<'tcx>], Span, Span)> {
|
||||
if let ExprKind::MethodCall(path, receiver, args, call_span) = recv.kind {
|
||||
if !args.iter().any(|e| e.span.from_expansion()) && !receiver.span.from_expansion() {
|
||||
let name = path.ident.name.as_str();
|
||||
return Some((name, receiver, args, path.ident.span, call_span));
|
||||
}
|
||||
if let ExprKind::MethodCall(path, receiver, args, call_span) = recv.kind
|
||||
&& !args.iter().any(|e| e.span.from_expansion())
|
||||
&& !receiver.span.from_expansion()
|
||||
{
|
||||
let name = path.ident.name.as_str();
|
||||
return Some((name, receiver, args, path.ident.span, call_span));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -377,20 +377,20 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
if let Some(hir_id) = path_to_local(recv) {
|
||||
if let Some(index) = self.hir_id_uses_map.remove(&hir_id) {
|
||||
if self
|
||||
.illegal_mutable_capture_ids
|
||||
.intersection(&self.current_mutably_captured_ids)
|
||||
.next()
|
||||
.is_none()
|
||||
{
|
||||
if let Some(hir_id) = self.current_statement_hir_id {
|
||||
self.hir_id_uses_map.insert(hir_id, index);
|
||||
}
|
||||
} else {
|
||||
self.uses[index] = None;
|
||||
if let Some(hir_id) = path_to_local(recv)
|
||||
&& let Some(index) = self.hir_id_uses_map.remove(&hir_id)
|
||||
{
|
||||
if self
|
||||
.illegal_mutable_capture_ids
|
||||
.intersection(&self.current_mutably_captured_ids)
|
||||
.next()
|
||||
.is_none()
|
||||
{
|
||||
if let Some(hir_id) = self.current_statement_hir_id {
|
||||
self.hir_id_uses_map.insert(hir_id, index);
|
||||
}
|
||||
} else {
|
||||
self.uses[index] = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,26 +9,27 @@ use super::NEEDLESS_OPTION_TAKE;
|
|||
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
|
||||
// Checks if expression type is equal to sym::Option and if the expr is not a syntactic place
|
||||
if !recv.is_syntactic_place_expr() && is_expr_option(cx, recv) {
|
||||
if let Some(function_name) = source_of_temporary_value(recv) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
NEEDLESS_OPTION_TAKE,
|
||||
expr.span,
|
||||
"called `Option::take()` on a temporary value",
|
||||
|diag| {
|
||||
diag.note(format!(
|
||||
"`{function_name}` creates a temporary value, so calling take() has no effect"
|
||||
));
|
||||
diag.span_suggestion(
|
||||
expr.span.with_lo(recv.span.hi()),
|
||||
"remove",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
if !recv.is_syntactic_place_expr()
|
||||
&& is_expr_option(cx, recv)
|
||||
&& let Some(function_name) = source_of_temporary_value(recv)
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
NEEDLESS_OPTION_TAKE,
|
||||
expr.span,
|
||||
"called `Option::take()` on a temporary value",
|
||||
|diag| {
|
||||
diag.note(format!(
|
||||
"`{function_name}` creates a temporary value, so calling take() has no effect"
|
||||
));
|
||||
diag.span_suggestion(
|
||||
expr.span.with_lo(recv.span.hi()),
|
||||
"remove",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -44,10 +45,10 @@ fn is_expr_option(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
|||
fn source_of_temporary_value<'a>(expr: &'a Expr<'_>) -> Option<&'a str> {
|
||||
match expr.peel_borrows().kind {
|
||||
ExprKind::Call(function, _) => {
|
||||
if let ExprKind::Path(QPath::Resolved(_, func_path)) = function.kind {
|
||||
if !func_path.segments.is_empty() {
|
||||
return Some(func_path.segments[0].ident.name.as_str());
|
||||
}
|
||||
if let ExprKind::Path(QPath::Resolved(_, func_path)) = function.kind
|
||||
&& !func_path.segments.is_empty()
|
||||
{
|
||||
return Some(func_path.segments[0].ident.name.as_str());
|
||||
}
|
||||
if let ExprKind::Path(QPath::TypeRelative(_, func_path_segment)) = function.kind {
|
||||
return Some(func_path_segment.ident.name.as_str());
|
||||
|
|
|
|||
|
|
@ -15,21 +15,22 @@ use super::SEEK_FROM_CURRENT;
|
|||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) {
|
||||
let ty = cx.typeck_results().expr_ty(recv);
|
||||
|
||||
if let Some(def_id) = cx.tcx.get_diagnostic_item(sym::IoSeek) {
|
||||
if implements_trait(cx, ty, def_id, &[]) && arg_is_seek_from_current(cx, arg) {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability);
|
||||
if let Some(def_id) = cx.tcx.get_diagnostic_item(sym::IoSeek)
|
||||
&& implements_trait(cx, ty, def_id, &[])
|
||||
&& arg_is_seek_from_current(cx, arg)
|
||||
{
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability);
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SEEK_FROM_CURRENT,
|
||||
expr.span,
|
||||
"using `SeekFrom::Current` to start from current position",
|
||||
"replace with",
|
||||
format!("{snip}.stream_position()"),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SEEK_FROM_CURRENT,
|
||||
expr.span,
|
||||
"using `SeekFrom::Current` to start from current position",
|
||||
"replace with",
|
||||
format!("{snip}.stream_position()"),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -238,15 +238,14 @@ fn indirect_usage<'tcx>(
|
|||
unwrap_kind: Some(unwrap_kind),
|
||||
..
|
||||
} = iter_usage
|
||||
&& parent_id == local_hir_id
|
||||
{
|
||||
if parent_id == local_hir_id {
|
||||
return Some(IndirectUsage {
|
||||
name: ident.name,
|
||||
span: stmt.span,
|
||||
init_expr,
|
||||
unwrap_kind,
|
||||
});
|
||||
}
|
||||
return Some(IndirectUsage {
|
||||
name: ident.name,
|
||||
span: stmt.span,
|
||||
init_expr,
|
||||
unwrap_kind,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<
|
|||
&& let closure_body = cx.tcx.hir_body(closure.body)
|
||||
&& !cx.typeck_results().expr_ty(closure_body.value).is_unit()
|
||||
{
|
||||
if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) {
|
||||
if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx)
|
||||
// A variable is used mutably inside of the closure. Suppress the lint.
|
||||
if !map_mutated_vars.is_empty() {
|
||||
return;
|
||||
}
|
||||
&& !map_mutated_vars.is_empty()
|
||||
{
|
||||
return;
|
||||
}
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
|
|
|
|||
|
|
@ -23,56 +23,56 @@ pub(super) fn check<'tcx>(
|
|||
let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
|
||||
let is_bool = cx.typeck_results().expr_ty(recv).is_bool();
|
||||
|
||||
if is_option || is_result || is_bool {
|
||||
if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl, .. }) = arg.kind {
|
||||
let body = cx.tcx.hir_body(body);
|
||||
let body_expr = &body.value;
|
||||
if (is_option || is_result || is_bool)
|
||||
&& let hir::ExprKind::Closure(&hir::Closure { body, fn_decl, .. }) = arg.kind
|
||||
{
|
||||
let body = cx.tcx.hir_body(body);
|
||||
let body_expr = &body.value;
|
||||
|
||||
if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) {
|
||||
return false;
|
||||
}
|
||||
if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if eager_or_lazy::switch_to_eager_eval(cx, body_expr) {
|
||||
let msg = if is_option {
|
||||
"unnecessary closure used to substitute value for `Option::None`"
|
||||
} else if is_result {
|
||||
"unnecessary closure used to substitute value for `Result::Err`"
|
||||
} else {
|
||||
"unnecessary closure used with `bool::then`"
|
||||
};
|
||||
let applicability = if body
|
||||
.params
|
||||
.iter()
|
||||
// bindings are checked to be unused above
|
||||
.all(|param| matches!(param.pat.kind, hir::PatKind::Binding(..) | hir::PatKind::Wild))
|
||||
&& matches!(
|
||||
fn_decl.output,
|
||||
FnRetTy::DefaultReturn(_)
|
||||
| FnRetTy::Return(hir::Ty {
|
||||
kind: hir::TyKind::Infer(()),
|
||||
..
|
||||
})
|
||||
) {
|
||||
Applicability::MachineApplicable
|
||||
} else {
|
||||
// replacing the lambda may break type inference
|
||||
Applicability::MaybeIncorrect
|
||||
};
|
||||
if eager_or_lazy::switch_to_eager_eval(cx, body_expr) {
|
||||
let msg = if is_option {
|
||||
"unnecessary closure used to substitute value for `Option::None`"
|
||||
} else if is_result {
|
||||
"unnecessary closure used to substitute value for `Result::Err`"
|
||||
} else {
|
||||
"unnecessary closure used with `bool::then`"
|
||||
};
|
||||
let applicability = if body
|
||||
.params
|
||||
.iter()
|
||||
// bindings are checked to be unused above
|
||||
.all(|param| matches!(param.pat.kind, hir::PatKind::Binding(..) | hir::PatKind::Wild))
|
||||
&& matches!(
|
||||
fn_decl.output,
|
||||
FnRetTy::DefaultReturn(_)
|
||||
| FnRetTy::Return(hir::Ty {
|
||||
kind: hir::TyKind::Infer(()),
|
||||
..
|
||||
})
|
||||
) {
|
||||
Applicability::MachineApplicable
|
||||
} else {
|
||||
// replacing the lambda may break type inference
|
||||
Applicability::MaybeIncorrect
|
||||
};
|
||||
|
||||
// This is a duplicate of what's happening in clippy_lints::methods::method_call,
|
||||
// which isn't ideal, We want to get the method call span,
|
||||
// but prefer to avoid changing the signature of the function itself.
|
||||
if let hir::ExprKind::MethodCall(.., span) = expr.kind {
|
||||
span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
|
||||
diag.span_suggestion_verbose(
|
||||
span,
|
||||
format!("use `{simplify_using}` instead"),
|
||||
format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")),
|
||||
applicability,
|
||||
);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
// This is a duplicate of what's happening in clippy_lints::methods::method_call,
|
||||
// which isn't ideal, We want to get the method call span,
|
||||
// but prefer to avoid changing the signature of the function itself.
|
||||
if let hir::ExprKind::MethodCall(.., span) = expr.kind {
|
||||
span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
|
||||
diag.span_suggestion_verbose(
|
||||
span,
|
||||
format!("use `{simplify_using}` instead"),
|
||||
format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")),
|
||||
applicability,
|
||||
);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue