Skip to content

Commit

Permalink
Add explanations and suggestions to irrefutable_let_patterns lint
Browse files Browse the repository at this point in the history
  • Loading branch information
camelid committed Feb 19, 2021
1 parent 0148b97 commit 5d2a2a1
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 19 deletions.
8 changes: 3 additions & 5 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1814,14 +1814,12 @@ declare_lint! {
}

declare_lint! {
/// The `irrefutable_let_patterns` lint detects detects [irrefutable
/// patterns] in [`if let`] and [`while let`] statements.
///
///
/// The `irrefutable_let_patterns` lint detects [irrefutable patterns]
/// in [`if let`]s, [`while let`]s, and `if let` guards.
///
/// ### Example
///
/// ```rust
/// ```
/// if let _ = 123 {
/// println!("always runs!");
/// }
Expand Down
35 changes: 26 additions & 9 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,14 +366,31 @@ fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<
}

fn irrefutable_let_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, source: hir::MatchSource) {
tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| {
let msg = match source {
hir::MatchSource::IfLetDesugar { .. } => "irrefutable `if let` pattern",
hir::MatchSource::WhileLetDesugar => "irrefutable `while let` pattern",
hir::MatchSource::IfLetGuardDesugar => "irrefutable `if let` guard",
_ => bug!(),
};
lint.build(msg).emit()
tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| match source {
hir::MatchSource::IfLetDesugar { .. } => {
let mut diag = lint.build("irrefutable `if let` pattern");
diag.note("this pattern will always match, so the `if let` is useless");
diag.help("consider replacing the `if let` with a `let`");
diag.emit()
}
hir::MatchSource::WhileLetDesugar => {
let mut diag = lint.build("irrefutable `while let` pattern");
diag.note("this pattern will always match, so the loop will never exit");
diag.help("consider instead using a `loop { ... }` with a `let` inside it");
diag.emit()
}
hir::MatchSource::IfLetGuardDesugar => {
let mut diag = lint.build("irrefutable `if let` guard pattern");
diag.note("this pattern will always match, so the guard is useless");
diag.help("consider removing the guard and adding a `let` inside the match arm");
diag.emit()
}
_ => {
bug!(
"expected `if let`, `while let`, or `if let` guard HIR match source, found {:?}",
source,
)
}
});
}

Expand All @@ -387,7 +404,7 @@ fn check_if_let_guard<'p, 'tcx>(
report_arm_reachability(&cx, &report, hir::MatchSource::IfLetGuardDesugar);

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(cx.tcx, pat.span, pat_id, hir::MatchSource::IfLetGuardDesugar)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ LL | | }
| |_________^
|
= note: `#[warn(irrefutable_let_patterns)]` on by default
= note: this pattern will always match, so the `if let` is useless
= help: consider replacing the `if let` with a `let`

error[E0382]: use of moved value: `c`
--> $DIR/closure-origin-single-variant-diagnostics.rs:25:13
Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/expr/if/if-let.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ LL | | });
| |_______- in this macro invocation
|
= note: `#[warn(irrefutable_let_patterns)]` on by default
= note: this pattern will always match, so the `if let` is useless
= help: consider replacing the `if let` with a `let`
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

warning: irrefutable `if let` pattern
Expand All @@ -23,6 +25,8 @@ LL | | println!("irrefutable pattern");
LL | | });
| |_______- in this macro invocation
|
= note: this pattern will always match, so the `if let` is useless
= help: consider replacing the `if let` with a `let`
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

warning: irrefutable `if let` pattern
Expand All @@ -32,6 +36,9 @@ LL | / if let a = 1 {
LL | | println!("irrefutable pattern");
LL | | }
| |_____^
|
= note: this pattern will always match, so the `if let` is useless
= help: consider replacing the `if let` with a `let`

warning: irrefutable `if let` pattern
--> $DIR/if-let.rs:30:5
Expand All @@ -44,6 +51,9 @@ LL | | } else {
LL | | println!("else in irrefutable `if let`");
LL | | }
| |_____^
|
= note: this pattern will always match, so the `if let` is useless
= help: consider replacing the `if let` with a `let`

warning: irrefutable `if let` pattern
--> $DIR/if-let.rs:40:12
Expand All @@ -53,6 +63,9 @@ LL | } else if let a = 1 {
LL | | println!("irrefutable pattern");
LL | | }
| |_____^
|
= note: this pattern will always match, so the `if let` is useless
= help: consider replacing the `if let` with a `let`

warning: irrefutable `if let` pattern
--> $DIR/if-let.rs:46:12
Expand All @@ -62,6 +75,9 @@ LL | } else if let a = 1 {
LL | | println!("irrefutable pattern");
LL | | }
| |_____^
|
= note: this pattern will always match, so the `if let` is useless
= help: consider replacing the `if let` with a `let`

warning: 6 warnings emitted

Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#![feature(if_let_guard)]
#![allow(incomplete_features)]

#![deny(irrefutable_let_patterns)]

fn main() {
Expand All @@ -6,4 +9,9 @@ fn main() {
while let _ = 5 { //~ ERROR irrefutable `while let` pattern
break;
}

match 5 {
_ if let _ = 2 => {} //~ ERROR irrefutable `if let` guard pattern
_ => {}
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
error: irrefutable `if let` pattern
--> $DIR/deny-irrefutable-let-patterns.rs:4:5
--> $DIR/deny-irrefutable-let-patterns.rs:7:5
|
LL | if let _ = 5 {}
| ^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/deny-irrefutable-let-patterns.rs:1:9
--> $DIR/deny-irrefutable-let-patterns.rs:4:9
|
LL | #![deny(irrefutable_let_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this pattern will always match, so the `if let` is useless
= help: consider replacing the `if let` with a `let`

error: irrefutable `while let` pattern
--> $DIR/deny-irrefutable-let-patterns.rs:6:5
--> $DIR/deny-irrefutable-let-patterns.rs:9:5
|
LL | / while let _ = 5 {
LL | | break;
LL | | }
| |_____^
|
= note: this pattern will always match, so the loop will never exit
= help: consider instead using a `loop { ... }` with a `let` inside it

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

error: aborting due to 2 previous errors
error: aborting due to 3 previous errors

4 changes: 3 additions & 1 deletion src/test/ui/rfc-2294-if-let-guard/warns.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: irrefutable `if let` guard
error: irrefutable `if let` guard pattern
--> $DIR/warns.rs:7:24
|
LL | Some(x) if let () = x => {}
Expand All @@ -9,6 +9,8 @@ note: the lint level is defined here
|
LL | #[deny(irrefutable_let_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this pattern will always match, so the guard is useless
= help: consider removing the guard and adding a `let` inside the match arm

error: unreachable pattern
--> $DIR/warns.rs:16:25
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/while-let.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ LL | | });
| |_______- in this macro invocation
|
= note: `#[warn(irrefutable_let_patterns)]` on by default
= note: this pattern will always match, so the loop will never exit
= help: consider instead using a `loop { ... }` with a `let` inside it
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

warning: irrefutable `while let` pattern
Expand All @@ -23,6 +25,8 @@ LL | | println!("irrefutable pattern");
LL | | });
| |_______- in this macro invocation
|
= note: this pattern will always match, so the loop will never exit
= help: consider instead using a `loop { ... }` with a `let` inside it
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

warning: irrefutable `while let` pattern
Expand All @@ -33,6 +37,9 @@ LL | | println!("irrefutable pattern");
LL | | break;
LL | | }
| |_____^
|
= note: this pattern will always match, so the loop will never exit
= help: consider instead using a `loop { ... }` with a `let` inside it

warning: 3 warnings emitted

0 comments on commit 5d2a2a1

Please sign in to comment.