Skip to content
Open
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
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
// also nested delegations may need to access information about this code (#154332),
// so it is better to leave this code as opposed to bodies of extern functions,
// which are completely erased from existence.
// FIXME(fn_delegation): fix `help` in error message (see `inner-attr.stderr`)
if param_count == 0
&& let Some(block) = block
{
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub(super) enum Owners<'a, 'hir> {
}

impl<'hir> Owners<'_, 'hir> {
fn get_or_insert_mut(&mut self, def_id: LocalDefId) -> &mut hir::MaybeOwner<'hir> {
pub(super) fn get_or_insert_mut(&mut self, def_id: LocalDefId) -> &mut hir::MaybeOwner<'hir> {
match self {
Owners::IndexVec(index_vec) => {
index_vec.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom)
Expand Down
37 changes: 30 additions & 7 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use std::mem;
use std::sync::Arc;

use rustc_ast::node_id::NodeMap;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::{self as ast, *};
use rustc_attr_parsing::{AttributeParser, Late, OmitDoc};
use rustc_data_structures::fingerprint::Fingerprint;
Expand All @@ -53,8 +54,8 @@ use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
use rustc_hir::lints::{AttributeLint, DelayedLint};
use rustc_hir::{
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
LifetimeSyntax, ParamName, Target, TraitCandidate, find_attr,
self as hir, AngleBrackets, ConstArg, DelayedOwner, GenericArg, HirId, ItemLocalMap,
LifetimeSource, LifetimeSyntax, ParamName, Target, TraitCandidate, find_attr,
};
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension;
Expand Down Expand Up @@ -633,13 +634,35 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
let mut delayed_ids: FxIndexSet<LocalDefId> = Default::default();

for def_id in ast_index.indices() {
match &ast_index[def_id] {
AstOwner::Item(Item { kind: ItemKind::Delegation { .. }, .. })
| AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation { .. }, .. }, _) => {
delayed_ids.insert(def_id);
let delayed_owner = match &ast_index[def_id] {
AstOwner::Item(Item {
kind: ItemKind::Delegation(box Delegation { ident, .. }),
..
}) => Some(DelayedOwner { kind: hir::DelayedOwnerKind::Item, ident: *ident }),
AstOwner::AssocItem(
Item { kind: AssocItemKind::Delegation(box Delegation { ident, .. }), .. },
ctx,
) => {
let kind = match ctx {
AssocCtxt::Trait => hir::DelayedOwnerKind::TraitItem,
AssocCtxt::Impl { .. } => hir::DelayedOwnerKind::ImplItem,
};

Some(DelayedOwner { kind, ident: *ident })
}
_ => lowerer.lower_node(def_id),
_ => None,
};

if let Some(delayed_owner) = delayed_owner {
delayed_ids.insert(def_id);

let owner = lowerer.owners.get_or_insert_mut(def_id);
if let hir::MaybeOwner::Phantom = owner {
*owner = hir::MaybeOwner::Delayed(delayed_owner)
}
} else {
lowerer.lower_node(def_id);
}
}

// Don't hash unless necessary, because it's expensive.
Expand Down
22 changes: 20 additions & 2 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1641,10 +1641,24 @@ impl<'tcx> OwnerInfo<'tcx> {
}
}

#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum DelayedOwnerKind {
Item,
ImplItem,
TraitItem,
}

#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub struct DelayedOwner {
pub ident: Ident,
pub kind: DelayedOwnerKind,
}

#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum MaybeOwner<'tcx> {
Owner(&'tcx OwnerInfo<'tcx>),
NonOwner(HirId),
Delayed(DelayedOwner),
/// Used as a placeholder for unused LocalDefId.
Phantom,
}
Expand All @@ -1653,12 +1667,16 @@ impl<'tcx> MaybeOwner<'tcx> {
pub fn as_owner(self) -> Option<&'tcx OwnerInfo<'tcx>> {
match self {
MaybeOwner::Owner(i) => Some(i),
MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => None,
_ => None,
}
}

pub fn unwrap(self) -> &'tcx OwnerInfo<'tcx> {
self.as_owner().unwrap_or_else(|| panic!("Not a HIR owner"))
self.as_owner().unwrap_or_else(|| panic!("not a HIR owner"))
}

pub fn expect_delayed(self) -> DelayedOwner {
if let MaybeOwner::Delayed(owner) = self { owner } else { panic!("not a delayed owner") }
}
}

Expand Down
17 changes: 14 additions & 3 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ pub trait HirTyCtxt<'hir> {
fn hir_trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
fn hir_impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
fn hir_foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
fn is_delayed(&self, id: LocalDefId) -> bool;
}

// Used when no tcx is actually available, forcing manual implementation of nested visitors.
Expand All @@ -139,6 +140,9 @@ impl<'hir> HirTyCtxt<'hir> for ! {
fn hir_foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> {
unreachable!();
}
fn is_delayed(&self, _: LocalDefId) -> bool {
unreachable!()
}
}

pub mod nested_filter {
Expand Down Expand Up @@ -226,6 +230,8 @@ pub trait Visitor<'v>: Sized {
/// or `ControlFlow<T>`.
type Result: VisitorResult = ();

const VISIT_DELAYED: bool = true;

/// If `type NestedFilter` is set to visit nested items, this method
/// must also be overridden to provide a map to retrieve nested items.
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
Expand All @@ -244,18 +250,23 @@ pub trait Visitor<'v>: Sized {
/// this method is if you want a nested pattern but cannot supply a
/// `TyCtxt`; see `maybe_tcx` for advice.
fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
if Self::NestedFilter::INTER {
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
let item = self.maybe_tcx().hir_item(id);
try_visit!(self.visit_item(item));
}
Self::Result::output()
}

// Now delayed owners are only delegations, which are either item, trait item or impl item.
fn should_visit_maybe_delayed_inter(&mut self, id: LocalDefId) -> bool {
Self::NestedFilter::INTER && (Self::VISIT_DELAYED || !self.maybe_tcx().is_delayed(id))
}

/// Like `visit_nested_item()`, but for trait items. See
/// `visit_nested_item()` for advice on when to override this
/// method.
fn visit_nested_trait_item(&mut self, id: TraitItemId) -> Self::Result {
if Self::NestedFilter::INTER {
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
let item = self.maybe_tcx().hir_trait_item(id);
try_visit!(self.visit_trait_item(item));
}
Expand All @@ -266,7 +277,7 @@ pub trait Visitor<'v>: Sized {
/// `visit_nested_item()` for advice on when to override this
/// method.
fn visit_nested_impl_item(&mut self, id: ImplItemId) -> Self::Result {
if Self::NestedFilter::INTER {
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
let item = self.maybe_tcx().hir_impl_item(id);
try_visit!(self.visit_impl_item(item));
}
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,10 @@ pub fn emit_delayed_lints(tcx: TyCtxt<'_>) {
/// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.
/// This function never fails.
fn run_required_analyses(tcx: TyCtxt<'_>) {
// Forces all delayed owners to be lowered and drops AST crate after it.
// Also refetches hir_crate_items to prevent multiple threads from blocking on it later.
tcx.force_delayed_owners_lowering();

if tcx.sess.opts.unstable_opts.input_stats {
rustc_passes::input_stats::print_hir_stats(tcx);
}
Expand All @@ -1062,11 +1066,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
#[cfg(all(not(doc), debug_assertions))]
rustc_passes::hir_id_validator::check_crate(tcx);

// Prefetch this to prevent multiple threads from blocking on it later.
// This is needed since the `hir_id_validator::check_crate` call above is not guaranteed
// to use `hir_crate_items`.
tcx.ensure_done().hir_crate_items(());

let sess = tcx.sess;
sess.time("misc_checking_1", || {
par_fns(&mut [
Expand Down
81 changes: 45 additions & 36 deletions compiler/rustc_middle/src/hir/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc_ast::visit::{VisitorResult, walk_list};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{DynSend, DynSync, par_for_each_in, spawn, try_par_for_each_in};
use rustc_data_structures::sync::{DynSend, DynSync, par_for_each_in, try_par_for_each_in};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
Expand Down Expand Up @@ -835,18 +835,8 @@ impl<'tcx> TyCtxt<'tcx> {
}

#[inline]
fn hir_opt_ident(self, id: HirId) -> Option<Ident> {
match self.hir_node(id) {
Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
// A `Ctor` doesn't have an identifier itself, but its parent
// struct/variant does. Compare with `hir::Map::span`.
Node::Ctor(..) => match self.parent_hir_node(id) {
Node::Item(item) => Some(item.kind.ident().unwrap()),
Node::Variant(variant) => Some(variant.ident),
_ => unreachable!(),
},
node => node.ident(),
}
pub fn hir_opt_ident(self, id: HirId) -> Option<Ident> {
self.hir_crate(()).opt_ident(self, id)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This use of hir_crate looks like it may be a source of perf regressions in incremental mode, I'll run benchmarks.

}

#[inline]
Expand Down Expand Up @@ -1115,6 +1105,10 @@ impl<'tcx> intravisit::HirTyCtxt<'tcx> for TyCtxt<'tcx> {
fn hir_foreign_item(&self, id: ForeignItemId) -> &'tcx ForeignItem<'tcx> {
(*self).hir_foreign_item(id)
}

fn is_delayed(&self, id: LocalDefId) -> bool {
(*self).hir_crate(()).delayed_ids.contains(&id)
}
}

impl<'tcx> pprust_hir::PpAnn for TyCtxt<'tcx> {
Expand Down Expand Up @@ -1212,8 +1206,14 @@ fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
upstream_crates
}

#[derive(Clone, Copy)]
enum ItemCollectionKind {
Crate,
Mod(LocalModDefId),
}

pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> ModuleItems {
let mut collector = ItemCollector::new(tcx, false);
let mut collector = ItemCollector::new(tcx, ItemCollectionKind::Mod(module_id));

let (hir_mod, span, hir_id) = tcx.hir_get_module(module_id);
collector.visit_mod(hir_mod, span, hir_id);
Expand Down Expand Up @@ -1245,26 +1245,8 @@ pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> Mod
}
}

fn force_delayed_owners_lowering(tcx: TyCtxt<'_>) {
let krate = tcx.hir_crate(());
for &id in &krate.delayed_ids {
tcx.ensure_done().lower_delayed_owner(id);
}

let (_, krate) = krate.delayed_resolver.steal();
let prof = tcx.sess.prof.clone();

// Drop AST to free memory. It can be expensive so try to drop it on a separate thread.
spawn(move || {
let _timer = prof.verbose_generic_activity("drop_ast");
drop(krate);
});
}

pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
force_delayed_owners_lowering(tcx);

let mut collector = ItemCollector::new(tcx, true);
let mut collector = ItemCollector::new(tcx, ItemCollectionKind::Crate);

// A "crate collector" and "module collector" start at a
// module item (the former starts at the crate root) but only
Expand Down Expand Up @@ -1327,9 +1309,9 @@ struct ItemCollector<'tcx> {
}

impl<'tcx> ItemCollector<'tcx> {
fn new(tcx: TyCtxt<'tcx>, crate_collector: bool) -> ItemCollector<'tcx> {
ItemCollector {
crate_collector,
fn new(tcx: TyCtxt<'tcx>, collection_kind: ItemCollectionKind) -> ItemCollector<'tcx> {
let mut collector = ItemCollector {
crate_collector: matches!(collection_kind, ItemCollectionKind::Crate),
tcx,
submodules: Vec::default(),
items: Vec::default(),
Expand All @@ -1341,12 +1323,39 @@ impl<'tcx> ItemCollector<'tcx> {
nested_bodies: Vec::default(),
delayed_lint_items: Vec::default(),
eiis: Vec::default(),
};

let krate = tcx.hir_crate(());
let delayed_kinds = krate
.delayed_ids
.iter()
.copied()
.map(|id| (id, krate.owners[id].expect_delayed().kind))
.filter(|(id, _)| match collection_kind {
ItemCollectionKind::Crate => true,
ItemCollectionKind::Mod(mod_id) => tcx.parent_module_from_def_id(*id) == mod_id,
});

// FIXME(fn_delegation): need to add delayed lints, eiis
for (def_id, kind) in delayed_kinds {
let owner_id = OwnerId { def_id };

match kind {
DelayedOwnerKind::Item => collector.items.push(ItemId { owner_id }),
DelayedOwnerKind::ImplItem => collector.impl_items.push(ImplItemId { owner_id }),
DelayedOwnerKind::TraitItem => collector.trait_items.push(TraitItemId { owner_id }),
};

collector.body_owners.push(def_id);
}

collector
}
}

impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
type NestedFilter = nested_filter::All;
const VISIT_DELAYED: bool = false;

fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
self.tcx
Expand Down
Loading
Loading