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 50cbe0f71f5..90c451517c0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -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 + } +}