Skip to content

Commit c1c8bc6

Browse files
committed
Auto merge of rust-lang#5473 - Toxyxer:map-flatten-for-option, r=flip1995
Map flatten for option Fixes rust-lang#5175 changelog: - Trigger the map_flatten lint when map is called on an option - Add test for such case
2 parents 3704954 + 72a8fc2 commit c1c8bc6

File tree

4 files changed

+28
-2
lines changed

4 files changed

+28
-2
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2484,7 +2484,7 @@ fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, ok_args: &[hir
24842484
}
24852485
}
24862486

2487-
/// lint use of `map().flatten()` for `Iterators`
2487+
/// lint use of `map().flatten()` for `Iterators` and 'Options'
24882488
fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>, map_args: &'tcx [hir::Expr<'_>]) {
24892489
// lint if caller of `.map().flatten()` is an Iterator
24902490
if match_trait_method(cx, expr, &paths::ITERATOR) {
@@ -2503,6 +2503,24 @@ fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<
25032503
Applicability::MachineApplicable,
25042504
);
25052505
}
2506+
2507+
// lint if caller of `.map().flatten()` is an Option
2508+
if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) {
2509+
let msg = "called `map(..).flatten()` on an `Option`. \
2510+
This is more succinctly expressed by calling `.and_then(..)`";
2511+
let self_snippet = snippet(cx, map_args[0].span, "..");
2512+
let func_snippet = snippet(cx, map_args[1].span, "..");
2513+
let hint = format!("{0}.and_then({1})", self_snippet, func_snippet);
2514+
span_lint_and_sugg(
2515+
cx,
2516+
MAP_FLATTEN,
2517+
expr.span,
2518+
msg,
2519+
"try using `and_then` instead",
2520+
hint,
2521+
Applicability::MachineApplicable,
2522+
);
2523+
}
25062524
}
25072525

25082526
/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s

tests/ui/map_flatten.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55

66
fn main() {
77
let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect();
8+
let _: Option<_> = (Some(Some(1))).and_then(|x| x);
89
}

tests/ui/map_flatten.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55

66
fn main() {
77
let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
8+
let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
89
}

tests/ui/map_flatten.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,11 @@ LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().colle
66
|
77
= note: `-D clippy::map-flatten` implied by `-D warnings`
88

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

0 commit comments

Comments
 (0)