Skip to content

Commit 0015cda

Browse files
committed
introduce as_some_pattern
1 parent 2d6da74 commit 0015cda

File tree

7 files changed

+42
-58
lines changed

7 files changed

+42
-58
lines changed

clippy_lints/src/loops/while_let_on_iterator.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
55
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
66
use clippy_utils::source::snippet_with_applicability;
77
use clippy_utils::visitors::is_res_used;
8-
use clippy_utils::{get_enclosing_loop_or_multi_call_closure, higher, is_refutable};
8+
use clippy_utils::{as_some_pattern, get_enclosing_loop_or_multi_call_closure, higher, is_refutable};
99
use rustc_errors::Applicability;
1010
use rustc_hir::def::Res;
1111
use rustc_hir::intravisit::{Visitor, walk_expr};
12-
use rustc_hir::{Closure, Expr, ExprKind, HirId, LangItem, LetStmt, Mutability, PatKind, UnOp};
12+
use rustc_hir::{Closure, Expr, ExprKind, HirId, LetStmt, Mutability, UnOp};
1313
use rustc_lint::LateContext;
1414
use rustc_middle::hir::nested_filter::OnlyBodies;
1515
use rustc_middle::ty::adjustment::Adjust;
@@ -19,8 +19,7 @@ use rustc_span::symbol::sym;
1919
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
2020
if let Some(higher::WhileLet { if_then, let_pat, let_expr, label, .. }) = higher::WhileLet::hir(expr)
2121
// check for `Some(..)` pattern
22-
&& let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind
23-
&& cx.qpath_res(pat_path, let_pat.hir_id).ctor_parent(cx).is_lang_item(cx, LangItem::OptionSome)
22+
&& let Some(some_pat) = as_some_pattern(cx, let_pat)
2423
// check for call to `Iterator::next`
2524
&& let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind
2625
&& method_name.ident.name == sym::next

clippy_lints/src/manual_option_as_slice.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ use clippy_config::Conf;
22
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
33
use clippy_utils::msrvs::Msrv;
44
use clippy_utils::res::{MaybeDef, MaybeQPath, MaybeResPath};
5-
use clippy_utils::{is_none_pattern, msrvs, peel_hir_expr_refs, sym};
5+
use clippy_utils::{as_some_pattern, is_none_pattern, msrvs, peel_hir_expr_refs, sym};
66
use rustc_errors::Applicability;
7-
use rustc_hir::def::{DefKind, Res};
8-
use rustc_hir::{Arm, Expr, ExprKind, LangItem, Pat, PatKind, QPath, is_range_literal};
7+
use rustc_hir::{Arm, Expr, ExprKind, Pat, PatKind, QPath, is_range_literal};
98
use rustc_lint::{LateContext, LateLintPass};
109
use rustc_middle::ty;
1110
use rustc_session::impl_lint_pass;
@@ -152,10 +151,8 @@ fn check_as_ref(cx: &LateContext<'_>, expr: &Expr<'_>, span: Span, msrv: Msrv) {
152151
}
153152

154153
fn extract_ident_from_some_pat(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<Symbol> {
155-
if let PatKind::TupleStruct(QPath::Resolved(None, path), [binding], _) = pat.kind
156-
&& let Res::Def(DefKind::Ctor(..), def_id) = path.res
154+
if let Some([binding]) = as_some_pattern(cx, pat)
157155
&& let PatKind::Binding(_mode, _hir_id, ident, _inner_pat) = binding.kind
158-
&& clippy_utils::is_lang_item_or_ctor(cx, def_id, LangItem::OptionSome)
159156
{
160157
Some(ident.name)
161158
} else {

clippy_lints/src/match_result_ok.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::res::MaybeDef;
33
use clippy_utils::source::snippet_with_context;
4-
use clippy_utils::{higher, sym};
4+
use clippy_utils::{as_some_pattern, higher, sym};
55
use rustc_errors::Applicability;
6-
use rustc_hir::{Expr, ExprKind, LangItem, PatKind};
6+
use rustc_hir::{Expr, ExprKind};
77
use rustc_lint::{LateContext, LateLintPass};
88
use rustc_session::declare_lint_pass;
99

@@ -55,10 +55,9 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
5555
};
5656

5757
if let ExprKind::MethodCall(ok_path, recv, [], ..) = let_expr.kind //check is expr.ok() has type Result<T,E>.ok(, _)
58-
&& let PatKind::TupleStruct(ref pat_path, [ok_pat], _) = let_pat.kind //get operation
5958
&& ok_path.ident.name == sym::ok
6059
&& cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Result)
61-
&& cx.qpath_res(pat_path, let_pat.hir_id).ctor_parent(cx).is_lang_item(cx, LangItem::OptionSome)
60+
&& let Some([ok_pat]) = as_some_pattern(cx, let_pat) //get operation
6261
&& let ctxt = expr.span.ctxt()
6362
&& let_expr.span.ctxt() == ctxt
6463
&& let_pat.span.ctxt() == ctxt

clippy_lints/src/matches/manual_utils.rs

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ 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::{
8-
CaptureKind, can_move_expr_to_closure, expr_requires_coercion, is_else_clause, is_lint_allowed, peel_blocks,
9-
peel_hir_expr_refs, peel_hir_expr_while,
8+
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,
1010
};
1111
use rustc_ast::util::parser::ExprPrecedence;
1212
use rustc_errors::Applicability;
13-
use rustc_hir::LangItem::{OptionNone, OptionSome};
13+
use rustc_hir::LangItem::OptionNone;
1414
use rustc_hir::def::Res;
15-
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Mutability, Pat, PatExpr, PatExprKind, PatKind, Path, QPath};
15+
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath};
1616
use rustc_lint::LateContext;
1717
use rustc_span::{SyntaxContext, sym};
1818

@@ -255,23 +255,9 @@ pub(super) fn try_parse_pattern<'tcx>(
255255
match pat.kind {
256256
PatKind::Wild => Some(OptionPat::Wild),
257257
PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt),
258-
PatKind::Expr(PatExpr {
259-
kind: PatExprKind::Path(qpath),
260-
hir_id,
261-
..
262-
}) if cx
263-
.qpath_res(qpath, *hir_id)
264-
.ctor_parent(cx)
265-
.is_lang_item(cx, OptionNone) =>
266-
{
267-
Some(OptionPat::None)
268-
},
269-
PatKind::TupleStruct(ref qpath, [pattern], _)
270-
if cx
271-
.qpath_res(qpath, pat.hir_id)
272-
.ctor_parent(cx)
273-
.is_lang_item(cx, OptionSome)
274-
&& pat.span.ctxt() == ctxt =>
258+
_ if is_none_pattern(cx, pat) => Some(OptionPat::None),
259+
_ if let Some([pattern]) = as_some_pattern(cx, pat)
260+
&& pat.span.ctxt() == ctxt =>
275261
{
276262
Some(OptionPat::Some { pattern, ref_count })
277263
},

clippy_lints/src/matches/match_as_ref.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::res::{MaybeDef, MaybeQPath};
33
use clippy_utils::source::snippet_with_applicability;
4-
use clippy_utils::{is_none_arm, peel_blocks};
4+
use clippy_utils::{as_some_pattern, is_none_arm, peel_blocks};
55
use rustc_errors::Applicability;
66
use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
77
use rustc_lint::LateContext;
@@ -58,11 +58,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
5858

5959
// Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
6060
fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
61-
if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind
62-
&& cx
63-
.qpath_res(qpath, arm.pat.hir_id)
64-
.ctor_parent(cx)
65-
.is_lang_item(cx, LangItem::OptionSome)
61+
if let Some([first_pat, ..]) = as_some_pattern(cx, arm.pat)
6662
&& let PatKind::Binding(BindingMode(ByRef::Yes(mutabl), _), .., ident, _) = first_pat.kind
6763
&& let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind
6864
&& e.res(cx).ctor_parent(cx).is_lang_item(cx, LangItem::OptionSome)

clippy_lints/src/option_if_let_else.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,15 @@ use clippy_utils::sugg::Sugg;
66
use clippy_utils::ty::is_copy;
77
use clippy_utils::{
88
CaptureKind, can_move_expr_to_closure, eager_or_lazy, expr_requires_coercion, higher, is_else_clause,
9-
is_in_const_context, peel_blocks, peel_hir_expr_while,
9+
is_in_const_context, is_none_pattern, peel_blocks, peel_hir_expr_while,
1010
};
1111
use rustc_data_structures::fx::FxHashSet;
1212
use rustc_errors::Applicability;
13-
use rustc_hir::LangItem::{OptionNone, ResultErr};
13+
use rustc_hir::LangItem::ResultErr;
1414
use rustc_hir::def::Res;
1515
use rustc_hir::intravisit::{Visitor, walk_expr, walk_path};
1616
use rustc_hir::{
17-
Arm, BindingMode, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, PatExpr, PatExprKind, PatKind, Path,
18-
QPath, UnOp,
17+
Arm, BindingMode, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, UnOp,
1918
};
2019
use rustc_lint::{LateContext, LateLintPass};
2120
use rustc_middle::hir::nested_filter;
@@ -379,14 +378,7 @@ fn try_convert_match<'tcx>(
379378

380379
fn is_none_or_err_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
381380
match arm.pat.kind {
382-
PatKind::Expr(PatExpr {
383-
kind: PatExprKind::Path(qpath),
384-
hir_id,
385-
..
386-
}) => cx
387-
.qpath_res(qpath, *hir_id)
388-
.ctor_parent(cx)
389-
.is_lang_item(cx, OptionNone),
381+
_ if is_none_pattern(cx, arm.pat) => true,
390382
PatKind::TupleStruct(ref qpath, [first_pat], _) => {
391383
cx.qpath_res(qpath, arm.pat.hir_id)
392384
.ctor_parent(cx)

clippy_utils/src/lib.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,25 @@ pub fn is_wild(pat: &Pat<'_>) -> bool {
320320
matches!(pat.kind, PatKind::Wild)
321321
}
322322

323+
/// If `pat` is:
324+
/// - `Some(inner)`, returns `inner`
325+
/// - it will _usually_ contain just one element, but could have two, given patterns like
326+
/// `Some(inner, ..)` or `Some(.., inner)`
327+
/// - `Some`, returns `[]`
328+
/// - otherwise, returns `None`
329+
pub fn as_some_pattern<'a, 'hir>(cx: &LateContext<'_>, pat: &'a Pat<'hir>) -> Option<&'a [Pat<'hir>]> {
330+
if let PatKind::TupleStruct(ref qpath, inner, _) = pat.kind
331+
&& cx
332+
.qpath_res(qpath, pat.hir_id)
333+
.ctor_parent(cx)
334+
.is_lang_item(cx, OptionSome)
335+
{
336+
Some(inner)
337+
} else {
338+
None
339+
}
340+
}
341+
323342
/// Checks if the `pat` is `None`.
324343
pub fn is_none_pattern(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
325344
matches!(pat.kind,
@@ -2783,11 +2802,7 @@ pub fn pat_and_expr_can_be_question_mark<'a, 'hir>(
27832802
pat: &'a Pat<'hir>,
27842803
else_body: &Expr<'_>,
27852804
) -> Option<&'a Pat<'hir>> {
2786-
if let PatKind::TupleStruct(pat_path, [inner_pat], _) = pat.kind
2787-
&& cx
2788-
.qpath_res(&pat_path, pat.hir_id)
2789-
.ctor_parent(cx)
2790-
.is_lang_item(cx, OptionSome)
2805+
if let Some([inner_pat]) = as_some_pattern(cx, pat)
27912806
&& !is_refutable(cx, inner_pat)
27922807
&& let else_body = peel_blocks(else_body)
27932808
&& let ExprKind::Ret(Some(ret_val)) = else_body.kind

0 commit comments

Comments
 (0)