From e459000bc1509805e18a74c402fd78e2881d0248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 8 Jun 2018 19:14:03 +0200 Subject: [PATCH 1/2] Make privacy checking, intrinsic checking and liveness checking incremental --- src/librustc/dep_graph/dep_node.rs | 3 ++ src/librustc/hir/map/mod.rs | 15 ++++++++++ src/librustc/middle/intrinsicck.rs | 20 ++++++++++++-- src/librustc/middle/liveness.rs | 19 +++++++++++-- src/librustc/ty/query/config.rs | 27 ++++++++++++++++++ src/librustc/ty/query/mod.rs | 6 ++++ src/librustc/ty/query/plumbing.rs | 3 ++ src/librustc_driver/driver.rs | 2 ++ src/librustc_privacy/lib.rs | 44 +++++++++++++++++++++--------- 9 files changed, 121 insertions(+), 18 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 427fe51e6ff9c..d1067b70778ee 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -476,6 +476,9 @@ define_dep_nodes!( <'tcx> [] CheckModLoops(DefId), [] CheckModUnstableApiUsage(DefId), [] CheckModItemTypes(DefId), + [] CheckModPrivacy(DefId), + [] CheckModIntrinsics(DefId), + [] CheckModLiveness(DefId), [] CollectModItemTypes(DefId), [] Reachability, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 869baef1f5afc..d9ca37c937bc7 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -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(&self, module: DefId, visitor: &mut V) where V: ItemLikeVisitor<'hir> { diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 1716daaa107c4..a0f7954eb0c55 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -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> { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index a78cf1a471b4b..0a1802a4e12c9 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -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()) diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index ca5d1f6bd3203..c20846aebb877 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -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<'_, '_, '_>, diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 39d76ceed9507..88c20547a2108 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -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. diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 32d4070dfed2a..5fb6d33ded914 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -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); } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 380f9afd68de6..95c0facb6fd42 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 4890369e13f20..10ac1caa692ca 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -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 { tcx.privacy_access_levels(LOCAL_CRATE) } -fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - krate: CrateNum) - -> Lrc { - 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 { + 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. From e301f90f227ee2719cffa36b423d97360bfb3db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 15 Jan 2019 00:54:56 +0100 Subject: [PATCH 2/2] Address comments --- src/librustc_privacy/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 10ac1caa692ca..698037e237101 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -783,7 +783,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { } fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: ast::NodeId) { - // Don't visit modules inside + // Don't visit nested modules, since we run a separate visitor walk + // for each module in `privacy_access_levels` } fn visit_nested_body(&mut self, body: hir::BodyId) { @@ -922,7 +923,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: ast::NodeId) { - // Don't visit modules inside + // Don't visit nested modules, since we run a separate visitor walk + // for each module in `privacy_access_levels` } fn visit_nested_body(&mut self, body: hir::BodyId) { @@ -1710,7 +1712,7 @@ fn privacy_access_levels<'tcx>( let krate = tcx.hir().krate(); - for &module in tcx.hir().krate().modules.keys() { + for &module in krate.modules.keys() { queries::check_mod_privacy::ensure(tcx, tcx.hir().local_def_id(module)); }