RS.CLIPPY.REDUNDANT_PATTERN_MATCHING

Use the proper utility function avoiding an `if let`

This checker is a Clippy lint created by The Rust Project Contributors. The documentation shown here is a copy of the original documentation for: redundant_pattern_matching. Copyright ©2025 The Rust Team. All rights reserved.

What it does

Lint for redundant pattern matching over Result, Option, std::task::Poll, std::net::IpAddr or bools

Why is this bad?

It's more concise and clear to just use the proper utility function or using the condition directly

Known problems

For suggestions involving bindings in patterns, this will change the drop order for the matched type. Both if let and while let will drop the value at the end of the block, both if and while will drop the value before entering the block. For most types this change will not matter, but for a few types this will not be an acceptable change (e.g. locks). See the reference for more about drop order.

Example

if let Ok(_) = Ok::<i32, i32>(42) {}
if let Err(_) = Err::<i32, i32>(42) {}
if let None = None::<()> {}
if let Some(_) = Some(42) {}
if let Poll::Pending = Poll::Pending::<()> {}
if let Poll::Ready(_) = Poll::Ready(42) {}
if let IpAddr::V4(_) = IpAddr::V4(Ipv4Addr::LOCALHOST) {}
if let IpAddr::V6(_) = IpAddr::V6(Ipv6Addr::LOCALHOST) {}
match Ok::<i32, i32>(42) {
    Ok(_) => true,
    Err(_) => false,
};

let cond = true;
if let true = cond {}
matches!(cond, true);

The more idiomatic use would be:

if Ok::<i32, i32>(42).is_ok() {}
if Err::<i32, i32>(42).is_err() {}
if None::<()>.is_none() {}
if Some(42).is_some() {}
if Poll::Pending::<()>.is_pending() {}
if Poll::Ready(42).is_ready() {}
if IpAddr::V4(Ipv4Addr::LOCALHOST).is_ipv4() {}
if IpAddr::V6(Ipv6Addr::LOCALHOST).is_ipv6() {}
Ok::<i32, i32>(42).is_ok();

let cond = true;
if cond {}
cond;

Past names

  • if_let_redundant_pattern_matching