Make privacy checking, intrinsic checking and liveness checking incremental
This commit is contained in:
parent
03acbd71c9
commit
e459000bc1
@ -476,6 +476,9 @@ define_dep_nodes!( <'tcx>
|
||||
[] CheckModLoops(DefId),
|
||||
[] CheckModUnstableApiUsage(DefId),
|
||||
[] CheckModItemTypes(DefId),
|
||||
[] CheckModPrivacy(DefId),
|
||||
[] CheckModIntrinsics(DefId),
|
||||
[] CheckModLiveness(DefId),
|
||||
[] CollectModItemTypes(DefId),
|
||||
|
||||
[] Reachability,
|
||||
|
@ -509,6 +509,21 @@ impl<'hir> Map<'hir> {
|
||||
&self.forest.krate.attrs
|
||||
}
|
||||
|
||||
pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, NodeId)
|
||||
{
|
||||
let node_id = self.as_local_node_id(module).unwrap();
|
||||
self.read(node_id);
|
||||
match self.find_entry(node_id).unwrap().node {
|
||||
Node::Item(&Item {
|
||||
span,
|
||||
node: ItemKind::Mod(ref m),
|
||||
..
|
||||
}) => (m, span, node_id),
|
||||
Node::Crate => (&self.forest.krate.module, self.forest.krate.span, node_id),
|
||||
_ => panic!("not a module")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_item_likes_in_module<V>(&self, module: DefId, visitor: &mut V)
|
||||
where V: ItemLikeVisitor<'hir>
|
||||
{
|
||||
|
@ -2,6 +2,7 @@ use hir::def::Def;
|
||||
use hir::def_id::DefId;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
|
||||
use ty::query::{Providers, queries};
|
||||
|
||||
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
@ -10,10 +11,23 @@ use hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use hir;
|
||||
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
let mut visitor = ItemVisitor {
|
||||
tcx,
|
||||
for &module in tcx.hir().krate().modules.keys() {
|
||||
queries::check_mod_intrinsics::ensure(tcx, tcx.hir().local_def_id(module));
|
||||
}
|
||||
}
|
||||
|
||||
fn check_mod_intrinsics<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
|
||||
tcx.hir().visit_item_likes_in_module(
|
||||
module_def_id,
|
||||
&mut ItemVisitor { tcx }.as_deep_visitor()
|
||||
);
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers<'_>) {
|
||||
*providers = Providers {
|
||||
check_mod_intrinsics,
|
||||
..*providers
|
||||
};
|
||||
tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
|
||||
}
|
||||
|
||||
struct ItemVisitor<'a, 'tcx: 'a> {
|
||||
|
@ -100,6 +100,7 @@ use self::VarKind::*;
|
||||
use hir::def::*;
|
||||
use hir::Node;
|
||||
use ty::{self, TyCtxt};
|
||||
use ty::query::{Providers, queries};
|
||||
use lint;
|
||||
use errors::Applicability;
|
||||
use util::nodemap::{NodeMap, HirIdMap, HirIdSet};
|
||||
@ -114,8 +115,9 @@ use syntax::ptr::P;
|
||||
use syntax::symbol::keywords;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use hir::{Expr, HirId};
|
||||
use hir;
|
||||
use hir::{Expr, HirId};
|
||||
use hir::def_id::DefId;
|
||||
use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
|
||||
|
||||
/// For use with `propagate_through_loop`.
|
||||
@ -179,11 +181,24 @@ impl<'a, 'tcx> Visitor<'tcx> for IrMaps<'a, 'tcx> {
|
||||
fn visit_arm(&mut self, a: &'tcx hir::Arm) { visit_arm(self, a); }
|
||||
}
|
||||
|
||||
fn check_mod_liveness<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx).as_deep_visitor());
|
||||
}
|
||||
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
tcx.hir().krate().visit_all_item_likes(&mut IrMaps::new(tcx).as_deep_visitor());
|
||||
for &module in tcx.hir().krate().modules.keys() {
|
||||
queries::check_mod_liveness::ensure(tcx, tcx.hir().local_def_id(module));
|
||||
}
|
||||
tcx.sess.abort_if_errors();
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers<'_>) {
|
||||
*providers = Providers {
|
||||
check_mod_liveness,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
||||
impl fmt::Debug for LiveNode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "ln({})", self.get())
|
||||
|
@ -109,6 +109,33 @@ impl<'tcx> QueryDescription<'tcx> for queries::check_mod_item_types<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::check_mod_privacy<'tcx> {
|
||||
fn describe(
|
||||
tcx: TyCtxt<'_, '_, '_>,
|
||||
key: DefId,
|
||||
) -> Cow<'static, str> {
|
||||
format!("checking privacy in {}", key.describe_as_module(tcx)).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::check_mod_intrinsics<'tcx> {
|
||||
fn describe(
|
||||
tcx: TyCtxt<'_, '_, '_>,
|
||||
key: DefId,
|
||||
) -> Cow<'static, str> {
|
||||
format!("checking intrinsics in {}", key.describe_as_module(tcx)).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::check_mod_liveness<'tcx> {
|
||||
fn describe(
|
||||
tcx: TyCtxt<'_, '_, '_>,
|
||||
key: DefId,
|
||||
) -> Cow<'static, str> {
|
||||
format!("checking liveness of variables in {}", key.describe_as_module(tcx)).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::collect_mod_item_types<'tcx> {
|
||||
fn describe(
|
||||
tcx: TyCtxt<'_, '_, '_>,
|
||||
|
@ -264,6 +264,12 @@ define_queries! { <'tcx>
|
||||
|
||||
[] fn check_mod_item_types: CheckModItemTypes(DefId) -> (),
|
||||
|
||||
[] fn check_mod_privacy: CheckModPrivacy(DefId) -> (),
|
||||
|
||||
[] fn check_mod_intrinsics: CheckModIntrinsics(DefId) -> (),
|
||||
|
||||
[] fn check_mod_liveness: CheckModLiveness(DefId) -> (),
|
||||
|
||||
[] fn collect_mod_item_types: CollectModItemTypes(DefId) -> (),
|
||||
|
||||
/// Caches CoerceUnsized kinds for impls on custom types.
|
||||
|
@ -1280,6 +1280,9 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
||||
DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); }
|
||||
DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); }
|
||||
DepKind::CheckModItemTypes => { force!(check_mod_item_types, def_id!()); }
|
||||
DepKind::CheckModPrivacy => { force!(check_mod_privacy, def_id!()); }
|
||||
DepKind::CheckModIntrinsics => { force!(check_mod_intrinsics, def_id!()); }
|
||||
DepKind::CheckModLiveness => { force!(check_mod_liveness, def_id!()); }
|
||||
DepKind::CollectModItemTypes => { force!(collect_mod_item_types, def_id!()); }
|
||||
DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
|
||||
DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
|
||||
|
@ -1168,6 +1168,8 @@ pub fn default_provide(providers: &mut ty::query::Providers) {
|
||||
ty::provide(providers);
|
||||
traits::provide(providers);
|
||||
stability::provide(providers);
|
||||
middle::intrinsicck::provide(providers);
|
||||
middle::liveness::provide(providers);
|
||||
reachable::provide(providers);
|
||||
rustc_passes::provide(providers);
|
||||
rustc_traits::provide(providers);
|
||||
|
@ -22,12 +22,12 @@ use rustc::lint;
|
||||
use rustc::middle::privacy::{AccessLevel, AccessLevels};
|
||||
use rustc::ty::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind};
|
||||
use rustc::ty::fold::TypeVisitor;
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::query::{Providers, queries};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::util::nodemap::NodeSet;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use syntax::ast::{self, CRATE_NODE_ID, Ident};
|
||||
use syntax::ast::{self, DUMMY_NODE_ID, Ident};
|
||||
use syntax::attr;
|
||||
use syntax::symbol::keywords;
|
||||
use syntax_pos::Span;
|
||||
@ -782,6 +782,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
|
||||
NestedVisitorMap::All(&self.tcx.hir())
|
||||
}
|
||||
|
||||
fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: ast::NodeId) {
|
||||
// Don't visit modules inside
|
||||
}
|
||||
|
||||
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
||||
let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body));
|
||||
let body = self.tcx.hir().body(body);
|
||||
@ -917,6 +921,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
||||
NestedVisitorMap::All(&self.tcx.hir())
|
||||
}
|
||||
|
||||
fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: ast::NodeId) {
|
||||
// Don't visit modules inside
|
||||
}
|
||||
|
||||
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
||||
let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body));
|
||||
let orig_in_body = mem::replace(&mut self.in_body, true);
|
||||
@ -1659,6 +1667,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
privacy_access_levels,
|
||||
check_mod_privacy,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
@ -1667,34 +1676,43 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Lrc<AccessLevels> {
|
||||
tcx.privacy_access_levels(LOCAL_CRATE)
|
||||
}
|
||||
|
||||
fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
krate: CrateNum)
|
||||
-> Lrc<AccessLevels> {
|
||||
assert_eq!(krate, LOCAL_CRATE);
|
||||
|
||||
let krate = tcx.hir().krate();
|
||||
fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
|
||||
let empty_tables = ty::TypeckTables::empty(None);
|
||||
|
||||
// Check privacy of names not checked in previous compilation stages.
|
||||
let mut visitor = NamePrivacyVisitor {
|
||||
tcx,
|
||||
tables: &empty_tables,
|
||||
current_item: CRATE_NODE_ID,
|
||||
current_item: DUMMY_NODE_ID,
|
||||
empty_tables: &empty_tables,
|
||||
};
|
||||
intravisit::walk_crate(&mut visitor, krate);
|
||||
let (module, span, node_id) = tcx.hir().get_module(module_def_id);
|
||||
intravisit::walk_mod(&mut visitor, module, node_id);
|
||||
|
||||
// Check privacy of explicitly written types and traits as well as
|
||||
// inferred types of expressions and patterns.
|
||||
let mut visitor = TypePrivacyVisitor {
|
||||
tcx,
|
||||
tables: &empty_tables,
|
||||
current_item: DefId::local(CRATE_DEF_INDEX),
|
||||
current_item: module_def_id,
|
||||
in_body: false,
|
||||
span: krate.span,
|
||||
span,
|
||||
empty_tables: &empty_tables,
|
||||
};
|
||||
intravisit::walk_crate(&mut visitor, krate);
|
||||
intravisit::walk_mod(&mut visitor, module, node_id);
|
||||
}
|
||||
|
||||
fn privacy_access_levels<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
krate: CrateNum,
|
||||
) -> Lrc<AccessLevels> {
|
||||
assert_eq!(krate, LOCAL_CRATE);
|
||||
|
||||
let krate = tcx.hir().krate();
|
||||
|
||||
for &module in tcx.hir().krate().modules.keys() {
|
||||
queries::check_mod_privacy::ensure(tcx, tcx.hir().local_def_id(module));
|
||||
}
|
||||
|
||||
// Build up a set of all exported items in the AST. This is a set of all
|
||||
// items which are reachable from external crates based on visibility.
|
||||
|
Loading…
x
Reference in New Issue
Block a user