Make is_uninhabited respect privacy
This commit is contained in:
parent
a6cc398207
commit
d756f61a5a
3 changed files with 21 additions and 14 deletions
|
|
@ -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())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {} \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue