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 {}
}
```
This commit is contained in:
parent
a84eb95a7d
commit
87e544bca5
3 changed files with 19 additions and 9 deletions
|
|
@ -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 {} \
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(_) => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue