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

Add lint for opt.map_or(None, f) #2128

Merged
merged 3 commits into from
Oct 10, 2017
Merged

Conversation

lukasstevens
Copy link
Contributor

@lukasstevens lukasstevens commented Oct 10, 2017

fixes #2113

I don't know if my formatting is correct, since running rustfmt would have changed code which was not written by me. Furthermore, I hope that the implementation is correct, since this is the first time I had a look at the clippy internals.
Also, I saw that there is a move towards splitting the methods.rs into mutliple files. Maybe it would be sensible to move the code from this commit into another file.

Change to Warn and add multiline support

Fix typo

Update reference
pub OPTION_MAP_OR_NONE,
Warn,
"using `Option.map_or(None, f)`, which is more succinctly expressed as \
`map_or_else(g, f)`"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy paste error

/// lint use of `_.map_or(None, _)` for `Option`s
fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) {
// check if the first non-self argument to map_or() is None
let map_or_arg_is_none = if let hir::Expr_::ExprPath(ref qpath) = map_or_args[1].node {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to ensure that the type is Option before doing this check. Otherwise a random type with a map_or function can cause this lint to panic if the map_or has zero arguments (so just the self).

`and_then(f)` instead";
let map_or_none_snippet = snippet(cx, map_or_args[1].span, "..");
let map_or_func_snippet = snippet(cx, map_or_args[2].span, "..");
let multiline = map_or_func_snippet.lines().count() > 1 || map_or_none_snippet.lines().count() > 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please get rid of the multiline check (I know all the others still do it, but they are rather old lints). Use span_lint_and_then + span_suggestion to produce the suggestion. Rustc will take care of the rest.

@oli-obk
Copy link
Contributor

oli-obk commented Oct 10, 2017

Also, I saw that there is a move towards splitting the methods.rs into mutliple files. Maybe it would be sensible to move the code from this commit into another file.

I think we can move out a whole chunk of tests. But don't worry about it in this PR.

- Fix copy-paste error
- Check for opt.map_or argument after ensuring that opt is an Option
- Use span_lint_and_then and span_suggestion
- Update reference
@oli-obk oli-obk merged commit 2b491d5 into rust-lang:master Oct 10, 2017
@oli-obk
Copy link
Contributor

oli-obk commented Oct 10, 2017

Thanks for addressing my comments so fast!

@lukasstevens
Copy link
Contributor Author

You are welcome. Thanks for reviewing the pull request.

nickrtorres added a commit to nickrtorres/rust-clippy that referenced this pull request Apr 4, 2020
… -> Option

Result<T, E> has an `ok()` method that adapts a Result<T,E> into an Option<T>.
It's possible to get around this adapter by writing Result<T,E>.map_or(None, Some).

This lint is implemented as a new variant of the existing
[`option_map_none` lint](rust-lang#2128)
flip1995 added a commit to flip1995/rust-clippy that referenced this pull request Apr 7, 2020
Add new lint for `Result<T, E>.map_or(None, Some(T))`

Fixes rust-lang#5414

PR Checklist
---
- [x] Followed lint naming conventions (the name is a bit awkward, but it seems to conform)
- [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

`Result<T, E>` has an [`ok()`](https://doc.rust-lang.org/std/result/enum.Result.html#method.ok) method that adapts a `Result<T,E>` into an `Option<T>`.
It's possible to get around this adapter by writing `Result<T,E>.map_or(None, Some)`.

This lint is implemented as a new variant of the existing [`option_map_none` lint](rust-lang#2128)
flip1995 added a commit to flip1995/rust-clippy that referenced this pull request Apr 8, 2020
Add new lint for `Result<T, E>.map_or(None, Some(T))`

Fixes rust-lang#5414

PR Checklist
---
- [x] Followed lint naming conventions (the name is a bit awkward, but it seems to conform)
- [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

`Result<T, E>` has an [`ok()`](https://doc.rust-lang.org/std/result/enum.Result.html#method.ok) method that adapts a `Result<T,E>` into an `Option<T>`.
It's possible to get around this adapter by writing `Result<T,E>.map_or(None, Some)`.

This lint is implemented as a new variant of the existing [`option_map_none` lint](rust-lang#2128)
rokob pushed a commit to rokob/rust-clippy that referenced this pull request Apr 17, 2020
… -> Option

Result<T, E> has an `ok()` method that adapts a Result<T,E> into an Option<T>.
It's possible to get around this adapter by writing Result<T,E>.map_or(None, Some).

This lint is implemented as a new variant of the existing
[`option_map_none` lint](rust-lang#2128)
rokob pushed a commit to rokob/rust-clippy that referenced this pull request Apr 17, 2020
… -> Option

Result<T, E> has an `ok()` method that adapts a Result<T,E> into an Option<T>.
It's possible to get around this adapter by writing Result<T,E>.map_or(None, Some).

This lint is implemented as a new variant of the existing
[`option_map_none` lint](rust-lang#2128)
rokob pushed a commit to rokob/rust-clippy that referenced this pull request Apr 17, 2020
… -> Option

Result<T, E> has an `ok()` method that adapts a Result<T,E> into an Option<T>.
It's possible to get around this adapter by writing Result<T,E>.map_or(None, Some).

This lint is implemented as a new variant of the existing
[`option_map_none` lint](rust-lang#2128)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Suggest opt.and_then(f) over opt.map_or(None, f)
2 participants