Changes to data produced by privacy pass

This commit is contained in:
Vadim Petrochenkov 2015-11-19 14:16:35 +03:00
parent 3e48b0e380
commit c1ad5af4a6
13 changed files with 205 additions and 274 deletions

View File

@ -25,7 +25,7 @@
//! for all lint attributes. //! for all lint attributes.
use self::TargetLint::*; use self::TargetLint::*;
use middle::privacy::ExportedItems; use middle::privacy::AccessLevels;
use middle::ty::{self, Ty}; use middle::ty::{self, Ty};
use session::{early_error, Session}; use session::{early_error, Session};
use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass}; use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass};
@ -277,8 +277,8 @@ pub struct LateContext<'a, 'tcx: 'a> {
/// The crate being checked. /// The crate being checked.
pub krate: &'a hir::Crate, pub krate: &'a hir::Crate,
/// Items exported from the crate being checked. /// Items accessible from the crate being checked.
pub exported_items: &'a ExportedItems, pub access_levels: &'a AccessLevels,
/// The store of registered lints. /// The store of registered lints.
lints: LintStore, lints: LintStore,
@ -564,7 +564,7 @@ impl<'a> EarlyContext<'a> {
impl<'a, 'tcx> LateContext<'a, 'tcx> { impl<'a, 'tcx> LateContext<'a, 'tcx> {
fn new(tcx: &'a ty::ctxt<'tcx>, fn new(tcx: &'a ty::ctxt<'tcx>,
krate: &'a hir::Crate, krate: &'a hir::Crate,
exported_items: &'a ExportedItems) -> LateContext<'a, 'tcx> { access_levels: &'a AccessLevels) -> LateContext<'a, 'tcx> {
// We want to own the lint store, so move it out of the session. // We want to own the lint store, so move it out of the session.
let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(),
LintStore::new()); LintStore::new());
@ -572,7 +572,7 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
LateContext { LateContext {
tcx: tcx, tcx: tcx,
krate: krate, krate: krate,
exported_items: exported_items, access_levels: access_levels,
lints: lint_store, lints: lint_store,
level_stack: vec![], level_stack: vec![],
node_levels: RefCell::new(FnvHashMap()), node_levels: RefCell::new(FnvHashMap()),
@ -1014,10 +1014,9 @@ impl LateLintPass for GatherNodeLevels {
/// Perform lint checking on a crate. /// Perform lint checking on a crate.
/// ///
/// Consumes the `lint_store` field of the `Session`. /// Consumes the `lint_store` field of the `Session`.
pub fn check_crate(tcx: &ty::ctxt, pub fn check_crate(tcx: &ty::ctxt, access_levels: &AccessLevels) {
exported_items: &ExportedItems) {
let krate = tcx.map.krate(); let krate = tcx.map.krate();
let mut cx = LateContext::new(tcx, krate, exported_items); let mut cx = LateContext::new(tcx, krate, access_levels);
// Visit the whole crate. // Visit the whole crate.
cx.with_lint_attrs(&krate.attrs, |cx| { cx.with_lint_attrs(&krate.attrs, |cx| {

View File

@ -19,7 +19,6 @@ use rustc_front::intravisit::{self, Visitor};
use middle::{def, pat_util, privacy, ty}; use middle::{def, pat_util, privacy, ty};
use middle::def_id::{DefId}; use middle::def_id::{DefId};
use lint; use lint;
use util::nodemap::NodeSet;
use std::collections::HashSet; use std::collections::HashSet;
use syntax::{ast, codemap}; use syntax::{ast, codemap};
@ -370,25 +369,10 @@ impl<'v> Visitor<'v> for LifeSeeder {
} }
fn create_and_seed_worklist(tcx: &ty::ctxt, fn create_and_seed_worklist(tcx: &ty::ctxt,
exported_items: &privacy::ExportedItems, access_levels: &privacy::AccessLevels,
reachable_symbols: &NodeSet,
krate: &hir::Crate) -> Vec<ast::NodeId> { krate: &hir::Crate) -> Vec<ast::NodeId> {
let mut worklist = Vec::new(); let mut worklist = Vec::new();
for (id, _) in &access_levels.map {
// Preferably, we would only need to seed the worklist with reachable
// symbols. However, since the set of reachable symbols differs
// depending on whether a crate is built as bin or lib, and we want
// the warning to be consistent, we also seed the worklist with
// exported symbols.
for id in exported_items {
worklist.push(*id);
}
for id in reachable_symbols {
// Reachable variants can be dead, because we warn about
// variants never constructed, not variants never used.
if let Some(ast_map::NodeVariant(..)) = tcx.map.find(*id) {
continue;
}
worklist.push(*id); worklist.push(*id);
} }
@ -408,12 +392,10 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
} }
fn find_live(tcx: &ty::ctxt, fn find_live(tcx: &ty::ctxt,
exported_items: &privacy::ExportedItems, access_levels: &privacy::AccessLevels,
reachable_symbols: &NodeSet,
krate: &hir::Crate) krate: &hir::Crate)
-> Box<HashSet<ast::NodeId>> { -> Box<HashSet<ast::NodeId>> {
let worklist = create_and_seed_worklist(tcx, exported_items, let worklist = create_and_seed_worklist(tcx, access_levels, krate);
reachable_symbols, krate);
let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist); let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist);
symbol_visitor.mark_live_symbols(); symbol_visitor.mark_live_symbols();
symbol_visitor.live_symbols symbol_visitor.live_symbols
@ -607,12 +589,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
} }
} }
pub fn check_crate(tcx: &ty::ctxt, pub fn check_crate(tcx: &ty::ctxt, access_levels: &privacy::AccessLevels) {
exported_items: &privacy::ExportedItems,
reachable_symbols: &NodeSet) {
let krate = tcx.map.krate(); let krate = tcx.map.krate();
let live_symbols = find_live(tcx, exported_items, let live_symbols = find_live(tcx, access_levels, krate);
reachable_symbols, krate);
let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols }; let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols };
intravisit::walk_crate(&mut visitor, krate); intravisit::walk_crate(&mut visitor, krate);
} }

View File

@ -17,20 +17,54 @@ pub use self::ImportUse::*;
pub use self::LastPrivate::*; pub use self::LastPrivate::*;
use middle::def_id::DefId; use middle::def_id::DefId;
use util::nodemap::{DefIdSet, NodeSet}; use util::nodemap::{DefIdSet, FnvHashMap};
/// A set of AST nodes exported by the crate. use std::hash::Hash;
pub type ExportedItems = NodeSet; use syntax::ast::NodeId;
// Accessibility levels, sorted in ascending order
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum AccessLevel {
// 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 exported. Its values can be obtained by other crates
// even if the type itseld is not nameable.
// FIXME: Mostly unimplemented. Only `type` aliases export items currently.
Reachable,
// Public items + items accessible to other crates with help of `pub use` reexports
Exported,
// Items accessible to other crates directly, without help of reexports
Public,
}
// Accessibility levels for reachable HIR nodes
#[derive(Clone)]
pub struct AccessLevels<Id = NodeId> {
pub map: FnvHashMap<Id, AccessLevel>
}
impl<Id: Hash + Eq> AccessLevels<Id> {
pub fn is_reachable(&self, id: Id) -> bool {
self.map.contains_key(&id)
}
pub fn is_exported(&self, id: Id) -> bool {
self.map.get(&id) >= Some(&AccessLevel::Exported)
}
pub fn is_public(&self, id: Id) -> bool {
self.map.get(&id) >= Some(&AccessLevel::Public)
}
}
impl<Id: Hash + Eq> Default for AccessLevels<Id> {
fn default() -> Self {
AccessLevels { map: Default::default() }
}
}
/// A set containing all exported definitions from external crates. /// A set containing all exported definitions from external crates.
/// The set does not contain any entries from local crates. /// The set does not contain any entries from local crates.
pub type ExternalExports = DefIdSet; pub type ExternalExports = DefIdSet;
/// A set of AST nodes that are fully public in the crate. This map is used for
/// documentation purposes (reexporting a private struct inlines the doc,
/// reexporting a public struct doesn't inline the doc).
pub type PublicItems = NodeSet;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum LastPrivate { pub enum LastPrivate {
LastMod(PrivateDep), LastMod(PrivateDep),

View File

@ -329,7 +329,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
// trait items are used from inlinable code through method call syntax or UFCS, or their // trait items are used from inlinable code through method call syntax or UFCS, or their
// trait is a lang item. // trait is a lang item.
struct CollectPrivateImplItemsVisitor<'a> { struct CollectPrivateImplItemsVisitor<'a> {
exported_items: &'a privacy::ExportedItems, access_levels: &'a privacy::AccessLevels,
worklist: &'a mut Vec<ast::NodeId>, worklist: &'a mut Vec<ast::NodeId>,
} }
@ -337,7 +337,7 @@ impl<'a, 'v> Visitor<'v> for CollectPrivateImplItemsVisitor<'a> {
fn visit_item(&mut self, item: &hir::Item) { fn visit_item(&mut self, item: &hir::Item) {
// We need only trait impls here, not inherent impls, and only non-exported ones // We need only trait impls here, not inherent impls, and only non-exported ones
if let hir::ItemImpl(_, _, _, Some(_), _, ref impl_items) = item.node { if let hir::ItemImpl(_, _, _, Some(_), _, ref impl_items) = item.node {
if !self.exported_items.contains(&item.id) { if !self.access_levels.is_reachable(item.id) {
for impl_item in impl_items { for impl_item in impl_items {
self.worklist.push(impl_item.id); self.worklist.push(impl_item.id);
} }
@ -347,7 +347,7 @@ impl<'a, 'v> Visitor<'v> for CollectPrivateImplItemsVisitor<'a> {
} }
pub fn find_reachable(tcx: &ty::ctxt, pub fn find_reachable(tcx: &ty::ctxt,
exported_items: &privacy::ExportedItems) access_levels: &privacy::AccessLevels)
-> NodeSet { -> NodeSet {
let mut reachable_context = ReachableContext::new(tcx); let mut reachable_context = ReachableContext::new(tcx);
@ -357,7 +357,7 @@ pub fn find_reachable(tcx: &ty::ctxt,
// If other crates link to us, they're going to expect to be able to // If other crates link to us, they're going to expect to be able to
// use the lang items, so we need to be sure to mark them as // use the lang items, so we need to be sure to mark them as
// exported. // exported.
for id in exported_items { for (id, _) in &access_levels.map {
reachable_context.worklist.push(*id); reachable_context.worklist.push(*id);
} }
for (_, item) in tcx.lang_items.items() { for (_, item) in tcx.lang_items.items() {
@ -369,7 +369,7 @@ pub fn find_reachable(tcx: &ty::ctxt,
} }
{ {
let mut collect_private_impl_items = CollectPrivateImplItemsVisitor { let mut collect_private_impl_items = CollectPrivateImplItemsVisitor {
exported_items: exported_items, access_levels: access_levels,
worklist: &mut reachable_context.worklist, worklist: &mut reachable_context.worklist,
}; };
tcx.map.krate().visit_all_items(&mut collect_private_impl_items); tcx.map.krate().visit_all_items(&mut collect_private_impl_items);

View File

@ -19,7 +19,7 @@ use metadata::cstore::LOCAL_CRATE;
use middle::def; use middle::def;
use middle::def_id::{CRATE_DEF_INDEX, DefId}; use middle::def_id::{CRATE_DEF_INDEX, DefId};
use middle::ty; use middle::ty;
use middle::privacy::PublicItems; use middle::privacy::AccessLevels;
use metadata::csearch; use metadata::csearch;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use syntax::codemap::{Span, DUMMY_SP}; use syntax::codemap::{Span, DUMMY_SP};
@ -73,7 +73,7 @@ struct Annotator<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>, tcx: &'a ty::ctxt<'tcx>,
index: &'a mut Index<'tcx>, index: &'a mut Index<'tcx>,
parent: Option<&'tcx Stability>, parent: Option<&'tcx Stability>,
export_map: &'a PublicItems, access_levels: &'a AccessLevels,
in_trait_impl: bool, in_trait_impl: bool,
in_enum: bool, in_enum: bool,
} }
@ -143,7 +143,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
} else { } else {
debug!("annotate: not found, parent = {:?}", self.parent); debug!("annotate: not found, parent = {:?}", self.parent);
let mut is_error = kind == AnnotationKind::Required && let mut is_error = kind == AnnotationKind::Required &&
self.export_map.contains(&id) && self.access_levels.is_reachable(id) &&
!self.tcx.sess.opts.test; !self.tcx.sess.opts.test;
if let Some(stab) = self.parent { if let Some(stab) = self.parent {
if stab.level.is_unstable() { if stab.level.is_unstable() {
@ -266,12 +266,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
impl<'tcx> Index<'tcx> { impl<'tcx> Index<'tcx> {
/// Construct the stability index for a crate being compiled. /// Construct the stability index for a crate being compiled.
pub fn build(&mut self, tcx: &ty::ctxt<'tcx>, krate: &'tcx Crate, export_map: &PublicItems) { pub fn build(&mut self, tcx: &ty::ctxt<'tcx>, krate: &Crate, access_levels: &AccessLevels) {
let mut annotator = Annotator { let mut annotator = Annotator {
tcx: tcx, tcx: tcx,
index: self, index: self,
parent: None, parent: None,
export_map: export_map, access_levels: access_levels,
in_trait_impl: false, in_trait_impl: false,
in_enum: false, in_enum: false,
}; };

View File

@ -104,14 +104,12 @@ pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0;
/// produced by the driver and fed to trans and later passes. /// produced by the driver and fed to trans and later passes.
pub struct CrateAnalysis<'a> { pub struct CrateAnalysis<'a> {
pub export_map: ExportMap, pub export_map: ExportMap,
pub exported_items: middle::privacy::ExportedItems, pub access_levels: middle::privacy::AccessLevels,
pub public_items: middle::privacy::PublicItems,
pub reachable: NodeSet, pub reachable: NodeSet,
pub name: &'a str, pub name: &'a str,
pub glob_map: Option<GlobMap>, pub glob_map: Option<GlobMap>,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum DtorKind { pub enum DtorKind {
NoDtor, NoDtor,

View File

@ -746,7 +746,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
"const checking", "const checking",
|| middle::check_const::check_crate(tcx)); || middle::check_const::check_crate(tcx));
let (exported_items, public_items) = let access_levels =
time(time_passes, "privacy checking", || { time(time_passes, "privacy checking", || {
rustc_privacy::check_crate(tcx, rustc_privacy::check_crate(tcx,
&export_map, &export_map,
@ -755,7 +755,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
// Do not move this check past lint // Do not move this check past lint
time(time_passes, "stability index", || { time(time_passes, "stability index", || {
tcx.stability.borrow_mut().build(tcx, krate, &exported_items) tcx.stability.borrow_mut().build(tcx, krate, &access_levels)
}); });
time(time_passes, time(time_passes,
@ -807,12 +807,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
let reachable_map = let reachable_map =
time(time_passes, time(time_passes,
"reachability checking", "reachability checking",
|| reachable::find_reachable(tcx, &exported_items)); || reachable::find_reachable(tcx, &access_levels));
time(time_passes, "death checking", || { time(time_passes, "death checking", || {
middle::dead::check_crate(tcx, middle::dead::check_crate(tcx, &access_levels);
&exported_items,
&reachable_map)
}); });
let ref lib_features_used = let ref lib_features_used =
@ -827,7 +825,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
time(time_passes, time(time_passes,
"lint checking", "lint checking",
|| lint::check_crate(tcx, &exported_items)); || lint::check_crate(tcx, &access_levels));
// The above three passes generate errors w/o aborting // The above three passes generate errors w/o aborting
tcx.sess.abort_if_errors(); tcx.sess.abort_if_errors();
@ -836,8 +834,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
mir_map, mir_map,
ty::CrateAnalysis { ty::CrateAnalysis {
export_map: export_map, export_map: export_map,
exported_items: exported_items, access_levels: access_levels,
public_items: public_items,
reachable: reachable_map, reachable: reachable_map,
name: name, name: name,
glob_map: glob_map, glob_map: glob_map,

View File

@ -301,8 +301,8 @@ impl MissingDoc {
// Only check publicly-visible items, using the result from the privacy pass. // Only check publicly-visible items, using the result from the privacy pass.
// It's an option so the crate root can also use this function (it doesn't // It's an option so the crate root can also use this function (it doesn't
// have a NodeId). // have a NodeId).
if let Some(ref id) = id { if let Some(id) = id {
if !cx.exported_items.contains(id) { if !cx.access_levels.is_exported(id) {
return; return;
} }
} }
@ -470,7 +470,7 @@ impl LintPass for MissingCopyImplementations {
impl LateLintPass for MissingCopyImplementations { impl LateLintPass for MissingCopyImplementations {
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
if !cx.exported_items.contains(&item.id) { if !cx.access_levels.is_reachable(item.id) {
return; return;
} }
let (def, ty) = match item.node { let (def, ty) = match item.node {
@ -534,7 +534,7 @@ impl LintPass for MissingDebugImplementations {
impl LateLintPass for MissingDebugImplementations { impl LateLintPass for MissingDebugImplementations {
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
if !cx.exported_items.contains(&item.id) { if !cx.access_levels.is_reachable(item.id) {
return; return;
} }
@ -987,7 +987,7 @@ impl LateLintPass for InvalidNoMangleItems {
match it.node { match it.node {
hir::ItemFn(..) => { hir::ItemFn(..) => {
if attr::contains_name(&it.attrs, "no_mangle") && if attr::contains_name(&it.attrs, "no_mangle") &&
!cx.exported_items.contains(&it.id) { !cx.access_levels.is_reachable(it.id) {
let msg = format!("function {} is marked #[no_mangle], but not exported", let msg = format!("function {} is marked #[no_mangle], but not exported",
it.name); it.name);
cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg); cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg);
@ -995,7 +995,7 @@ impl LateLintPass for InvalidNoMangleItems {
}, },
hir::ItemStatic(..) => { hir::ItemStatic(..) => {
if attr::contains_name(&it.attrs, "no_mangle") && if attr::contains_name(&it.attrs, "no_mangle") &&
!cx.exported_items.contains(&it.id) { !cx.access_levels.is_reachable(it.id) {
let msg = format!("static {} is marked #[no_mangle], but not exported", let msg = format!("static {} is marked #[no_mangle], but not exported",
it.name); it.name);
cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg); cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg);

View File

@ -32,6 +32,7 @@ extern crate rustc_front;
use self::PrivacyResult::*; use self::PrivacyResult::*;
use self::FieldName::*; use self::FieldName::*;
use std::cmp;
use std::mem::replace; use std::mem::replace;
use rustc_front::hir; use rustc_front::hir;
@ -39,12 +40,13 @@ use rustc_front::intravisit::{self, Visitor};
use rustc::middle::def; use rustc::middle::def;
use rustc::middle::def_id::DefId; use rustc::middle::def_id::DefId;
use rustc::middle::privacy::{AccessLevel, AccessLevels};
use rustc::middle::privacy::ImportUse::*; use rustc::middle::privacy::ImportUse::*;
use rustc::middle::privacy::LastPrivate::*; use rustc::middle::privacy::LastPrivate::*;
use rustc::middle::privacy::PrivateDep::*; use rustc::middle::privacy::PrivateDep::*;
use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems}; use rustc::middle::privacy::ExternalExports;
use rustc::middle::ty::{self, Ty}; use rustc::middle::ty::{self, Ty};
use rustc::util::nodemap::{NodeMap, NodeSet}; use rustc::util::nodemap::NodeMap;
use rustc::front::map as ast_map; use rustc::front::map as ast_map;
use syntax::ast; use syntax::ast;
@ -159,64 +161,57 @@ struct EmbargoVisitor<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>, tcx: &'a ty::ctxt<'tcx>,
export_map: &'a def::ExportMap, export_map: &'a def::ExportMap,
// This flag is an indicator of whether the previous item in the // Accessibility levels for reachable nodes
// hierarchical chain was exported or not. This is the indicator of whether access_levels: AccessLevels,
// children should be exported as well. Note that this can flip from false // Previous accessibility level, None means unreachable
// to true if a reexported module is entered (or an action similar). prev_level: Option<AccessLevel>,
prev_exported: bool, // Have something changed in the level map?
changed: bool,
// This is a list of all exported items in the AST. An exported item is any
// function/method/item which is usable by external crates. This essentially
// means that the result is "public all the way down", but the "path down"
// may jump across private boundaries through reexport statements or type aliases.
exported_items: ExportedItems,
// Items that are directly public without help of reexports or type aliases.
// These two fields are closely related to one another in that they are only
// used for generation of the `public_items` set, not for privacy checking at
// all. Invariant: at any moment public items are a subset of exported items.
public_items: PublicItems,
prev_public: bool,
} }
impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
// Returns tuple (is_public, is_exported) for a type fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
fn is_public_exported_ty(&self, ty: &hir::Ty) -> (bool, bool) {
if let hir::TyPath(..) = ty.node { if let hir::TyPath(..) = ty.node {
match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() { match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => { def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {
(true, true) Some(AccessLevel::Public)
} }
def => { def => {
if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) { if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) {
(self.public_items.contains(&node_id), self.get(node_id)
self.exported_items.contains(&node_id))
} else { } else {
(true, true) Some(AccessLevel::Public)
} }
} }
} }
} else { } else {
(true, true) Some(AccessLevel::Public)
} }
} }
// Returns tuple (is_public, is_exported) for a trait fn trait_level(&self, trait_ref: &hir::TraitRef) -> Option<AccessLevel> {
fn is_public_exported_trait(&self, trait_ref: &hir::TraitRef) -> (bool, bool) {
let did = self.tcx.trait_ref_to_def_id(trait_ref); let did = self.tcx.trait_ref_to_def_id(trait_ref);
if let Some(node_id) = self.tcx.map.as_local_node_id(did) { if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
(self.public_items.contains(&node_id), self.exported_items.contains(&node_id)) self.get(node_id)
} else { } else {
(true, true) Some(AccessLevel::Public)
} }
} }
fn maybe_insert_id(&mut self, id: ast::NodeId) { fn get(&self, id: ast::NodeId) -> Option<AccessLevel> {
if self.prev_public { self.access_levels.map.get(&id).cloned()
self.public_items.insert(id); }
}
if self.prev_exported { // Updates node level and returns the updated level
self.exported_items.insert(id); fn update(&mut self, id: ast::NodeId, level: Option<AccessLevel>) -> Option<AccessLevel> {
let old_level = self.get(id);
// Accessibility levels can only grow
if level > old_level {
self.access_levels.map.insert(id, level.unwrap());
self.changed = true;
level
} else {
old_level
} }
} }
} }
@ -227,187 +222,126 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
fn visit_nested_item(&mut self, item: hir::ItemId) { fn visit_nested_item(&mut self, item: hir::ItemId) {
self.visit_item(self.tcx.map.expect_item(item.id)) self.visit_item(self.tcx.map.expect_item(item.id))
} }
fn visit_item(&mut self, item: &hir::Item) { fn visit_item(&mut self, item: &hir::Item) {
let orig_all_public = self.prev_public; let inherited_item_level = match item.node {
let orig_all_exported = self.prev_exported; // Impls inherit level from their types and traits
match item.node { hir::ItemImpl(_, _, _, None, ref ty, _) => {
// impls/extern blocks do not break the "public chain" because they self.ty_level(&ty)
// cannot have visibility qualifiers on them anyway. Impls are also not }
// added to public/exported sets based on inherited publicity. hir::ItemImpl(_, _, _, Some(ref trait_ref), ref ty, _) => {
hir::ItemImpl(..) | hir::ItemDefaultImpl(..) => {} cmp::min(self.ty_level(&ty), self.trait_level(trait_ref))
}
hir::ItemDefaultImpl(_, ref trait_ref) => {
self.trait_level(trait_ref)
}
// Foreign mods inherit level from parents
hir::ItemForeignMod(..) => { hir::ItemForeignMod(..) => {
self.maybe_insert_id(item.id); self.prev_level
} }
// Other `pub` items inherit levels from parents
// Private by default, hence we only retain the "public chain" if
// `pub` is explicitly listed.
_ => { _ => {
self.prev_public = self.prev_public && item.vis == hir::Public; if item.vis == hir::Public { self.prev_level } else { None }
self.prev_exported = (self.prev_exported && item.vis == hir::Public) ||
self.exported_items.contains(&item.id);
self.maybe_insert_id(item.id);
} }
} };
// Update id of the item itself
let item_level = self.update(item.id, inherited_item_level);
// Update ids of nested things
match item.node { match item.node {
// Enum variants inherit from their parent, so if the enum is
// public all variants are public
hir::ItemEnum(ref def, _) => { hir::ItemEnum(ref def, _) => {
for variant in &def.variants { for variant in &def.variants {
self.maybe_insert_id(variant.node.data.id()); let variant_level = self.update(variant.node.data.id(), item_level);
for field in variant.node.data.fields() { for field in variant.node.data.fields() {
// Variant fields are always public self.update(field.node.id, variant_level);
self.maybe_insert_id(field.node.id);
} }
} }
} }
hir::ItemImpl(_, _, _, None, _, ref impl_items) => {
// Inherent impls for public/exported types and their public items are public/exported
hir::ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
let (public_ty, exported_ty) = self.is_public_exported_ty(&ty);
if public_ty {
self.public_items.insert(item.id);
}
if exported_ty {
self.exported_items.insert(item.id);
}
for impl_item in impl_items { for impl_item in impl_items {
if impl_item.vis == hir::Public { if impl_item.vis == hir::Public {
if public_ty { self.update(impl_item.id, item_level);
self.public_items.insert(impl_item.id);
}
if exported_ty {
self.exported_items.insert(impl_item.id);
}
} }
} }
} }
hir::ItemImpl(_, _, _, Some(_), _, ref impl_items) => {
// Trait impl and its items are public/exported if both the self type and the trait
// of this impl are public/exported
hir::ItemImpl(_, _, _, Some(ref trait_ref), ref ty, ref impl_items) => {
let (public_ty, exported_ty) = self.is_public_exported_ty(&ty);
let (public_trait, exported_trait) = self.is_public_exported_trait(trait_ref);
if public_ty && public_trait {
self.public_items.insert(item.id);
}
if exported_ty && exported_trait {
self.exported_items.insert(item.id);
}
for impl_item in impl_items { for impl_item in impl_items {
if public_ty && public_trait { self.update(impl_item.id, item_level);
self.public_items.insert(impl_item.id);
}
if exported_ty && exported_trait {
self.exported_items.insert(impl_item.id);
}
} }
} }
// Default trait impls are public/exported for public/exported traits
hir::ItemDefaultImpl(_, ref trait_ref) => {
let (public_trait, exported_trait) = self.is_public_exported_trait(trait_ref);
if public_trait {
self.public_items.insert(item.id);
}
if exported_trait {
self.exported_items.insert(item.id);
}
}
// Default methods on traits are all public/exported so long as the trait
// is public/exported
hir::ItemTrait(_, _, _, ref trait_items) => { hir::ItemTrait(_, _, _, ref trait_items) => {
for trait_item in trait_items { for trait_item in trait_items {
self.maybe_insert_id(trait_item.id); self.update(trait_item.id, item_level);
} }
} }
// Struct constructors are public if the struct is all public.
hir::ItemStruct(ref def, _) => { hir::ItemStruct(ref def, _) => {
if !def.is_struct() { if !def.is_struct() {
self.maybe_insert_id(def.id()); self.update(def.id(), item_level);
} }
for field in def.fields() { for field in def.fields() {
// Struct fields can be public or private, so lets check
if field.node.kind.visibility() == hir::Public { if field.node.kind.visibility() == hir::Public {
self.maybe_insert_id(field.node.id); self.update(field.node.id, item_level);
} }
} }
} }
hir::ItemForeignMod(ref foreign_mod) => {
hir::ItemTy(ref ty, _) if self.prev_exported => { for foreign_item in &foreign_mod.items {
if foreign_item.vis == hir::Public {
self.update(foreign_item.id, item_level);
}
}
}
hir::ItemTy(ref ty, _) if item_level.is_some() => {
if let hir::TyPath(..) = ty.node { if let hir::TyPath(..) = ty.node {
match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() { match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {}, def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {},
def => { def => {
if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) { if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) {
self.exported_items.insert(node_id); self.update(node_id, Some(AccessLevel::Reachable));
} }
} }
} }
} }
} }
hir::ItemForeignMod(ref foreign_mod) => {
for foreign_item in &foreign_mod.items {
let public = self.prev_public && foreign_item.vis == hir::Public;
let exported = (self.prev_exported && foreign_item.vis == hir::Public) ||
self.exported_items.contains(&foreign_item.id);
if public {
self.public_items.insert(foreign_item.id);
}
if exported {
self.exported_items.insert(foreign_item.id);
}
}
}
_ => {} _ => {}
} }
let orig_level = self.prev_level;
self.prev_level = item_level;
intravisit::walk_item(self, item); intravisit::walk_item(self, item);
self.prev_public = orig_all_public; self.prev_level = orig_level;
self.prev_exported = orig_all_exported;
} }
fn visit_block(&mut self, b: &'v hir::Block) { fn visit_block(&mut self, b: &'v hir::Block) {
let orig_all_public = replace(&mut self.prev_public, false); let orig_level = replace(&mut self.prev_level, None);
let orig_all_exported = replace(&mut self.prev_exported, false);
// Blocks can have exported and public items, for example impls, but they always // Blocks can have public items, for example impls, but they always
// start as non-public and non-exported regardless of publicity of a function, // start as completely private regardless of publicity of a function,
// constant, type, field, etc. in which this block resides // constant, type, field, etc. in which this block resides
intravisit::walk_block(self, b); intravisit::walk_block(self, b);
self.prev_public = orig_all_public; self.prev_level = orig_level;
self.prev_exported = orig_all_exported;
} }
fn visit_mod(&mut self, m: &hir::Mod, _sp: Span, id: ast::NodeId) { fn visit_mod(&mut self, m: &hir::Mod, _sp: Span, id: ast::NodeId) {
// This code is here instead of in visit_item so that the // This code is here instead of in visit_item so that the
// crate module gets processed as well. // crate module gets processed as well.
if self.prev_exported { if self.prev_level.is_some() {
assert!(self.export_map.contains_key(&id), "wut {}", id); for export in self.export_map.get(&id).expect("module isn't found in export map") {
for export in self.export_map.get(&id).unwrap() {
if let Some(node_id) = self.tcx.map.as_local_node_id(export.def_id) { if let Some(node_id) = self.tcx.map.as_local_node_id(export.def_id) {
self.exported_items.insert(node_id); self.update(node_id, Some(AccessLevel::Exported));
} }
} }
} }
intravisit::walk_mod(self, m)
intravisit::walk_mod(self, m);
} }
fn visit_macro_def(&mut self, md: &'v hir::MacroDef) { fn visit_macro_def(&mut self, md: &'v hir::MacroDef) {
self.maybe_insert_id(md.id); self.update(md.id, Some(AccessLevel::Public));
} }
} }
@ -1169,8 +1103,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
struct VisiblePrivateTypesVisitor<'a, 'tcx: 'a> { struct VisiblePrivateTypesVisitor<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>, tcx: &'a ty::ctxt<'tcx>,
exported_items: &'a ExportedItems, access_levels: &'a AccessLevels,
public_items: &'a PublicItems,
in_variant: bool, in_variant: bool,
} }
@ -1210,7 +1143,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
fn trait_is_public(&self, trait_id: ast::NodeId) -> bool { fn trait_is_public(&self, trait_id: ast::NodeId) -> bool {
// FIXME: this would preferably be using `exported_items`, but all // FIXME: this would preferably be using `exported_items`, but all
// traits are exported currently (see `EmbargoVisitor.exported_trait`) // traits are exported currently (see `EmbargoVisitor.exported_trait`)
self.public_items.contains(&trait_id) self.access_levels.is_public(trait_id)
} }
fn check_ty_param_bound(&self, fn check_ty_param_bound(&self,
@ -1226,7 +1159,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
} }
fn item_is_public(&self, id: &ast::NodeId, vis: hir::Visibility) -> bool { fn item_is_public(&self, id: &ast::NodeId, vis: hir::Visibility) -> bool {
self.exported_items.contains(id) || vis == hir::Public self.access_levels.is_reachable(*id) || vis == hir::Public
} }
} }
@ -1332,7 +1265,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
match impl_item.node { match impl_item.node {
hir::ImplItemKind::Const(..) | hir::ImplItemKind::Const(..) |
hir::ImplItemKind::Method(..) => { hir::ImplItemKind::Method(..) => {
self.exported_items.contains(&impl_item.id) self.access_levels.is_reachable(impl_item.id)
} }
hir::ImplItemKind::Type(_) => false, hir::ImplItemKind::Type(_) => false,
} }
@ -1461,7 +1394,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
} }
fn visit_foreign_item(&mut self, item: &hir::ForeignItem) { fn visit_foreign_item(&mut self, item: &hir::ForeignItem) {
if self.exported_items.contains(&item.id) { if self.access_levels.is_reachable(item.id) {
intravisit::walk_foreign_item(self, item) intravisit::walk_foreign_item(self, item)
} }
} }
@ -1479,7 +1412,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
} }
fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics, item_id: ast::NodeId) { fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics, item_id: ast::NodeId) {
if self.exported_items.contains(&v.node.data.id()) { if self.access_levels.is_reachable(v.node.data.id()) {
self.in_variant = true; self.in_variant = true;
intravisit::walk_variant(self, v, g, item_id); intravisit::walk_variant(self, v, g, item_id);
self.in_variant = false; self.in_variant = false;
@ -1509,7 +1442,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
pub fn check_crate(tcx: &ty::ctxt, pub fn check_crate(tcx: &ty::ctxt,
export_map: &def::ExportMap, export_map: &def::ExportMap,
external_exports: ExternalExports) external_exports: ExternalExports)
-> (ExportedItems, PublicItems) { -> AccessLevels {
let krate = tcx.map.krate(); let krate = tcx.map.krate();
// Sanity check to make sure that all privacy usage and controls are // Sanity check to make sure that all privacy usage and controls are
@ -1544,33 +1477,31 @@ pub fn check_crate(tcx: &ty::ctxt,
// items which are reachable from external crates based on visibility. // items which are reachable from external crates based on visibility.
let mut visitor = EmbargoVisitor { let mut visitor = EmbargoVisitor {
tcx: tcx, tcx: tcx,
exported_items: NodeSet(),
public_items: NodeSet(),
export_map: export_map, export_map: export_map,
prev_exported: true, access_levels: Default::default(),
prev_public: true, prev_level: Some(AccessLevel::Public),
changed: false,
}; };
visitor.exported_items.insert(ast::CRATE_NODE_ID);
visitor.public_items.insert(ast::CRATE_NODE_ID);
loop { loop {
let before = (visitor.exported_items.len(), visitor.public_items.len());
intravisit::walk_crate(&mut visitor, krate); intravisit::walk_crate(&mut visitor, krate);
let after = (visitor.exported_items.len(), visitor.public_items.len()); if visitor.changed {
if after == before { visitor.changed = false;
} else {
break break
} }
} }
visitor.update(ast::CRATE_NODE_ID, Some(AccessLevel::Public));
let EmbargoVisitor { exported_items, public_items, .. } = visitor; let EmbargoVisitor { access_levels, .. } = visitor;
{ {
let mut visitor = VisiblePrivateTypesVisitor { let mut visitor = VisiblePrivateTypesVisitor {
tcx: tcx, tcx: tcx,
exported_items: &exported_items, access_levels: &access_levels,
public_items: &public_items,
in_variant: false, in_variant: false,
}; };
intravisit::walk_crate(&mut visitor, krate); intravisit::walk_crate(&mut visitor, krate);
} }
return (exported_items, public_items);
access_levels
} }

View File

@ -13,10 +13,10 @@ use rustc_lint;
use rustc_driver::{driver, target_features}; use rustc_driver::{driver, target_features};
use rustc::session::{self, config}; use rustc::session::{self, config};
use rustc::middle::def_id::DefId; use rustc::middle::def_id::DefId;
use rustc::middle::privacy::AccessLevels;
use rustc::middle::ty; use rustc::middle::ty;
use rustc::front::map as hir_map; use rustc::front::map as hir_map;
use rustc::lint; use rustc::lint;
use rustc::util::nodemap::DefIdSet;
use rustc_trans::back::link; use rustc_trans::back::link;
use rustc_resolve as resolve; use rustc_resolve as resolve;
use rustc_front::lowering::{lower_crate, LoweringContext}; use rustc_front::lowering::{lower_crate, LoweringContext};
@ -77,8 +77,7 @@ impl<'b, 'tcx> DocContext<'b, 'tcx> {
} }
pub struct CrateAnalysis { pub struct CrateAnalysis {
pub exported_items: DefIdSet, pub access_levels: AccessLevels<DefId>,
pub public_items: DefIdSet,
pub external_paths: ExternalPaths, pub external_paths: ExternalPaths,
pub external_typarams: RefCell<Option<HashMap<DefId, String>>>, pub external_typarams: RefCell<Option<HashMap<DefId, String>>>,
pub inlined: RefCell<Option<HashSet<DefId>>>, pub inlined: RefCell<Option<HashSet<DefId>>>,
@ -147,18 +146,15 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
&name, &name,
resolve::MakeGlobMap::No, resolve::MakeGlobMap::No,
|tcx, _, analysis| { |tcx, _, analysis| {
let ty::CrateAnalysis { exported_items, public_items, .. } = analysis; let ty::CrateAnalysis { access_levels, .. } = analysis;
// Convert from a NodeId set to a DefId set since we don't always have easy access // Convert from a NodeId set to a DefId set since we don't always have easy access
// to the map from defid -> nodeid // to the map from defid -> nodeid
let exported_items: DefIdSet = let access_levels = AccessLevels {
exported_items.into_iter() map: access_levels.map.into_iter()
.map(|n| tcx.map.local_def_id(n)) .map(|(k, v)| (tcx.map.local_def_id(k), v))
.collect(); .collect()
let public_items: DefIdSet = };
public_items.into_iter()
.map(|n| tcx.map.local_def_id(n))
.collect();
let ctxt = DocContext { let ctxt = DocContext {
map: &tcx.map, map: &tcx.map,
@ -174,8 +170,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
debug!("crate: {:?}", ctxt.map.krate()); debug!("crate: {:?}", ctxt.map.krate());
let mut analysis = CrateAnalysis { let mut analysis = CrateAnalysis {
exported_items: exported_items, access_levels: access_levels,
public_items: public_items,
external_paths: RefCell::new(None), external_paths: RefCell::new(None),
external_typarams: RefCell::new(None), external_typarams: RefCell::new(None),
inlined: RefCell::new(None), inlined: RefCell::new(None),

View File

@ -56,8 +56,8 @@ use serialize::json::{self, ToJson};
use syntax::{abi, ast}; use syntax::{abi, ast};
use rustc::metadata::cstore::LOCAL_CRATE; use rustc::metadata::cstore::LOCAL_CRATE;
use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::middle::privacy::AccessLevels;
use rustc::middle::stability; use rustc::middle::stability;
use rustc::util::nodemap::DefIdSet;
use rustc_front::hir; use rustc_front::hir;
use clean::{self, SelfTy}; use clean::{self, SelfTy};
@ -244,7 +244,7 @@ pub struct Cache {
search_index: Vec<IndexItem>, search_index: Vec<IndexItem>,
privmod: bool, privmod: bool,
remove_priv: bool, remove_priv: bool,
public_items: DefIdSet, access_levels: AccessLevels<DefId>,
deref_trait_did: Option<DefId>, deref_trait_did: Option<DefId>,
// In rare case where a structure is defined in one module but implemented // In rare case where a structure is defined in one module but implemented
@ -415,8 +415,8 @@ pub fn run(mut krate: clean::Crate,
// Crawl the crate to build various caches used for the output // Crawl the crate to build various caches used for the output
let analysis = ::ANALYSISKEY.with(|a| a.clone()); let analysis = ::ANALYSISKEY.with(|a| a.clone());
let analysis = analysis.borrow(); let analysis = analysis.borrow();
let public_items = analysis.as_ref().map(|a| a.public_items.clone()); let access_levels = analysis.as_ref().map(|a| a.access_levels.clone());
let public_items = public_items.unwrap_or(DefIdSet()); let access_levels = access_levels.unwrap_or(Default::default());
let paths: HashMap<DefId, (Vec<String>, ItemType)> = let paths: HashMap<DefId, (Vec<String>, ItemType)> =
analysis.as_ref().map(|a| { analysis.as_ref().map(|a| {
let paths = a.external_paths.borrow_mut().take().unwrap(); let paths = a.external_paths.borrow_mut().take().unwrap();
@ -435,7 +435,7 @@ pub fn run(mut krate: clean::Crate,
primitive_locations: HashMap::new(), primitive_locations: HashMap::new(),
remove_priv: cx.passes.contains("strip-private"), remove_priv: cx.passes.contains("strip-private"),
privmod: false, privmod: false,
public_items: public_items, access_levels: access_levels,
orphan_methods: Vec::new(), orphan_methods: Vec::new(),
traits: mem::replace(&mut krate.external_traits, HashMap::new()), traits: mem::replace(&mut krate.external_traits, HashMap::new()),
deref_trait_did: analysis.as_ref().and_then(|a| a.deref_trait_did), deref_trait_did: analysis.as_ref().and_then(|a| a.deref_trait_did),
@ -1053,7 +1053,7 @@ impl DocFolder for Cache {
if if
!self.paths.contains_key(&item.def_id) || !self.paths.contains_key(&item.def_id) ||
!item.def_id.is_local() || !item.def_id.is_local() ||
self.public_items.contains(&item.def_id) self.access_levels.is_public(item.def_id)
{ {
self.paths.insert(item.def_id, self.paths.insert(item.def_id,
(self.stack.clone(), shortty(&item))); (self.stack.clone(), shortty(&item)));

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use rustc::middle::def_id::DefId;
use rustc::middle::privacy::AccessLevels;
use rustc::util::nodemap::DefIdSet; use rustc::util::nodemap::DefIdSet;
use std::cmp; use std::cmp;
use std::string::String; use std::string::String;
@ -96,13 +98,13 @@ pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult {
let analysis = super::ANALYSISKEY.with(|a| a.clone()); let analysis = super::ANALYSISKEY.with(|a| a.clone());
let analysis = analysis.borrow(); let analysis = analysis.borrow();
let analysis = analysis.as_ref().unwrap(); let analysis = analysis.as_ref().unwrap();
let exported_items = analysis.exported_items.clone(); let access_levels = analysis.access_levels.clone();
// strip all private items // strip all private items
{ {
let mut stripper = Stripper { let mut stripper = Stripper {
retained: &mut retained, retained: &mut retained,
exported_items: &exported_items, access_levels: &access_levels,
}; };
krate = stripper.fold_crate(krate); krate = stripper.fold_crate(krate);
} }
@ -117,7 +119,7 @@ pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult {
struct Stripper<'a> { struct Stripper<'a> {
retained: &'a mut DefIdSet, retained: &'a mut DefIdSet,
exported_items: &'a DefIdSet, access_levels: &'a AccessLevels<DefId>,
} }
impl<'a> fold::DocFolder for Stripper<'a> { impl<'a> fold::DocFolder for Stripper<'a> {
@ -130,18 +132,14 @@ impl<'a> fold::DocFolder for Stripper<'a> {
clean::VariantItem(..) | clean::MethodItem(..) | clean::VariantItem(..) | clean::MethodItem(..) |
clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) => { clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) => {
if i.def_id.is_local() { if i.def_id.is_local() {
if !self.exported_items.contains(&i.def_id) { if !self.access_levels.is_exported(i.def_id) {
return None;
}
// Traits are in exported_items even when they're totally private.
if i.is_trait() && i.visibility != Some(hir::Public) {
return None; return None;
} }
} }
} }
clean::ConstantItem(..) => { clean::ConstantItem(..) => {
if i.def_id.is_local() && !self.exported_items.contains(&i.def_id) { if i.def_id.is_local() && !self.access_levels.is_exported(i.def_id) {
return None; return None;
} }
} }
@ -168,7 +166,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
clean::ImplItem(clean::Impl{ clean::ImplItem(clean::Impl{
for_: clean::ResolvedPath{ did, .. }, .. for_: clean::ResolvedPath{ did, .. }, ..
}) => { }) => {
if did.is_local() && !self.exported_items.contains(&did) { if did.is_local() && !self.access_levels.is_exported(did) {
return None; return None;
} }
} }

View File

@ -214,7 +214,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
let analysis = match self.analysis { let analysis = match self.analysis {
Some(analysis) => analysis, None => return false Some(analysis) => analysis, None => return false
}; };
if !please_inline && analysis.public_items.contains(&def) { if !please_inline && analysis.access_levels.is_public(def) {
return false return false
} }
if !self.view_item_stack.insert(def_node_id) { return false } if !self.view_item_stack.insert(def_node_id) { return false }