use util::nodemap::{FxHashMap, FxHashSet};
use ty::context::TyCtxt;
-use ty::{AdtDef, VariantDef, FieldDef, TyS};
+use ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
use ty::{DefId, Substs};
use ty::{AdtKind, Visibility};
use ty::TypeVariants::*;
// This code should only compile in modules where the uninhabitedness of Foo is
// visible.
+impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
+ /// Checks whether a type is visibly uninhabited from a particular module.
+ /// # Example
+ /// ```rust
+ /// enum Void {}
+ /// mod a {
+ /// pub mod b {
+ /// pub struct SecretlyUninhabited {
+ /// _priv: !,
+ /// }
+ /// }
+ /// }
+ ///
+ /// mod c {
+ /// pub struct AlsoSecretlyUninhabited {
+ /// _priv: Void,
+ /// }
+ /// mod d {
+ /// }
+ /// }
+ ///
+ /// struct Foo {
+ /// x: a::b::SecretlyUninhabited,
+ /// y: c::AlsoSecretlyUninhabited,
+ /// }
+ /// ```
+ /// In this code, the type `Foo` will only be visibly uninhabited inside the
+ /// modules b, c and d. This effects pattern-matching on `Foo` or types that
+ /// contain `Foo`.
+ ///
+ /// # Example
+ /// ```rust
+ /// let foo_result: Result<T, Foo> = ... ;
+ /// let Ok(t) = foo_result;
+ /// ```
+ /// This code should only compile in modules where the uninhabitedness of Foo is
+ /// visible.
+ pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool {
+ let forest = ty.uninhabited_from(&mut FxHashMap(), self);
+
+ // To check whether this type is uninhabited at all (not just from the
+ // given node) you could check whether the forest is empty.
+ // ```
+ // forest.is_empty()
+ // ```
+ forest.contains(self, module)
+ }
+
+ pub fn is_enum_variant_uninhabited_from(self,
+ module: DefId,
+ variant: &'tcx VariantDef,
+ substs: &'tcx Substs<'tcx>)
+ -> bool
+ {
+ let adt_kind = AdtKind::Enum;
+ variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind).contains(self, module)
+ }
+
+ pub fn is_variant_uninhabited_from_all_modules(self,
+ variant: &'tcx VariantDef,
+ substs: &'tcx Substs<'tcx>,
+ adt_kind: AdtKind)
+ -> bool
+ {
+ !variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind).is_empty()
+ }
+}
+
impl<'a, 'gcx, 'tcx> AdtDef {
/// Calculate the forest of DefIds from which this adt is visibly uninhabited.
- pub fn uninhabited_from(
- &self,
- visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- substs: &'tcx Substs<'tcx>) -> DefIdForest
+ fn uninhabited_from(
+ &self,
+ visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ substs: &'tcx Substs<'tcx>) -> DefIdForest
{
DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
v.uninhabited_from(visited, tcx, substs, self.adt_kind())
impl<'a, 'gcx, 'tcx> VariantDef {
/// Calculate the forest of DefIds from which this variant is visibly uninhabited.
- pub fn uninhabited_from(
- &self,
- visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- substs: &'tcx Substs<'tcx>,
- adt_kind: AdtKind) -> DefIdForest
+ fn uninhabited_from(
+ &self,
+ visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ substs: &'tcx Substs<'tcx>,
+ adt_kind: AdtKind) -> DefIdForest
{
match adt_kind {
AdtKind::Union => {
impl<'a, 'gcx, 'tcx> FieldDef {
/// Calculate the forest of DefIds from which this field is visibly uninhabited.
- pub fn uninhabited_from(
- &self,
- visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- substs: &'tcx Substs<'tcx>,
- is_enum: bool) -> DefIdForest
+ fn uninhabited_from(
+ &self,
+ visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ substs: &'tcx Substs<'tcx>,
+ is_enum: bool) -> DefIdForest
{
let mut data_uninhabitedness = move || {
self.ty(tcx, substs).uninhabited_from(visited, tcx)
impl<'a, 'gcx, 'tcx> TyS<'tcx> {
/// Calculate the forest of DefIds from which this type is visibly uninhabited.
- pub fn uninhabited_from(
- &self,
- visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
- tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
+ fn uninhabited_from(
+ &self,
+ visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
{
match tcx.lift_to_global(&self) {
Some(global_ty) => {
use syntax::abi;
use syntax::ast::{self, Name};
use syntax::symbol::keywords;
-use util::nodemap::FxHashMap;
use serialize;
}
}
- /// Checks whether a type is visibly uninhabited from a particular module.
- /// # Example
- /// ```rust
- /// enum Void {}
- /// mod a {
- /// pub mod b {
- /// pub struct SecretlyUninhabited {
- /// _priv: !,
- /// }
- /// }
- /// }
- ///
- /// mod c {
- /// pub struct AlsoSecretlyUninhabited {
- /// _priv: Void,
- /// }
- /// mod d {
- /// }
- /// }
- ///
- /// struct Foo {
- /// x: a::b::SecretlyUninhabited,
- /// y: c::AlsoSecretlyUninhabited,
- /// }
- /// ```
- /// In this code, the type `Foo` will only be visibly uninhabited inside the
- /// modules b, c and d. This effects pattern-matching on `Foo` or types that
- /// contain `Foo`.
- ///
- /// # Example
- /// ```rust
- /// let foo_result: Result<T, Foo> = ... ;
- /// let Ok(t) = foo_result;
- /// ```
- /// This code should only compile in modules where the uninhabitedness of Foo is
- /// visible.
- pub fn is_uninhabited_from(&self, module: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
- let mut visited = FxHashMap::default();
- let forest = self.uninhabited_from(&mut visited, tcx);
-
- // To check whether this type is uninhabited at all (not just from the
- // given node) you could check whether the forest is empty.
- // ```
- // forest.is_empty()
- // ```
- forest.contains(tcx, module)
- }
-
pub fn is_primitive(&self) -> bool {
match self.sty {
TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true,
use rustc::hir::def_id::DefId;
use rustc::hir::RangeEnd;
-use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::mir::Field;
use rustc::util::common::ErrorReported;
fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
if self.tcx.sess.features.borrow().never_type {
- ty.is_uninhabited_from(self.module, self.tcx)
+ self.tcx.is_ty_uninhabited_from(self.module, ty)
} else {
false
}
fn is_variant_uninhabited(&self,
variant: &'tcx ty::VariantDef,
- substs: &'tcx ty::subst::Substs<'tcx>) -> bool
+ substs: &'tcx ty::subst::Substs<'tcx>)
+ -> bool
{
if self.tcx.sess.features.borrow().never_type {
- let forest = variant.uninhabited_from(
- &mut FxHashMap::default(), self.tcx, substs, AdtKind::Enum
- );
- forest.contains(self.tcx, self.module)
+ self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs)
} else {
false
}