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:
Samuel Tardieu 2025-03-26 20:38:58 +01:00
parent cd70152470
commit 79c69112dc
135 changed files with 1870 additions and 1913 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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, [], _) => {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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