rust-lang / rust-lang/rust-clippy

option_if_let_else suggestion does not compile

Open
#6,137 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug E-medium I-suggestion-causes-error L-nursery
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

I tried this code:

#![warn(clippy::all)]
#![warn(clippy::pedantic)]

use core::convert::TryFrom;

#[derive(Clone, Copy)]
struct X;

struct Foo;

impl From<X> for Option<Foo> {
    fn from(_: X) -> Self {
        Some(Foo)
    }
}

#[derive(Clone)]
struct Bar;

impl From<X> for Option<Bar> {
    fn from(_: X) -> Self {
        Some(Bar)
    }
}

pub struct NoBlockGiven(X);

impl From<X> for NoBlockGiven {
    fn from(value: X) -> Self {
        Self(value)
    }
}

impl TryFrom<X> for Bar {
    type Error = NoBlockGiven;

    fn try_from(value: X) -> Result<Self, Self::Error> {
        if let Some(block) = value.into() {
            Ok(block)
        } else {
            Err(NoBlockGiven::from(value))
        }
    }
}

Clippy made this suggestion:

$ cargo clippy
    Checking clippy-test v0.1.0 (/Users/lopopolo/Downloads/clippy-test)
warning: use Option::map_or instead of an if let/else
  --> src/lib.rs:38:9
   |
38 | /         if let Some(block) = value.into() {
39 | |             Ok(block)
40 | |         } else {
41 | |             Err(NoBlockGiven::from(value))
42 | |         }
   | |_________^ help: try: `value.into().map_or(Err(NoBlockGiven::from(value)), |block| Ok(block))`
   |
note: the lint level is defined here
  --> src/lib.rs:2:9
   |
2  | #![warn(clippy::pedantic)]
   |         ^^^^^^^^^^^^^^^^
   = note: `#[warn(clippy::option_if_let_else)]` implied by `#[warn(clippy::pedantic)]`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#option_if_let_else

warning: 1 warning emitted

    Finished dev [unoptimized + debuginfo] target(s) in 0.08s

Applying the fix results in code that does not compile:

#![warn(clippy::all)]
#![warn(clippy::pedantic)]

use core::convert::TryFrom;

#[derive(Clone, Copy)]
struct X;

struct Foo;

impl From<X> for Option<Foo> {
    fn from(_: X) -> Self {
        Some(Foo)
    }
}

#[derive(Clone)]
struct Bar;

impl From<X> for Option<Bar> {
    fn from(_: X) -> Self {
        Some(Bar)
    }
}

pub struct NoBlockGiven(X);

impl From<X> for NoBlockGiven {
    fn from(value: X) -> Self {
        Self(value)
    }
}

impl TryFrom<X> for Bar {
    type Error = NoBlockGiven;

    fn try_from(value: X) -> Result<Self, Self::Error> {
        value
            .into()
            .map_or(Err(NoBlockGiven::from(value)), |block| Ok(block))
    }
}
$ cargo clippy
    Checking clippy-test v0.1.0 (/Users/lopopolo/Downloads/clippy-test)
error[E0282]: type annotations needed
  --> src/lib.rs:39:14
   |
38 | /         value
39 | |             .into()
   | |______________^^^^_- this method call resolves to `T`
   |                |
   |                cannot infer type for type parameter `T` declared on the trait `Into`
   |
   = note: type must be known at this point

error: aborting due to previous error

For more information about this error, try `rustc --explain E0282`.
error: could not compile `clippy-test`.

To learn more, run the command again with --verbose.
Meta
  • cargo clippy -V: clippy 0.0.212 (18bf6b4f0 2020-10-07)
  • rustc -Vv:
    rustc 1.47.0 (18bf6b4f0 2020-10-07)
    binary: rustc
    commit-hash: 18bf6b4f01a6feaf7259ba7cdae58031af1b7b39
    commit-date: 2020-10-07
    host: x86_64-apple-darwin
    release: 1.47.0
    LLVM version: 11.0
    

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the option_if_let_else lint and reproduce the failure using the Rust example in src/lib.rs, then run cargo clippy to inspect the suggested rewrite. Done means the lint's suggestion compiles for this case and a regression test covers the ambiguous Into conversion.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.