Skip to content

Commit

Permalink
Fix build after rebase.
Browse files Browse the repository at this point in the history
Mostly just rename stuff.
Visibility checks use DefIds rather than NodeIds now.
  • Loading branch information
canndrew committed Jan 3, 2017
1 parent 4136ba0 commit 9f83e96
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 118 deletions.
4 changes: 2 additions & 2 deletions src/librustc/ty/context.rs
Expand Up @@ -33,7 +33,7 @@ use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
use ty::TypeVariants::*;
use ty::layout::{Layout, TargetDataLayout};
use ty::inhabitedness::NodeForrest;
use ty::inhabitedness::DefIdForrest;
use ty::maps;
use util::common::MemoizationMap;
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
Expand Down Expand Up @@ -460,7 +460,7 @@ pub struct GlobalCtxt<'tcx> {
// FIXME dep tracking -- should be harmless enough
pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,

pub inhabitedness_cache: RefCell<FxHashMap<Ty<'tcx>, NodeForrest>>,
pub inhabitedness_cache: RefCell<FxHashMap<Ty<'tcx>, DefIdForrest>>,

pub lang_items: middle::lang_items::LanguageItems,

Expand Down
174 changes: 88 additions & 86 deletions src/librustc/ty/inhabitedness.rs
Expand Up @@ -10,137 +10,139 @@

use std::mem;
use rustc_data_structures::small_vec::SmallVec;
use syntax::ast::{CRATE_NODE_ID, NodeId};
use syntax::ast::CRATE_NODE_ID;
use util::nodemap::FxHashSet;
use ty::context::TyCtxt;
use ty::{AdtDef, VariantDef, FieldDef, TyS};
use ty::{DefId, Substs};
use ty::{AdtKind, Visibility, NodeIdTree};
use ty::{AdtKind, Visibility, DefIdTree};
use ty::TypeVariants::*;

/// Represents a set of nodes closed under the ancestor relation. That is, if a
/// node is in this set then so are all its descendants.
/// Represents a set of DefIds closed under the ancestor relation. That is, if
/// a DefId is in this set then so are all its descendants.
#[derive(Clone)]
pub struct NodeForrest {
/// The minimal set of nodes required to represent the whole set.
/// If A and B are nodes in the NodeForrest, and A is a desecendant
/// of B, then only B will be in root_nodes.
pub struct DefIdForrest {
/// The minimal set of DefIds required to represent the whole set.
/// If A and B are DefIds in the DefIdForrest, and A is a desecendant
/// of B, then only B will be in root_ids.
/// We use a SmallVec here because (for its use in this module) its rare
/// that this will contain more than one or two nodes.
root_nodes: SmallVec<[NodeId; 1]>,
/// that this will contain even two ids.
root_ids: SmallVec<[DefId; 1]>,
}

impl<'a, 'gcx, 'tcx> NodeForrest {
/// Create an empty set.
pub fn empty() -> NodeForrest {
NodeForrest {
root_nodes: SmallVec::new(),
impl<'a, 'gcx, 'tcx> DefIdForrest {
/// Create an empty forrest.
pub fn empty() -> DefIdForrest {
DefIdForrest {
root_ids: SmallVec::new(),
}
}

/// Create a set containing every node.
/// Create a forrest consisting of a single tree representing the entire
/// crate.
#[inline]
pub fn full() -> NodeForrest {
NodeForrest::from_node(CRATE_NODE_ID)
pub fn full(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForrest {
let crate_id = tcx.map.local_def_id(CRATE_NODE_ID);
DefIdForrest::from_id(crate_id)
}

/// Create a set containing a node and all its descendants.
pub fn from_node(node: NodeId) -> NodeForrest {
let mut root_nodes = SmallVec::new();
root_nodes.push(node);
NodeForrest {
root_nodes: root_nodes,
/// Create a forrest containing a DefId and all its descendants.
pub fn from_id(id: DefId) -> DefIdForrest {
let mut root_ids = SmallVec::new();
root_ids.push(id);
DefIdForrest {
root_ids: root_ids,
}
}

/// Test whether the set is empty.
/// Test whether the forrest is empty.
pub fn is_empty(&self) -> bool {
self.root_nodes.is_empty()
self.root_ids.is_empty()
}

/// Test whether the set conains a node.
/// Test whether the forrest conains a given DefId.
pub fn contains(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
node: NodeId) -> bool
id: DefId) -> bool
{
for root_node in self.root_nodes.iter() {
if tcx.map.is_descendant_of(node, *root_node) {
for root_id in self.root_ids.iter() {
if tcx.is_descendant_of(id, *root_id) {
return true;
}
}
false
}

/// Calculate the intersection of a collection of sets.
/// Calculate the intersection of a collection of forrests.
pub fn intersection<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
iter: I) -> NodeForrest
where I: IntoIterator<Item=NodeForrest>
iter: I) -> DefIdForrest
where I: IntoIterator<Item=DefIdForrest>
{
let mut ret = NodeForrest::full();
let mut ret = DefIdForrest::full(tcx);
let mut next_ret = SmallVec::new();
let mut old_ret: SmallVec<[NodeId; 1]> = SmallVec::new();
for next_set in iter {
for node in ret.root_nodes.drain(..) {
if next_set.contains(tcx, node) {
next_ret.push(node);
let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
for next_forrest in iter {
for id in ret.root_ids.drain(..) {
if next_forrest.contains(tcx, id) {
next_ret.push(id);
} else {
old_ret.push(node);
old_ret.push(id);
}
}
ret.root_nodes.extend(old_ret.drain(..));
ret.root_ids.extend(old_ret.drain(..));

for node in next_set.root_nodes {
if ret.contains(tcx, node) {
next_ret.push(node);
for id in next_forrest.root_ids {
if ret.contains(tcx, id) {
next_ret.push(id);
}
}

mem::swap(&mut next_ret, &mut ret.root_nodes);
mem::swap(&mut next_ret, &mut ret.root_ids);
next_ret.drain(..);
}
ret
}

/// Calculate the union of a collection of sets.
/// Calculate the union of a collection of forrests.
pub fn union<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
iter: I) -> NodeForrest
where I: IntoIterator<Item=NodeForrest>
iter: I) -> DefIdForrest
where I: IntoIterator<Item=DefIdForrest>
{
let mut ret = NodeForrest::empty();
let mut ret = DefIdForrest::empty();
let mut next_ret = SmallVec::new();
for next_set in iter {
for node in ret.root_nodes.drain(..) {
if !next_set.contains(tcx, node) {
next_ret.push(node);
for next_forrest in iter {
for id in ret.root_ids.drain(..) {
if !next_forrest.contains(tcx, id) {
next_ret.push(id);
}
}

for node in next_set.root_nodes {
if !next_ret.contains(&node) {
next_ret.push(node);
for id in next_forrest.root_ids {
if !next_ret.contains(&id) {
next_ret.push(id);
}
}

mem::swap(&mut next_ret, &mut ret.root_nodes);
mem::swap(&mut next_ret, &mut ret.root_ids);
next_ret.drain(..);
}
ret
}
}

impl<'a, 'gcx, 'tcx> AdtDef {
/// Calculate the set of nodes from which this adt is visibly uninhabited.
/// Calculate the forrest of DefIds from which this adt is visibly uninhabited.
pub fn uninhabited_from(
&self,
visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &'tcx Substs<'tcx>) -> NodeForrest
substs: &'tcx Substs<'tcx>) -> DefIdForrest
{
if !visited.insert((self.did, substs)) {
return NodeForrest::empty();
return DefIdForrest::empty();
}

let ret = NodeForrest::intersection(tcx, self.variants.iter().map(|v| {
let ret = DefIdForrest::intersection(tcx, self.variants.iter().map(|v| {
v.uninhabited_from(visited, tcx, substs, self.adt_kind())
}));
visited.remove(&(self.did, substs));
Expand All @@ -149,27 +151,27 @@ impl<'a, 'gcx, 'tcx> AdtDef {
}

impl<'a, 'gcx, 'tcx> VariantDef {
/// Calculate the set of nodes from which this variant is visibly uninhabited.
/// Calculate the forrest of DefIds from which this variant is visibly uninhabited.
pub fn uninhabited_from(
&self,
visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &'tcx Substs<'tcx>,
adt_kind: AdtKind) -> NodeForrest
adt_kind: AdtKind) -> DefIdForrest
{
match adt_kind {
AdtKind::Union => {
NodeForrest::intersection(tcx, self.fields.iter().map(|f| {
DefIdForrest::intersection(tcx, self.fields.iter().map(|f| {
f.uninhabited_from(visited, tcx, substs, false)
}))
},
AdtKind::Struct => {
NodeForrest::union(tcx, self.fields.iter().map(|f| {
DefIdForrest::union(tcx, self.fields.iter().map(|f| {
f.uninhabited_from(visited, tcx, substs, false)
}))
},
AdtKind::Enum => {
NodeForrest::union(tcx, self.fields.iter().map(|f| {
DefIdForrest::union(tcx, self.fields.iter().map(|f| {
f.uninhabited_from(visited, tcx, substs, true)
}))
},
Expand All @@ -178,24 +180,24 @@ impl<'a, 'gcx, 'tcx> VariantDef {
}

impl<'a, 'gcx, 'tcx> FieldDef {
/// Calculate the set of nodes from which this field is visibly uninhabited.
/// Calculate the forrest of DefIds from which this field is visibly uninhabited.
pub fn uninhabited_from(
&self,
visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &'tcx Substs<'tcx>,
is_enum: bool) -> NodeForrest
is_enum: bool) -> DefIdForrest
{
let mut data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(visited, tcx);
if is_enum {
data_uninhabitedness()
} else {
match self.vis {
Visibility::PrivateExternal => NodeForrest::empty(),
Visibility::Invisible => DefIdForrest::empty(),
Visibility::Restricted(from) => {
let node_set = NodeForrest::from_node(from);
let iter = Some(node_set).into_iter().chain(Some(data_uninhabitedness()));
NodeForrest::intersection(tcx, iter)
let forrest = DefIdForrest::from_id(from);
let iter = Some(forrest).into_iter().chain(Some(data_uninhabitedness()));
DefIdForrest::intersection(tcx, iter)
},
Visibility::Public => data_uninhabitedness(),
}
Expand All @@ -204,58 +206,58 @@ impl<'a, 'gcx, 'tcx> FieldDef {
}

impl<'a, 'gcx, 'tcx> TyS<'tcx> {
/// Calculate the set of nodes from which this type is visibly uninhabited.
/// Calculate the forrest of DefIds from which this type is visibly uninhabited.
pub fn uninhabited_from(
&self,
visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> NodeForrest
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForrest
{
match tcx.lift_to_global(&self) {
Some(global_ty) => {
{
let cache = tcx.inhabitedness_cache.borrow();
if let Some(closed_node_set) = cache.get(&global_ty) {
return closed_node_set.clone();
if let Some(forrest) = cache.get(&global_ty) {
return forrest.clone();
}
}
let node_set = global_ty.uninhabited_from_inner(visited, tcx);
let forrest = global_ty.uninhabited_from_inner(visited, tcx);
let mut cache = tcx.inhabitedness_cache.borrow_mut();
cache.insert(global_ty, node_set.clone());
node_set
cache.insert(global_ty, forrest.clone());
forrest
},
None => {
let node_set = self.uninhabited_from_inner(visited, tcx);
node_set
let forrest = self.uninhabited_from_inner(visited, tcx);
forrest
},
}
}

fn uninhabited_from_inner(
&self,
visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> NodeForrest
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForrest
{
match self.sty {
TyAdt(def, substs) => {
def.uninhabited_from(visited, tcx, substs)
},

TyNever => NodeForrest::full(),
TyNever => DefIdForrest::full(tcx),
TyTuple(ref tys) => {
NodeForrest::union(tcx, tys.iter().map(|ty| {
DefIdForrest::union(tcx, tys.iter().map(|ty| {
ty.uninhabited_from(visited, tcx)
}))
},
TyArray(ty, len) => {
if len == 0 {
NodeForrest::empty()
DefIdForrest::empty()
} else {
ty.uninhabited_from(visited, tcx)
}
}
TyRef(_, ref tm) => tm.ty.uninhabited_from(visited, tcx),

_ => NodeForrest::empty(),
_ => DefIdForrest::empty(),
}
}
}
Expand Down

0 comments on commit 9f83e96

Please sign in to comment.