mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-20 11:37:32 +00:00
Uncomplicate check_let_chain
This commit is contained in:
parent
fedee8d524
commit
1f9a2f73e1
@ -150,8 +150,8 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
|
|||||||
ExprKind::Let { box ref pat, expr } => {
|
ExprKind::Let { box ref pat, expr } => {
|
||||||
self.check_let(pat, expr, self.let_source, ex.span);
|
self.check_let(pat, expr, self.let_source, ex.span);
|
||||||
}
|
}
|
||||||
ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => {
|
ExprKind::LogicalOp { op: LogicalOp::And, .. } => {
|
||||||
self.check_let_chain(self.let_source, ex.span, lhs, rhs);
|
self.check_let_chain(self.let_source, ex);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
@ -326,71 +326,61 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
fn check_let_chain(
|
fn check_let_chain(&mut self, let_source: LetSource, expr: &Expr<'tcx>) {
|
||||||
&mut self,
|
|
||||||
let_source: LetSource,
|
|
||||||
top_expr_span: Span,
|
|
||||||
mut lhs: ExprId,
|
|
||||||
rhs: ExprId,
|
|
||||||
) {
|
|
||||||
if let LetSource::None = let_source {
|
if let LetSource::None = let_source {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lint level enclosing the next `lhs`.
|
let top_expr_span = expr.span;
|
||||||
let mut cur_lint_level = self.lint_level;
|
|
||||||
|
// Lint level enclosing `next_expr`.
|
||||||
|
let mut next_expr_lint_level = self.lint_level;
|
||||||
|
|
||||||
// Obtain the refutabilities of all exprs in the chain,
|
// Obtain the refutabilities of all exprs in the chain,
|
||||||
// and record chain members that aren't let exprs.
|
// and record chain members that aren't let exprs.
|
||||||
let mut chain_refutabilities = Vec::new();
|
let mut chain_refutabilities = Vec::new();
|
||||||
|
|
||||||
let mut error = Ok(());
|
let mut error = Ok(());
|
||||||
let mut add = |expr: ExprId, mut local_lint_level| {
|
let mut next_expr = Some(expr);
|
||||||
// `local_lint_level` is the lint level enclosing the pattern inside `expr`.
|
while let Some(mut expr) = next_expr {
|
||||||
let mut expr = &self.thir[expr];
|
|
||||||
debug!(?expr, ?local_lint_level, "add");
|
|
||||||
// Fast-forward through scopes.
|
|
||||||
while let ExprKind::Scope { value, lint_level, .. } = expr.kind {
|
while let ExprKind::Scope { value, lint_level, .. } = expr.kind {
|
||||||
if let LintLevel::Explicit(hir_id) = lint_level {
|
if let LintLevel::Explicit(hir_id) = lint_level {
|
||||||
local_lint_level = hir_id
|
next_expr_lint_level = hir_id
|
||||||
}
|
}
|
||||||
expr = &self.thir[value];
|
expr = &self.thir[value];
|
||||||
}
|
}
|
||||||
debug!(?expr, ?local_lint_level, "after scopes");
|
if let ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } = expr.kind {
|
||||||
match expr.kind {
|
expr = &self.thir[rhs];
|
||||||
|
// Let chains recurse on the left, so we recurse into the lhs.
|
||||||
|
next_expr = Some(&self.thir[lhs]);
|
||||||
|
} else {
|
||||||
|
next_expr = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lint level enclosing `expr`.
|
||||||
|
let mut expr_lint_level = next_expr_lint_level;
|
||||||
|
// Fast-forward through scopes.
|
||||||
|
while let ExprKind::Scope { value, lint_level, .. } = expr.kind {
|
||||||
|
if let LintLevel::Explicit(hir_id) = lint_level {
|
||||||
|
expr_lint_level = hir_id
|
||||||
|
}
|
||||||
|
expr = &self.thir[value];
|
||||||
|
}
|
||||||
|
let value = match expr.kind {
|
||||||
ExprKind::Let { box ref pat, expr: _ } => {
|
ExprKind::Let { box ref pat, expr: _ } => {
|
||||||
if let Err(err) = pat.pat_error_reported() {
|
if let Err(err) = pat.pat_error_reported() {
|
||||||
error = Err(err);
|
error = Err(err);
|
||||||
return None;
|
None
|
||||||
|
} else {
|
||||||
|
let mut ncx = self.new_cx(expr_lint_level, true);
|
||||||
|
let tpat = self.lower_pattern(&mut ncx, pat);
|
||||||
|
let refutable = !is_let_irrefutable(&mut ncx, expr_lint_level, tpat);
|
||||||
|
Some((expr.span, refutable))
|
||||||
}
|
}
|
||||||
let mut ncx = self.new_cx(local_lint_level, true);
|
|
||||||
let tpat = self.lower_pattern(&mut ncx, pat);
|
|
||||||
let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat);
|
|
||||||
Some((expr.span, refutable))
|
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
};
|
||||||
};
|
chain_refutabilities.push(value);
|
||||||
|
|
||||||
// Let chains recurse on the left, so we start by adding the rightmost.
|
|
||||||
chain_refutabilities.push(add(rhs, cur_lint_level));
|
|
||||||
|
|
||||||
loop {
|
|
||||||
while let ExprKind::Scope { value, lint_level, .. } = self.thir[lhs].kind {
|
|
||||||
if let LintLevel::Explicit(hir_id) = lint_level {
|
|
||||||
cur_lint_level = hir_id
|
|
||||||
}
|
|
||||||
lhs = value;
|
|
||||||
}
|
|
||||||
if let ExprKind::LogicalOp { op: LogicalOp::And, lhs: new_lhs, rhs: expr } =
|
|
||||||
self.thir[lhs].kind
|
|
||||||
{
|
|
||||||
chain_refutabilities.push(add(expr, cur_lint_level));
|
|
||||||
lhs = new_lhs;
|
|
||||||
} else {
|
|
||||||
chain_refutabilities.push(add(lhs, cur_lint_level));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
debug!(?chain_refutabilities);
|
debug!(?chain_refutabilities);
|
||||||
chain_refutabilities.reverse();
|
chain_refutabilities.reverse();
|
||||||
|
Loading…
Reference in New Issue
Block a user