Skip to content

Commit 1430623

Browse files
committed
move methods out of impl and remove unused &self param
1 parent 0671d78 commit 1430623

File tree

3 files changed

+149
-130
lines changed

3 files changed

+149
-130
lines changed

clippy_lints/src/question_mark.rs

+102-99
Original file line numberDiff line numberDiff line change
@@ -203,106 +203,106 @@ fn expr_return_none_or_err(
203203
}
204204
}
205205

206-
impl QuestionMark {
207-
fn inside_try_block(&self) -> bool {
208-
self.try_block_depth_stack.last() > Some(&0)
209-
}
210-
211-
/// Checks if the given expression on the given context matches the following structure:
212-
///
213-
/// ```ignore
214-
/// if option.is_none() {
215-
/// return None;
216-
/// }
217-
/// ```
218-
///
219-
/// ```ignore
220-
/// if result.is_err() {
221-
/// return result;
222-
/// }
223-
/// ```
224-
///
225-
/// If it matches, it will suggest to use the question mark operator instead
226-
fn check_is_none_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
227-
if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr)
228-
&& !is_else_clause(cx.tcx, expr)
229-
&& let ExprKind::MethodCall(segment, caller, ..) = &cond.kind
230-
&& let caller_ty = cx.typeck_results().expr_ty(caller)
231-
&& let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then)
232-
&& (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block))
233-
{
234-
let mut applicability = Applicability::MachineApplicable;
235-
let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
236-
let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
237-
&& !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
238-
let sugg = if let Some(else_inner) = r#else {
239-
if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
240-
format!("Some({receiver_str}?)")
241-
} else {
242-
return;
243-
}
206+
/// Checks if the given expression on the given context matches the following structure:
207+
///
208+
/// ```ignore
209+
/// if option.is_none() {
210+
/// return None;
211+
/// }
212+
/// ```
213+
///
214+
/// ```ignore
215+
/// if result.is_err() {
216+
/// return result;
217+
/// }
218+
/// ```
219+
///
220+
/// If it matches, it will suggest to use the question mark operator instead
221+
fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
222+
if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr)
223+
&& !is_else_clause(cx.tcx, expr)
224+
&& let ExprKind::MethodCall(segment, caller, ..) = &cond.kind
225+
&& let caller_ty = cx.typeck_results().expr_ty(caller)
226+
&& let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then)
227+
&& (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block))
228+
{
229+
let mut applicability = Applicability::MachineApplicable;
230+
let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
231+
let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
232+
&& !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
233+
let sugg = if let Some(else_inner) = r#else {
234+
if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
235+
format!("Some({receiver_str}?)")
244236
} else {
245-
format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
246-
};
237+
return;
238+
}
239+
} else {
240+
format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
241+
};
247242

248-
span_lint_and_sugg(
249-
cx,
250-
QUESTION_MARK,
251-
expr.span,
252-
"this block may be rewritten with the `?` operator",
253-
"replace it with",
254-
sugg,
255-
applicability,
256-
);
257-
}
243+
span_lint_and_sugg(
244+
cx,
245+
QUESTION_MARK,
246+
expr.span,
247+
"this block may be rewritten with the `?` operator",
248+
"replace it with",
249+
sugg,
250+
applicability,
251+
);
258252
}
253+
}
259254

260-
fn check_if_let_some_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
261-
if let Some(higher::IfLet {
262-
let_pat,
263-
let_expr,
264-
if_then,
265-
if_else,
266-
..
267-
}) = higher::IfLet::hir(cx, expr)
268-
&& !is_else_clause(cx.tcx, expr)
269-
&& let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind
270-
&& ddpos.as_opt_usize().is_none()
271-
&& let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind
272-
&& let caller_ty = cx.typeck_results().expr_ty(let_expr)
273-
&& let if_block = IfBlockType::IfLet(
274-
cx.qpath_res(path1, let_pat.hir_id),
275-
caller_ty,
276-
ident.name,
277-
let_expr,
278-
if_then,
279-
if_else,
280-
)
281-
&& ((is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
282-
|| is_early_return(sym::Result, cx, &if_block))
283-
&& if_else
284-
.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e)))
285-
.filter(|e| *e)
286-
.is_none()
287-
{
288-
let mut applicability = Applicability::MachineApplicable;
289-
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
290-
let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_));
291-
let sugg = format!(
292-
"{receiver_str}{}?{}",
293-
if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
294-
if requires_semi { ";" } else { "" }
295-
);
296-
span_lint_and_sugg(
297-
cx,
298-
QUESTION_MARK,
299-
expr.span,
300-
"this block may be rewritten with the `?` operator",
301-
"replace it with",
302-
sugg,
303-
applicability,
304-
);
305-
}
255+
fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
256+
if let Some(higher::IfLet {
257+
let_pat,
258+
let_expr,
259+
if_then,
260+
if_else,
261+
..
262+
}) = higher::IfLet::hir(cx, expr)
263+
&& !is_else_clause(cx.tcx, expr)
264+
&& let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind
265+
&& ddpos.as_opt_usize().is_none()
266+
&& let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind
267+
&& let caller_ty = cx.typeck_results().expr_ty(let_expr)
268+
&& let if_block = IfBlockType::IfLet(
269+
cx.qpath_res(path1, let_pat.hir_id),
270+
caller_ty,
271+
ident.name,
272+
let_expr,
273+
if_then,
274+
if_else,
275+
)
276+
&& ((is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
277+
|| is_early_return(sym::Result, cx, &if_block))
278+
&& if_else
279+
.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e)))
280+
.filter(|e| *e)
281+
.is_none()
282+
{
283+
let mut applicability = Applicability::MachineApplicable;
284+
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
285+
let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_));
286+
let sugg = format!(
287+
"{receiver_str}{}?{}",
288+
if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
289+
if requires_semi { ";" } else { "" }
290+
);
291+
span_lint_and_sugg(
292+
cx,
293+
QUESTION_MARK,
294+
expr.span,
295+
"this block may be rewritten with the `?` operator",
296+
"replace it with",
297+
sugg,
298+
applicability,
299+
);
300+
}
301+
}
302+
303+
impl QuestionMark {
304+
fn inside_try_block(&self) -> bool {
305+
self.try_block_depth_stack.last() > Some(&0)
306306
}
307307
}
308308

@@ -328,9 +328,12 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
328328
self.check_manual_let_else(cx, stmt);
329329
}
330330
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
331-
if !self.inside_try_block() && !in_constant(cx, expr.hir_id) && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id) {
332-
self.check_is_none_or_err_and_early_return(cx, expr);
333-
self.check_if_let_some_or_err_and_early_return(cx, expr);
331+
if !self.inside_try_block()
332+
&& !in_constant(cx, expr.hir_id)
333+
&& is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id)
334+
{
335+
check_is_none_or_err_and_early_return(cx, expr);
336+
check_if_let_some_or_err_and_early_return(cx, expr);
334337
}
335338
}
336339

tests/ui/manual_let_else.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(try_blocks)]
12
#![allow(unused_braces, unused_variables, dead_code)]
23
#![allow(
34
clippy::collapsible_else_if,
@@ -446,3 +447,12 @@ struct U<T> {
446447
w: T,
447448
x: T,
448449
}
450+
451+
fn issue12337() {
452+
// We want to generally silence question_mark lints within try blocks, since `?` has different
453+
// behavior to `return`, and question_mark calls into manual_let_else logic, so make sure that
454+
// we still emit a lint for manual_let_else
455+
let _: Option<()> = try {
456+
let v = if let Some(v_some) = g() { v_some } else { return };
457+
};
458+
}

0 commit comments

Comments
 (0)