Skip to content

Commit 87e544b

Browse files
committed
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 {} } ```
1 parent a84eb95 commit 87e544b

File tree

3 files changed

+19
-9
lines changed

3 files changed

+19
-9
lines changed

src/librustc_const_eval/check_match.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,12 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
182182
let pat_ty = self.tables.node_id_to_type(scrut.id);
183183
let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id));
184184
if inlined_arms.is_empty() {
185-
if !pat_ty.is_uninhabited_from(module, self.tcx) {
185+
let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type {
186+
pat_ty.is_uninhabited_from(module, self.tcx)
187+
} else {
188+
self.conservative_is_uninhabited(pat_ty)
189+
};
190+
if !scrutinee_is_uninhabited {
186191
// We know the type is inhabited, so this must be wrong
187192
let mut err = create_e0004(self.tcx.sess, scrut.span,
188193
format!("non-exhaustive patterns: type {} \
@@ -208,6 +213,15 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
208213
})
209214
}
210215

216+
fn conservative_is_uninhabited(&self, scrutinee_ty: Ty<'tcx>) -> bool {
217+
// "rustc-1.0-style" uncontentious uninhabitableness check
218+
match scrutinee_ty.sty {
219+
ty::TyNever => true,
220+
ty::TyAdt(def, _) => def.variants.is_empty(),
221+
_ => false
222+
}
223+
}
224+
211225
fn check_irrefutable(&self, pat: &Pat, is_fn_arg: bool) {
212226
let origin = if is_fn_arg {
213227
"function argument"

src/test/compile-fail/uninhabited-matches-feature-gated.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ fn main() {
1919
};
2020

2121
let x: &Void = unsafe { std::mem::uninitialized() };
22-
let _ = match x {}; // okay
22+
let _ = match x {}; //~ ERROR non-exhaustive
2323

2424
let x: (Void,) = unsafe { std::mem::uninitialized() };
25-
let _ = match x {}; // okay
25+
let _ = match x {}; //~ ERROR non-exhaustive
2626

2727
let x: [Void; 1] = unsafe { std::mem::uninitialized() };
28-
let _ = match x {}; // okay
28+
let _ = match x {}; //~ ERROR non-exhaustive
2929

3030
let x: &[Void] = unsafe { std::mem::uninitialized() };
3131
let _ = match x { //~ ERROR non-exhaustive

src/test/run-pass/issue-38972.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,10 @@ enum Foo { }
1616

1717
fn make_foo() -> Option<Foo> { None }
1818

19-
fn use_foo(v: &Foo) -> ! {
20-
match v { }
21-
}
22-
2319
#[deny(warnings)]
2420
fn main() {
2521
match make_foo() {
2622
None => {},
27-
Some(ref v) => use_foo(v),
23+
Some(_) => {}
2824
}
2925
}

0 commit comments

Comments
 (0)