Skip to content

Commit

Permalink
Auto merge of #5473 - Toxyxer:map-flatten-for-option, r=flip1995
Browse files Browse the repository at this point in the history
Map flatten for option

Fixes #5175

changelog:
- Trigger the map_flatten lint when map is called on an option
- Add test for such case
  • Loading branch information
bors committed Apr 16, 2020
2 parents 3704954 + 72a8fc2 commit c1c8bc6
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 2 deletions.
20 changes: 19 additions & 1 deletion clippy_lints/src/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2484,7 +2484,7 @@ fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, ok_args: &[hir
}
}

/// lint use of `map().flatten()` for `Iterators`
/// lint use of `map().flatten()` for `Iterators` and 'Options'
fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>, map_args: &'tcx [hir::Expr<'_>]) {
// lint if caller of `.map().flatten()` is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) {
Expand All @@ -2503,6 +2503,24 @@ fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<
Applicability::MachineApplicable,
);
}

// lint if caller of `.map().flatten()` is an Option
if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) {
let msg = "called `map(..).flatten()` on an `Option`. \
This is more succinctly expressed by calling `.and_then(..)`";
let self_snippet = snippet(cx, map_args[0].span, "..");
let func_snippet = snippet(cx, map_args[1].span, "..");
let hint = format!("{0}.and_then({1})", self_snippet, func_snippet);
span_lint_and_sugg(
cx,
MAP_FLATTEN,
expr.span,
msg,
"try using `and_then` instead",
hint,
Applicability::MachineApplicable,
);
}
}

/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s
Expand Down
1 change: 1 addition & 0 deletions tests/ui/map_flatten.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@

fn main() {
let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect();
let _: Option<_> = (Some(Some(1))).and_then(|x| x);
}
1 change: 1 addition & 0 deletions tests/ui/map_flatten.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@

fn main() {
let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
}
8 changes: 7 additions & 1 deletion tests/ui/map_flatten.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,11 @@ LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().colle
|
= note: `-D clippy::map-flatten` implied by `-D warnings`

error: aborting due to previous error
error: called `map(..).flatten()` on an `Option`. This is more succinctly expressed by calling `.and_then(..)`
--> $DIR/map_flatten.rs:8:24
|
LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `(Some(Some(1))).and_then(|x| x)`

error: aborting due to 2 previous errors

0 comments on commit c1c8bc6

Please sign in to comment.