Skip to content

Commit 1e3f332

Browse files
committed
introduce as_some_expr, is_none_expr
1 parent 30c4144 commit 1e3f332

13 files changed

+62
-63
lines changed

clippy_lints/src/if_then_some_else_none.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ use clippy_config::Conf;
22
use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
44
use clippy_utils::msrvs::{self, Msrv};
5-
use clippy_utils::res::{MaybeDef, MaybeQPath};
65
use clippy_utils::source::{snippet_with_applicability, snippet_with_context, walk_span_to_context};
76
use clippy_utils::sugg::Sugg;
87
use clippy_utils::{
9-
contains_return, expr_adjustment_requires_coercion, higher, is_else_clause, is_in_const_context, peel_blocks, sym,
8+
as_some_expr, contains_return, expr_adjustment_requires_coercion, higher, is_else_clause, is_in_const_context,
9+
is_none_expr, peel_blocks, sym,
1010
};
1111
use rustc_errors::Applicability;
12-
use rustc_hir::LangItem::{OptionNone, OptionSome};
1312
use rustc_hir::{Expr, ExprKind};
1413
use rustc_lint::{LateContext, LateLintPass};
1514
use rustc_session::impl_lint_pass;
@@ -70,11 +69,10 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
7069
}) = higher::If::hir(expr)
7170
&& let ExprKind::Block(then_block, _) = then.kind
7271
&& let Some(then_expr) = then_block.expr
73-
&& let ExprKind::Call(then_call, [then_arg]) = then_expr.kind
72+
&& let Some(then_arg) = as_some_expr(cx, then_expr)
7473
&& !expr.span.from_expansion()
7574
&& !then_expr.span.from_expansion()
76-
&& then_call.res(cx).ctor_parent(cx).is_lang_item(cx, OptionSome)
77-
&& peel_blocks(els).res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone)
75+
&& is_none_expr(cx, peel_blocks(els))
7876
&& !is_else_clause(cx.tcx, expr)
7977
&& !is_in_const_context(cx)
8078
&& self.msrv.meets(cx, msrvs::BOOL_THEN)

clippy_lints/src/loops/manual_find.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use clippy_utils::res::{MaybeDef, MaybeQPath, MaybeResPath};
55
use clippy_utils::source::snippet_with_applicability;
66
use clippy_utils::ty::implements_trait;
77
use clippy_utils::usage::contains_return_break_continue_macro;
8-
use clippy_utils::{higher, peel_blocks_with_stmt};
8+
use clippy_utils::{as_some_expr, higher, peel_blocks_with_stmt};
99
use rustc_errors::Applicability;
1010
use rustc_hir::lang_items::LangItem;
1111
use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind};
@@ -33,8 +33,7 @@ pub(super) fn check<'tcx>(
3333
&& let [stmt] = block.stmts
3434
&& let StmtKind::Semi(semi) = stmt.kind
3535
&& let ExprKind::Ret(Some(ret_value)) = semi.kind
36-
&& let ExprKind::Call(ctor, [inner_ret]) = ret_value.kind
37-
&& ctor.res(cx).ctor_parent(cx).is_lang_item(cx, LangItem::OptionSome)
36+
&& let Some(inner_ret) = as_some_expr(cx, ret_value)
3837
&& inner_ret.res_local_id() == Some(binding_id)
3938
&& !contains_return_break_continue_macro(cond)
4039
&& let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr)

clippy_lints/src/matches/manual_filter.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
use clippy_utils::as_some_expr;
12
use clippy_utils::diagnostics::span_lint_and_sugg;
23
use clippy_utils::res::{MaybeDef, MaybeQPath, MaybeResPath};
34
use clippy_utils::visitors::contains_unsafe_block;
45

5-
use rustc_hir::LangItem::{OptionNone, OptionSome};
6+
use rustc_hir::LangItem::OptionNone;
67
use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind};
78
use rustc_lint::LateContext;
89
use rustc_span::{SyntaxContext, sym};
@@ -62,11 +63,9 @@ fn peels_blocks_incl_unsafe<'a>(expr: &'a Expr<'a>) -> &'a Expr<'a> {
6263
fn is_some_expr(cx: &LateContext<'_>, target: HirId, ctxt: SyntaxContext, expr: &Expr<'_>) -> bool {
6364
if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr)
6465
// there can be not statements in the block as they would be removed when switching to `.filter`
65-
&& let ExprKind::Call(callee, [arg]) = inner_expr.kind
66+
&& let Some(arg) = as_some_expr(cx, inner_expr)
6667
{
67-
return ctxt == expr.span.ctxt()
68-
&& callee.res(cx).ctor_parent(cx).is_lang_item(cx, OptionSome)
69-
&& arg.res_local_id() == Some(target);
68+
return ctxt == expr.span.ctxt() && arg.res_local_id() == Some(target);
7069
}
7170
false
7271
}

clippy_lints/src/matches/manual_ok_err.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::res::{MaybeDef, MaybeQPath};
2+
use clippy_utils::res::MaybeDef;
33
use clippy_utils::source::{indent_of, reindent_multiline};
44
use clippy_utils::sugg::Sugg;
55
use clippy_utils::ty::{option_arg_ty, peel_and_count_ty_refs};
6-
use clippy_utils::{get_parent_expr, peel_blocks, span_contains_comment};
6+
use clippy_utils::{as_some_expr, get_parent_expr, is_none_expr, peel_blocks, span_contains_comment};
77
use rustc_ast::{BindingMode, Mutability};
88
use rustc_errors::Applicability;
9-
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr};
9+
use rustc_hir::LangItem::ResultErr;
1010
use rustc_hir::def::{DefKind, Res};
1111
use rustc_hir::{Arm, Expr, ExprKind, Pat, PatExpr, PatExprKind, PatKind, Path, QPath};
1212
use rustc_lint::{LateContext, LintContext};
@@ -106,8 +106,7 @@ fn is_ok_or_err<'hir>(cx: &LateContext<'_>, pat: &Pat<'hir>) -> Option<(bool, &'
106106

107107
/// Check if `expr` contains `Some(ident)`, possibly as a block
108108
fn is_some_ident<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, ident: &Ident, ty: Ty<'tcx>) -> bool {
109-
if let ExprKind::Call(body_callee, [body_arg]) = peel_blocks(expr).kind
110-
&& body_callee.res(cx).ctor_parent(cx).is_lang_item(cx, OptionSome)
109+
if let Some(body_arg) = as_some_expr(cx, peel_blocks(expr))
111110
&& cx.typeck_results().expr_ty(body_arg) == ty
112111
&& let ExprKind::Path(QPath::Resolved(
113112
_,
@@ -124,7 +123,7 @@ fn is_some_ident<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, ident: &Ident, t
124123

125124
/// Check if `expr` is `None`, possibly as a block
126125
fn is_none(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
127-
peel_blocks(expr).res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone)
126+
is_none_expr(cx, peel_blocks(expr))
128127
}
129128

130129
/// Suggest replacing `expr` by `scrutinee.METHOD()`, where `METHOD` is either `ok` or

clippy_lints/src/matches/manual_utils.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
use crate::map_unit_fn::OPTION_MAP_UNIT_FN;
22
use crate::matches::MATCH_AS_REF;
3-
use clippy_utils::res::{MaybeDef, MaybeQPath, MaybeResPath};
3+
use clippy_utils::res::{MaybeDef, MaybeResPath};
44
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
55
use clippy_utils::sugg::Sugg;
66
use clippy_utils::ty::{is_copy, is_unsafe_fn, peel_and_count_ty_refs};
77
use clippy_utils::{
88
CaptureKind, as_some_pattern, can_move_expr_to_closure, expr_requires_coercion, is_else_clause, is_lint_allowed,
9-
is_none_pattern, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while,
9+
is_none_expr, is_none_pattern, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while,
1010
};
1111
use rustc_ast::util::parser::ExprPrecedence;
1212
use rustc_errors::Applicability;
13-
use rustc_hir::LangItem::OptionNone;
1413
use rustc_hir::def::Res;
1514
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath};
1615
use rustc_lint::LateContext;
@@ -44,16 +43,16 @@ where
4443
try_parse_pattern(cx, then_pat, expr_ctxt),
4544
else_pat.map_or(Some(OptionPat::Wild), |p| try_parse_pattern(cx, p, expr_ctxt)),
4645
) {
47-
(Some(OptionPat::Wild), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_body) => {
46+
(Some(OptionPat::Wild), Some(OptionPat::Some { pattern, ref_count })) if is_none_arm_body(cx, then_body) => {
4847
(else_body, pattern, ref_count, true)
4948
},
50-
(Some(OptionPat::None), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_body) => {
49+
(Some(OptionPat::None), Some(OptionPat::Some { pattern, ref_count })) if is_none_arm_body(cx, then_body) => {
5150
(else_body, pattern, ref_count, false)
5251
},
53-
(Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::Wild)) if is_none_expr(cx, else_body) => {
52+
(Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::Wild)) if is_none_arm_body(cx, else_body) => {
5453
(then_body, pattern, ref_count, true)
5554
},
56-
(Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::None)) if is_none_expr(cx, else_body) => {
55+
(Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::None)) if is_none_arm_body(cx, else_body) => {
5756
(then_body, pattern, ref_count, false)
5857
},
5958
_ => return None,
@@ -268,6 +267,6 @@ pub(super) fn try_parse_pattern<'tcx>(
268267
}
269268

270269
/// Checks for the `None` value, possibly in a block.
271-
fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
272-
peel_blocks(expr).res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone)
270+
fn is_none_arm_body(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
271+
is_none_expr(cx, peel_blocks(expr))
273272
}

clippy_lints/src/matches/match_as_ref.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::res::{MaybeDef, MaybeQPath};
32
use clippy_utils::source::snippet_with_applicability;
4-
use clippy_utils::{as_some_pattern, is_none_arm, peel_blocks};
3+
use clippy_utils::{as_some_expr, as_some_pattern, is_none_arm, peel_blocks};
54
use rustc_errors::Applicability;
6-
use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
5+
use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, Mutability, PatKind, QPath};
76
use rustc_lint::LateContext;
87
use rustc_middle::ty;
98

@@ -60,8 +59,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
6059
fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
6160
if let Some([first_pat, ..]) = as_some_pattern(cx, arm.pat)
6261
&& let PatKind::Binding(BindingMode(ByRef::Yes(mutabl), _), .., ident, _) = first_pat.kind
63-
&& let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind
64-
&& e.res(cx).ctor_parent(cx).is_lang_item(cx, LangItem::OptionSome)
62+
&& let Some(arg) = as_some_expr(cx, peel_blocks(arm.body))
6563
&& let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind
6664
&& path2.segments.len() == 1
6765
&& ident.name == path2.segments[0].ident.name

clippy_lints/src/mem_replace.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use clippy_config::Conf;
22
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
33
use clippy_utils::msrvs::{self, Msrv};
4-
use clippy_utils::res::{MaybeDef, MaybeQPath};
4+
use clippy_utils::res::MaybeDef;
55
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
66
use clippy_utils::sugg::Sugg;
77
use clippy_utils::ty::is_non_aggregate_primitive_type;
8-
use clippy_utils::{is_default_equivalent, is_expr_used_or_unified, peel_ref_operators, std_or_core};
8+
use clippy_utils::{
9+
as_some_expr, is_default_equivalent, is_expr_used_or_unified, is_none_expr, peel_ref_operators, std_or_core,
10+
};
911
use rustc_errors::Applicability;
10-
use rustc_hir::LangItem::{OptionNone, OptionSome};
1112
use rustc_hir::{Expr, ExprKind};
1213
use rustc_lint::{LateContext, LateLintPass};
1314
use rustc_session::impl_lint_pass;
@@ -128,7 +129,7 @@ impl_lint_pass!(MemReplace =>
128129
[MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_OPTION_WITH_SOME, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]);
129130

130131
fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) -> bool {
131-
if src.res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone) {
132+
if is_none_expr(cx, src) {
132133
// Since this is a late pass (already type-checked),
133134
// and we already know that the second argument is an
134135
// `Option`, we do not need to check the first
@@ -161,8 +162,7 @@ fn check_replace_option_with_some(
161162
expr_span: Span,
162163
msrv: Msrv,
163164
) -> bool {
164-
if let ExprKind::Call(src_func, [src_arg]) = src.kind
165-
&& src_func.res(cx).ctor_parent(cx).is_lang_item(cx, OptionSome)
165+
if let Some(src_arg) = as_some_expr(cx, src)
166166
&& msrv.meets(cx, msrvs::OPTION_REPLACE)
167167
{
168168
// We do not have to check for a `const` context here, because `core::mem::replace()` and

clippy_lints/src/methods/iter_on_single_or_empty_collections.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
use std::iter::once;
22

33
use clippy_utils::diagnostics::span_lint_and_sugg;
4-
use clippy_utils::res::{MaybeDef, MaybeQPath};
54
use clippy_utils::source::snippet;
65
use clippy_utils::ty::{ExprFnSig, expr_sig, ty_sig};
7-
use clippy_utils::{get_expr_use_or_unification_node, std_or_core, sym};
6+
use clippy_utils::{as_some_expr, get_expr_use_or_unification_node, is_none_expr, std_or_core, sym};
87

98
use rustc_errors::Applicability;
10-
use rustc_hir::LangItem::{OptionNone, OptionSome};
119
use rustc_hir::hir_id::HirId;
1210
use rustc_hir::{Expr, ExprKind, Node};
1311
use rustc_lint::LateContext;
@@ -68,15 +66,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method
6866
let item = match recv.kind {
6967
ExprKind::Array([]) => None,
7068
ExprKind::Array([e]) => Some(e),
71-
ExprKind::Path(ref p)
72-
if cx
73-
.qpath_res(p, recv.hir_id)
74-
.ctor_parent(cx)
75-
.is_lang_item(cx, OptionNone) =>
76-
{
77-
None
78-
},
79-
ExprKind::Call(f, [arg]) if f.res(cx).ctor_parent(cx).is_lang_item(cx, OptionSome) => Some(arg),
69+
_ if is_none_expr(cx, recv) => None,
70+
_ if let Some(arg) = as_some_expr(cx, recv) => Some(arg),
8071
_ => return,
8172
};
8273
let iter_type = match method_name {

clippy_lints/src/methods/option_map_or_none.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::is_none_expr;
23
use clippy_utils::res::{MaybeDef, MaybeQPath};
34
use clippy_utils::source::snippet;
45
use rustc_errors::Applicability;
56
use rustc_hir as hir;
6-
use rustc_hir::LangItem::{OptionNone, OptionSome};
7+
use rustc_hir::LangItem::OptionSome;
78
use rustc_lint::LateContext;
89
use rustc_span::symbol::sym;
910

@@ -48,7 +49,7 @@ pub(super) fn check<'tcx>(
4849
return;
4950
}
5051

51-
if !def_arg.res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone) {
52+
if !is_none_expr(cx, def_arg) {
5253
// nothing to lint!
5354
return;
5455
}

clippy_lints/src/methods/result_map_or_else_none.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::peel_blocks;
32
use clippy_utils::res::{MaybeDef, MaybeQPath};
43
use clippy_utils::source::snippet;
4+
use clippy_utils::{is_none_expr, peel_blocks};
55
use rustc_errors::Applicability;
66
use rustc_hir as hir;
7-
use rustc_hir::LangItem::{OptionNone, OptionSome};
7+
use rustc_hir::LangItem::OptionSome;
88
use rustc_lint::LateContext;
99
use rustc_span::symbol::sym;
1010

@@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(
2525
&& let hir::ExprKind::Closure(&hir::Closure { body, .. }) = def_arg.kind
2626
&& let body = cx.tcx.hir_body(body)
2727
// And finally we check that we return a `None` in the "else case".
28-
&& peel_blocks(body.value).res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone)
28+
&& is_none_expr(cx, peel_blocks(body.value))
2929
{
3030
let msg = "called `map_or_else(|_| None, Some)` on a `Result` value";
3131
let self_snippet = snippet(cx, recv.span, "..");

0 commit comments

Comments
 (0)