diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index a3600c04800..365434062a3 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1086,6 +1086,7 @@ impl_stable_hash_for!(enum traits::Reveal { }); impl_stable_hash_for!(enum ::middle::privacy::AccessLevel { + ReachableFromImplTrait, Reachable, Exported, Public diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index c7e093380fa..39ddaca8925 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -22,7 +22,7 @@ use syntax::ast::NodeId; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum AccessLevel { // Superset of Reachable used to mark impl Trait items. - // ReachableFromImplTrait, + ReachableFromImplTrait, // Exported items + items participating in various kinds of public interfaces, // but not directly nameable. For example, if function `fn f() -> T {...}` is // public, then type `T` is reachable. Its values can be obtained by other crates @@ -42,7 +42,8 @@ pub struct AccessLevels { impl AccessLevels { pub fn is_reachable(&self, id: Id) -> bool { - self.map.contains_key(&id) + // self.map.contains_key(&id) + self.map.get(&id) >= Some(&AccessLevel::Reachable) } pub fn is_exported(&self, id: Id) -> bool { self.map.get(&id) >= Some(&AccessLevel::Exported) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index fea0e3a7435..b6b56cad839 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -84,6 +84,7 @@ struct EmbargoVisitor<'a, 'tcx: 'a> { } struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> { + access_level: Option, item_def_id: DefId, ev: &'b mut EmbargoVisitor<'a, 'tcx>, } @@ -134,6 +135,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { fn reach<'b>(&'b mut self, item_id: ast::NodeId) -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { ReachEverythingInTheInterfaceVisitor { + access_level: self.prev_level.map(|l| l.min(AccessLevel::Reachable)), item_def_id: self.tcx.hir.local_def_id(item_id), ev: self, } @@ -164,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::Existential(ref ty_data) => { if let Some(impl_trait_fn) = ty_data.impl_trait_fn { if let Some(node_id) = self.tcx.hir.as_local_node_id(impl_trait_fn) { - self.update(node_id, Some(AccessLevel::Reachable)); + self.update(node_id, Some(AccessLevel::ReachableFromImplTrait)); } } if item.vis.node.is_pub() { self.prev_level } else { None } @@ -240,6 +242,9 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::ExternCrate(..) => {} } + let orig_level = self.prev_level; + self.prev_level = item_level; + // Mark all items in interfaces of reachable items as reachable match item.node { // The interface is empty @@ -337,9 +342,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } - let orig_level = self.prev_level; - self.prev_level = item_level; - intravisit::walk_item(self, item); self.prev_level = orig_level; @@ -475,7 +477,7 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) { let item = self.ev.tcx.hir.expect_item(node_id); - self.ev.update(item.id, Some(AccessLevel::Reachable)); + self.ev.update(item.id, self.access_level); } } } @@ -496,7 +498,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b if let Some(def_id) = ty_def_id { if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(def_id) { - self.ev.update(node_id, Some(AccessLevel::Reachable)); + self.ev.update(node_id, self.access_level); } }