Skip to content

Commit d648251

Browse files
committed
Expand is_uninhabited to recurse into datatypes
1 parent 69bb5fa commit d648251

File tree

2 files changed

+53
-7
lines changed

2 files changed

+53
-7
lines changed

src/librustc/ty/mod.rs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub use self::IntVarValue::*;
1616
pub use self::LvaluePreference::*;
1717
pub use self::fold::TypeFoldable;
1818

19+
use std::collections::{hash_map, HashMap};
1920
use dep_graph::{self, DepNode};
2021
use hir::map as ast_map;
2122
use middle;
@@ -1389,6 +1390,20 @@ impl<'tcx> serialize::UseSpecializedEncodable for AdtDef<'tcx> {
13891390

13901391
impl<'tcx> serialize::UseSpecializedDecodable for AdtDef<'tcx> {}
13911392

1393+
impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> {
1394+
#[inline]
1395+
pub fn is_uninhabited_recurse(&'tcx self,
1396+
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
1397+
cx: TyCtxt<'a, 'gcx, 'tcx>,
1398+
substs: &'tcx Substs<'tcx>) -> bool {
1399+
match visited.entry((self.did, substs)) {
1400+
hash_map::Entry::Occupied(_) => return true,
1401+
hash_map::Entry::Vacant(ve) => ve.insert(()),
1402+
};
1403+
self.variants.iter().all(|v| v.is_uninhabited_recurse(visited, cx, substs, self.is_union()))
1404+
}
1405+
}
1406+
13921407
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
13931408
pub enum AdtKind { Struct, Union, Enum }
13941409

@@ -1531,11 +1546,6 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
15311546
self.variants.iter().flat_map(VariantDefData::fields_iter)
15321547
}
15331548

1534-
#[inline]
1535-
pub fn is_empty(&self) -> bool {
1536-
self.variants.is_empty()
1537-
}
1538-
15391549
#[inline]
15401550
pub fn is_univariant(&self) -> bool {
15411551
self.variants.len() == 1
@@ -1795,6 +1805,21 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
17951805
}
17961806
}
17971807

1808+
impl<'a, 'gcx, 'tcx> VariantDefData<'tcx, 'static> {
1809+
#[inline]
1810+
pub fn is_uninhabited_recurse(&'tcx self,
1811+
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
1812+
cx: TyCtxt<'a, 'gcx, 'tcx>,
1813+
substs: &'tcx Substs<'tcx>,
1814+
is_union: bool) -> bool {
1815+
if is_union {
1816+
self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, cx, substs))
1817+
} else {
1818+
self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, cx, substs))
1819+
}
1820+
}
1821+
}
1822+
17981823
impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> {
17991824
pub fn new(did: DefId,
18001825
name: Name,
@@ -1820,6 +1845,16 @@ impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> {
18201845
}
18211846
}
18221847

1848+
impl<'a, 'gcx, 'tcx> FieldDefData<'tcx, 'static> {
1849+
#[inline]
1850+
pub fn is_uninhabited_recurse(&'tcx self,
1851+
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
1852+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
1853+
substs: &'tcx Substs<'tcx>) -> bool {
1854+
self.ty(tcx, substs).is_uninhabited_recurse(visited, tcx)
1855+
}
1856+
}
1857+
18231858
/// Records the substitutions used to translate the polytype for an
18241859
/// item into the monotype of an item reference.
18251860
#[derive(Clone, RustcEncodable, RustcDecodable)]

src/librustc/ty/sty.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use util::common::ErrorReported;
2121
use collections::enum_set::{self, EnumSet, CLike};
2222
use std::fmt;
2323
use std::ops;
24+
use std::collections::HashMap;
2425
use syntax::abi;
2526
use syntax::ast::{self, Name};
2627
use syntax::symbol::{keywords, InternedString};
@@ -929,14 +930,24 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
929930
}
930931
}
931932

932-
pub fn is_uninhabited(&self, cx: TyCtxt) -> bool {
933+
pub fn is_uninhabited(&self, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
934+
let mut visited = HashMap::new();
935+
self.is_uninhabited_recurse(&mut visited, cx)
936+
}
937+
938+
pub fn is_uninhabited_recurse(&self,
939+
visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
940+
cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
933941
// FIXME(#24885): be smarter here, the AdtDefData::is_empty method could easily be made
934942
// more complete.
935943
match self.sty {
936-
TyAdt(def, _) => def.is_empty(),
944+
TyAdt(def, substs) => {
945+
def.is_uninhabited_recurse(visited, cx, substs)
946+
},
937947

938948
TyNever => true,
939949
TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited(cx)),
950+
TyArray(ty, len) => len > 0 && ty.is_uninhabited(cx),
940951

941952
// FIXME(canndrew): this line breaks core::fmt
942953
//TyRef(_, ref tm) => tm.ty.is_uninhabited(cx),

0 commit comments

Comments
 (0)