From 87e544bca5ae1bd187f11239abcab1f73c836049 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 23 Feb 2017 22:46:19 +0200 Subject: [PATCH] use a more conservative inhabitableness rule This is a [breaking-change] from 1.15, because this used to compile: ```Rust enum Void {} fn foo(x: &Void) { match x {} } ``` --- src/librustc_const_eval/check_match.rs | 16 +++++++++++++++- .../uninhabited-matches-feature-gated.rs | 6 +++--- src/test/run-pass/issue-38972.rs | 6 +----- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index e5362a70e53..9b30946c0be 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -182,7 +182,12 @@ fn check_match( let pat_ty = self.tables.node_id_to_type(scrut.id); let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id)); if inlined_arms.is_empty() { - if !pat_ty.is_uninhabited_from(module, self.tcx) { + let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type { + pat_ty.is_uninhabited_from(module, self.tcx) + } else { + self.conservative_is_uninhabited(pat_ty) + }; + if !scrutinee_is_uninhabited { // We know the type is inhabited, so this must be wrong let mut err = create_e0004(self.tcx.sess, scrut.span, format!("non-exhaustive patterns: type {} \ @@ -208,6 +213,15 @@ fn check_match( }) } + fn conservative_is_uninhabited(&self, scrutinee_ty: Ty<'tcx>) -> bool { + // "rustc-1.0-style" uncontentious uninhabitableness check + match scrutinee_ty.sty { + ty::TyNever => true, + ty::TyAdt(def, _) => def.variants.is_empty(), + _ => false + } + } + fn check_irrefutable(&self, pat: &Pat, is_fn_arg: bool) { let origin = if is_fn_arg { "function argument" diff --git a/src/test/compile-fail/uninhabited-matches-feature-gated.rs b/src/test/compile-fail/uninhabited-matches-feature-gated.rs index 68781a407cc..0c3ea53a903 100644 --- a/src/test/compile-fail/uninhabited-matches-feature-gated.rs +++ b/src/test/compile-fail/uninhabited-matches-feature-gated.rs @@ -19,13 +19,13 @@ fn main() { }; let x: &Void = unsafe { std::mem::uninitialized() }; - let _ = match x {}; // okay + let _ = match x {}; //~ ERROR non-exhaustive let x: (Void,) = unsafe { std::mem::uninitialized() }; - let _ = match x {}; // okay + let _ = match x {}; //~ ERROR non-exhaustive let x: [Void; 1] = unsafe { std::mem::uninitialized() }; - let _ = match x {}; // okay + let _ = match x {}; //~ ERROR non-exhaustive let x: &[Void] = unsafe { std::mem::uninitialized() }; let _ = match x { //~ ERROR non-exhaustive diff --git a/src/test/run-pass/issue-38972.rs b/src/test/run-pass/issue-38972.rs index 9c440503214..d5df84e0fb0 100644 --- a/src/test/run-pass/issue-38972.rs +++ b/src/test/run-pass/issue-38972.rs @@ -16,14 +16,10 @@ enum Foo { } fn make_foo() -> Option { None } -fn use_foo(v: &Foo) -> ! { - match v { } -} - #[deny(warnings)] fn main() { match make_foo() { None => {}, - Some(ref v) => use_foo(v), + Some(_) => {} } } -- 2.44.0