Fix build after rebase.

Mostly just rename stuff.
Visibility checks use DefIds rather than NodeIds now.
This commit is contained in:
Andrew Cann 2016-12-29 17:08:33 +08:00
parent 4136ba072e
commit 9f83e962de
6 changed files with 129 additions and 118 deletions

View file

@ -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};
@ -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,

View file

@ -10,118 +10,120 @@
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
@ -129,18 +131,18 @@ impl<'a, 'gcx, 'tcx> NodeForrest {
}
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));
@ -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)
}))
},
@ -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(),
}
@ -204,28 +206,28 @@ 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
},
}
}
@ -233,29 +235,29 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
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(),
}
}
}

View file

@ -227,6 +227,20 @@ pub enum Visibility {
pub trait DefIdTree: Copy {
fn parent(self, id: DefId) -> Option<DefId>;
fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
if descendant.krate != ancestor.krate {
return false;
}
while descendant != ancestor {
match self.parent(descendant) {
Some(parent) => descendant = parent,
None => return false,
}
}
true
}
}
impl<'a, 'gcx, 'tcx> DefIdTree for TyCtxt<'a, 'gcx, 'tcx> {
@ -253,7 +267,7 @@ impl Visibility {
}
/// Returns true if an item with this visibility is accessible from the given block.
pub fn is_accessible_from<T: DefIdTree>(self, mut module: DefId, tree: T) -> bool {
pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool {
let restriction = match self {
// Public items are visible everywhere.
Visibility::Public => return true,
@ -264,14 +278,7 @@ impl Visibility {
Visibility::Restricted(module) => module,
};
while module != restriction {
match tree.parent(module) {
Some(parent) => module = parent,
None => return false,
}
}
true
tree.is_descendant_of(module, restriction)
}
/// Returns true if this visibility is at least as accessible as the given visibility

View file

@ -22,7 +22,7 @@ use std::fmt;
use std::iter;
use std::cmp::Ordering;
use syntax::abi;
use syntax::ast::{self, Name, NodeId};
use syntax::ast::{self, Name};
use syntax::symbol::{keywords, InternedString};
use util::nodemap::FxHashSet;
@ -979,11 +979,11 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
}
/// Checks whether a type is visibly uninhabited from a particular node.
pub fn is_uninhabited_from(&self, block: NodeId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
/// Checks whether a type is visibly uninhabited from a particular module.
pub fn is_uninhabited_from(&self, module: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
let mut visited = FxHashSet::default();
let node_set = self.uninhabited_from(&mut visited, tcx);
node_set.contains(tcx, block)
let forrest = self.uninhabited_from(&mut visited, tcx);
forrest.contains(tcx, module)
}
/// Checks whether a type is uninhabited.