Skip to content

Commit 6cbdd1e

Browse files
committed
Merge option_map_unwrap_or, option_map_unwrap_or_else and result_map_unwrap_or_else lints into map_unwrap lint
1 parent 945c944 commit 6cbdd1e

File tree

9 files changed

+94
-166
lines changed

9 files changed

+94
-166
lines changed

CHANGELOG.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,7 @@ Released 2018-09-13
14301430
[`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
14311431
[`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry
14321432
[`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
1433+
[`map_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap
14331434
[`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref
14341435
[`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool
14351436
[`match_on_vec_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_on_vec_items
@@ -1499,8 +1500,6 @@ Released 2018-09-13
14991500
[`option_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_expect_used
15001501
[`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none
15011502
[`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn
1502-
[`option_map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or
1503-
[`option_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or_else
15041503
[`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option
15051504
[`option_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_unwrap_used
15061505
[`or_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call
@@ -1542,7 +1541,6 @@ Released 2018-09-13
15421541
[`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used
15431542
[`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_or_into_option
15441543
[`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn
1545-
[`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else
15461544
[`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used
15471545
[`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges
15481546
[`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition

clippy_lints/src/lib.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -673,19 +673,17 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
673673
&methods::ITER_SKIP_NEXT,
674674
&methods::MANUAL_SATURATING_ARITHMETIC,
675675
&methods::MAP_FLATTEN,
676+
&methods::MAP_UNWRAP,
676677
&methods::NEW_RET_NO_SELF,
677678
&methods::OK_EXPECT,
678679
&methods::OPTION_AND_THEN_SOME,
679680
&methods::OPTION_AS_REF_DEREF,
680681
&methods::OPTION_EXPECT_USED,
681682
&methods::OPTION_MAP_OR_NONE,
682-
&methods::OPTION_MAP_UNWRAP_OR,
683-
&methods::OPTION_MAP_UNWRAP_OR_ELSE,
684683
&methods::OPTION_UNWRAP_USED,
685684
&methods::OR_FUN_CALL,
686685
&methods::RESULT_EXPECT_USED,
687686
&methods::RESULT_MAP_OR_INTO_OPTION,
688-
&methods::RESULT_MAP_UNWRAP_OR_ELSE,
689687
&methods::RESULT_UNWRAP_USED,
690688
&methods::SEARCH_IS_SOME,
691689
&methods::SHOULD_IMPLEMENT_TRAIT,
@@ -1152,9 +1150,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11521150
LintId::of(&methods::FIND_MAP),
11531151
LintId::of(&methods::INEFFICIENT_TO_STRING),
11541152
LintId::of(&methods::MAP_FLATTEN),
1155-
LintId::of(&methods::OPTION_MAP_UNWRAP_OR),
1156-
LintId::of(&methods::OPTION_MAP_UNWRAP_OR_ELSE),
1157-
LintId::of(&methods::RESULT_MAP_UNWRAP_OR_ELSE),
1153+
LintId::of(&methods::MAP_UNWRAP),
11581154
LintId::of(&misc::USED_UNDERSCORE_BINDING),
11591155
LintId::of(&misc_early::UNSEPARATED_LITERAL_SUFFIX),
11601156
LintId::of(&mut_mut::MUT_MUT),

clippy_lints/src/methods/mod.rs

Lines changed: 28 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -257,59 +257,40 @@ declare_clippy_lint! {
257257
}
258258

259259
declare_clippy_lint! {
260-
/// **What it does:** Checks for usage of `_.map(_).unwrap_or(_)`.
260+
/// **What it does:** Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or
261+
/// `result.map(_).unwrap_or_else(_)`.
261262
///
262-
/// **Why is this bad?** Readability, this can be written more concisely as
263-
/// `_.map_or(_, _)`.
263+
/// **Why is this bad?** Readability, these can be written more concisely (resp.) as
264+
/// `option.map_or(_, _)`, `option.map_or_else(_, _)` and `result.map_or_else(_, _)`.
264265
///
265266
/// **Known problems:** The order of the arguments is not in execution order
266267
///
267-
/// **Example:**
268+
/// **Examples:**
268269
/// ```rust
269270
/// # let x = Some(1);
270-
/// x.map(|a| a + 1).unwrap_or(0);
271-
/// ```
272-
pub OPTION_MAP_UNWRAP_OR,
273-
pedantic,
274-
"using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)`"
275-
}
276-
277-
declare_clippy_lint! {
278-
/// **What it does:** Checks for usage of `_.map(_).unwrap_or_else(_)`.
279-
///
280-
/// **Why is this bad?** Readability, this can be written more concisely as
281-
/// `_.map_or_else(_, _)`.
282271
///
283-
/// **Known problems:** The order of the arguments is not in execution order.
272+
/// // Bad
273+
/// x.map(|a| a + 1).unwrap_or(0);
284274
///
285-
/// **Example:**
286-
/// ```rust
287-
/// # let x = Some(1);
288-
/// # fn some_function() -> usize { 1 }
289-
/// x.map(|a| a + 1).unwrap_or_else(some_function);
275+
/// // Good
276+
/// x.map_or(0, |a| a + 1);
290277
/// ```
291-
pub OPTION_MAP_UNWRAP_OR_ELSE,
292-
pedantic,
293-
"using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`"
294-
}
295-
296-
declare_clippy_lint! {
297-
/// **What it does:** Checks for usage of `result.map(_).unwrap_or_else(_)`.
298278
///
299-
/// **Why is this bad?** Readability, this can be written more concisely as
300-
/// `result.map_or_else(_, _)`.
301-
///
302-
/// **Known problems:** None.
279+
/// // or
303280
///
304-
/// **Example:**
305281
/// ```rust
306282
/// # let x: Result<usize, ()> = Ok(1);
307283
/// # fn some_function(foo: ()) -> usize { 1 }
284+
///
285+
/// // Bad
308286
/// x.map(|a| a + 1).unwrap_or_else(some_function);
287+
///
288+
/// // Good
289+
/// x.map_or_else(some_function, |a| a + 1);
309290
/// ```
310-
pub RESULT_MAP_UNWRAP_OR_ELSE,
291+
pub MAP_UNWRAP,
311292
pedantic,
312-
"using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.map_or_else(g, f)`"
293+
"using `.map(f).unwrap_or(a)` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)` or `map_or_else(a, f)`"
313294
}
314295

315296
declare_clippy_lint! {
@@ -1294,9 +1275,7 @@ declare_lint_pass!(Methods => [
12941275
WRONG_SELF_CONVENTION,
12951276
WRONG_PUB_SELF_CONVENTION,
12961277
OK_EXPECT,
1297-
OPTION_MAP_UNWRAP_OR,
1298-
OPTION_MAP_UNWRAP_OR_ELSE,
1299-
RESULT_MAP_UNWRAP_OR_ELSE,
1278+
MAP_UNWRAP,
13001279
RESULT_MAP_OR_INTO_OPTION,
13011280
OPTION_MAP_OR_NONE,
13021281
OPTION_AND_THEN_SOME,
@@ -1503,9 +1482,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
15031482
cx,
15041483
lint,
15051484
first_arg.pat.span,
1506-
&format!(
1507-
"methods called `{}` usually take {}; consider choosing a less \
1508-
ambiguous name",
1485+
&format!("methods called `{}` usually take {}; consider choosing a less ambiguous name",
15091486
conv,
15101487
&self_kinds
15111488
.iter()
@@ -1678,7 +1655,7 @@ fn lint_or_fun_call<'a, 'tcx>(
16781655
let self_ty = cx.tables.expr_ty(self_expr);
16791656

16801657
if let Some(&(_, fn_has_arguments, poss, suffix)) =
1681-
know_types.iter().find(|&&i| match_type(cx, self_ty, i.0));
1658+
know_types.iter().find(|&&i| match_type(cx, self_ty, i.0));
16821659

16831660
if poss.contains(&name);
16841661

@@ -1931,7 +1908,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir:
19311908
CLONE_DOUBLE_REF,
19321909
expr.span,
19331910
"using `clone` on a double-reference; \
1934-
this will copy the reference instead of cloning the inner type",
1911+
this will copy the reference instead of cloning the inner type",
19351912
|diag| {
19361913
if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
19371914
let mut ty = innermost;
@@ -2121,7 +2098,7 @@ fn lint_iter_cloned_collect<'a, 'tcx>(
21212098
ITER_CLONED_COLLECT,
21222099
to_replace,
21232100
"called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \
2124-
more readable",
2101+
more readable",
21252102
"try",
21262103
".to_vec()".to_string(),
21272104
Applicability::MachineApplicable,
@@ -2436,7 +2413,7 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hi
24362413
None,
24372414
&format!(
24382415
"if you don't want to handle the `{}` case gracefully, consider \
2439-
using `expect()` to provide a better panic message",
2416+
using `expect()` to provide a better panic message",
24402417
none_value,
24412418
),
24422419
);
@@ -2494,7 +2471,7 @@ fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<
24942471
// lint if caller of `.map().flatten()` is an Iterator
24952472
if match_trait_method(cx, expr, &paths::ITERATOR) {
24962473
let msg = "called `map(..).flatten()` on an `Iterator`. \
2497-
This is more succinctly expressed by calling `.flat_map(..)`";
2474+
This is more succinctly expressed by calling `.flat_map(..)`";
24982475
let self_snippet = snippet(cx, map_args[0].span, "..");
24992476
let func_snippet = snippet(cx, map_args[1].span, "..");
25002477
let hint = format!("{0}.flat_map({1})", self_snippet, func_snippet);
@@ -2555,10 +2532,10 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(
25552532
// lint message
25562533
let msg = if is_option {
25572534
"called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling \
2558-
`map_or_else(g, f)` instead"
2535+
`map_or_else(g, f)` instead"
25592536
} else {
25602537
"called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling \
2561-
`.map_or_else(g, f)` instead"
2538+
`.map_or_else(g, f)` instead"
25622539
};
25632540
// get snippets for args to map() and unwrap_or_else()
25642541
let map_snippet = snippet(cx, map_args[1].span, "..");
@@ -2570,11 +2547,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(
25702547
if same_span && !multiline {
25712548
span_lint_and_note(
25722549
cx,
2573-
if is_option {
2574-
OPTION_MAP_UNWRAP_OR_ELSE
2575-
} else {
2576-
RESULT_MAP_UNWRAP_OR_ELSE
2577-
},
2550+
MAP_UNWRAP,
25782551
expr.span,
25792552
msg,
25802553
None,
@@ -2584,16 +2557,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(
25842557
),
25852558
);
25862559
} else if same_span && multiline {
2587-
span_lint(
2588-
cx,
2589-
if is_option {
2590-
OPTION_MAP_UNWRAP_OR_ELSE
2591-
} else {
2592-
RESULT_MAP_UNWRAP_OR_ELSE
2593-
},
2594-
expr.span,
2595-
msg,
2596-
);
2560+
span_lint(cx, MAP_UNWRAP, expr.span, msg);
25972561
};
25982562
}
25992563
}

clippy_lints/src/methods/option_map_unwrap_or.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::hir::map::Map;
99
use rustc_span::source_map::Span;
1010
use rustc_span::symbol::Symbol;
1111

12-
use super::OPTION_MAP_UNWRAP_OR;
12+
use super::MAP_UNWRAP;
1313

1414
/// lint use of `map().unwrap_or()` for `Option`s
1515
pub(super) fn lint<'a, 'tcx>(
@@ -62,11 +62,11 @@ pub(super) fn lint<'a, 'tcx>(
6262
};
6363
let msg = &format!(
6464
"called `map(f).unwrap_or({})` on an `Option` value. \
65-
This can be done more directly by calling `{}` instead",
65+
This can be done more directly by calling `{}` instead",
6666
arg, suggest
6767
);
6868

69-
span_lint_and_then(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, |diag| {
69+
span_lint_and_then(cx, MAP_UNWRAP, expr.span, msg, |diag| {
7070
let map_arg_span = map_args[1].span;
7171

7272
let mut suggestion = vec![

src/lintlist/mod.rs

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
11371137
deprecation: None,
11381138
module: "methods",
11391139
},
1140+
Lint {
1141+
name: "map_unwrap",
1142+
group: "pedantic",
1143+
desc: "using `.map(f).unwrap_or(a)` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)` or `map_or_else(a, f)`",
1144+
deprecation: None,
1145+
module: "methods",
1146+
},
11401147
Lint {
11411148
name: "match_as_ref",
11421149
group: "complexity",
@@ -1613,20 +1620,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
16131620
deprecation: None,
16141621
module: "map_unit_fn",
16151622
},
1616-
Lint {
1617-
name: "option_map_unwrap_or",
1618-
group: "pedantic",
1619-
desc: "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)`",
1620-
deprecation: None,
1621-
module: "methods",
1622-
},
1623-
Lint {
1624-
name: "option_map_unwrap_or_else",
1625-
group: "pedantic",
1626-
desc: "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`",
1627-
deprecation: None,
1628-
module: "methods",
1629-
},
16301623
Lint {
16311624
name: "option_option",
16321625
group: "pedantic",
@@ -1900,13 +1893,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
19001893
deprecation: None,
19011894
module: "map_unit_fn",
19021895
},
1903-
Lint {
1904-
name: "result_map_unwrap_or_else",
1905-
group: "pedantic",
1906-
desc: "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.map_or_else(g, f)`",
1907-
deprecation: None,
1908-
module: "methods",
1909-
},
19101896
Lint {
19111897
name: "result_unwrap_used",
19121898
group: "restriction",

tests/ui/option_map_unwrap_or.rs renamed to tests/ui/map_unwrap.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
// FIXME: Add "run-rustfix" once it's supported for multipart suggestions
22
// aux-build:option_helpers.rs
33

4-
#![warn(clippy::option_map_unwrap_or, clippy::option_map_unwrap_or_else)]
4+
#![warn(clippy::map_unwrap)]
55

66
#[macro_use]
77
extern crate option_helpers;
88

99
use std::collections::HashMap;
1010

11-
/// Checks implementation of the following lints:
12-
/// * `OPTION_MAP_UNWRAP_OR`
13-
/// * `OPTION_MAP_UNWRAP_OR_ELSE`
1411
#[rustfmt::skip]
1512
fn option_methods() {
1613
let opt = Some(1);
1714

18-
// Check `OPTION_MAP_UNWRAP_OR`.
15+
// Check for `option.map(_).unwrap_or(_)` use.
1916
// Single line case.
2017
let _ = opt.map(|x| x + 1)
2118
// Should lint even though this call is on a separate line.
@@ -49,7 +46,7 @@ fn option_methods() {
4946
let id: String = "identifier".to_string();
5047
let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id);
5148

52-
// Check OPTION_MAP_UNWRAP_OR_ELSE
49+
// Check for `option.map(_).unwrap_or_else(_)` use.
5350
// single line case
5451
let _ = opt.map(|x| x + 1)
5552
// Should lint even though this call is on a separate line.
@@ -83,6 +80,20 @@ fn option_methods() {
8380
}
8481
}
8582

83+
fn result_methods() {
84+
let res: Result<i32, ()> = Ok(1);
85+
86+
// Check for `result.map(_).unwrap_or_else(_)` use.
87+
// single line case
88+
let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line
89+
// multi line cases
90+
let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0);
91+
let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0);
92+
// macro case
93+
let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint
94+
}
95+
8696
fn main() {
8797
option_methods();
98+
result_methods();
8899
}

0 commit comments

Comments
 (0)