Skip to content

Commit

Permalink
use a more conservative inhabitableness rule
Browse files Browse the repository at this point in the history
This is a [breaking-change] from 1.15, because this used to compile:

```Rust
enum Void {}
fn foo(x: &Void) {
    match x {}
}
```
  • Loading branch information
arielb1 committed Feb 23, 2017
1 parent a84eb95 commit 87e544b
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 9 deletions.
16 changes: 15 additions & 1 deletion src/librustc_const_eval/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,12 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
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 {} \
Expand All @@ -208,6 +213,15 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
})
}

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"
Expand Down
6 changes: 3 additions & 3 deletions src/test/compile-fail/uninhabited-matches-feature-gated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 1 addition & 5 deletions src/test/run-pass/issue-38972.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,10 @@ enum Foo { }

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

fn use_foo(v: &Foo) -> ! {
match v { }
}

#[deny(warnings)]
fn main() {
match make_foo() {
None => {},
Some(ref v) => use_foo(v),
Some(_) => {}
}
}

0 comments on commit 87e544b

Please sign in to comment.