Skip to content
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

Make more passes incremental #51487

Merged
merged 3 commits into from
Jan 13, 2019
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
6 changes: 6 additions & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
26 changes: 23 additions & 3 deletions src/librustc/hir/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@
//! conflicts between multiple such attributes attached to the same
//! item.


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 ty::TyCtxt;
use std::fmt::{self, Display};
use syntax_pos::Span;

Expand Down Expand Up @@ -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 {
Expand All @@ -381,3 +387,17 @@ fn is_c_like_enum(item: &hir::Item) -> bool {
false
}
}

fn check_mod_attrs<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(
module_def_id,
&mut CheckAttrVisitor { tcx }.as_deep_visitor()
);
}

pub(crate) fn provide(providers: &mut Providers<'_>) {
*providers = Providers {
check_mod_attrs,
..*providers
};
}
9 changes: 9 additions & 0 deletions src/librustc/hir/def_id.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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 {}
Expand Down
37 changes: 32 additions & 5 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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>,
Expand Down Expand Up @@ -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)>,
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -414,11 +420,24 @@ 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) {
self.lctx.modules.insert(n, hir::ModuleItems {
items: BTreeSet::new(),
trait_items: BTreeSet::new(),
impl_items: BTreeSet::new(),
});

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;
}
Expand Down Expand Up @@ -451,6 +470,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);
Expand All @@ -461,6 +481,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);
}
Expand Down Expand Up @@ -492,9 +513,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!(
Expand Down Expand Up @@ -1370,7 +1397,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)
Expand Down Expand Up @@ -3026,7 +3053,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,
Expand Down Expand Up @@ -3133,7 +3160,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,
Expand Down
1 change: 1 addition & 0 deletions src/librustc/hir/map/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
trait_impls: _,
trait_auto_impl: _,
body_ids: _,
modules: _,
} = *krate;

alloc_hir_dep_nodes(
Expand Down
27 changes: 27 additions & 0 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -506,6 +507,32 @@ impl<'hir> Map<'hir> {
&self.forest.krate.attrs
}

pub fn visit_item_likes_in_module<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 reads
// in the expect_* calls the loops below
self.read(node_id);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't actually work as intended yet (see #40876). We should try and see if we can make this work properly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of adding a HIRModule dep-node. That would reduce the dep nodes used by the passes too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of adding a HIRModule dep-node.

So that the hash of the HIRModule dep-node would be a combination of the hashes of the module's items?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, maybe. I've just opened #51982 though, which should fix the problem. If that works out, we can use the existing solution in this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#51982 seems to work out just fine.


let module = &self.forest.krate.modules[&node_id];

for id in &module.items {
visitor.visit_item(self.expect_item(*id));
}

for id in &module.trait_items {
visitor.visit_trait_item(self.expect_trait_item(id.node_id));
}

for id in &module.impl_items {
visitor.visit_impl_item(self.expect_impl_item(id.node_id));
}
}

/// Retrieve the Node corresponding to `id`, panicking if it cannot
/// be found.
pub fn get(&self, id: NodeId) -> Node<'hir> {
Expand Down
16 changes: 15 additions & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}

Expand Down
20 changes: 17 additions & 3 deletions src/librustc/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
fn check_mod_unstable_api_usage<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(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
Expand Down
47 changes: 46 additions & 1 deletion src/librustc/ty/query/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<'_, '_, '_>,
Expand Down
Loading