Skip to content

match_single_binding: match within a match suggests broken code #6572

@liquidnya

Description

@liquidnya

This issue is similar to #5347.
When a match could be written as a let statement and is within another match the suggested code by clippy will not compile, the suggested code needs to be put in curly brackets for it to compile.

I tried this code:

pub struct AppendIter<I>
where
    I: Iterator,
{
    inner: Option<(I, <I as Iterator>::Item)>,
}

pub fn size_hint<I: Iterator>(iter: &AppendIter<I>) -> (usize, Option<usize>) {
    match &iter.inner {
        Some((iter, _item)) => match iter.size_hint() {
            (min, max) => (
                min.saturating_add(1),
                max.and_then(|max| max.checked_add(1)),
            ),
        },
        None => (0, Some(0)),
    }
}

This code emits the following warning using cargo clippy:

warning: this match could be written as a `let` statement
  --> src/lib.rs:10:32
   |
10 |           Some((iter, _item)) => match iter.size_hint() {
   |  ________________________________^
11 | |             (min, max) => (
12 | |                 min.saturating_add(1),
13 | |                 max.and_then(|max| max.checked_add(1)),
14 | |             ),
15 | |         },
   | |_________^
   |
   = note: `#[warn(clippy::match_single_binding)]` on by default
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#match_single_binding
help: consider using `let` statement
   |
10 |         Some((iter, _item)) => let (min, max) = iter.size_hint();
11 |         (
12 |             min.saturating_add(1),
13 |             max.and_then(|max| max.checked_add(1)),
14 |         ),
   |

The suggested code in the help text will not compile cargo check:

error: expected one of `,`, `.`, `?`, `}`, or an operator, found `;`
  --> src/lib.rs:10:65
   |
10 |         Some((iter, _item)) => let (min, max) = iter.size_hint();
   |                             --                                  ^ expected one of `,`, `.`, `?`, `}`, or an operator
   |                             |
   |                             while parsing the `match` arm starting here

error[E0658]: `let` expressions in this position are experimental
  --> src/lib.rs:10:32
   |
10 |         Some((iter, _item)) => let (min, max) = iter.size_hint();
   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information

I suggest adding curly brackets to the help text like this:

        Some((iter, _item)) => {
            let (min, max) = iter.size_hint();
            (
                min.saturating_add(1),
                max.and_then(|max| max.checked_add(1)),
            )
        }

Meta

Tested with cargo clippy on the Rust Playground (as of 2021-01-10 14:31 UTC) as well as on my local installation:

  • cargo clippy on https://play.rust-lang.org/ as of 2021-01-10 14:31 UTC: 0.1.51 (2021-01-09 6184f23)
  • cargo clippy -V: clippy 0.0.212 (e1884a8 2020-12-29)
  • rustc -Vv:
    rustc 1.49.0 (e1884a8e3 2020-12-29)
    binary: rustc
    commit-hash: e1884a8e3c3e813aada8254edfa120e85bf5ffca
    commit-date: 2020-12-29
    host: x86_64-unknown-linux-gnu
    release: 1.49.0
    

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thingI-suggestion-causes-errorIssue: The suggestions provided by this Lint cause an ICE/error when applied

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions