Skip to content

Commit 4dd78d3

Browse files
committed
Move pat_and_expr_can_be_question_mark into clippy_utils
1 parent 977496e commit 4dd78d3

File tree

3 files changed

+50
-49
lines changed

3 files changed

+50
-49
lines changed

clippy_lints/src/manual_let_else.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use crate::question_mark::{pat_and_expr_can_be_question_mark, QuestionMark, QUESTION_MARK};
1+
use crate::question_mark::{QuestionMark, QUESTION_MARK};
22
use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::higher::IfLetOrMatch;
44
use clippy_utils::source::snippet_with_context;
55
use clippy_utils::ty::is_type_diagnostic_item;
66
use clippy_utils::visitors::{Descend, Visitable};
7-
use clippy_utils::{is_lint_allowed, msrvs, peel_blocks};
7+
use clippy_utils::{is_lint_allowed, msrvs, pat_and_expr_can_be_question_mark, peel_blocks};
88
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
99
use rustc_errors::Applicability;
1010
use rustc_hir::intravisit::{walk_expr, Visitor};

clippy_lints/src/question_mark.rs

+3-47
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ use clippy_utils::msrvs::Msrv;
44
use clippy_utils::source::snippet_with_applicability;
55
use clippy_utils::ty::is_type_diagnostic_item;
66
use clippy_utils::{
7-
eq_expr_value, get_parent_node, in_constant, is_else_clause, is_refutable, is_res_lang_ctor, path_to_local,
8-
path_to_local_id, peel_blocks, peel_blocks_with_stmt,
7+
eq_expr_value, get_parent_node, in_constant, is_else_clause, is_res_lang_ctor, pat_and_expr_can_be_question_mark,
8+
path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt,
99
};
1010
use clippy_utils::{higher, is_path_lang_item};
1111
use if_chain::if_chain;
1212
use rustc_errors::Applicability;
1313
use rustc_hir::def::Res;
1414
use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk};
1515
use rustc_hir::{
16-
BindingAnnotation, Block, ByRef, Expr, ExprKind, Local, Node, Pat, PatKind, PathSegment, QPath, Stmt, StmtKind,
16+
BindingAnnotation, Block, ByRef, Expr, ExprKind, Local, Node, PatKind, PathSegment, QPath, Stmt, StmtKind,
1717
};
1818
use rustc_lint::{LateContext, LateLintPass};
1919
use rustc_middle::ty::Ty;
@@ -95,50 +95,6 @@ enum IfBlockType<'hir> {
9595
),
9696
}
9797

98-
/// Returns whether the given let pattern and else body can be turned into a question mark
99-
///
100-
/// For this example:
101-
/// ```ignore
102-
/// let FooBar { a, b } = if let Some(a) = ex { a } else { return None };
103-
/// ```
104-
/// We get as parameters:
105-
/// ```ignore
106-
/// pat: Some(a)
107-
/// else_body: return None
108-
/// ```
109-
110-
/// And for this example:
111-
/// ```ignore
112-
/// let Some(FooBar { a, b }) = ex else { return None };
113-
/// ```
114-
/// We get as parameters:
115-
/// ```ignore
116-
/// pat: Some(FooBar { a, b })
117-
/// else_body: return None
118-
/// ```
119-
120-
/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because
121-
/// the question mark operator is applicable here. Callers have to check whether we are in a
122-
/// constant or not.
123-
pub(crate) fn pat_and_expr_can_be_question_mark<'a, 'hir>(
124-
cx: &LateContext<'_>,
125-
pat: &'a Pat<'hir>,
126-
else_body: &Expr<'_>,
127-
) -> Option<&'a Pat<'hir>> {
128-
if let PatKind::TupleStruct(pat_path, [inner_pat], _) = pat.kind &&
129-
is_res_lang_ctor(cx, cx.qpath_res(&pat_path, pat.hir_id), OptionSome) &&
130-
!is_refutable(cx, inner_pat) &&
131-
let else_body = peel_blocks(else_body) &&
132-
let ExprKind::Ret(Some(ret_val)) = else_body.kind &&
133-
let ExprKind::Path(ret_path) = ret_val.kind &&
134-
is_res_lang_ctor(cx, cx.qpath_res(&ret_path, ret_val.hir_id), OptionNone)
135-
{
136-
Some(inner_pat)
137-
} else {
138-
None
139-
}
140-
}
141-
14298
fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
14399
if let StmtKind::Local(Local { pat, init: Some(init_expr), els: Some(els), .. }) = stmt.kind &&
144100
let Block { stmts: &[], expr: Some(els), .. } = els &&

clippy_utils/src/lib.rs

+45
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ use rustc_hir::def::{DefKind, Res};
8787
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
8888
use rustc_hir::hir_id::{HirIdMap, HirIdSet};
8989
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
90+
use rustc_hir::LangItem::OptionSome;
9091
use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
9192
use rustc_hir::{
9293
self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr,
@@ -2542,6 +2543,50 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
25422543
sm.span_take_while(span, |&ch| ch == ' ' || ch == ';')
25432544
}
25442545

2546+
/// Returns whether the given let pattern and else body can be turned into a question mark
2547+
///
2548+
/// For this example:
2549+
/// ```ignore
2550+
/// let FooBar { a, b } = if let Some(a) = ex { a } else { return None };
2551+
/// ```
2552+
/// We get as parameters:
2553+
/// ```ignore
2554+
/// pat: Some(a)
2555+
/// else_body: return None
2556+
/// ```
2557+
2558+
/// And for this example:
2559+
/// ```ignore
2560+
/// let Some(FooBar { a, b }) = ex else { return None };
2561+
/// ```
2562+
/// We get as parameters:
2563+
/// ```ignore
2564+
/// pat: Some(FooBar { a, b })
2565+
/// else_body: return None
2566+
/// ```
2567+
2568+
/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because
2569+
/// the question mark operator is applicable here. Callers have to check whether we are in a
2570+
/// constant or not.
2571+
pub fn pat_and_expr_can_be_question_mark<'a, 'hir>(
2572+
cx: &LateContext<'_>,
2573+
pat: &'a Pat<'hir>,
2574+
else_body: &Expr<'_>,
2575+
) -> Option<&'a Pat<'hir>> {
2576+
if let PatKind::TupleStruct(pat_path, [inner_pat], _) = pat.kind &&
2577+
is_res_lang_ctor(cx, cx.qpath_res(&pat_path, pat.hir_id), OptionSome) &&
2578+
!is_refutable(cx, inner_pat) &&
2579+
let else_body = peel_blocks(else_body) &&
2580+
let ExprKind::Ret(Some(ret_val)) = else_body.kind &&
2581+
let ExprKind::Path(ret_path) = ret_val.kind &&
2582+
is_res_lang_ctor(cx, cx.qpath_res(&ret_path, ret_val.hir_id), OptionNone)
2583+
{
2584+
Some(inner_pat)
2585+
} else {
2586+
None
2587+
}
2588+
}
2589+
25452590
macro_rules! op_utils {
25462591
($($name:ident $assign:ident)*) => {
25472592
/// Binary operation traits like `LangItem::Add`

0 commit comments

Comments
 (0)