Handle irrufutable or unreachable let-else

This commit is contained in:
Cameron Steffen 2021-07-30 17:14:34 -05:00
parent dc028f6568
commit df9a2e0687
3 changed files with 41 additions and 13 deletions

View File

@ -17,7 +17,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
use rustc_session::Session;
use rustc_span::Span;
use rustc_span::{DesugaringKind, ExpnKind, Span};
use std::slice;
crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
@ -381,6 +381,10 @@ fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
}
let source = let_source(tcx, id);
let span = match source {
LetSource::LetElse(span) => span,
_ => span,
};
tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| match source {
LetSource::GenericLet => {
emit_diag!(lint, "`let`", "`let` is useless", "removing `let`");
@ -401,6 +405,14 @@ fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
"removing the guard and adding a `let` inside the match arm"
);
}
LetSource::LetElse(..) => {
emit_diag!(
lint,
"`let...else`",
"`else` clause is useless",
"removing the `else` clause"
);
}
LetSource::WhileLet => {
emit_diag!(
lint,
@ -755,6 +767,7 @@ pub enum LetSource {
GenericLet,
IfLet,
IfLetGuard,
LetElse(Span),
WhileLet,
}
@ -768,6 +781,12 @@ fn let_source(tcx: TyCtxt<'_>, pat_id: HirId) -> LetSource {
}) if hir_id == pat_id => {
return LetSource::IfLetGuard;
}
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Let(..), span, .. }) => {
let expn_data = span.ctxt().outer_expn_data();
if let ExpnKind::Desugaring(DesugaringKind::LetElse) = expn_data.kind {
return LetSource::LetElse(expn_data.call_site);
}
}
_ => {}
}
let parent_parent = hir.get_parent_node(parent);

View File

@ -1,3 +1,5 @@
#![feature(let_else)]
#![deny(unreachable_patterns)]
fn main() {
@ -53,4 +55,5 @@ fn main() {
1..=2 => {}, //~ ERROR unreachable pattern
_ => {},
}
let (0 | 0) = 0 else { return }; //~ ERROR unreachable pattern
}

View File

@ -1,68 +1,74 @@
error: unreachable pattern
--> $DIR/top-level-alternation.rs:4:23
--> $DIR/top-level-alternation.rs:6:23
|
LL | while let 0..=2 | 1 = 0 {}
| ^
|
note: the lint level is defined here
--> $DIR/top-level-alternation.rs:1:9
--> $DIR/top-level-alternation.rs:3:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
--> $DIR/top-level-alternation.rs:5:20
--> $DIR/top-level-alternation.rs:7:20
|
LL | if let 0..=2 | 1 = 0 {}
| ^
error: unreachable pattern
--> $DIR/top-level-alternation.rs:9:15
--> $DIR/top-level-alternation.rs:11:15
|
LL | | 0 => {}
| ^
error: unreachable pattern
--> $DIR/top-level-alternation.rs:14:15
--> $DIR/top-level-alternation.rs:16:15
|
LL | | Some(0) => {}
| ^^^^^^^
error: unreachable pattern
--> $DIR/top-level-alternation.rs:19:9
--> $DIR/top-level-alternation.rs:21:9
|
LL | (0, 0) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/top-level-alternation.rs:39:9
--> $DIR/top-level-alternation.rs:41:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/top-level-alternation.rs:43:9
--> $DIR/top-level-alternation.rs:45:9
|
LL | Some(_) => {}
| ^^^^^^^
error: unreachable pattern
--> $DIR/top-level-alternation.rs:44:9
--> $DIR/top-level-alternation.rs:46:9
|
LL | None => {}
| ^^^^
error: unreachable pattern
--> $DIR/top-level-alternation.rs:49:9
--> $DIR/top-level-alternation.rs:51:9
|
LL | None | Some(_) => {}
| ^^^^^^^^^^^^^^
error: unreachable pattern
--> $DIR/top-level-alternation.rs:53:9
--> $DIR/top-level-alternation.rs:55:9
|
LL | 1..=2 => {},
| ^^^^^
error: aborting due to 10 previous errors
error: unreachable pattern
--> $DIR/top-level-alternation.rs:58:14
|
LL | let (0 | 0) = 0 else { return };
| ^
error: aborting due to 11 previous errors