Skip to content

Changes to data produced by privacy pass #29822

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
//! for all lint attributes.
use self::TargetLint::*;

use middle::privacy::ExportedItems;
use middle::privacy::AccessLevels;
use middle::ty::{self, Ty};
use session::{early_error, Session};
use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass};
Expand Down Expand Up @@ -277,8 +277,8 @@ pub struct LateContext<'a, 'tcx: 'a> {
/// The crate being checked.
pub krate: &'a hir::Crate,

/// Items exported from the crate being checked.
pub exported_items: &'a ExportedItems,
/// Items accessible from the crate being checked.
pub access_levels: &'a AccessLevels,

/// The store of registered lints.
lints: LintStore,
Expand Down Expand Up @@ -564,15 +564,15 @@ impl<'a> EarlyContext<'a> {
impl<'a, 'tcx> LateContext<'a, 'tcx> {
fn new(tcx: &'a ty::ctxt<'tcx>,
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.
let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(),
LintStore::new());

LateContext {
tcx: tcx,
krate: krate,
exported_items: exported_items,
access_levels: access_levels,
lints: lint_store,
level_stack: vec![],
node_levels: RefCell::new(FnvHashMap()),
Expand Down Expand Up @@ -1014,10 +1014,9 @@ impl LateLintPass for GatherNodeLevels {
/// Perform lint checking on a crate.
///
/// Consumes the `lint_store` field of the `Session`.
pub fn check_crate(tcx: &ty::ctxt,
exported_items: &ExportedItems) {
pub fn check_crate(tcx: &ty::ctxt, access_levels: &AccessLevels) {
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.
cx.with_lint_attrs(&krate.attrs, |cx| {
Expand Down
33 changes: 6 additions & 27 deletions src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use rustc_front::intravisit::{self, Visitor};
use middle::{def, pat_util, privacy, ty};
use middle::def_id::{DefId};
use lint;
use util::nodemap::NodeSet;

use std::collections::HashSet;
use syntax::{ast, codemap};
Expand Down Expand Up @@ -370,25 +369,10 @@ impl<'v> Visitor<'v> for LifeSeeder {
}

fn create_and_seed_worklist(tcx: &ty::ctxt,
exported_items: &privacy::ExportedItems,
reachable_symbols: &NodeSet,
access_levels: &privacy::AccessLevels,
krate: &hir::Crate) -> Vec<ast::NodeId> {
let mut worklist = Vec::new();

// 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;
}
for (id, _) in &access_levels.map {
worklist.push(*id);
}

Expand All @@ -408,12 +392,10 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
}

fn find_live(tcx: &ty::ctxt,
exported_items: &privacy::ExportedItems,
reachable_symbols: &NodeSet,
access_levels: &privacy::AccessLevels,
krate: &hir::Crate)
-> Box<HashSet<ast::NodeId>> {
let worklist = create_and_seed_worklist(tcx, exported_items,
reachable_symbols, krate);
let worklist = create_and_seed_worklist(tcx, access_levels, krate);
let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist);
symbol_visitor.mark_live_symbols();
symbol_visitor.live_symbols
Expand Down Expand Up @@ -607,12 +589,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
}
}

pub fn check_crate(tcx: &ty::ctxt,
exported_items: &privacy::ExportedItems,
reachable_symbols: &NodeSet) {
pub fn check_crate(tcx: &ty::ctxt, access_levels: &privacy::AccessLevels) {
let krate = tcx.map.krate();
let live_symbols = find_live(tcx, exported_items,
reachable_symbols, krate);
let live_symbols = find_live(tcx, access_levels, krate);
let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols };
intravisit::walk_crate(&mut visitor, krate);
}
50 changes: 42 additions & 8 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,54 @@ pub use self::ImportUse::*;
pub use self::LastPrivate::*;

use middle::def_id::DefId;
use util::nodemap::{DefIdSet, NodeSet};
use util::nodemap::{DefIdSet, FnvHashMap};

/// A set of AST nodes exported by the crate.
pub type ExportedItems = NodeSet;
use std::hash::Hash;
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.
/// The set does not contain any entries from local crates.
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)]
pub enum LastPrivate {
LastMod(PrivateDep),
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/middle/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,15 +329,15 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
// trait items are used from inlinable code through method call syntax or UFCS, or their
// trait is a lang item.
struct CollectPrivateImplItemsVisitor<'a> {
exported_items: &'a privacy::ExportedItems,
access_levels: &'a privacy::AccessLevels,
worklist: &'a mut Vec<ast::NodeId>,
}

impl<'a, 'v> Visitor<'v> for CollectPrivateImplItemsVisitor<'a> {
fn visit_item(&mut self, item: &hir::Item) {
// 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 !self.exported_items.contains(&item.id) {
if !self.access_levels.is_reachable(item.id) {
for impl_item in impl_items {
self.worklist.push(impl_item.id);
}
Expand All @@ -347,7 +347,7 @@ impl<'a, 'v> Visitor<'v> for CollectPrivateImplItemsVisitor<'a> {
}

pub fn find_reachable(tcx: &ty::ctxt,
exported_items: &privacy::ExportedItems)
access_levels: &privacy::AccessLevels)
-> NodeSet {

let mut reachable_context = ReachableContext::new(tcx);
Expand All @@ -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
// use the lang items, so we need to be sure to mark them as
// exported.
for id in exported_items {
for (id, _) in &access_levels.map {
reachable_context.worklist.push(*id);
}
for (_, item) in tcx.lang_items.items() {
Expand All @@ -369,7 +369,7 @@ pub fn find_reachable(tcx: &ty::ctxt,
}
{
let mut collect_private_impl_items = CollectPrivateImplItemsVisitor {
exported_items: exported_items,
access_levels: access_levels,
worklist: &mut reachable_context.worklist,
};
tcx.map.krate().visit_all_items(&mut collect_private_impl_items);
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use metadata::cstore::LOCAL_CRATE;
use middle::def;
use middle::def_id::{CRATE_DEF_INDEX, DefId};
use middle::ty;
use middle::privacy::PublicItems;
use middle::privacy::AccessLevels;
use metadata::csearch;
use syntax::parse::token::InternedString;
use syntax::codemap::{Span, DUMMY_SP};
Expand Down Expand Up @@ -73,7 +73,7 @@ struct Annotator<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>,
index: &'a mut Index<'tcx>,
parent: Option<&'tcx Stability>,
export_map: &'a PublicItems,
access_levels: &'a AccessLevels,
in_trait_impl: bool,
in_enum: bool,
}
Expand Down Expand Up @@ -143,7 +143,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
} else {
debug!("annotate: not found, parent = {:?}", self.parent);
let mut is_error = kind == AnnotationKind::Required &&
self.export_map.contains(&id) &&
self.access_levels.is_reachable(id) &&
!self.tcx.sess.opts.test;
if let Some(stab) = self.parent {
if stab.level.is_unstable() {
Expand Down Expand Up @@ -266,12 +266,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {

impl<'tcx> Index<'tcx> {
/// 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 {
tcx: tcx,
index: self,
parent: None,
export_map: export_map,
access_levels: access_levels,
in_trait_impl: false,
in_enum: false,
};
Expand Down
4 changes: 1 addition & 3 deletions src/librustc/middle/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,12 @@ pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0;
/// produced by the driver and fed to trans and later passes.
pub struct CrateAnalysis<'a> {
pub export_map: ExportMap,
pub exported_items: middle::privacy::ExportedItems,
pub public_items: middle::privacy::PublicItems,
pub access_levels: middle::privacy::AccessLevels,
pub reachable: NodeSet,
pub name: &'a str,
pub glob_map: Option<GlobMap>,
}


#[derive(Copy, Clone)]
pub enum DtorKind {
NoDtor,
Expand Down
15 changes: 6 additions & 9 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
"const checking",
|| middle::check_const::check_crate(tcx));

let (exported_items, public_items) =
let access_levels =
time(time_passes, "privacy checking", || {
rustc_privacy::check_crate(tcx,
&export_map,
Expand All @@ -755,7 +755,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,

// Do not move this check past lint
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,
Expand Down Expand Up @@ -807,12 +807,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
let reachable_map =
time(time_passes,
"reachability checking",
|| reachable::find_reachable(tcx, &exported_items));
|| reachable::find_reachable(tcx, &access_levels));

time(time_passes, "death checking", || {
middle::dead::check_crate(tcx,
&exported_items,
&reachable_map)
middle::dead::check_crate(tcx, &access_levels);
});

let ref lib_features_used =
Expand All @@ -827,7 +825,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,

time(time_passes,
"lint checking",
|| lint::check_crate(tcx, &exported_items));
|| lint::check_crate(tcx, &access_levels));

// The above three passes generate errors w/o aborting
tcx.sess.abort_if_errors();
Expand All @@ -836,8 +834,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
mir_map,
ty::CrateAnalysis {
export_map: export_map,
exported_items: exported_items,
public_items: public_items,
access_levels: access_levels,
reachable: reachable_map,
name: name,
glob_map: glob_map,
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,8 @@ impl MissingDoc {
// 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
// have a NodeId).
if let Some(ref id) = id {
if !cx.exported_items.contains(id) {
if let Some(id) = id {
if !cx.access_levels.is_exported(id) {
return;
}
}
Expand Down Expand Up @@ -470,7 +470,7 @@ impl LintPass for MissingCopyImplementations {

impl LateLintPass for MissingCopyImplementations {
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;
}
let (def, ty) = match item.node {
Expand Down Expand Up @@ -534,7 +534,7 @@ impl LintPass for MissingDebugImplementations {

impl LateLintPass for MissingDebugImplementations {
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;
}

Expand Down Expand Up @@ -987,15 +987,15 @@ impl LateLintPass for InvalidNoMangleItems {
match it.node {
hir::ItemFn(..) => {
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",
it.name);
cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg);
}
},
hir::ItemStatic(..) => {
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",
it.name);
cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg);
Expand Down
Loading