Expand is_uninhabited
to recurse into datatypes
This commit is contained in:
parent
69bb5fa852
commit
d6482510f4
@ -16,6 +16,7 @@ pub use self::IntVarValue::*;
|
||||
pub use self::LvaluePreference::*;
|
||||
pub use self::fold::TypeFoldable;
|
||||
|
||||
use std::collections::{hash_map, HashMap};
|
||||
use dep_graph::{self, DepNode};
|
||||
use hir::map as ast_map;
|
||||
use middle;
|
||||
@ -1389,6 +1390,20 @@ impl<'tcx> serialize::UseSpecializedEncodable for AdtDef<'tcx> {
|
||||
|
||||
impl<'tcx> serialize::UseSpecializedDecodable for AdtDef<'tcx> {}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> {
|
||||
#[inline]
|
||||
pub fn is_uninhabited_recurse(&'tcx self,
|
||||
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
|
||||
cx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
substs: &'tcx Substs<'tcx>) -> bool {
|
||||
match visited.entry((self.did, substs)) {
|
||||
hash_map::Entry::Occupied(_) => return true,
|
||||
hash_map::Entry::Vacant(ve) => ve.insert(()),
|
||||
};
|
||||
self.variants.iter().all(|v| v.is_uninhabited_recurse(visited, cx, substs, self.is_union()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum AdtKind { Struct, Union, Enum }
|
||||
|
||||
@ -1531,11 +1546,6 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
|
||||
self.variants.iter().flat_map(VariantDefData::fields_iter)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.variants.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_univariant(&self) -> bool {
|
||||
self.variants.len() == 1
|
||||
@ -1795,6 +1805,21 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> VariantDefData<'tcx, 'static> {
|
||||
#[inline]
|
||||
pub fn is_uninhabited_recurse(&'tcx self,
|
||||
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
|
||||
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))
|
||||
} else {
|
||||
self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, cx, substs))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> {
|
||||
pub fn new(did: DefId,
|
||||
name: Name,
|
||||
@ -1820,6 +1845,16 @@ impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FieldDefData<'tcx, 'static> {
|
||||
#[inline]
|
||||
pub fn is_uninhabited_recurse(&'tcx self,
|
||||
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
substs: &'tcx Substs<'tcx>) -> bool {
|
||||
self.ty(tcx, substs).is_uninhabited_recurse(visited, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
/// Records the substitutions used to translate the polytype for an
|
||||
/// item into the monotype of an item reference.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
|
@ -21,6 +21,7 @@ use util::common::ErrorReported;
|
||||
use collections::enum_set::{self, EnumSet, CLike};
|
||||
use std::fmt;
|
||||
use std::ops;
|
||||
use std::collections::HashMap;
|
||||
use syntax::abi;
|
||||
use syntax::ast::{self, Name};
|
||||
use syntax::symbol::{keywords, InternedString};
|
||||
@ -929,14 +930,24 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_uninhabited(&self, cx: TyCtxt) -> bool {
|
||||
pub fn is_uninhabited(&self, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
|
||||
let mut visited = HashMap::new();
|
||||
self.is_uninhabited_recurse(&mut visited, cx)
|
||||
}
|
||||
|
||||
pub fn is_uninhabited_recurse(&self,
|
||||
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
|
||||
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, _) => def.is_empty(),
|
||||
TyAdt(def, substs) => {
|
||||
def.is_uninhabited_recurse(visited, cx, substs)
|
||||
},
|
||||
|
||||
TyNever => true,
|
||||
TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited(cx)),
|
||||
TyArray(ty, len) => len > 0 && ty.is_uninhabited(cx),
|
||||
|
||||
// FIXME(canndrew): this line breaks core::fmt
|
||||
//TyRef(_, ref tm) => tm.ty.is_uninhabited(cx),
|
||||
|
Loading…
Reference in New Issue
Block a user