Skip to content

Commit 34ad33c

Browse files
committed
refactor: move into methods module
1 parent fd2c860 commit 34ad33c

File tree

7 files changed

+112
-107
lines changed

7 files changed

+112
-107
lines changed

clippy_lints/src/lib.register_all.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
181181
LintId::of(methods::OPTION_FILTER_MAP),
182182
LintId::of(methods::OPTION_MAP_OR_NONE),
183183
LintId::of(methods::OR_FUN_CALL),
184+
LintId::of(methods::OR_THEN_UNWRAP),
184185
LintId::of(methods::RESULT_MAP_OR_INTO_OPTION),
185186
LintId::of(methods::SEARCH_IS_SOME),
186187
LintId::of(methods::SHOULD_IMPLEMENT_TRAIT),
@@ -238,7 +239,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
238239
LintId::of(only_used_in_recursion::ONLY_USED_IN_RECURSION),
239240
LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS),
240241
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
241-
LintId::of(or_then_unwrap::OR_THEN_UNWRAP),
242242
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
243243
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
244244
LintId::of(precedence::PRECEDENCE),

clippy_lints/src/lib.register_complexity.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec!
4747
LintId::of(methods::NEEDLESS_SPLITN),
4848
LintId::of(methods::OPTION_AS_REF_DEREF),
4949
LintId::of(methods::OPTION_FILTER_MAP),
50+
LintId::of(methods::OR_THEN_UNWRAP),
5051
LintId::of(methods::SEARCH_IS_SOME),
5152
LintId::of(methods::SKIP_WHILE_NEXT),
5253
LintId::of(methods::UNNECESSARY_FILTER_MAP),
@@ -66,7 +67,6 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec!
6667
LintId::of(no_effect::NO_EFFECT),
6768
LintId::of(no_effect::UNNECESSARY_OPERATION),
6869
LintId::of(only_used_in_recursion::ONLY_USED_IN_RECURSION),
69-
LintId::of(or_then_unwrap::OR_THEN_UNWRAP),
7070
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
7171
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
7272
LintId::of(precedence::PRECEDENCE),

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ store.register_lints(&[
319319
methods::OPTION_FILTER_MAP,
320320
methods::OPTION_MAP_OR_NONE,
321321
methods::OR_FUN_CALL,
322+
methods::OR_THEN_UNWRAP,
322323
methods::RESULT_MAP_OR_INTO_OPTION,
323324
methods::SEARCH_IS_SOME,
324325
methods::SHOULD_IMPLEMENT_TRAIT,
@@ -404,7 +405,6 @@ store.register_lints(&[
404405
open_options::NONSENSICAL_OPEN_OPTIONS,
405406
option_env_unwrap::OPTION_ENV_UNWRAP,
406407
option_if_let_else::OPTION_IF_LET_ELSE,
407-
or_then_unwrap::OR_THEN_UNWRAP,
408408
overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL,
409409
panic_in_result_fn::PANIC_IN_RESULT_FN,
410410
panic_unimplemented::PANIC,

clippy_lints/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,6 @@ mod only_used_in_recursion;
322322
mod open_options;
323323
mod option_env_unwrap;
324324
mod option_if_let_else;
325-
mod or_then_unwrap;
326325
mod overflow_check_conditional;
327326
mod panic_in_result_fn;
328327
mod panic_unimplemented;
@@ -867,7 +866,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
867866
ignore_publish: cargo_ignore_publish,
868867
})
869868
});
870-
store.register_late_pass(|| Box::new(or_then_unwrap::OrThenUnwrap));
871869
// add lints here, do not remove this comment, it's used in `new_lint`
872870
}
873871

clippy_lints/src/methods/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ mod option_as_ref_deref;
4545
mod option_map_or_none;
4646
mod option_map_unwrap_or;
4747
mod or_fun_call;
48+
mod or_then_unwrap;
4849
mod search_is_some;
4950
mod single_char_add_str;
5051
mod single_char_insert_string;
@@ -778,6 +779,42 @@ declare_clippy_lint! {
778779
"using any `*or` method with a function call, which suggests `*or_else`"
779780
}
780781

782+
declare_clippy_lint! {
783+
/// ### What it does
784+
/// Checks for `.or(…).unwrap()` calls to Options and Results.
785+
///
786+
/// ### Why is this bad?
787+
/// You should use `.unwrap_or(…)` instead for clarity.
788+
///
789+
/// ### Example
790+
/// ```rust
791+
/// # let fallback = "fallback";
792+
/// // Result
793+
/// # type Error = &'static str;
794+
/// # let result: Result<&str, Error> = Err("error");
795+
/// let value = result.or::<Error>(Ok(fallback)).unwrap();
796+
///
797+
/// // Option
798+
/// # let option: Option<&str> = None;
799+
/// let value = option.or(Some(fallback)).unwrap();
800+
/// ```
801+
/// Use instead:
802+
/// ```rust
803+
/// # let fallback = "fallback";
804+
/// // Result
805+
/// # let result: Result<&str, &str> = Err("error");
806+
/// let value = result.unwrap_or(fallback);
807+
///
808+
/// // Option
809+
/// # let option: Option<&str> = None;
810+
/// let value = option.unwrap_or(fallback);
811+
/// ```
812+
#[clippy::version = "1.61.0"]
813+
pub OR_THEN_UNWRAP,
814+
complexity,
815+
"checks for `.or(…).unwrap()` calls to Options and Results."
816+
}
817+
781818
declare_clippy_lint! {
782819
/// ### What it does
783820
/// Checks for calls to `.expect(&format!(...))`, `.expect(foo(..))`,
@@ -2039,6 +2076,7 @@ impl_lint_pass!(Methods => [
20392076
OPTION_MAP_OR_NONE,
20402077
BIND_INSTEAD_OF_MAP,
20412078
OR_FUN_CALL,
2079+
OR_THEN_UNWRAP,
20422080
EXPECT_FUN_CALL,
20432081
CHARS_NEXT_CMP,
20442082
CHARS_LAST_CMP,
@@ -2474,6 +2512,9 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
24742512
Some(("get_mut", [recv, get_arg], _)) => {
24752513
get_unwrap::check(cx, expr, recv, get_arg, true);
24762514
},
2515+
Some(("or", [recv, or_arg], or_span)) => {
2516+
or_then_unwrap::check(cx, expr, recv, or_arg, or_span);
2517+
},
24772518
_ => {},
24782519
}
24792520
unwrap_used::check(cx, expr, recv);
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use clippy_utils::diagnostics::span_lint_and_help;
2+
use clippy_utils::ty::is_type_diagnostic_item;
3+
use if_chain::if_chain;
4+
use rustc_hir::{Expr, ExprKind, QPath};
5+
use rustc_lint::LateContext;
6+
use rustc_span::{sym, Span};
7+
8+
use super::OR_THEN_UNWRAP;
9+
10+
pub(super) fn check<'tcx>(
11+
cx: &LateContext<'tcx>,
12+
unwrap_expr: &Expr<'_>,
13+
recv: &'tcx Expr<'tcx>,
14+
or_arg: &'tcx Expr<'_>,
15+
or_span: Span,
16+
) {
17+
let ty = cx.typeck_results().expr_ty(recv); // get type of x (we later check if it's Option or Result)
18+
let title;
19+
20+
if is_type_diagnostic_item(cx, ty, sym::Option) {
21+
title = ".or(Some(…)).unwrap() found";
22+
if !is(or_arg, "Some") {
23+
return;
24+
}
25+
} else if is_type_diagnostic_item(cx, ty, sym::Result) {
26+
title = ".or(Ok(…)).unwrap() found";
27+
if !is(or_arg, "Ok") {
28+
return;
29+
}
30+
} else {
31+
// Someone has implemented a struct with .or(...).unwrap() chaining,
32+
// but it's not an Option or a Result, so bail
33+
return;
34+
}
35+
36+
let unwrap_span = if let ExprKind::MethodCall(_, _, span) = unwrap_expr.kind {
37+
span
38+
} else {
39+
// unreachable. but fallback to ident's span ("()" are missing)
40+
unwrap_expr.span
41+
};
42+
43+
span_lint_and_help(
44+
cx,
45+
OR_THEN_UNWRAP,
46+
or_span.to(unwrap_span),
47+
title,
48+
None,
49+
"use `unwrap_or()` instead",
50+
);
51+
}
52+
53+
/// is expr a Call to name?
54+
/// name might be "Some", "Ok", "Err", etc.
55+
fn is<'a>(expr: &Expr<'a>, name: &str) -> bool {
56+
if_chain! {
57+
if let ExprKind::Call(some_expr, _some_args) = expr.kind;
58+
if let ExprKind::Path(QPath::Resolved(_, path)) = &some_expr.kind;
59+
if let Some(path_segment) = path.segments.first();
60+
if path_segment.ident.name.as_str() == name;
61+
then {
62+
true
63+
}
64+
else {
65+
false
66+
}
67+
}
68+
}

clippy_lints/src/or_then_unwrap.rs

Lines changed: 0 additions & 102 deletions
This file was deleted.

0 commit comments

Comments
 (0)