From 083eedc3691b4d6ea7a83b61a86815d7294caa75 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 18 Jan 2024 18:22:08 +0100 Subject: [PATCH] Never pattern in `let` statement diverges --- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 6 ++++++ .../diverge-causes-unreachable-code.rs | 15 ++++++++------- .../diverge-causes-unreachable-code.stderr | 15 +++++++++++++-- tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs | 12 ++++++------ 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 4704d52abfc2f..52c5e2752b941 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1473,6 +1473,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Type check a `let` statement. pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) { self.check_decl(local.into()); + if local.pat.is_never_pattern() { + self.diverges.set(Diverges::Always { + span: local.pat.span, + custom_note: Some("any code following a never pattern is unreachable"), + }); + } } pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) { diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.rs b/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.rs index 5c852c8adcccf..f7e4007b920d9 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.rs @@ -17,13 +17,14 @@ fn ref_never_arg(&!: &Void) -> u32 { //~^ ERROR unreachable statement } -//fn never_let() -> u32 { -// let ptr: *const Void = std::ptr::null(); -// unsafe { -// let ! = *ptr; -// } -// println!(); -//} +fn never_let() -> u32 { + let ptr: *const Void = std::ptr::null(); + unsafe { + let ! = *ptr; + } + println!(); + //~^ ERROR unreachable statement +} fn never_match() -> u32 { let ptr: *const Void = std::ptr::null(); diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.stderr index c9cd3f53944e4..c33a5855d5068 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.stderr @@ -24,7 +24,18 @@ LL | println!(); = note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error: unreachable statement - --> $DIR/diverge-causes-unreachable-code.rs:33:5 + --> $DIR/diverge-causes-unreachable-code.rs:25:5 + | +LL | let ! = *ptr; + | - any code following a never pattern is unreachable +LL | } +LL | println!(); + | ^^^^^^^^^^ unreachable statement + | + = note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unreachable statement + --> $DIR/diverge-causes-unreachable-code.rs:34:5 | LL | match *ptr { ! }; | ---------------- any code following this `match` expression is unreachable, as all arms diverge @@ -34,5 +45,5 @@ LL | println!(); | = note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs b/tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs index 40aa2bd29e594..6f4b81b9b25b0 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs @@ -13,12 +13,12 @@ fn never_arg(!: Void) -> u32 {} fn ref_never_arg(&!: &Void) -> u32 {} -// fn never_let() -> u32 { -// let ptr: *const Void = std::ptr::null(); -// unsafe { -// let ! = *ptr; -// } -// } +fn never_let() -> u32 { + let ptr: *const Void = std::ptr::null(); + unsafe { + let ! = *ptr; + } +} fn never_match() -> u32 { let ptr: *const Void = std::ptr::null();