Calculate LetSource later

This commit is contained in:
Cameron Steffen 2021-08-27 12:53:50 -05:00
parent 29bc94ff0d
commit dc028f6568

View file

@ -118,31 +118,6 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
check_for_bindings_named_same_as_variants(self, pat);
}
fn let_source(&mut self, pat: &'tcx hir::Pat<'tcx>, _expr: &hir::Expr<'_>) -> LetSource {
let hir = self.tcx.hir();
let parent = hir.get_parent_node(pat.hir_id);
let parent_parent = hir.get_parent_node(parent);
let parent_parent_node = hir.get(parent_parent);
let parent_parent_parent = hir.get_parent_node(parent_parent);
let parent_parent_parent_parent = hir.get_parent_node(parent_parent_parent);
let parent_parent_parent_parent_node = hir.get(parent_parent_parent_parent);
if let hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _),
..
}) = parent_parent_parent_parent_node
{
LetSource::WhileLet
} else if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::If { .. }, .. }) =
parent_parent_node
{
LetSource::IfLet
} else {
LetSource::GenericLet
}
}
fn lower_pattern<'p>(
&self,
cx: &mut MatchCheckCtxt<'p, 'tcx>,
@ -172,10 +147,9 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, expr: &hir::Expr<'_>, span: Span) {
self.check_patterns(pat);
let ls = self.let_source(pat, expr);
let mut cx = self.new_cx(expr.hir_id);
let tpat = self.lower_pattern(&mut cx, pat, &mut false).0;
check_let_reachability(&mut cx, ls, pat.hir_id, &tpat, span);
check_let_reachability(&mut cx, pat.hir_id, &tpat, span);
}
fn check_match(
@ -192,13 +166,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
self.check_patterns(pat);
let tpat = self.lower_pattern(&mut cx, pat, &mut false).0;
check_let_reachability(
&mut cx,
LetSource::IfLetGuard,
pat.hir_id,
&tpat,
tpat.span,
);
check_let_reachability(&mut cx, pat.hir_id, &tpat, tpat.span);
}
}
@ -397,7 +365,7 @@ fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<
});
}
fn irrefutable_let_pattern(id: HirId, ls: LetSource, span: Span, tcx: TyCtxt<'_>) {
fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
macro_rules! emit_diag {
(
$lint:expr,
@ -412,7 +380,8 @@ fn irrefutable_let_pattern(id: HirId, ls: LetSource, span: Span, tcx: TyCtxt<'_>
}};
}
tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| match ls {
let source = let_source(tcx, id);
tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| match source {
LetSource::GenericLet => {
emit_diag!(lint, "`let`", "`let` is useless", "removing `let`");
}
@ -445,7 +414,6 @@ fn irrefutable_let_pattern(id: HirId, ls: LetSource, span: Span, tcx: TyCtxt<'_>
fn check_let_reachability<'p, 'tcx>(
cx: &mut MatchCheckCtxt<'p, 'tcx>,
ls: LetSource,
pat_id: HirId,
pat: &'p super::Pat<'tcx>,
span: Span,
@ -454,13 +422,13 @@ fn check_let_reachability<'p, 'tcx>(
let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty);
report_arm_reachability(&cx, &report, |arm_index, arm_span, arm_hir_id, _| {
match ls {
match let_source(cx.tcx, pat_id) {
LetSource::IfLet | LetSource::WhileLet => {
match arm_index {
// The arm with the user-specified pattern.
0 => unreachable_pattern(cx.tcx, arm_span, arm_hir_id, None),
// The arm with the wildcard pattern.
1 => irrefutable_let_pattern(pat_id, ls, arm_span, cx.tcx),
1 => irrefutable_let_pattern(cx.tcx, pat_id, arm_span),
_ => bug!(),
}
}
@ -473,7 +441,7 @@ fn check_let_reachability<'p, 'tcx>(
if report.non_exhaustiveness_witnesses.is_empty() {
// The match is exhaustive, i.e. the `if let` pattern is irrefutable.
irrefutable_let_pattern(pat_id, ls, span, cx.tcx);
irrefutable_let_pattern(cx.tcx, pat_id, span);
}
}
@ -789,3 +757,37 @@ pub enum LetSource {
IfLetGuard,
WhileLet,
}
fn let_source(tcx: TyCtxt<'_>, pat_id: HirId) -> LetSource {
let hir = tcx.hir();
let parent = hir.get_parent_node(pat_id);
match hir.get(parent) {
hir::Node::Arm(hir::Arm {
guard: Some(hir::Guard::IfLet(&hir::Pat { hir_id, .. }, _)),
..
}) if hir_id == pat_id => {
return LetSource::IfLetGuard;
}
_ => {}
}
let parent_parent = hir.get_parent_node(parent);
let parent_parent_node = hir.get(parent_parent);
let parent_parent_parent = hir.get_parent_node(parent_parent);
let parent_parent_parent_parent = hir.get_parent_node(parent_parent_parent);
let parent_parent_parent_parent_node = hir.get(parent_parent_parent_parent);
if let hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _),
..
}) = parent_parent_parent_parent_node
{
LetSource::WhileLet
} else if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::If { .. }, .. }) =
parent_parent_node
{
LetSource::IfLet
} else {
LetSource::GenericLet
}
}