Skip to content

Commit

Permalink
Hide uninhabitedness checks behind feature gate
Browse files Browse the repository at this point in the history
  • Loading branch information
canndrew committed Jan 25, 2017
1 parent c0d0e68 commit 2b7a23e
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 41 deletions.
6 changes: 1 addition & 5 deletions src/librustc/ty/inhabitedness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
}
TyRef(_, ref tm) => {
if tcx.sess.features.borrow().never_type {
tm.ty.uninhabited_from(visited, tcx)
} else {
DefIdForest::empty()
}
tm.ty.uninhabited_from(visited, tcx)
}

_ => DefIdForest::empty(),
Expand Down
17 changes: 13 additions & 4 deletions src/librustc_const_eval/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,19 +379,24 @@ impl<'tcx> Witness<'tcx> {
fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
pcx: PatternContext<'tcx>) -> Vec<Constructor>
{
let check_inhabited = cx.tcx.sess.features.borrow().never_type;
debug!("all_constructors({:?})", pcx.ty);
match pcx.ty.sty {
ty::TyBool =>
[true, false].iter().map(|b| ConstantValue(ConstVal::Bool(*b))).collect(),
ty::TySlice(ref sub_ty) => {
if sub_ty.is_uninhabited_from(cx.module, cx.tcx) {
if sub_ty.is_uninhabited_from(cx.module, cx.tcx)
&& check_inhabited
{
vec![Slice(0)]
} else {
(0..pcx.max_slice_length+1).map(|length| Slice(length)).collect()
}
}
ty::TyArray(ref sub_ty, length) => {
if length == 0 || !sub_ty.is_uninhabited_from(cx.module, cx.tcx) {
if length == 0 || !(sub_ty.is_uninhabited_from(cx.module, cx.tcx)
&& check_inhabited)
{
vec![Slice(length)]
} else {
vec![]
Expand All @@ -403,15 +408,19 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
let forest = v.uninhabited_from(&mut visited,
cx.tcx, substs,
AdtKind::Enum);
if forest.contains(cx.tcx, cx.module) {
if forest.contains(cx.tcx, cx.module)
&& check_inhabited
{
None
} else {
Some(Variant(v.did))
}
}).collect()
}
_ => {
if pcx.ty.is_uninhabited_from(cx.module, cx.tcx) {
if pcx.ty.is_uninhabited_from(cx.module, cx.tcx)
&& check_inhabited
{
vec![]
} else {
vec![Single]
Expand Down
30 changes: 17 additions & 13 deletions src/librustc_mir/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,20 +99,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}

PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
i == variant_index || {
let mut visited = FxHashSet::default();
let node_set = v.uninhabited_from(&mut visited,
self.hir.tcx(),
substs,
adt_def.adt_kind());
!node_set.is_empty()
if self.hir.tcx().sess.features.borrow().never_type {
let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
i == variant_index || {
let mut visited = FxHashSet::default();
let node_set = v.uninhabited_from(&mut visited,
self.hir.tcx(),
substs,
adt_def.adt_kind());
!node_set.is_empty()
}
});
if irrefutable {
let lvalue = match_pair.lvalue.downcast(adt_def, variant_index);
candidate.match_pairs.extend(self.field_match_pairs(lvalue, subpatterns));
Ok(())
} else {
Err(match_pair)
}
});
if irrefutable {
let lvalue = match_pair.lvalue.downcast(adt_def, variant_index);
candidate.match_pairs.extend(self.field_match_pairs(lvalue, subpatterns));
Ok(())
} else {
Err(match_pair)
}
Expand Down
50 changes: 50 additions & 0 deletions src/test/compile-fail/uninhabited-matches-feature-gated.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(slice_patterns)]

enum Void {}

fn main() {
let x: Result<u32, &'static Void> = Ok(23);
let _ = match x { //~ ERROR non-exhaustive
Ok(n) => n,
};

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

let x: (Void,) = unsafe { std::mem::uninitialized() };
let _ = match x {};
//~^ ERROR non-exhaustive

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

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

let x: Void = unsafe { std::mem::uninitialized() };
let _ = match x {}; // okay

let x: Result<u32, Void> = Ok(23);
let _ = match x { //~ ERROR non-exhaustive
Ok(x) => x,
};

let x: Result<u32, Void> = Ok(23);
let Ok(x) = x;
//~^ ERROR refutable
}

19 changes: 0 additions & 19 deletions src/test/compile-fail/uninhabited-reference-type-feature-gated.rs

This file was deleted.

0 comments on commit 2b7a23e

Please sign in to comment.