mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-14 17:07:17 +00:00
Auto merge of #12341 - y21:issue12337, r=dswij
Check for try blocks in `question_mark` more consistently Fixes #12337 I split this PR up into two commits since this moves a method out of an `impl`, which makes for a pretty bad diff (the `&self` parameter is now unused, and there isn't a reason for that function to be part of the `impl` now). The first commit is the actual relevant change and the 2nd commit just moves stuff (github's "hide whitespace" makes the diff easier to look at) ------------ Now for the actual issue: `?` within `try {}` blocks desugars to a `break` to the block, rather than a `return`, so that changes behavior in those cases. The lint has multiple patterns to look for and in *some* of them it already does correctly check whether we're in a try block, but this isn't done for all of its patterns. We could add another `self.inside_try_block()` check to the function that looks for `let-else-return`, but I chose to actually just move those checks out and instead have them in `LintPass::check_{stmt,expr}`. This has the advantage that we can't (easily) accidentally forget to add that check in new patterns that might be added in the future. (There's also a bit of a subtle interaction between two lints, where `question_mark`'s LintPass calls into `manual_let_else`, so I added a check to make sure we don't avoid linting for something that doesn't have anything to do with `?`) changelog: [`question_mark`]: avoid linting on try blocks in more cases
This commit is contained in:
commit
e970fa52e7
5 changed files with 171 additions and 134 deletions
|
@ -203,109 +203,107 @@ fn expr_return_none_or_err(
|
|||
}
|
||||
}
|
||||
|
||||
/// Checks if the given expression on the given context matches the following structure:
|
||||
///
|
||||
/// ```ignore
|
||||
/// if option.is_none() {
|
||||
/// return None;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ```ignore
|
||||
/// if result.is_err() {
|
||||
/// return result;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If it matches, it will suggest to use the question mark operator instead
|
||||
fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||
if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr)
|
||||
&& !is_else_clause(cx.tcx, expr)
|
||||
&& let ExprKind::MethodCall(segment, caller, ..) = &cond.kind
|
||||
&& let caller_ty = cx.typeck_results().expr_ty(caller)
|
||||
&& let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then)
|
||||
&& (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block))
|
||||
{
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
|
||||
let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
|
||||
&& !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
|
||||
let sugg = if let Some(else_inner) = r#else {
|
||||
if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
|
||||
format!("Some({receiver_str}?)")
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
QUESTION_MARK,
|
||||
expr.span,
|
||||
"this block may be rewritten with the `?` operator",
|
||||
"replace it with",
|
||||
sugg,
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||
if let Some(higher::IfLet {
|
||||
let_pat,
|
||||
let_expr,
|
||||
if_then,
|
||||
if_else,
|
||||
..
|
||||
}) = higher::IfLet::hir(cx, expr)
|
||||
&& !is_else_clause(cx.tcx, expr)
|
||||
&& let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind
|
||||
&& ddpos.as_opt_usize().is_none()
|
||||
&& let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind
|
||||
&& let caller_ty = cx.typeck_results().expr_ty(let_expr)
|
||||
&& let if_block = IfBlockType::IfLet(
|
||||
cx.qpath_res(path1, let_pat.hir_id),
|
||||
caller_ty,
|
||||
ident.name,
|
||||
let_expr,
|
||||
if_then,
|
||||
if_else,
|
||||
)
|
||||
&& ((is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
|
||||
|| is_early_return(sym::Result, cx, &if_block))
|
||||
&& if_else
|
||||
.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e)))
|
||||
.filter(|e| *e)
|
||||
.is_none()
|
||||
{
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
|
||||
let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_));
|
||||
let sugg = format!(
|
||||
"{receiver_str}{}?{}",
|
||||
if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
|
||||
if requires_semi { ";" } else { "" }
|
||||
);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
QUESTION_MARK,
|
||||
expr.span,
|
||||
"this block may be rewritten with the `?` operator",
|
||||
"replace it with",
|
||||
sugg,
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl QuestionMark {
|
||||
fn inside_try_block(&self) -> bool {
|
||||
self.try_block_depth_stack.last() > Some(&0)
|
||||
}
|
||||
|
||||
/// Checks if the given expression on the given context matches the following structure:
|
||||
///
|
||||
/// ```ignore
|
||||
/// if option.is_none() {
|
||||
/// return None;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ```ignore
|
||||
/// if result.is_err() {
|
||||
/// return result;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If it matches, it will suggest to use the question mark operator instead
|
||||
fn check_is_none_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||
if !self.inside_try_block()
|
||||
&& let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr)
|
||||
&& !is_else_clause(cx.tcx, expr)
|
||||
&& let ExprKind::MethodCall(segment, caller, ..) = &cond.kind
|
||||
&& let caller_ty = cx.typeck_results().expr_ty(caller)
|
||||
&& let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then)
|
||||
&& (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block))
|
||||
{
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
|
||||
let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
|
||||
&& !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
|
||||
let sugg = if let Some(else_inner) = r#else {
|
||||
if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
|
||||
format!("Some({receiver_str}?)")
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
QUESTION_MARK,
|
||||
expr.span,
|
||||
"this block may be rewritten with the `?` operator",
|
||||
"replace it with",
|
||||
sugg,
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_if_let_some_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||
if !self.inside_try_block()
|
||||
&& let Some(higher::IfLet {
|
||||
let_pat,
|
||||
let_expr,
|
||||
if_then,
|
||||
if_else,
|
||||
..
|
||||
}) = higher::IfLet::hir(cx, expr)
|
||||
&& !is_else_clause(cx.tcx, expr)
|
||||
&& let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind
|
||||
&& ddpos.as_opt_usize().is_none()
|
||||
&& let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind
|
||||
&& let caller_ty = cx.typeck_results().expr_ty(let_expr)
|
||||
&& let if_block = IfBlockType::IfLet(
|
||||
cx.qpath_res(path1, let_pat.hir_id),
|
||||
caller_ty,
|
||||
ident.name,
|
||||
let_expr,
|
||||
if_then,
|
||||
if_else,
|
||||
)
|
||||
&& ((is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
|
||||
|| is_early_return(sym::Result, cx, &if_block))
|
||||
&& if_else
|
||||
.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e)))
|
||||
.filter(|e| *e)
|
||||
.is_none()
|
||||
{
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
|
||||
let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_));
|
||||
let sugg = format!(
|
||||
"{receiver_str}{}?{}",
|
||||
if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
|
||||
if requires_semi { ";" } else { "" }
|
||||
);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
QUESTION_MARK,
|
||||
expr.span,
|
||||
"this block may be rewritten with the `?` operator",
|
||||
"replace it with",
|
||||
sugg,
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_try_block(cx: &LateContext<'_>, bl: &rustc_hir::Block<'_>) -> bool {
|
||||
|
@ -324,15 +322,18 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
|
|||
return;
|
||||
}
|
||||
|
||||
if !in_constant(cx, stmt.hir_id) {
|
||||
if !self.inside_try_block() && !in_constant(cx, stmt.hir_id) {
|
||||
check_let_some_else_return_none(cx, stmt);
|
||||
}
|
||||
self.check_manual_let_else(cx, stmt);
|
||||
}
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if !in_constant(cx, expr.hir_id) && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id) {
|
||||
self.check_is_none_or_err_and_early_return(cx, expr);
|
||||
self.check_if_let_some_or_err_and_early_return(cx, expr);
|
||||
if !self.inside_try_block()
|
||||
&& !in_constant(cx, expr.hir_id)
|
||||
&& is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id)
|
||||
{
|
||||
check_is_none_or_err_and_early_return(cx, expr);
|
||||
check_if_let_some_or_err_and_early_return(cx, expr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#![feature(try_blocks)]
|
||||
#![allow(unused_braces, unused_variables, dead_code)]
|
||||
#![allow(
|
||||
clippy::collapsible_else_if,
|
||||
|
@ -446,3 +447,12 @@ struct U<T> {
|
|||
w: T,
|
||||
x: T,
|
||||
}
|
||||
|
||||
fn issue12337() {
|
||||
// We want to generally silence question_mark lints within try blocks, since `?` has different
|
||||
// behavior to `return`, and question_mark calls into manual_let_else logic, so make sure that
|
||||
// we still emit a lint for manual_let_else
|
||||
let _: Option<()> = try {
|
||||
let v = if let Some(v_some) = g() { v_some } else { return };
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:27:5
|
||||
--> tests/ui/manual_let_else.rs:28:5
|
||||
|
|
||||
LL | let v = if let Some(v_some) = g() { v_some } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
|
||||
|
@ -8,7 +8,7 @@ LL | let v = if let Some(v_some) = g() { v_some } else { return };
|
|||
= help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:30:5
|
||||
--> tests/ui/manual_let_else.rs:31:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -26,7 +26,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:37:5
|
||||
--> tests/ui/manual_let_else.rs:38:5
|
||||
|
|
||||
LL | / let v = if let Some(v) = g() {
|
||||
LL | |
|
||||
|
@ -47,25 +47,25 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:49:9
|
||||
--> tests/ui/manual_let_else.rs:50:9
|
||||
|
|
||||
LL | let v = if let Some(v_some) = g() { v_some } else { continue };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:51:9
|
||||
--> tests/ui/manual_let_else.rs:52:9
|
||||
|
|
||||
LL | let v = if let Some(v_some) = g() { v_some } else { break };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:56:5
|
||||
--> tests/ui/manual_let_else.rs:57:5
|
||||
|
|
||||
LL | let v = if let Some(v_some) = g() { v_some } else { panic!() };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:60:5
|
||||
--> tests/ui/manual_let_else.rs:61:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -83,7 +83,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:68:5
|
||||
--> tests/ui/manual_let_else.rs:69:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -101,7 +101,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:76:5
|
||||
--> tests/ui/manual_let_else.rs:77:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -121,7 +121,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:85:5
|
||||
--> tests/ui/manual_let_else.rs:86:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -141,7 +141,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:94:5
|
||||
--> tests/ui/manual_let_else.rs:95:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -168,7 +168,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:110:5
|
||||
--> tests/ui/manual_let_else.rs:111:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -190,7 +190,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:121:5
|
||||
--> tests/ui/manual_let_else.rs:122:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -217,7 +217,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:137:5
|
||||
--> tests/ui/manual_let_else.rs:138:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -239,7 +239,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:148:5
|
||||
--> tests/ui/manual_let_else.rs:149:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -257,7 +257,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:156:5
|
||||
--> tests/ui/manual_let_else.rs:157:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -278,7 +278,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:166:5
|
||||
--> tests/ui/manual_let_else.rs:167:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -299,7 +299,7 @@ LL + } };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:176:5
|
||||
--> tests/ui/manual_let_else.rs:177:5
|
||||
|
|
||||
LL | / let v = if let Some(v_some) = g() {
|
||||
LL | |
|
||||
|
@ -328,7 +328,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:194:5
|
||||
--> tests/ui/manual_let_else.rs:195:5
|
||||
|
|
||||
LL | / let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
|
||||
LL | |
|
||||
|
@ -346,7 +346,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:202:5
|
||||
--> tests/ui/manual_let_else.rs:203:5
|
||||
|
|
||||
LL | / let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) {
|
||||
LL | |
|
||||
|
@ -364,7 +364,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:212:13
|
||||
--> tests/ui/manual_let_else.rs:213:13
|
||||
|
|
||||
LL | let $n = if let Some(v) = $e { v } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };`
|
||||
|
@ -375,19 +375,19 @@ LL | create_binding_if_some!(w, g());
|
|||
= note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:221:5
|
||||
--> tests/ui/manual_let_else.rs:222:5
|
||||
|
|
||||
LL | let v = if let Variant::A(a, 0) = e() { a } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:225:5
|
||||
--> tests/ui/manual_let_else.rs:226:5
|
||||
|
|
||||
LL | let mut v = if let Variant::B(b) = e() { b } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:230:5
|
||||
--> tests/ui/manual_let_else.rs:231:5
|
||||
|
|
||||
LL | / let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested {
|
||||
LL | |
|
||||
|
@ -405,19 +405,19 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:237:5
|
||||
--> tests/ui/manual_let_else.rs:238:5
|
||||
|
|
||||
LL | let v = if let Variant::A(.., a) = e() { a } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:241:5
|
||||
--> tests/ui/manual_let_else.rs:242:5
|
||||
|
|
||||
LL | let w = if let (Some(v), ()) = (g(), ()) { v } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:245:5
|
||||
--> tests/ui/manual_let_else.rs:246:5
|
||||
|
|
||||
LL | / let w = if let Some(S { v: x }) = Some(S { v: 0 }) {
|
||||
LL | |
|
||||
|
@ -435,7 +435,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:253:5
|
||||
--> tests/ui/manual_let_else.rs:254:5
|
||||
|
|
||||
LL | / let v = if let Some(S { v: x }) = Some(S { v: 0 }) {
|
||||
LL | |
|
||||
|
@ -453,7 +453,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:261:5
|
||||
--> tests/ui/manual_let_else.rs:262:5
|
||||
|
|
||||
LL | / let (x, S { v }, w) = if let Some(U { v, w, x }) = None::<U<S<()>>> {
|
||||
LL | |
|
||||
|
@ -471,7 +471,7 @@ LL + };
|
|||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:378:5
|
||||
--> tests/ui/manual_let_else.rs:379:5
|
||||
|
|
||||
LL | / let _ = match ff {
|
||||
LL | |
|
||||
|
@ -480,5 +480,11 @@ LL | | _ => macro_call!(),
|
|||
LL | | };
|
||||
| |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
|
||||
|
||||
error: aborting due to 30 previous errors
|
||||
error: this could be rewritten as `let...else`
|
||||
--> tests/ui/manual_let_else.rs:456:9
|
||||
|
|
||||
LL | let v = if let Some(v_some) = g() { v_some } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
|
||||
|
||||
error: aborting due to 31 previous errors
|
||||
|
||||
|
|
|
@ -273,3 +273,13 @@ const fn issue9175(option: Option<()>) -> Option<()> {
|
|||
//stuff
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn issue12337() -> Option<i32> {
|
||||
let _: Option<i32> = try {
|
||||
let Some(_) = Some(42) else {
|
||||
return None;
|
||||
};
|
||||
123
|
||||
};
|
||||
Some(42)
|
||||
}
|
||||
|
|
|
@ -313,3 +313,13 @@ const fn issue9175(option: Option<()>) -> Option<()> {
|
|||
//stuff
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn issue12337() -> Option<i32> {
|
||||
let _: Option<i32> = try {
|
||||
let Some(_) = Some(42) else {
|
||||
return None;
|
||||
};
|
||||
123
|
||||
};
|
||||
Some(42)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue