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
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
27 changes: 22 additions & 5 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 Down Expand Up @@ -633,13 +634,29 @@ 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 kind = match &ast_index[def_id] {
AstOwner::Item(Item { kind: ItemKind::Delegation { .. }, .. }) => {
Some(hir::DelayedOwnerKind::Item)
}
_ => lowerer.lower_node(def_id),
AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation { .. }, .. }, ctx) => {
match ctx {
AssocCtxt::Trait => Some(hir::DelayedOwnerKind::TraitItem),
AssocCtxt::Impl { .. } => Some(hir::DelayedOwnerKind::ImplItem),
}
}
_ => None,
};

if let Some(kind) = kind {
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(kind)
}
} else {
lowerer.lower_node(def_id);
}
}

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

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

#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum MaybeOwner<'tcx> {
Owner(&'tcx OwnerInfo<'tcx>),
NonOwner(HirId),
Delayed(DelayedOwnerKind),
/// Used as a placeholder for unused LocalDefId.
Phantom,
}
Expand All @@ -1653,13 +1661,17 @@ 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"))
}

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

#[derive(Debug, Clone, Copy, HashStable_Generic)]
Expand Down
16 changes: 13 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,22 @@ 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()
}

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 +276,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 @@ -1028,6 +1028,10 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
/// 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<'_>) {
// Prefetches hir_crate_items to prevent multiple threads from blocking on it later.
// Also forces all delayed owners to be lowered and drops AST crate after it.
tcx.force_delayed_owners_lowering();

if tcx.sess.opts.unstable_opts.input_stats {
rustc_passes::input_stats::print_hir_stats(tcx);
}
Expand All @@ -1036,11 +1040,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
62 changes: 38 additions & 24 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 @@ -1115,6 +1115,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 +1216,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 +1255,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 +1319,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 +1333,34 @@ impl<'tcx> ItemCollector<'tcx> {
nested_bodies: Vec::default(),
delayed_lint_items: Vec::default(),
eiis: Vec::default(),
};

let delayed_kinds = tcx.hir_crate(()).delayed_owners_kinds();
let delayed_kinds = delayed_kinds.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
30 changes: 27 additions & 3 deletions compiler/rustc_middle/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{DynSend, DynSync, try_par_for_each_in};
use rustc_data_structures::sync::{DynSend, DynSync, spawn, try_par_for_each_in};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::lints::DelayedLint;
Expand Down Expand Up @@ -64,7 +64,8 @@ impl<'hir> Crate<'hir> {
// which is greater than delayed LocalDefId, we use IndexVec for owners,
// so we will call ensure_contains_elem which will grow it.
if let Some(owner) = self.owners.get(def_id)
&& (self.delayed_ids.is_empty() || !matches!(owner, MaybeOwner::Phantom))
&& (self.delayed_ids.is_empty()
|| !matches!(owner, MaybeOwner::Phantom | MaybeOwner::Delayed(_)))
{
return *owner;
}
Expand All @@ -75,6 +76,10 @@ impl<'hir> Crate<'hir> {

tcx.delayed_owner(def_id)
}

pub fn delayed_owners_kinds(&self) -> impl Iterator<Item = (LocalDefId, DelayedOwnerKind)> {
self.delayed_ids.iter().copied().map(|id| (id, self.owners[id].expect_delayed()))
}
}

impl<HirCtx: HashStableContext> HashStable<HirCtx> for Crate<'_> {
Expand Down Expand Up @@ -207,6 +212,24 @@ impl ModuleItems {
}

impl<'tcx> TyCtxt<'tcx> {
pub fn force_delayed_owners_lowering(self) {
let krate = self.hir_crate(());
self.ensure_done().hir_crate_items(());

for &id in &krate.delayed_ids {
self.ensure_done().lower_delayed_owner(id);
}

let (_, krate) = krate.delayed_resolver.steal();
let prof = self.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 fn parent_module(self, id: HirId) -> LocalModDefId {
if !id.is_owner() && self.def_kind(id.owner) == DefKind::Mod {
LocalModDefId::new_unchecked(id.owner.def_id)
Expand Down Expand Up @@ -475,7 +498,8 @@ pub fn provide(providers: &mut Providers) {
providers.local_def_id_to_hir_id = |tcx, def_id| match tcx.hir_crate(()).owner(tcx, def_id) {
MaybeOwner::Owner(_) => HirId::make_owner(def_id),
MaybeOwner::NonOwner(hir_id) => hir_id,
MaybeOwner::Phantom => bug!("No HirId for {:?}", def_id),
MaybeOwner::Phantom => bug!("no HirId for {:?}", def_id),
MaybeOwner::Delayed(_) => bug!("delayed owner should be lowered {:?}", def_id),
};
providers.opt_hir_owner_nodes =
|tcx, id| tcx.hir_crate(()).owner(tcx, id).as_owner().map(|i| &i.nodes);
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,7 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
return;
}

tcx.force_delayed_owners_lowering();
for owner_id in tcx.hir_crate_items(()).delayed_lint_items() {
if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) {
for lint in &delayed_lints.lints {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,6 @@ help: consider introducing lifetime `'a` here
LL | impl<'a> Trait for Z {
| ++++

error[E0599]: no function or associated item named `new` found for struct `InvariantRef<'a, T>` in the current scope
--> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:9:41
|
LL | pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
| -------------------------------------- function or associated item `new` not found for this struct
...
LL | pub const NEW: Self = InvariantRef::new(&());
| ^^^ function or associated item not found in `InvariantRef<'_, _>`

error[E0277]: the trait bound `u8: Trait` is not satisfied
--> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:12
|
Expand Down Expand Up @@ -119,6 +110,15 @@ LL | reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW
found struct `InvariantRef<'_, ()>`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0599]: no function or associated item named `new` found for struct `InvariantRef<'a, T>` in the current scope
--> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:9:41
|
LL | pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
| -------------------------------------- function or associated item `new` not found for this struct
...
LL | pub const NEW: Self = InvariantRef::new(&());
| ^^^ function or associated item not found in `InvariantRef<'_, _>`

error: aborting due to 10 previous errors

Some errors have detailed explanations: E0261, E0277, E0308, E0599.
Expand Down
Loading
Loading