Calculate LetSource later
This commit is contained in:
parent
29bc94ff0d
commit
dc028f6568
1 changed files with 42 additions and 40 deletions
|
@ -118,31 +118,6 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
|
||||||
check_for_bindings_named_same_as_variants(self, pat);
|
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>(
|
fn lower_pattern<'p>(
|
||||||
&self,
|
&self,
|
||||||
cx: &mut MatchCheckCtxt<'p, 'tcx>,
|
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) {
|
fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, expr: &hir::Expr<'_>, span: Span) {
|
||||||
self.check_patterns(pat);
|
self.check_patterns(pat);
|
||||||
let ls = self.let_source(pat, expr);
|
|
||||||
let mut cx = self.new_cx(expr.hir_id);
|
let mut cx = self.new_cx(expr.hir_id);
|
||||||
let tpat = self.lower_pattern(&mut cx, pat, &mut false).0;
|
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(
|
fn check_match(
|
||||||
|
@ -192,13 +166,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
|
||||||
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
|
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
|
||||||
self.check_patterns(pat);
|
self.check_patterns(pat);
|
||||||
let tpat = self.lower_pattern(&mut cx, pat, &mut false).0;
|
let tpat = self.lower_pattern(&mut cx, pat, &mut false).0;
|
||||||
check_let_reachability(
|
check_let_reachability(&mut cx, pat.hir_id, &tpat, tpat.span);
|
||||||
&mut cx,
|
|
||||||
LetSource::IfLetGuard,
|
|
||||||
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 {
|
macro_rules! emit_diag {
|
||||||
(
|
(
|
||||||
$lint:expr,
|
$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 => {
|
LetSource::GenericLet => {
|
||||||
emit_diag!(lint, "`let`", "`let` is useless", "removing `let`");
|
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>(
|
fn check_let_reachability<'p, 'tcx>(
|
||||||
cx: &mut MatchCheckCtxt<'p, 'tcx>,
|
cx: &mut MatchCheckCtxt<'p, 'tcx>,
|
||||||
ls: LetSource,
|
|
||||||
pat_id: HirId,
|
pat_id: HirId,
|
||||||
pat: &'p super::Pat<'tcx>,
|
pat: &'p super::Pat<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
@ -454,13 +422,13 @@ fn check_let_reachability<'p, 'tcx>(
|
||||||
let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty);
|
let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty);
|
||||||
|
|
||||||
report_arm_reachability(&cx, &report, |arm_index, arm_span, arm_hir_id, _| {
|
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 => {
|
LetSource::IfLet | LetSource::WhileLet => {
|
||||||
match arm_index {
|
match arm_index {
|
||||||
// The arm with the user-specified pattern.
|
// The arm with the user-specified pattern.
|
||||||
0 => unreachable_pattern(cx.tcx, arm_span, arm_hir_id, None),
|
0 => unreachable_pattern(cx.tcx, arm_span, arm_hir_id, None),
|
||||||
// The arm with the wildcard pattern.
|
// 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!(),
|
_ => bug!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,7 +441,7 @@ fn check_let_reachability<'p, 'tcx>(
|
||||||
|
|
||||||
if report.non_exhaustiveness_witnesses.is_empty() {
|
if report.non_exhaustiveness_witnesses.is_empty() {
|
||||||
// The match is exhaustive, i.e. the `if let` pattern is irrefutable.
|
// 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,
|
IfLetGuard,
|
||||||
WhileLet,
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue