Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New lint: map_unwrap_or_bool #5895

Open
jhwgh1968 opened this issue Aug 12, 2020 · 5 comments
Open

New lint: map_unwrap_or_bool #5895

jhwgh1968 opened this issue Aug 12, 2020 · 5 comments
Labels
A-lint Area: New lints

Comments

@jhwgh1968
Copy link

jhwgh1968 commented Aug 12, 2020

What it does

This lint discourages a less readable idiom when checking an operation which returns an Option<T> chained with a boolean predicate.

My main motivation is to avoid a bad habit of mine while I was still learning all the parts of the APIs. I imagine I am not the only one who learned it.

Categories

  • Kind: clippy::pedantic

What is the advantage of the recommended code over the original code

  • Makes the intention clearer
  • Uses a function that is literally designed for this
  • Allows additional access to the returned value, such as let Some(...) clauses

Drawbacks

Could be superseded by rust-lang/rust#75298

Example

fn main() {
    let https_proxy: Option<String> = std::env::var("HTTPS_PROXY").ok();

    if https_proxy.map(|v| v.starts_with("https://")).unwrap_or(false) {
        eprintln!("You have an HTTPS proxy set in the environment");
    } else {
        eprintln!("You do not have an HTTPS proxy set in the environment");
    }
}

Could be written as:

fn main() {
    let https_proxy: Option<String> = std::env::var("HTTPS_PROXY").ok();

    if https_proxy.filter(|v| v.starts_with("https://")).is_some() {
        eprintln!("You have an HTTPS proxy set in the environment");
    } else {
        eprintln!("You do not have an HTTPS proxy set in the environment");
    }
}
@jhwgh1968 jhwgh1968 added the A-lint Area: New lints label Aug 12, 2020
@jhwgh1968
Copy link
Author

Hmm, that doesn't quite work, does it? Surely there must be some way to handle that operator chaining better...

@jhwgh1968
Copy link
Author

Ah, it's filter. I'll update the issue.

@jhwgh1968 jhwgh1968 changed the title New lint: unwrap_or_bool New lint: map_unwrap_or_bool Aug 12, 2020
@ghost
Copy link

ghost commented Aug 12, 2020

This seems like it belongs in pedantic to me.

I prefer both to comparison with Some(true) which I see every now and then.

if https_proxy.map(|v| v.starts_with("https://")) == Some(true) {
     //...
}

Also Clippy will ask you to use map_or in the first example.
map_unwrap_or

@jhwgh1968
Copy link
Author

This seems like it belongs in pedantic to me.

I did not update that part after my edit. Perhaps you are right. I will fix that.

Also Clippy will ask you to use map_or in the first example.
map_unwrap_or

I saw that lint, but even specifying -D clippy::pedantic I couldn't get it to trigger on my code example. I presumed it had an exception for booleans.

Even if I am wrong, though, I feel there is a better suggestion than unwrap_or(false, |c| c.condition()). If I don't get much agreement that my suggestion is an improvement, I would be willing to take others.


Related, which I just found: rust-lang/rust#75298

Ironically, the only alternative not mentioned in that discussion is what I suggested linting this to.

@ghost
Copy link

ghost commented Aug 13, 2020

I actually think map_or looks the best. I like that it's compact and the default is close to the mapping function. Let's see what others think.

I saw that lint, but even specifying -D clippy::pedantic I couldn't get it to trigger on my code example. I presumed it had an exception for booleans.

It works for me. Playground

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints
Projects
None yet
Development

No branches or pull requests

1 participant