Make more passes incremental

This commit is contained in:
John Kåre Alsaker 2018-06-06 22:13:52 +02:00
parent c2d381d39d
commit 69d18a3986
16 changed files with 247 additions and 35 deletions

View file

@ -472,6 +472,12 @@ define_dep_nodes!( <'tcx>
[] UnsafetyCheckResult(DefId),
[] UnsafeDeriveOnReprPacked(DefId),
[] CheckModAttrs(DefId),
[] CheckModLoops(DefId),
[] CheckModUnstableApiUsage(DefId),
[] CheckModItemTypes(DefId),
[] CollectModItemTypes(DefId),
[] Reachability,
[] MirKeys,
[eval_always] CrateVariances,

View file

@ -4,9 +4,14 @@
//! conflicts between multiple such attributes attached to the same
//! item.
use hir;
use hir::intravisit::{self, Visitor, NestedVisitorMap};
use ty::TyCtxt;
use ty::query::Providers;
use ty::query::queries;
use hir;
use hir::def_id::DefId;
use hir::intravisit::{self, Visitor, NestedVisitorMap};
use std::fmt::{self, Display};
use syntax_pos::Span;
@ -364,8 +369,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> {
}
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let mut checker = CheckAttrVisitor { tcx };
tcx.hir().krate().visit_all_item_likes(&mut checker.as_deep_visitor());
for &module in tcx.hir().krate().modules.keys() {
queries::check_mod_attrs::ensure(tcx, tcx.hir().local_def_id(module));
}
}
fn is_c_like_enum(item: &hir::Item) -> bool {
@ -381,3 +387,17 @@ fn is_c_like_enum(item: &hir::Item) -> bool {
false
}
}
pub fn check_mod_attrs<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_module_item_likes(
module_def_id,
&mut CheckAttrVisitor { tcx }.as_deep_visitor()
);
}
pub(crate) fn provide(providers: &mut Providers<'_>) {
*providers = Providers {
check_mod_attrs,
..*providers
};
}

View file

@ -1,4 +1,5 @@
use ty;
use ty::TyCtxt;
use hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX;
use rustc_data_structures::indexed_vec::Idx;
use serialize;
@ -247,6 +248,14 @@ impl DefId {
pub fn to_local(self) -> LocalDefId {
LocalDefId::from_def_id(self)
}
pub fn describe_as_module(&self, tcx: TyCtxt<'_, '_, '_>) -> String {
if self.is_local() && self.index == CRATE_DEF_INDEX {
format!("top-level module")
} else {
format!("module `{}`", tcx.item_path_str(*self))
}
}
}
impl serialize::UseSpecializedEncodable for DefId {}

View file

@ -48,7 +48,7 @@ use session::config::nightly_options;
use util::common::FN_OUTPUT_NAME;
use util::nodemap::{DefIdMap, NodeMap};
use std::collections::BTreeMap;
use std::collections::{BTreeSet, BTreeMap};
use std::fmt::Debug;
use std::mem;
use smallvec::SmallVec;
@ -90,6 +90,8 @@ pub struct LoweringContext<'a> {
trait_impls: BTreeMap<DefId, Vec<NodeId>>,
trait_auto_impl: BTreeMap<DefId, NodeId>,
modules: BTreeMap<NodeId, hir::ModuleItems>,
is_generator: bool,
catch_scopes: Vec<NodeId>,
@ -124,6 +126,8 @@ pub struct LoweringContext<'a> {
// needs to be created for it.
in_scope_lifetimes: Vec<Ident>,
current_module: NodeId,
type_def_lifetime_params: DefIdMap<usize>,
current_hir_id_owner: Vec<(DefIndex, u32)>,
@ -228,12 +232,14 @@ pub fn lower_crate(
bodies: BTreeMap::new(),
trait_impls: BTreeMap::new(),
trait_auto_impl: BTreeMap::new(),
modules: BTreeMap::new(),
exported_macros: Vec::new(),
catch_scopes: Vec::new(),
loop_scopes: Vec::new(),
is_in_loop_condition: false,
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
type_def_lifetime_params: Default::default(),
current_module: CRATE_NODE_ID,
current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)],
item_local_id_counters: Default::default(),
node_id_to_hir_id: IndexVec::new(),
@ -356,6 +362,15 @@ impl<'a> LoweringContext<'a> {
}
impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> {
fn visit_mod(&mut self, m: &'lcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
self.lctx.modules.insert(n, hir::ModuleItems {
items: BTreeSet::new(),
trait_items: BTreeSet::new(),
impl_items: BTreeSet::new(),
});
visit::walk_mod(self, m);
}
fn visit_item(&mut self, item: &'lcx Item) {
self.lctx.allocate_hir_id_counter(item.id, item);
@ -414,11 +429,18 @@ impl<'a> LoweringContext<'a> {
}
impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> {
fn visit_mod(&mut self, m: &'lcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
let old = self.lctx.current_module;
self.lctx.current_module = n;
visit::walk_mod(self, m);
self.lctx.current_module = old;
}
fn visit_item(&mut self, item: &'lcx Item) {
let mut item_lowered = true;
self.lctx.with_hir_id_owner(item.id, |lctx| {
if let Some(hir_item) = lctx.lower_item(item) {
lctx.items.insert(item.id, hir_item);
lctx.insert_item(item.id, hir_item);
} else {
item_lowered = false;
}
@ -451,6 +473,7 @@ impl<'a> LoweringContext<'a> {
let id = hir::TraitItemId { node_id: item.id };
let hir_item = lctx.lower_trait_item(item);
lctx.trait_items.insert(id, hir_item);
lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id);
});
visit::walk_trait_item(self, item);
@ -461,6 +484,7 @@ impl<'a> LoweringContext<'a> {
let id = hir::ImplItemId { node_id: item.id };
let hir_item = lctx.lower_impl_item(item);
lctx.impl_items.insert(id, hir_item);
lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id);
});
visit::walk_impl_item(self, item);
}
@ -492,9 +516,15 @@ impl<'a> LoweringContext<'a> {
body_ids,
trait_impls: self.trait_impls,
trait_auto_impl: self.trait_auto_impl,
modules: self.modules,
}
}
fn insert_item(&mut self, id: NodeId, item: hir::Item) {
self.items.insert(id, item);
self.modules.get_mut(&self.current_module).unwrap().items.insert(id);
}
fn allocate_hir_id_counter<T: Debug>(&mut self, owner: NodeId, debug: &T) -> LoweredNodeId {
if self.item_local_id_counters.insert(owner, 0).is_some() {
bug!(
@ -1370,7 +1400,7 @@ impl<'a> LoweringContext<'a> {
// Insert the item into the global list. This usually happens
// automatically for all AST items. But this existential type item
// does not actually exist in the AST.
lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
lctx.insert_item(exist_ty_id.node_id, exist_ty_item);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes)
@ -3026,7 +3056,7 @@ impl<'a> LoweringContext<'a> {
};
let vis = respan(vis.span, vis_kind);
this.items.insert(
this.insert_item(
new_id.node_id,
hir::Item {
id: new_id.node_id,
@ -3133,7 +3163,7 @@ impl<'a> LoweringContext<'a> {
};
let vis = respan(vis.span, vis_kind);
this.items.insert(
this.insert_item(
new_id,
hir::Item {
id: new_id,

View file

@ -119,6 +119,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
trait_impls: _,
trait_auto_impl: _,
body_ids: _,
modules: _,
} = *krate;
alloc_hir_dep_nodes(

View file

@ -17,6 +17,7 @@ use syntax::ext::base::MacroKind;
use syntax_pos::{Span, DUMMY_SP};
use hir::*;
use hir::itemlikevisit::ItemLikeVisitor;
use hir::print::Nested;
use util::nodemap::FxHashMap;
@ -506,6 +507,35 @@ impl<'hir> Map<'hir> {
&self.forest.krate.attrs
}
pub fn visit_module_item_likes<V>(&self, module: DefId, visitor: &mut V)
where V: ItemLikeVisitor<'hir>
{
let node_id = self.as_local_node_id(module).unwrap();
// Read the module so we'll be re-executed if new items
// appear immediately under in the module. If some new item appears
// in some nested item in the module, we'll be re-executed due to the reads
// in the loops below
self.read(node_id);
let module = &self.forest.krate.modules[&node_id];
for id in &module.items {
self.read(*id);
visitor.visit_item(&self.forest.krate.items[id]);
}
for id in &module.trait_items {
self.read(id.node_id);
visitor.visit_trait_item(&self.forest.krate.trait_items[id]);
}
for id in &module.impl_items {
self.read(id.node_id);
visitor.visit_impl_item(&self.forest.krate.impl_items[id]);
}
}
/// Retrieve the Node corresponding to `id`, panicking if it cannot
/// be found.
pub fn get(&self, id: NodeId) -> Node<'hir> {

View file

@ -33,7 +33,7 @@ use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope}
use rustc_data_structures::thin_vec::ThinVec;
use serialize::{self, Encoder, Encodable, Decoder, Decodable};
use std::collections::BTreeMap;
use std::collections::{BTreeSet, BTreeMap};
use std::fmt;
/// HIR doesn't commit to a concrete storage type and has its own alias for a vector.
@ -676,6 +676,15 @@ pub struct WhereEqPredicate {
pub rhs_ty: P<Ty>,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ModuleItems {
// Use BTreeSets here so items are in the same order as in the
// list of all items in Crate
pub items: BTreeSet<NodeId>,
pub trait_items: BTreeSet<TraitItemId>,
pub impl_items: BTreeSet<ImplItemId>,
}
/// The top-level data structure that stores the entire contents of
/// the crate currently being compiled.
///
@ -708,6 +717,10 @@ pub struct Crate {
/// in the crate, you should iterate over this list rather than the keys
/// of bodies.
pub body_ids: Vec<BodyId>,
/// A list of modules written out in the order in which they
/// appear in the crate. This includes the main crate module.
pub modules: BTreeMap<NodeId, ModuleItems>,
}
impl Crate {
@ -2408,6 +2421,7 @@ pub type GlobMap = NodeMap<FxHashSet<Name>>;
pub fn provide(providers: &mut Providers<'_>) {
check_attr::provide(providers);
providers.describe_def = map::describe_def;
}

View file

@ -8,6 +8,8 @@ use hir::{self, Item, Generics, StructField, Variant, HirId};
use hir::def::Def;
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use hir::intravisit::{self, Visitor, NestedVisitorMap};
use ty::query::Providers;
use ty::query::queries;
use middle::privacy::AccessLevels;
use session::{DiagnosticMessageId, Session};
use syntax::symbol::Symbol;
@ -454,11 +456,23 @@ impl<'a, 'tcx> Index<'tcx> {
}
}
pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
queries::check_mod_unstable_api_usage::ensure(tcx, tcx.hir().local_def_id(module));
}
}
/// Cross-references the feature names of unstable APIs with enabled
/// features and possibly prints errors.
pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let mut checker = Checker { tcx };
tcx.hir().krate().visit_all_item_likes(&mut checker.as_deep_visitor());
pub fn check_mod_unstable_api_usage<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_module_item_likes(module_def_id, &mut Checker { tcx }.as_deep_visitor());
}
pub fn provide(providers: &mut Providers<'_>) {
*providers = Providers {
check_mod_unstable_api_usage,
..*providers
};
}
/// Check whether an item marked with `deprecated(since="X")` is currently

View file

@ -68,11 +68,56 @@ impl<'tcx, M: QueryAccessors<'tcx, Key=DefId>> QueryDescription<'tcx> for M {
format!("processing `{}`", tcx.item_path_str(def_id)).into()
} else {
let name = unsafe { ::std::intrinsics::type_name::<M>() };
format!("processing `{}` applied to `{:?}`", name, def_id).into()
format!("processing {:?} with query `{}`", def_id, name).into()
}
}
}
impl<'tcx> QueryDescription<'tcx> for queries::check_mod_attrs<'tcx> {
fn describe(
tcx: TyCtxt<'_, '_, '_>,
key: DefId,
) -> Cow<'static, str> {
format!("checking attributes in {}", key.describe_as_module(tcx)).into()
}
}
impl<'tcx> QueryDescription<'tcx> for queries::check_mod_unstable_api_usage<'tcx> {
fn describe(
tcx: TyCtxt<'_, '_, '_>,
key: DefId,
) -> Cow<'static, str> {
format!("checking for unstable API usage in {}", key.describe_as_module(tcx)).into()
}
}
impl<'tcx> QueryDescription<'tcx> for queries::check_mod_loops<'tcx> {
fn describe(
tcx: TyCtxt<'_, '_, '_>,
key: DefId,
) -> Cow<'static, str> {
format!("checking loops in {}", key.describe_as_module(tcx)).into()
}
}
impl<'tcx> QueryDescription<'tcx> for queries::check_mod_item_types<'tcx> {
fn describe(
tcx: TyCtxt<'_, '_, '_>,
key: DefId,
) -> Cow<'static, str> {
format!("checking item types in {}", key.describe_as_module(tcx)).into()
}
}
impl<'tcx> QueryDescription<'tcx> for queries::collect_mod_item_types<'tcx> {
fn describe(
tcx: TyCtxt<'_, '_, '_>,
key: DefId,
) -> Cow<'static, str> {
format!("collecting item types in {}", key.describe_as_module(tcx)).into()
}
}
impl<'tcx> QueryDescription<'tcx> for queries::normalize_projection_ty<'tcx> {
fn describe(
_tcx: TyCtxt<'_, '_, '_>,

View file

@ -254,6 +254,18 @@ define_queries! { <'tcx>
},
Other {
/// Checks the attributes in the module
[] fn check_mod_attrs: CheckModAttrs(DefId) -> (),
[] fn check_mod_unstable_api_usage: CheckModUnstableApiUsage(DefId) -> (),
/// Checks the loops in the module
[] fn check_mod_loops: CheckModLoops(DefId) -> (),
[] fn check_mod_item_types: CheckModItemTypes(DefId) -> (),
[] fn collect_mod_item_types: CollectModItemTypes(DefId) -> (),
/// Caches CoerceUnsized kinds for impls on custom types.
[] fn coerce_unsized_info: CoerceUnsizedInfo(DefId)
-> ty::adjustment::CoerceUnsizedInfo,

View file

@ -1262,6 +1262,11 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); }
DepKind::UnsafeDeriveOnReprPacked => { force!(unsafe_derive_on_repr_packed, def_id!()); }
DepKind::CheckModAttrs => { force!(check_mod_attrs, def_id!()); }
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::CollectModItemTypes => { force!(collect_mod_item_types, def_id!()); }
DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }

View file

@ -1167,6 +1167,7 @@ pub fn default_provide(providers: &mut ty::query::Providers) {
typeck::provide(providers);
ty::provide(providers);
traits::provide(providers);
stability::provide(providers);
reachable::provide(providers);
rustc_passes::provide(providers);
rustc_traits::provide(providers);
@ -1218,8 +1219,6 @@ where
sess.proc_macro_decls_static
.set(proc_macro_decls::find(&hir_map));
time(sess, "loop checking", || loops::check_crate(sess, &hir_map));
let mut local_providers = ty::query::Providers::default();
default_provide(&mut local_providers);
codegen_backend.provide(&mut local_providers);
@ -1247,7 +1246,9 @@ where
|tcx| {
// Do some initialization of the DepGraph that can only be done with the
// tcx available.
rustc_incremental::dep_graph_tcx_init(tcx);
time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
time(sess, "loop checking", || loops::check_crate(tcx));
time(sess, "attribute checking", || {
hir::check_attr::check_crate(tcx)

View file

@ -38,4 +38,5 @@ __build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
pub fn provide(providers: &mut Providers) {
rvalue_promotion::provide(providers);
loops::provide(providers);
}

View file

@ -2,6 +2,10 @@ use self::Context::*;
use rustc::session::Session;
use rustc::ty::query::Providers;
use rustc::ty::query::queries;
use rustc::ty::TyCtxt;
use rustc::hir::def_id::DefId;
use rustc::hir::map::Map;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::{self, Node, Destination};
@ -42,28 +46,32 @@ struct CheckLoopVisitor<'a, 'hir: 'a> {
cx: Context,
}
pub fn check_crate(sess: &Session, map: &Map) {
let krate = map.krate();
krate.visit_all_item_likes(&mut CheckLoopVisitor {
sess,
hir_map: map,
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
queries::check_mod_loops::ensure(tcx, tcx.hir().local_def_id(module));
}
}
pub fn check_mod_loops<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_module_item_likes(module_def_id, &mut CheckLoopVisitor {
sess: &tcx.sess,
hir_map: &tcx.hir(),
cx: Normal,
}.as_deep_visitor());
}
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
check_mod_loops,
..*providers
};
}
impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
NestedVisitorMap::OnlyBodies(&self.hir_map)
}
fn visit_item(&mut self, i: &'hir hir::Item) {
self.with_context(Normal, |v| intravisit::walk_item(v, i));
}
fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) {
self.with_context(Normal, |v| intravisit::walk_impl_item(v, i));
}
fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
self.with_context(AnonConst, |v| intravisit::walk_anon_const(v, c));
}

View file

@ -109,6 +109,7 @@ use rustc::ty::{
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::query::Providers;
use rustc::ty::query::queries;
use rustc::ty::subst::{UnpackedKind, Subst, Substs, UserSelfTy, UserSubsts};
use rustc::ty::util::{Representability, IntTypeExt, Discr};
use rustc::ty::layout::VariantIdx;
@ -700,10 +701,16 @@ pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorRe
pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
tcx.sess.track_errors(|| {
tcx.hir().krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx });
for &module in tcx.hir().krate().modules.keys() {
queries::check_mod_item_types::ensure(tcx, tcx.hir().local_def_id(module));
}
})
}
fn check_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_module_item_likes(module_def_id, &mut CheckItemTypesVisitor { tcx });
}
pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> {
tcx.typeck_item_bodies(LOCAL_CRATE)
}
@ -742,6 +749,7 @@ pub fn provide(providers: &mut Providers) {
check_item_well_formed,
check_trait_item_well_formed,
check_impl_item_well_formed,
check_mod_item_types,
..*providers
};
}

View file

@ -22,6 +22,7 @@ use middle::resolve_lifetime as rl;
use middle::weak_lang_items;
use rustc::mir::mono::Linkage;
use rustc::ty::query::Providers;
use rustc::ty::query::queries;
use rustc::ty::subst::Substs;
use rustc::ty::util::Discr;
use rustc::ty::util::IntTypeExt;
@ -55,10 +56,16 @@ struct OnlySelfBounds(bool);
// Main entry point
pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let mut visitor = CollectItemTypesVisitor { tcx };
tcx.hir()
.krate()
.visit_all_item_likes(&mut visitor.as_deep_visitor());
for &module in tcx.hir().krate().modules.keys() {
queries::collect_mod_item_types::ensure(tcx, tcx.hir().local_def_id(module));
}
}
fn collect_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_module_item_likes(
module_def_id,
&mut CollectItemTypesVisitor { tcx }.as_deep_visitor()
);
}
pub fn provide(providers: &mut Providers) {
@ -77,6 +84,7 @@ pub fn provide(providers: &mut Providers) {
impl_polarity,
is_foreign_item,
codegen_fn_attrs,
collect_mod_item_types,
..*providers
};
}