Skip to content

Commit 5b7c07d

Browse files
committed
Point at whole let guard on irrefutable let pattern
1 parent cc85d1f commit 5b7c07d

File tree

16 files changed

+42
-32
lines changed

16 files changed

+42
-32
lines changed

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
532532
let pat = self.lower_pat(&arm.pat);
533533
let guard = arm.guard.as_ref().map(|cond| {
534534
if let ExprKind::Let(ref pat, ref scrutinee) = cond.kind {
535-
hir::Guard::IfLet(self.lower_pat(pat), self.lower_expr(scrutinee))
535+
hir::Guard::IfLet(self.lower_pat(pat), self.lower_expr(scrutinee), cond.span)
536536
} else {
537537
hir::Guard::If(self.lower_expr(cond))
538538
}

compiler/rustc_hir/src/hir.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,7 +1210,7 @@ pub struct Arm<'hir> {
12101210
#[derive(Debug, HashStable_Generic)]
12111211
pub enum Guard<'hir> {
12121212
If(&'hir Expr<'hir>),
1213-
IfLet(&'hir Pat<'hir>, &'hir Expr<'hir>),
1213+
IfLet(&'hir Pat<'hir>, &'hir Expr<'hir>, Span),
12141214
}
12151215

12161216
#[derive(Debug, HashStable_Generic)]
@@ -1881,7 +1881,7 @@ pub enum MatchSource {
18811881
/// An `if let _ = _ { .. }` (optionally with `else { .. }`).
18821882
IfLetDesugar { contains_else_clause: bool, let_span: Span },
18831883
/// An `if let _ = _ => { .. }` match guard.
1884-
IfLetGuardDesugar,
1884+
IfLetGuardDesugar { let_span: Span },
18851885
/// A `while _ { .. }` (which was desugared to a `loop { match _ { .. } }`).
18861886
WhileDesugar,
18871887
/// A `while let _ = _ { .. }` (which was desugared to a
@@ -1900,7 +1900,7 @@ impl MatchSource {
19001900
use MatchSource::*;
19011901
match self {
19021902
Normal => "match",
1903-
IfLetDesugar { .. } | IfLetGuardDesugar => "if",
1903+
IfLetDesugar { .. } | IfLetGuardDesugar { .. } => "if",
19041904
WhileDesugar | WhileLetDesugar { .. } => "while",
19051905
ForLoopDesugar => "for",
19061906
TryDesugar => "?",

compiler/rustc_hir/src/intravisit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1239,7 +1239,7 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
12391239
if let Some(ref g) = arm.guard {
12401240
match g {
12411241
Guard::If(ref e) => visitor.visit_expr(e),
1242-
Guard::IfLet(ref pat, ref e) => {
1242+
Guard::IfLet(ref pat, ref e, _) => {
12431243
visitor.visit_pat(pat);
12441244
visitor.visit_expr(e);
12451245
}

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2043,7 +2043,7 @@ impl<'a> State<'a> {
20432043
self.print_expr(&e);
20442044
self.s.space();
20452045
}
2046-
hir::Guard::IfLet(pat, e) => {
2046+
hir::Guard::IfLet(pat, e, _) => {
20472047
self.word_nbsp("if");
20482048
self.word_nbsp("let");
20492049
self.print_pat(&pat);

compiler/rustc_mir_build/src/thir/cx/expr.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,9 @@ fn convert_arm<'tcx>(cx: &mut Cx<'_, 'tcx>, arm: &'tcx hir::Arm<'tcx>) -> Arm<'t
781781
pattern: cx.pattern_from_hir(&arm.pat),
782782
guard: arm.guard.as_ref().map(|g| match g {
783783
hir::Guard::If(ref e) => Guard::If(e.to_ref()),
784-
hir::Guard::IfLet(ref pat, ref e) => Guard::IfLet(cx.pattern_from_hir(pat), e.to_ref()),
784+
hir::Guard::IfLet(ref pat, ref e, _) => {
785+
Guard::IfLet(cx.pattern_from_hir(pat), e.to_ref())
786+
}
785787
}),
786788
body: arm.body.to_ref(),
787789
lint_level: LintLevel::Explicit(arm.hir_id),

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,17 +164,17 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
164164
for arm in arms {
165165
// Check the arm for some things unrelated to exhaustiveness.
166166
self.check_patterns(&arm.pat);
167-
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
167+
if let Some(hir::Guard::IfLet(ref pat, _, _)) = arm.guard {
168168
self.check_patterns(pat);
169169
}
170170
}
171171

172172
let mut cx = self.new_cx(scrut.hir_id);
173173

174174
for arm in arms {
175-
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
175+
if let Some(hir::Guard::IfLet(ref pat, _, span)) = arm.guard {
176176
let tpat = self.lower_pattern(&mut cx, pat, &mut false).0;
177-
check_if_let_guard(&mut cx, &tpat, pat.hir_id);
177+
check_if_let_guard(&mut cx, &tpat, pat.hir_id, span);
178178
}
179179
}
180180

@@ -379,7 +379,7 @@ fn irrefutable_let_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, source: hir::
379379
diag.help("consider instead using a `loop { ... }` with a `let` inside it");
380380
diag.emit()
381381
}
382-
hir::MatchSource::IfLetGuardDesugar => {
382+
hir::MatchSource::IfLetGuardDesugar { .. }=> {
383383
let mut diag = lint.build("irrefutable `if let` guard pattern");
384384
diag.note("this pattern will always match, so the guard is useless");
385385
diag.help("consider removing the guard and adding a `let` inside the match arm");
@@ -398,14 +398,20 @@ fn check_if_let_guard<'p, 'tcx>(
398398
cx: &mut MatchCheckCtxt<'p, 'tcx>,
399399
pat: &'p super::Pat<'tcx>,
400400
pat_id: HirId,
401+
let_span: Span,
401402
) {
402403
let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }];
403404
let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty);
404-
report_arm_reachability(&cx, &report, hir::MatchSource::IfLetGuardDesugar);
405+
report_arm_reachability(&cx, &report, hir::MatchSource::IfLetGuardDesugar { let_span });
405406

406407
if report.non_exhaustiveness_witnesses.is_empty() {
407-
// The match is exhaustive, i.e. the `if let` pattern is irrefutable.
408-
irrefutable_let_pattern(cx.tcx, pat.span, pat_id, hir::MatchSource::IfLetGuardDesugar)
408+
// The match is exhaustive, i.e. the if let pattern is irrefutable.
409+
irrefutable_let_pattern(
410+
cx.tcx,
411+
let_span,
412+
pat_id,
413+
hir::MatchSource::IfLetGuardDesugar { let_span },
414+
)
409415
}
410416
}
411417

@@ -435,9 +441,9 @@ fn report_arm_reachability<'p, 'tcx>(
435441
}
436442
}
437443

438-
hir::MatchSource::IfLetGuardDesugar => {
444+
hir::MatchSource::IfLetGuardDesugar { let_span } => {
439445
assert_eq!(arm_index, 0);
440-
unreachable_pattern(cx.tcx, arm.pat.span, arm.hir_id, None);
446+
unreachable_pattern(cx.tcx, let_span, arm.hir_id, None);
441447
}
442448

443449
hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {

compiler/rustc_passes/src/check_const.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ impl NonConstExpr {
4545
return None;
4646
}
4747

48-
Self::Match(IfLetGuardDesugar) => bug!("`if let` guard outside a `match` expression"),
48+
Self::Match(IfLetGuardDesugar { .. }) => {
49+
bug!("if-let guard outside a `match` expression")
50+
}
4951

5052
// All other expressions are allowed.
5153
Self::Loop(Loop | While | WhileLet)

compiler/rustc_passes/src/liveness.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
360360

361361
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
362362
self.add_from_pat(&arm.pat);
363-
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
363+
if let Some(hir::Guard::IfLet(ref pat, _, _)) = arm.guard {
364364
self.add_from_pat(pat);
365365
}
366366
intravisit::walk_arm(self, arm);
@@ -891,7 +891,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
891891

892892
let guard_succ = arm.guard.as_ref().map_or(body_succ, |g| match g {
893893
hir::Guard::If(e) => self.propagate_through_expr(e, body_succ),
894-
hir::Guard::IfLet(pat, e) => {
894+
hir::Guard::IfLet(pat, e, _) => {
895895
let let_bind = self.define_bindings_in_pat(pat, body_succ);
896896
self.propagate_through_expr(e, let_bind)
897897
}

compiler/rustc_typeck/src/check/_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
134134
hir::Guard::If(e) => {
135135
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
136136
}
137-
hir::Guard::IfLet(pat, e) => {
137+
hir::Guard::IfLet(pat, e, _) => {
138138
let scrutinee_ty = self.demand_scrutinee_type(
139139
e,
140140
pat.contains_explicit_ref_binding(),

compiler/rustc_typeck/src/check/generator_interior.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
248248
Guard::If(ref e) => {
249249
self.visit_expr(e);
250250
}
251-
Guard::IfLet(ref pat, ref e) => {
251+
Guard::IfLet(ref pat, ref e, _) => {
252252
self.visit_pat(pat);
253253
self.visit_expr(e);
254254
}

src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ LL | while let _ = 5 {
2222
= help: consider instead using a `loop { ... }` with a `let` inside it
2323

2424
error: irrefutable `if let` guard pattern
25-
--> $DIR/deny-irrefutable-let-patterns.rs:14:18
25+
--> $DIR/deny-irrefutable-let-patterns.rs:14:14
2626
|
2727
LL | _ if let _ = 2 => {}
28-
| ^
28+
| ^^^^^^^^^
2929
|
3030
= note: this pattern will always match, so the guard is useless
3131
= help: consider removing the guard and adding a `let` inside the match arm

src/test/ui/rfc-2294-if-let-guard/warns.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: irrefutable `if let` guard pattern
2-
--> $DIR/warns.rs:7:24
2+
--> $DIR/warns.rs:7:20
33
|
44
LL | Some(x) if let () = x => {}
5-
| ^^
5+
| ^^^^^^^^^^
66
|
77
note: the lint level is defined here
88
--> $DIR/warns.rs:4:8

src/tools/clippy/clippy_lints/src/shadow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
349349
if let Some(ref guard) = arm.guard {
350350
match guard {
351351
Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
352-
Guard::IfLet(guard_pat, guard_expr) => {
352+
Guard::IfLet(guard_pat, guard_expr, _) => {
353353
check_pat(cx, guard_pat, Some(*guard_expr), guard_pat.span, bindings);
354354
check_expr(cx, guard_expr, bindings);
355355
},

src/tools/clippy/clippy_lints/src/utils/author.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,11 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
365365
self.current = if_expr_pat;
366366
self.visit_expr(if_expr);
367367
},
368-
hir::Guard::IfLet(ref if_let_pat, ref if_let_expr) => {
368+
hir::Guard::IfLet(ref if_let_pat, ref if_let_expr, _) => {
369369
let if_let_pat_pat = self.next("pat");
370370
let if_let_expr_pat = self.next("expr");
371371
println!(
372-
" if let Guard::IfLet(ref {}, ref {}) = {};",
372+
" if let Guard::IfLet(ref {}, ref {}, _) = {};",
373373
if_let_pat_pat, if_let_expr_pat, guard_pat
374374
);
375375
self.current = if_let_expr_pat;
@@ -735,7 +735,7 @@ fn desugaring_name(des: hir::MatchSource) -> String {
735735
"MatchSource::IfLetDesugar {{ contains_else_clause: {} }}",
736736
contains_else_clause
737737
),
738-
hir::MatchSource::IfLetGuardDesugar => "MatchSource::IfLetGuardDesugar".to_string(),
738+
hir::MatchSource::IfLetGuardDesugar { .. }=> "MatchSource::IfLetGuardDesugar".to_string(),
739739
hir::MatchSource::AwaitDesugar => "MatchSource::AwaitDesugar".to_string(),
740740
}
741741
}

src/tools/clippy/clippy_lints/src/utils/inspector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ fn print_guard(cx: &LateContext<'_>, guard: &hir::Guard<'_>, indent: usize) {
568568
println!("{}If", ind);
569569
print_expr(cx, expr, indent + 1);
570570
},
571-
hir::Guard::IfLet(pat, expr) => {
571+
hir::Guard::IfLet(pat, expr, _) => {
572572
println!("{}IfLet", ind);
573573
print_pat(cx, pat, indent + 1);
574574
print_expr(cx, expr, indent + 1);

src/tools/clippy/clippy_utils/src/hir_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ impl HirEqInterExpr<'_, '_, '_> {
223223
fn eq_guard(&mut self, left: &Guard<'_>, right: &Guard<'_>) -> bool {
224224
match (left, right) {
225225
(Guard::If(l), Guard::If(r)) => self.eq_expr(l, r),
226-
(Guard::IfLet(lp, le), Guard::IfLet(rp, re)) => self.eq_pat(lp, rp) && self.eq_expr(le, re),
226+
(Guard::IfLet(lp, le, _), Guard::IfLet(rp, re, _)) => self.eq_pat(lp, rp) && self.eq_expr(le, re),
227227
_ => false,
228228
}
229229
}
@@ -736,7 +736,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
736736

737737
pub fn hash_guard(&mut self, g: &Guard<'_>) {
738738
match g {
739-
Guard::If(ref expr) | Guard::IfLet(_, ref expr) => {
739+
Guard::If(ref expr) | Guard::IfLet(_, ref expr, _) => {
740740
self.hash_expr(expr);
741741
},
742742
}

0 commit comments

Comments
 (0)