diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index eadd7a310b7..d94272bcc79 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -56,7 +56,7 @@ fn create_e0004(
struct_span_err!(sess, sp, E0004, "{}", &error_message)
}
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq)]
enum RefutableFlag {
Irrefutable,
Refutable,
@@ -151,18 +151,22 @@ impl<'thir, 'tcx> Visitor<'thir, 'tcx> for MatchVisitor<'thir, '_, 'tcx> {
};
self.check_match(scrutinee, arms, source, ex.span);
}
- ExprKind::Let { box ref pat, expr } if !matches!(self.let_source, LetSource::None) => {
+ ExprKind::Let { box ref pat, expr } => {
self.check_let(pat, Some(expr), ex.span);
}
ExprKind::LogicalOp { op: LogicalOp::And, .. }
if !matches!(self.let_source, LetSource::None) =>
{
- self.check_let_chain(ex);
+ let mut chain_refutabilities = Vec::new();
+ let Ok(()) = self.visit_land(ex, &mut chain_refutabilities) else { return };
+ // If at least one of the operands is a `let ... = ...`.
+ if chain_refutabilities.iter().any(|x| x.is_some()) {
+ self.check_let_chain(chain_refutabilities, ex.span);
+ }
+ return;
}
_ => {}
};
- // If we got e.g. `let pat1 = x1 && let pat2 = x2` above, we will now traverse the two
- // `let`s. In order not to check them twice we set `LetSource::None`.
self.with_let_source(LetSource::None, |this| visit::walk_expr(this, ex));
}
@@ -212,6 +216,58 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
}
}
+ /// Visit a nested chain of `&&`. Used for if-let chains. This must call `visit_expr` on the
+ /// subexpressions we are not handling ourselves.
+ fn visit_land(
+ &mut self,
+ ex: &Expr<'tcx>,
+ accumulator: &mut Vec