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: if let Some iter element #6564

Closed
camsteffen opened this issue Jan 7, 2021 · 7 comments
Closed

New lint: if let Some iter element #6564

camsteffen opened this issue Jan 7, 2021 · 7 comments
Labels
A-lint Area: New lints good-first-issue These issues are a good way to get started with Clippy L-complexity Lint: Belongs in the complexity lint group

Comments

@camsteffen
Copy link
Contributor

What it does

Checks for iteration of Options with if let Some inside. Can use flatten() instead. The lint should also work in iter.for_each().

Categories (optional)

  • Kind: complexity

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

It is simpler.

Drawbacks

None.

Example

for x in y {
    if let Some(z) = x {
        println!("{}", z);
    }
}

Could be written as:

for z in y.flatten() {
    println!("{}", z);
}
@camsteffen camsteffen added A-lint Area: New lints L-complexity Lint: Belongs in the complexity lint group good-first-issue These issues are a good way to get started with Clippy labels Jan 7, 2021
@nahuakang
Copy link
Contributor

Nice suggestion Cam 😄 Can I take this issue?

@camsteffen
Copy link
Contributor Author

@nahuakang yes!

@camsteffen
Copy link
Contributor Author

It can also cover option.map(), result.map() and if let Ok.

@nahuakang
Copy link
Contributor

@flip1995 @camsteffen I've started looking into the code base. Seems like this lint should be included in loops.rs and be run inside fn check_for_loop?

Cam, can I cover the original case first before looking into option.map(), result.map() and if let Ok? (I also don't understand them unless you give some snippets 🙈)

@camsteffen
Copy link
Contributor Author

Seems like this lint should be included in loops.rs and be run inside fn check_for_loop?

Sounds like a good start!

Cam, can I cover the original case first before looking into option.map(), result.map() and if let Ok?

Absolutely. You can always leave some cases to be added later as an enhancement. You also can open a PR to get feedback before you are done.

Here are some examples (each can be changed to use flatten()):

for n in vec![Some(1)] {
    // if let Some
    if let Some(n) = n {
        println!("sup");
    }
}
let vec: Vec<Result<i32, i32>> = vec![];
for n in vec.clone() {
    // if let Ok
    if let Ok(n) = n {
        println!("sup");
    }
}
for n in vec.clone() {
    // Option::map or Result::map
    n.map(|n| println!("sup"));
}
// for_each and match
Some(Some(1)).into_iter().for_each(|n| match n {
    Some(_) => println!("sup"),
    None => {}
});

One note that may help is that if let .. is "desugared" into an equivalent match .. expression, so your code will just be looking for match instead of if let.

Good luck!

@flip1995
Copy link
Member

flip1995 commented Jan 25, 2021

You have to be careful that the if let ... expression is the only expression inside the for loop. Otherwise applying this lint would change the semantics. (Best way to address such cases is to add tests for it right away, before you even defined the lint. This also makes sure, that you don't address the happy path with your tests)

bors added a commit that referenced this issue Feb 4, 2021
…flip1995

New Lint: Manual Flatten

This is a draft PR for [Issue 6564](#6564).

r? `@camsteffen`

- \[x] Followed [lint naming conventions][lint_naming]
- \[x] Added passing UI tests (including committed `.stderr` file)
- \[x] `cargo test` passes locally
- \[x] Executed `cargo dev update_lints`
- \[x] Added lint documentation
- \[x] Run `cargo dev fmt`

---

*Please write a short comment explaining your change (or "none" for internal only changes)*
changelog:
Add new lint `manual_flatten` to check for loops over a single `if let` expression with `Result` or `Option`.
bors added a commit that referenced this issue Feb 4, 2021
…flip1995

New Lint: Manual Flatten

This is a draft PR for [Issue 6564](#6564).

r? `@camsteffen`

- \[x] Followed [lint naming conventions][lint_naming]
- \[x] Added passing UI tests (including committed `.stderr` file)
- \[x] `cargo test` passes locally
- \[x] Executed `cargo dev update_lints`
- \[x] Added lint documentation
- \[x] Run `cargo dev fmt`

---

*Please write a short comment explaining your change (or "none" for internal only changes)*
changelog: Add new lint [`manual_flatten`] to check for loops over a single `if let` expression with `Result` or `Option`.
@flip1995
Copy link
Member

flip1995 commented Feb 4, 2021

Implemented in #6646

@flip1995 flip1995 closed this as completed Feb 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints good-first-issue These issues are a good way to get started with Clippy L-complexity Lint: Belongs in the complexity lint group
Projects
None yet
Development

No branches or pull requests

3 participants