Skip to content

Commit

Permalink
Make is_uninhabited respect privacy
Browse files Browse the repository at this point in the history
  • Loading branch information
canndrew committed Nov 22, 2016
1 parent a6cc398 commit d756f61
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 14 deletions.
14 changes: 10 additions & 4 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1394,13 +1394,16 @@ impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> {
#[inline]
pub fn is_uninhabited_recurse(&'tcx self,
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
block: Option<NodeId>,
cx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &'tcx Substs<'tcx>) -> bool {
match visited.entry((self.did, substs)) {
hash_map::Entry::Occupied(_) => return false,
hash_map::Entry::Vacant(ve) => ve.insert(()),
};
self.variants.iter().all(|v| v.is_uninhabited_recurse(visited, cx, substs, self.is_union()))
self.variants.iter().all(|v| {
v.is_uninhabited_recurse(visited, block, cx, substs, self.is_union())
})
}
}

Expand Down Expand Up @@ -1809,13 +1812,14 @@ impl<'a, 'gcx, 'tcx> VariantDefData<'tcx, 'static> {
#[inline]
pub fn is_uninhabited_recurse(&'tcx self,
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
block: Option<NodeId>,
cx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &'tcx Substs<'tcx>,
is_union: bool) -> bool {
if is_union {
self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, cx, substs))
self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, block, cx, substs))
} else {
self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, cx, substs))
self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, block, cx, substs))
}
}
}
Expand Down Expand Up @@ -1849,9 +1853,11 @@ impl<'a, 'gcx, 'tcx> FieldDefData<'tcx, 'static> {
#[inline]
pub fn is_uninhabited_recurse(&'tcx self,
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
block: Option<NodeId>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &'tcx Substs<'tcx>) -> bool {
self.ty(tcx, substs).is_uninhabited_recurse(visited, tcx)
block.map_or(true, |b| self.vis.is_accessible_from(b, &tcx.map)) &&
self.ty(tcx, substs).is_uninhabited_recurse(visited, block, tcx)
}
}

Expand Down
19 changes: 10 additions & 9 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use std::fmt;
use std::ops;
use std::collections::HashMap;
use syntax::abi;
use syntax::ast::{self, Name};
use syntax::ast::{self, Name, NodeId};
use syntax::symbol::{keywords, InternedString};

use serialize;
Expand Down Expand Up @@ -930,25 +930,26 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
}

pub fn is_uninhabited(&self, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
/// Checks whether a type is uninhabited.
/// If `block` is `Some(id)` it also checks that the uninhabited-ness is visible from `id`.
pub fn is_uninhabited(&self, block: Option<NodeId>, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
let mut visited = HashMap::new();
self.is_uninhabited_recurse(&mut visited, cx)
self.is_uninhabited_recurse(&mut visited, block, cx)
}

pub fn is_uninhabited_recurse(&self,
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
block: Option<NodeId>,
cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
// FIXME(#24885): be smarter here, the AdtDefData::is_empty method could easily be made
// more complete.
match self.sty {
TyAdt(def, substs) => {
def.is_uninhabited_recurse(visited, cx, substs)
def.is_uninhabited_recurse(visited, block, cx, substs)
},

TyNever => true,
TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited_recurse(visited, cx)),
TyArray(ty, len) => len > 0 && ty.is_uninhabited_recurse(visited, cx),
TyRef(_, ref tm) => tm.ty.is_uninhabited_recurse(visited, cx),
TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited_recurse(visited, block, cx)),
TyArray(ty, len) => len > 0 && ty.is_uninhabited_recurse(visited, block, cx),
TyRef(_, ref tm) => tm.ty.is_uninhabited_recurse(visited, block, cx),

_ => false,
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_const_eval/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
// Check for empty enum, because is_useful only works on inhabited types.
let pat_ty = self.tcx.tables().node_id_to_type(scrut.id);
if inlined_arms.is_empty() {
if !pat_ty.is_uninhabited(self.tcx) {
if !pat_ty.is_uninhabited(Some(scrut.id), self.tcx) {
// We know the type is inhabited, so this must be wrong
let mut err = create_e0004(self.tcx.sess, span,
format!("non-exhaustive patterns: type {} \
Expand Down

0 comments on commit d756f61

Please sign in to comment.