diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 7ca950e50e610..23ca73647f2bd 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -45,6 +45,7 @@ pub mod visit; pub use self::ast::*; pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasSpan, HasTokens}; +pub use ptr::{AstOwner, AstOwnerRef}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs index 34c539ea16b48..812a338fee5a9 100644 --- a/compiler/rustc_ast/src/ptr.rs +++ b/compiler/rustc_ast/src/ptr.rs @@ -24,6 +24,8 @@ use std::{slice, vec}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::sync::{DynSend, DynSync, Lrc}; + /// An owned smart pointer. /// /// See the [module level documentation][crate::ptr] for details. @@ -208,3 +210,75 @@ where (**self).hash_stable(hcx, hasher); } } + +#[derive(Debug)] +pub enum AstOwnerRef<'a> { + NonOwner, + Synthetic(rustc_span::def_id::LocalDefId), + Crate(&'a crate::Crate), + Item(&'a crate::Item), + TraitItem(&'a crate::AssocItem), + ImplItem(&'a crate::AssocItem), + ForeignItem(&'a crate::ForeignItem), +} + +#[derive(Debug)] +enum AstOwnerPtr { + NonOwner, + Synthetic(rustc_span::def_id::LocalDefId), + Crate, + Item(*const crate::Item), + TraitItem(*const crate::AssocItem), + ImplItem(*const crate::AssocItem), + ForeignItem(*const crate::ForeignItem), +} + +/// Derived pointer to a part of the AST. This data structure is strongly inspired from +/// `owning_ref`, but with restricted API to suit its single use. +#[derive(Debug)] +pub struct AstOwner { + /// Pointer to the full crate. + krate: Lrc, + /// Pointer to an item in that crate. + ptr: AstOwnerPtr, +} + +unsafe impl DynSend for AstOwner {} +unsafe impl DynSync for AstOwner {} + +impl AstOwner { + /// Create a new `AstOwner` from the crate and an item derived from it. + pub unsafe fn new(krate: Lrc, item: AstOwnerRef<'_>) -> AstOwner { + let ptr = match item { + AstOwnerRef::NonOwner => AstOwnerPtr::NonOwner, + AstOwnerRef::Synthetic(def_id) => AstOwnerPtr::Synthetic(def_id), + AstOwnerRef::Crate(_) => AstOwnerPtr::Crate, + AstOwnerRef::Item(item) => AstOwnerPtr::Item(item as *const _), + AstOwnerRef::TraitItem(item) => AstOwnerPtr::TraitItem(item as *const _), + AstOwnerRef::ImplItem(item) => AstOwnerPtr::ImplItem(item as *const _), + AstOwnerRef::ForeignItem(item) => AstOwnerPtr::ForeignItem(item as *const _), + }; + + AstOwner { krate, ptr } + } + + pub fn new_non_owner(krate: Lrc) -> AstOwner { + AstOwner { krate, ptr: AstOwnerPtr::NonOwner } + } + + pub fn as_ref(&self) -> AstOwnerRef<'_> { + match self.ptr { + AstOwnerPtr::NonOwner => AstOwnerRef::NonOwner, + AstOwnerPtr::Synthetic(def_id) => AstOwnerRef::Synthetic(def_id), + AstOwnerPtr::Crate => AstOwnerRef::Crate(&*self.krate), + // SAFETY: the item is live as long as `krate` is. + AstOwnerPtr::Item(item) => AstOwnerRef::Item(unsafe { &*item }), + // SAFETY: the item is live as long as `krate` is. + AstOwnerPtr::TraitItem(item) => AstOwnerRef::TraitItem(unsafe { &*item }), + // SAFETY: the item is live as long as `krate` is. + AstOwnerPtr::ImplItem(item) => AstOwnerRef::ImplItem(unsafe { &*item }), + // SAFETY: the item is live as long as `krate` is. + AstOwnerPtr::ForeignItem(item) => AstOwnerRef::ForeignItem(unsafe { &*item }), + } + } +} diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 666e7763e6276..423bd3e6e09de 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -21,7 +21,7 @@ use rustc_target::asm; use std::collections::hash_map::Entry; use std::fmt::Write; -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub(crate) fn lower_inline_asm( &mut self, diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index e821a08bf1817..ef0098d8cc876 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -4,7 +4,7 @@ use rustc_hir as hir; use smallvec::SmallVec; -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { pub(super) fn lower_block( &mut self, b: &Block, diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 678cac210f413..f50afb6ca5b22 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -60,7 +60,7 @@ pub(crate) struct DelegationResults<'hir> { pub generics: &'hir hir::Generics<'hir>, } -impl<'hir> LoweringContext<'_, 'hir> { +impl<'hir> LoweringContext<'hir> { pub(crate) fn delegation_has_self(&self, item_id: NodeId, path_id: NodeId, span: Span) -> bool { let sig_id = self.get_delegation_sig_id(item_id, path_id, span); let Ok(sig_id) = sig_id else { @@ -253,12 +253,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let arg = if let Some(block) = block && idx == 0 { - let mut self_resolver = SelfResolver { + // TODO + /* let mut self_resolver = SelfResolver { resolver: this.resolver, path_id: delegation.id, self_param_id: pat_node_id, }; - self_resolver.visit_block(block); + self_resolver.visit_block(block); */ let block = this.lower_block(block, false); this.mk_expr(hir::ExprKind::Block(block, None), block.span) } else { @@ -342,6 +343,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } +#[allow(unused)] // TODO struct SelfResolver<'a> { resolver: &'a mut ResolverAstLowering, path_id: NodeId, @@ -349,6 +351,7 @@ struct SelfResolver<'a> { } impl<'a> SelfResolver<'a> { + #[allow(unused)] fn try_replace_id(&mut self, id: NodeId) { if let Some(res) = self.resolver.partial_res_map.get(&id) && let Some(Res::Local(sig_id)) = res.full_res() diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 218fa9740229d..82c1ed945f764 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -24,7 +24,7 @@ use rustc_span::DUMMY_SP; use rustc_span::{DesugaringKind, Span}; use thin_vec::{thin_vec, ThinVec}; -impl<'hir> LoweringContext<'_, 'hir> { +impl<'hir> LoweringContext<'hir> { fn lower_exprs(&mut self, exprs: &[AstP]) -> &'hir [hir::Expr<'hir>] { self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x))) } @@ -1133,7 +1133,7 @@ impl<'hir> LoweringContext<'_, 'hir> { whole_span: Span, ) -> hir::ExprKind<'hir> { // Return early in case of an ordinary assignment. - fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool { + fn is_ordinary(lower_ctx: &mut LoweringContext<'_>, lhs: &Expr) -> bool { match &lhs.kind { ExprKind::Array(..) | ExprKind::Struct(..) diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index ca4604c60c580..ced640f89f0b2 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -12,7 +12,7 @@ use rustc_span::{ }; use std::borrow::Cow; -impl<'hir> LoweringContext<'_, 'hir> { +impl<'hir> LoweringContext<'hir> { pub(crate) fn lower_format_args(&mut self, sp: Span, fmt: &FormatArgs) -> hir::ExprKind<'hir> { // Never call the const constructor of `fmt::Arguments` if the // format_args!() had any arguments _before_ flattening/inlining. @@ -233,7 +233,7 @@ enum ArgumentType { /// ::new_…(arg) /// ``` fn make_argument<'hir>( - ctx: &mut LoweringContext<'_, 'hir>, + ctx: &mut LoweringContext<'hir>, sp: Span, arg: &'hir hir::Expr<'hir>, ty: ArgumentType, @@ -279,7 +279,7 @@ fn make_argument<'hir>( /// ::Implied /// ``` fn make_count<'hir>( - ctx: &mut LoweringContext<'_, 'hir>, + ctx: &mut LoweringContext<'hir>, sp: Span, count: &Option, argmap: &mut FxIndexMap<(usize, ArgumentType), Option>, @@ -332,7 +332,7 @@ fn make_count<'hir>( /// ) /// ``` fn make_format_spec<'hir>( - ctx: &mut LoweringContext<'_, 'hir>, + ctx: &mut LoweringContext<'hir>, sp: Span, placeholder: &FormatPlaceholder, argmap: &mut FxIndexMap<(usize, ArgumentType), Option>, @@ -391,7 +391,7 @@ fn make_format_spec<'hir>( } fn expand_format_args<'hir>( - ctx: &mut LoweringContext<'_, 'hir>, + ctx: &mut LoweringContext<'hir>, macsp: Span, fmt: &FormatArgs, allow_const: bool, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d59ac5766298d..55bf9b1225ad9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,18 +1,15 @@ use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound}; use super::ResolverAstLoweringExt; -use super::{AstOwner, ImplTraitContext, ImplTraitPosition}; use super::{FnDeclKind, LoweringContext, ParamMode}; +use super::{ImplTraitContext, ImplTraitPosition}; use rustc_ast::ptr::P; -use rustc_ast::visit::AssocCtxt; use rustc_ast::*; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::CRATE_DEF_ID; use rustc_hir::PredicateOrigin; -use rustc_index::{IndexSlice, IndexVec}; -use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{kw, sym, Ident}; @@ -22,11 +19,9 @@ use smallvec::{smallvec, SmallVec}; use thin_vec::ThinVec; use tracing::instrument; -pub(super) struct ItemLowerer<'a, 'hir> { +pub(super) struct ItemLowerer<'hir> { pub(super) tcx: TyCtxt<'hir>, - pub(super) resolver: &'a mut ResolverAstLowering, - pub(super) ast_index: &'a IndexSlice>, - pub(super) owners: &'a mut IndexVec>, + pub(super) resolver: &'hir ResolverAstLowering, } /// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span @@ -50,40 +45,24 @@ fn add_ty_alias_where_clause( generics.where_clause.span = where_clause.span; } -impl<'a, 'hir> ItemLowerer<'a, 'hir> { +impl<'hir> ItemLowerer<'hir> { fn with_lctx( &mut self, owner: NodeId, - f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, - ) { - let mut lctx = LoweringContext::new(self.tcx, self.resolver, self.ast_index); - lctx.with_hir_id_owner(owner, |lctx| f(lctx)); - - for (def_id, info) in lctx.children { - let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); - debug_assert!(matches!(owner, hir::MaybeOwner::Phantom)); - *owner = info; - } - } + f: impl FnOnce(&mut LoweringContext<'hir>) -> hir::OwnerNode<'hir>, + ) -> hir::MaybeOwner<'hir> { + let mut lctx = LoweringContext::new(self.tcx, self.resolver, owner); - pub(super) fn lower_node(&mut self, def_id: LocalDefId) -> hir::MaybeOwner<'hir> { - let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); - if let hir::MaybeOwner::Phantom = owner { - let node = self.ast_index[def_id]; - match node { - AstOwner::NonOwner => {} - AstOwner::Crate(c) => self.lower_crate(c), - AstOwner::Item(item) => self.lower_item(item), - AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(item, ctxt), - AstOwner::ForeignItem(item) => self.lower_foreign_item(item), - } - } + let item = f(&mut lctx); + debug_assert_eq!(lctx.current_hir_id_owner, item.def_id()); + + let info = lctx.make_owner_info(item); - self.owners[def_id] + hir::MaybeOwner::Owner(self.tcx.hir_arena.alloc(info)) } #[instrument(level = "debug", skip(self, c))] - fn lower_crate(&mut self, c: &Crate) { + pub(super) fn lower_crate(&mut self, c: &Crate) -> hir::MaybeOwner<'hir> { debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID); self.with_lctx(CRATE_NODE_ID, |lctx| { let module = lctx.lower_mod(&c.items, &c.spans); @@ -93,23 +72,24 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_item(&mut self, item: &Item) { + pub(super) fn lower_item(&mut self, item: &Item) -> hir::MaybeOwner<'hir> { self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) } - fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { - let def_id = self.resolver.node_id_to_def_id[&item.id]; - let parent_id = self.tcx.local_parent(def_id); - let parent_hir = self.lower_node(parent_id).unwrap(); - self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_hir)) + pub(super) fn lower_trait_item(&mut self, item: &AssocItem) -> hir::MaybeOwner<'hir> { + self.with_lctx(item.id, |lctx| hir::OwnerNode::TraitItem(lctx.lower_trait_item(item))) } - fn lower_foreign_item(&mut self, item: &ForeignItem) { + pub(super) fn lower_impl_item(&mut self, item: &AssocItem) -> hir::MaybeOwner<'hir> { + self.with_lctx(item.id, |lctx| hir::OwnerNode::ImplItem(lctx.lower_impl_item(item))) + } + + pub(super) fn lower_foreign_item(&mut self, item: &ForeignItem) -> hir::MaybeOwner<'hir> { self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) } } -impl<'hir> LoweringContext<'_, 'hir> { +impl<'hir> LoweringContext<'hir> { pub(super) fn lower_mod( &mut self, items: &[P], @@ -598,58 +578,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_assoc_item( - &mut self, - item: &AssocItem, - ctxt: AssocCtxt, - parent_hir: &'hir hir::OwnerInfo<'hir>, - ) -> hir::OwnerNode<'hir> { - // Evaluate with the lifetimes in `params` in-scope. - // This is used to track which lifetimes have already been defined, - // and which need to be replicated when lowering an async fn. - - let parent_item = parent_hir.node().expect_item(); - let constness = match parent_item.kind { - hir::ItemKind::Impl(impl_) => { - self.is_in_trait_impl = impl_.of_trait.is_some(); - // N.B. the impl should always lower to methods that have `const host: bool` params if the trait - // is const. It doesn't matter whether the `impl` itself is const. Disallowing const fn from - // calling non-const impls are done through associated types. - if let Some(def_id) = impl_.of_trait.and_then(|tr| tr.trait_def_id()) { - if let Some(local_def) = def_id.as_local() { - match &self.ast_index[local_def] { - AstOwner::Item(ast::Item { attrs, .. }) => attrs - .iter() - .find(|attr| attr.has_name(sym::const_trait)) - .map_or(Const::No, |attr| Const::Yes(attr.span)), - _ => Const::No, - } - } else { - self.tcx - .get_attr(def_id, sym::const_trait) - .map_or(Const::No, |attr| Const::Yes(attr.span)) - } - } else { - Const::No - } - } - hir::ItemKind::Trait(_, _, _, _, _) => parent_hir - .attrs - .get(parent_item.hir_id().local_id) - .iter() - .find(|attr| attr.has_name(sym::const_trait)) - .map_or(Const::No, |attr| Const::Yes(attr.span)), - kind => { - span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr()) - } - }; - - match ctxt { - AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item, constness)), - AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item, constness)), - } - } - fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = self.lower_node_id(i.id); let owner_id = hir_id.expect_owner(); @@ -779,11 +707,14 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_trait_item( - &mut self, - i: &AssocItem, - trait_constness: Const, - ) -> &'hir hir::TraitItem<'hir> { + fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { + let def_id = self.resolver.node_id_to_def_id[&i.id]; + let parent_id = self.tcx.local_parent(def_id); + let constness = self + .tcx + .get_attr(parent_id, sym::const_trait) + .map_or(Const::No, |attr| Const::Yes(attr.span)); + let hir_id = self.lower_node_id(i.id); self.lower_attrs(hir_id, &i.attrs); let trait_item_def_id = hir_id.expect_owner(); @@ -814,7 +745,7 @@ impl<'hir> LoweringContext<'_, 'hir> { i.id, FnDeclKind::Trait, sig.header.coroutine_kind, - trait_constness, + constness, ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } @@ -833,7 +764,7 @@ impl<'hir> LoweringContext<'_, 'hir> { i.id, FnDeclKind::Trait, sig.header.coroutine_kind, - trait_constness, + constness, ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) } @@ -916,11 +847,27 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr(span, hir::ExprKind::Err(guar)) } - fn lower_impl_item( - &mut self, - i: &AssocItem, - constness_of_trait: Const, - ) -> &'hir hir::ImplItem<'hir> { + fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { + let def_id = self.resolver.node_id_to_def_id[&i.id]; + let parent_id = self.tcx.local_parent(def_id); + let parent_item = self.tcx.hir().expect_item(parent_id); + let mut constness_of_trait = Const::No; + match parent_item.kind { + hir::ItemKind::Impl(impl_) => { + self.is_in_trait_impl = impl_.of_trait.is_some(); + // N.B. the impl should always lower to methods that have `const host: bool` params if the trait + // is const. It doesn't matter whether the `impl` itself is const. Disallowing const fn from + // calling non-const impls are done through associated types. + if let Some(def_id) = impl_.of_trait.and_then(|tr| tr.trait_def_id()) { + constness_of_trait = self + .tcx + .get_attr(def_id, sym::const_trait) + .map_or(Const::No, |attr| Const::Yes(attr.span)) + } + } + _ => (), + } + // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); @@ -1178,7 +1125,7 @@ impl<'hir> LoweringContext<'_, 'hir> { pub fn lower_coroutine_body_with_moved_arguments( &mut self, decl: &FnDecl, - lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>, + lower_body: impl FnOnce(&mut LoweringContext<'hir>) -> hir::Expr<'hir>, fn_decl_span: Span, body_span: Span, coroutine_kind: CoroutineKind, @@ -1317,7 +1264,7 @@ impl<'hir> LoweringContext<'_, 'hir> { parameters.push(new_parameter); } - let mkbody = |this: &mut LoweringContext<'_, 'hir>| { + let mkbody = |this: &mut LoweringContext<'hir>| { // Create a block from the user's function body: let user_body = lower_body(this); @@ -1575,8 +1522,8 @@ impl<'hir> LoweringContext<'_, 'hir> { .collect(); // Introduce extra lifetimes if late resolution tells us to. - let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id); - params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| { + let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id); + params.extend(extra_lifetimes.iter().filter_map(|&(ident, node_id, res)| { self.lifetime_res_to_generic_param( ident, node_id, @@ -1605,8 +1552,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let const_expr_id = self.next_id(); let bool_id = self.next_id(); - self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); - self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id))); + self.children.insert(def_id, hir::MaybeOwner::NonOwner(hir_id)); + self.children.insert(anon_const, hir::MaybeOwner::NonOwner(const_id)); let const_body = self.lower_body(|this| { ( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8fba46625ab9a..48935f2440929 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -42,22 +42,23 @@ use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait}; use rustc_ast::node_id::NodeMap; use rustc_ast::ptr::P; +use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; -use rustc_data_structures::fingerprint::Fingerprint; 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::Lrc; +use rustc_data_structures::unord::ExtendUnord; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; -use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; -use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def::{DefKind, FreshLifetimeResId, LifetimeRes, Namespace, PartialRes, PerNS, Res}; +use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, LOCAL_CRATE}; use rustc_hir::{self as hir}; use rustc_hir::{ ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate, }; -use rustc_index::{Idx, IndexSlice, IndexVec}; +use rustc_index::{Idx, IndexVec}; use rustc_macros::extension; use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; @@ -86,12 +87,15 @@ mod item; mod lifetime_collector; mod pat; mod path; +mod query; + +pub use query::provide; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } -struct LoweringContext<'a, 'hir> { +struct LoweringContext<'hir> { tcx: TyCtxt<'hir>, - resolver: &'a mut ResolverAstLowering, + resolver: &'hir ResolverAstLowering, /// Used to allocate HIR nodes. arena: &'hir hir::Arena<'hir>, @@ -101,7 +105,7 @@ struct LoweringContext<'a, 'hir> { /// Attributes inside the owner being lowered. attrs: SortedMap, /// Collect items that were created by lowering the current owner. - children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>, + children: LocalDefIdMap>, coroutine_kind: Option, @@ -121,13 +125,19 @@ struct LoweringContext<'a, 'hir> { current_hir_id_owner: hir::OwnerId, item_local_id_counter: hir::ItemLocalId, - trait_map: ItemLocalMap>, + trait_map: ItemLocalMap<&'hir [TraitCandidate]>, impl_trait_defs: Vec>, impl_trait_bounds: Vec>, /// NodeIds that are lowered inside the current HIR owner. node_id_to_local_id: NodeMap, + /// The `NodeId` space is split in two. + /// `0..resolver.next_node_id` are created by the resolver on the AST. + /// The higher part `resolver.next_node_id..next_node_id` are created during lowering. + next_node_id: NodeId, + /// Maps the `NodeId`s created during lowering to `LocalDefId`s. + node_id_to_def_id: NodeMap, allow_try_trait: Lrc<[Symbol]>, allow_gen_future: Lrc<[Symbol]>, @@ -142,15 +152,11 @@ struct LoweringContext<'a, 'hir> { generics_def_id_map: Vec>, host_param_id: Option, - ast_index: &'a IndexSlice>, } -impl<'a, 'hir> LoweringContext<'a, 'hir> { - fn new( - tcx: TyCtxt<'hir>, - resolver: &'a mut ResolverAstLowering, - ast_index: &'a IndexSlice>, - ) -> Self { +impl<'hir> LoweringContext<'hir> { + fn new(tcx: TyCtxt<'hir>, resolver: &'hir ResolverAstLowering, owner: NodeId) -> Self { + let current_hir_id_owner = hir::OwnerId { def_id: resolver.node_id_to_def_id[&owner] }; Self { // Pseudo-globals. tcx, @@ -160,11 +166,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // HirId handling. bodies: Vec::new(), attrs: SortedMap::default(), - children: Vec::default(), - current_hir_id_owner: hir::CRATE_OWNER_ID, - item_local_id_counter: hir::ItemLocalId::ZERO, - node_id_to_local_id: Default::default(), + children: LocalDefIdMap::default(), + current_hir_id_owner, + item_local_id_counter: hir::ItemLocalId::new(1), + node_id_to_local_id: [(owner, hir::ItemLocalId::ZERO)].into_iter().collect(), trait_map: Default::default(), + next_node_id: resolver.next_node_id, + node_id_to_def_id: NodeMap::default(), // Lowering state. catch_scope: None, @@ -190,7 +198,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { allow_async_iterator: [sym::gen_future, sym::async_iterator].into(), generics_def_id_map: Default::default(), host_param_id: None, - ast_index, } } @@ -253,8 +260,8 @@ impl ResolverAstLowering { /// /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring /// should appear at the enclosing `PolyTraitRef`. - fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> { - self.extra_lifetime_params_map.remove(&id).unwrap_or_default() + fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, LifetimeRes)] { + self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) } } @@ -352,114 +359,123 @@ enum FnDeclKind { Impl, } -#[derive(Copy, Clone)] -enum AstOwner<'a> { - NonOwner, - Crate(&'a ast::Crate), - Item(&'a ast::Item), - AssocItem(&'a ast::AssocItem, visit::AssocCtxt), - ForeignItem(&'a ast::ForeignItem), -} +fn index_ast<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexVec> { + // Queries that borrow `resolver_for_lowering`. + tcx.ensure_with_value().output_filenames(()); + tcx.ensure_with_value().early_lint_checks(()); + tcx.ensure_with_value().get_lang_items(()); + tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE); -fn index_crate<'a>( - node_id_to_def_id: &NodeMap, - krate: &'a Crate, -) -> IndexVec> { - let mut indexer = Indexer { node_id_to_def_id, index: IndexVec::new() }; - *indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner) = - AstOwner::Crate(krate); - visit::walk_crate(&mut indexer, krate); - return indexer.index; - - struct Indexer<'s, 'a> { + let (resolver, krate) = tcx.resolver_for_lowering(); + let krate = krate.steal(); + + let mut indexer = Indexer { + krate: krate.clone(), + node_id_to_def_id: &resolver.node_id_to_def_id, + index: IndexVec::new(), + }; + indexer.visit_crate(&krate); + indexer.insert(CRATE_NODE_ID, AstOwnerRef::Crate(&*krate)); + return tcx.arena.alloc(indexer.index); + + struct Indexer<'s> { + krate: Lrc, node_id_to_def_id: &'s NodeMap, - index: IndexVec>, + index: IndexVec>, + } + + impl Indexer<'_> { + fn insert(&mut self, id: NodeId, node: AstOwnerRef<'_>) { + let def_id = self.node_id_to_def_id[&id]; + self.index.ensure_contains_elem(def_id, || { + Steal::new(AstOwner::new_non_owner(self.krate.clone())) + }); + let node = unsafe { AstOwner::new(self.krate.clone(), node) }; + self.index[def_id] = Steal::new(node); + } + + fn visit_item_id_use_tree(&mut self, tree: &UseTree, parent: LocalDefId) { + match tree.kind { + UseTreeKind::Glob | UseTreeKind::Simple(_) => {} + UseTreeKind::Nested { items: ref nested_vec, span: _ } => { + for &(ref nested, id) in nested_vec { + self.insert(id, AstOwnerRef::Synthetic(parent)); + + let def_id = self.node_id_to_def_id[&id]; + self.visit_item_id_use_tree(nested, def_id); + } + } + } + } } - impl<'a> visit::Visitor<'a> for Indexer<'_, 'a> { - fn visit_attribute(&mut self, _: &'a Attribute) { + impl<'ast> Visitor<'ast> for Indexer<'_> { + fn visit_attribute(&mut self, _: &Attribute) { // We do not want to lower expressions that appear in attributes, // as they are not accessible to the rest of the HIR. } - fn visit_item(&mut self, item: &'a ast::Item) { + fn visit_item(&mut self, item: &'ast Item) { let def_id = self.node_id_to_def_id[&item.id]; - *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = AstOwner::Item(item); - visit::walk_item(self, item) + if let ItemKind::Use(ref use_tree) = item.kind { + self.visit_item_id_use_tree(use_tree, def_id); + } + visit::walk_item(self, item); + self.insert(item.id, AstOwnerRef::Item(item)); } - fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) { - let def_id = self.node_id_to_def_id[&item.id]; - *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = - AstOwner::AssocItem(item, ctxt); - visit::walk_assoc_item(self, item, ctxt); + fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: visit::AssocCtxt) { + visit::walk_item(self, item); + let owner_ref = match ctxt { + visit::AssocCtxt::Trait => AstOwnerRef::TraitItem(item), + visit::AssocCtxt::Impl => AstOwnerRef::ImplItem(item), + }; + self.insert(item.id, owner_ref); } - fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) { - let def_id = self.node_id_to_def_id[&item.id]; - *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = - AstOwner::ForeignItem(item); + fn visit_foreign_item(&mut self, item: &'ast ForeignItem) { visit::walk_item(self, item); + self.insert(item.id, AstOwnerRef::ForeignItem(item)); } } } -/// Compute the hash for the HIR of the full crate. -/// This hash will then be part of the crate_hash which is stored in the metadata. -fn compute_hir_hash( - tcx: TyCtxt<'_>, - owners: &IndexSlice>, -) -> Fingerprint { - let mut hir_body_nodes: Vec<_> = owners - .iter_enumerated() - .filter_map(|(def_id, info)| { - let info = info.as_owner()?; - let def_path_hash = tcx.hir().def_path_hash(def_id); - Some((def_path_hash, info)) - }) - .collect(); - hir_body_nodes.sort_unstable_by_key(|bn| bn.0); - - tcx.with_stable_hashing_context(|mut hcx| { - let mut stable_hasher = StableHasher::new(); - hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); - stable_hasher.finish() - }) -} - -pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { - let sess = tcx.sess; - // Queries that borrow `resolver_for_lowering`. - tcx.ensure_with_value().output_filenames(()); - tcx.ensure_with_value().early_lint_checks(()); - tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE); - tcx.ensure_with_value().get_lang_items(()); - let (mut resolver, krate) = tcx.resolver_for_lowering().steal(); +fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> { + let (resolver, _) = tcx.resolver_for_lowering(); + let ast_index = tcx.index_ast(()); + let node = ast_index.get(def_id).map(Steal::steal); - let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); - let mut owners = IndexVec::from_fn_n( - |_| hir::MaybeOwner::Phantom, - tcx.definitions_untracked().def_index_count(), - ); + let mut item_lowerer = item::ItemLowerer { tcx, resolver }; - for def_id in ast_index.indices() { - item::ItemLowerer { - tcx, - resolver: &mut resolver, - ast_index: &ast_index, - owners: &mut owners, + // The item existed in the AST. + let parent_id = match node.as_ref().map(AstOwner::as_ref) { + Some(AstOwnerRef::Crate(c)) => return item_lowerer.lower_crate(&c), + Some(AstOwnerRef::Item(item)) => return item_lowerer.lower_item(&item), + Some(AstOwnerRef::TraitItem(item)) => { + return item_lowerer.lower_trait_item(&item); } - .lower_node(def_id); - } + Some(AstOwnerRef::ImplItem(item)) => { + return item_lowerer.lower_impl_item(&item); + } + Some(AstOwnerRef::ForeignItem(item)) => return item_lowerer.lower_foreign_item(&item), + Some(AstOwnerRef::Synthetic(parent_id)) => parent_id, + Some(AstOwnerRef::NonOwner) | None => tcx.local_parent(def_id), + }; - // Drop AST to free memory - drop(ast_index); - sess.time("drop_ast", || drop(krate)); + // The item did not exist in the AST, it was created by its parent. + let mut parent_info = tcx.lower_to_hir(parent_id); + if let hir::MaybeOwner::NonOwner(hir_id) = parent_info { + parent_info = tcx.lower_to_hir(hir_id.owner); + } - // Don't hash unless necessary, because it's expensive. - let opt_hir_hash = - if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None }; - hir::Crate { owners, opt_hir_hash } + let parent_info = parent_info.unwrap(); + *parent_info.children.get(&def_id).unwrap_or_else(|| { + panic!( + "{:?} does not appear in children of {:?}", + def_id, + parent_info.nodes.node().def_id() + ) + }) } #[derive(Copy, Clone, PartialEq, Debug)] @@ -477,7 +493,7 @@ enum ParenthesizedGenericArgs { Err, } -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { fn create_def( &mut self, parent: LocalDefId, @@ -498,22 +514,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id(); debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); - self.resolver.node_id_to_def_id.insert(node_id, def_id); + self.node_id_to_def_id.insert(node_id, def_id); def_id } fn next_node_id(&mut self) -> NodeId { - let start = self.resolver.next_node_id; + let start = self.next_node_id; let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds"); - self.resolver.next_node_id = ast::NodeId::from_u32(next); + self.next_node_id = ast::NodeId::from_u32(next); start } /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name /// resolver (if any). fn orig_opt_local_def_id(&self, node: NodeId) -> Option { - self.resolver.node_id_to_def_id.get(&node).copied() + self.resolver + .node_id_to_def_id + .get(&node) + .or_else(|| self.node_id_to_def_id.get(&node)) + .copied() } /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name @@ -583,6 +603,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1)); let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs); let current_impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds); + let current_children = std::mem::take(&mut self.children); // Do not reset `next_node_id` and `node_id_to_def_id`: // we want `f` to be able to refer to the `LocalDefId`s that the caller created. @@ -607,9 +628,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.item_local_id_counter = current_local_counter; self.impl_trait_defs = current_impl_trait_defs; self.impl_trait_bounds = current_impl_trait_bounds; + self.children = current_children; + self.children.extend_unord(info.children.items().map(|(&def_id, &info)| (def_id, info))); - debug_assert!(!self.children.iter().any(|(id, _)| id == &def_id)); - self.children.push((def_id, hir::MaybeOwner::Owner(info))); + debug_assert!(!self.children.contains_key(&def_id)); + self.children.insert(def_id, hir::MaybeOwner::Owner(info)); } /// Installs the remapping `remap` in scope while `f` is being executed. @@ -637,6 +660,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let attrs = std::mem::take(&mut self.attrs); let mut bodies = std::mem::take(&mut self.bodies); let trait_map = std::mem::take(&mut self.trait_map); + let children = std::mem::take(&mut self.children); #[cfg(debug_assertions)] for (id, attrs) in attrs.iter() { @@ -657,7 +681,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies }; let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash }; - self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map }) + self.tcx.hir_arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map, children }) } /// This method allocates a new `HirId` for the given `NodeId` and stores it in @@ -683,11 +707,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { assert_ne!(local_id, hir::ItemLocalId::ZERO); if let Some(def_id) = self.opt_local_def_id(ast_node_id) { - self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); + self.children.insert(def_id, hir::MaybeOwner::NonOwner(hir_id)); } - if let Some(traits) = self.resolver.trait_map.remove(&ast_node_id) { - self.trait_map.insert(hir_id.local_id, traits.into_boxed_slice()); + if let Some(traits) = self.resolver.trait_map.get(&ast_node_id) { + self.trait_map.insert(hir_id.local_id, &traits[..]); } hir_id @@ -790,6 +814,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Ident::new(ident.name, self.lower_span(ident.span)) } + fn lower_fresh_lifetime_res(&mut self, id: FreshLifetimeResId, node_id: NodeId) -> LocalDefId { + let def_id = self.tcx.fresh_lifetime_def_id(id); + // make sure that this `NodeId` is known to us. + self.node_id_to_def_id.insert(node_id, def_id); + trace!(?self.current_hir_id_owner, ?def_id); + def_id + } + /// Converts a lifetime into a new generic parameter. #[instrument(level = "debug", skip(self))] fn lifetime_res_to_generic_param( @@ -803,17 +835,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Param { .. } => { (hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit) } - LifetimeRes::Fresh { param, kind, .. } => { - // Late resolution delegates to us the creation of the `LocalDefId`. - let _def_id = self.create_def( - self.current_hir_id_owner.def_id, - param, - kw::UnderscoreLifetime, - DefKind::LifetimeParam, - ident.span, - ); - debug!(?_def_id); - + LifetimeRes::Fresh { id, kind, param, .. } => { + debug_assert_eq!(param, node_id); + self.lower_fresh_lifetime_res(id, node_id); (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind)) } LifetimeRes::Static | LifetimeRes::Error => return None, @@ -851,9 +875,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut generic_params: Vec<_> = self .lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder) .collect(); - let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder); + let extra_lifetimes = self.resolver.extra_lifetime_params(binder); debug!(?extra_lifetimes); - generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| { + generic_params.extend(extra_lifetimes.iter().filter_map(|&(ident, node_id, res)| { self.lifetime_res_to_generic_param(ident, node_id, res, hir::GenericParamSource::Binder) })); let generic_params = self.arena.alloc_from_iter(generic_params); @@ -1567,9 +1591,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // decided to capture all in-scope lifetimes, which we collect for // all opaques during resolution. self.resolver - .take_extra_lifetime_params(opaque_ty_node_id) - .into_iter() - .map(|(ident, id, _)| Lifetime { id, ident }) + .extra_lifetime_params(opaque_ty_node_id) + .iter() + .map(|&(ident, id, _)| Lifetime { id, ident }) .collect() } hir::OpaqueTyOrigin::FnReturn(..) => { @@ -1582,9 +1606,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // return-position impl trait in trait was decided to capture all // in-scope lifetimes, which we collect for all opaques during resolution. self.resolver - .take_extra_lifetime_params(opaque_ty_node_id) - .into_iter() - .map(|(ident, id, _)| Lifetime { id, ident }) + .extra_lifetime_params(opaque_ty_node_id) + .iter() + .map(|&(ident, id, _)| Lifetime { id, ident }) .collect() } else { // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` @@ -1667,15 +1691,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (old_def_id, missing_kind) = match res { LifetimeRes::Param { param: old_def_id, binder: _ } => (old_def_id, None), - LifetimeRes::Fresh { param, kind, .. } => { + LifetimeRes::Fresh { id, kind, .. } => { debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); - if let Some(old_def_id) = self.orig_opt_local_def_id(param) { - (old_def_id, Some(kind)) - } else { - self.dcx() - .span_delayed_bug(lifetime.ident.span, "no def-id for fresh lifetime"); - continue; - } + (self.tcx.fresh_lifetime_def_id(id), Some(kind)) } // Opaques do not capture `'static` @@ -1969,9 +1987,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let captured_lifetimes = self .resolver - .take_extra_lifetime_params(opaque_ty_node_id) - .into_iter() - .map(|(ident, id, _)| Lifetime { id, ident }) + .extra_lifetime_params(opaque_ty_node_id) + .iter() + .map(|&(ident, id, _)| Lifetime { id, ident }) .collect(); let opaque_ty_ref = self.lower_opaque_inner( @@ -2087,8 +2105,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let param = self.get_remapped_def_id(param); hir::LifetimeName::Param(param) } - LifetimeRes::Fresh { param, .. } => { - let param = self.local_def_id(param); + LifetimeRes::Fresh { id, .. } => { + let param = self.get_remapped_def_id(self.tcx.fresh_lifetime_def_id(id)); hir::LifetimeName::Param(param) } LifetimeRes::Infer => hir::LifetimeName::Infer, @@ -2123,7 +2141,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &'s mut self, params: &'s [GenericParam], source: hir::GenericParamSource, - ) -> impl Iterator> + Captures<'a> + Captures<'s> { + ) -> impl Iterator> + Captures<'s> { params.iter().map(move |param| self.lower_generic_param(param, source)) } @@ -2287,7 +2305,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &'s mut self, bounds: &'s [GenericBound], itctx: ImplTraitContext, - ) -> impl Iterator> + Captures<'s> + Captures<'a> { + ) -> impl Iterator> + Captures<'s> { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) } @@ -2624,7 +2642,7 @@ impl<'hir> GenericArgsCtor<'hir> { && self.parenthesized == hir::GenericArgsParentheses::No } - fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> { + fn into_generic_args(self, this: &LoweringContext<'hir>) -> &'hir hir::GenericArgs<'hir> { let ga = hir::GenericArgs { args: this.arena.alloc_from_iter(self.args), constraints: self.constraints, diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 32de07a0755e2..47dcf15f773fb 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -13,7 +13,7 @@ use rustc_hir::def::Res; use rustc_span::symbol::Ident; use rustc_span::{source_map::Spanned, Span}; -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> { self.arena.alloc(self.lower_pat_mut(pattern)) } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 9a1ca703699a8..5e62d0ae341e8 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -20,7 +20,7 @@ use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use tracing::{debug, instrument}; -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { #[instrument(level = "trace", skip(self))] pub(crate) fn lower_qpath( &mut self, diff --git a/compiler/rustc_ast_lowering/src/query.rs b/compiler/rustc_ast_lowering/src/query.rs new file mode 100644 index 0000000000000..9376e261a88db --- /dev/null +++ b/compiler/rustc_ast_lowering/src/query.rs @@ -0,0 +1,275 @@ +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::svh::Svh; +use rustc_hir::def::{DefKind, FreshLifetimeResId}; +use rustc_hir::def_id::{LocalDefId, LocalModDefId, StableCrateId, LOCAL_CRATE}; +use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::*; +use rustc_middle::hir::{nested_filter, ModuleItems}; +use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; +use rustc_middle::query::{LocalCrate, Providers}; +use rustc_middle::ty::TyCtxt; +use rustc_span::symbol::kw; +use rustc_span::DUMMY_SP; + +use crate::{index_ast, lower_to_hir}; + +pub fn provide(providers: &mut Providers) { + *providers = Providers { + lower_to_hir, + index_ast, + fresh_lifetime_def_id, + crate_hash, + hir_module_items, + hir_crate_items, + ..*providers + }; +} + +fn fresh_lifetime_def_id(tcx: TyCtxt<'_>, id: FreshLifetimeResId) -> LocalDefId { + let (resolver, _) = tcx.resolver_for_lowering(); + let (span, node_id) = resolver.fresh_lifetime_res_info[id]; + let parent = *resolver + .node_id_to_def_id + .get(&node_id) + .expect("binder for fresh lifetime is not associated with a DefId?"); + + tcx.at(span).create_def(parent, kw::UnderscoreLifetime, DefKind::LifetimeParam).def_id() +} + +fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { + let mut hir_body_nodes: Vec<_> = tcx + .hir_crate_items(()) + .owners() + .map(|owner| { + let def_id = owner.def_id; + let def_path_hash = tcx.hir().def_path_hash(def_id); + let info = tcx.lower_to_hir(def_id).unwrap(); + let span = if tcx.sess.opts.incremental.is_some() { + tcx.source_span(def_id) + } else { + DUMMY_SP + }; + debug_assert_eq!(span.parent(), None); + (def_path_hash, info, span) + }) + .collect(); + hir_body_nodes.sort_unstable_by_key(|bn| bn.0); + + let upstream_crates = upstream_crates(tcx); + + let resolutions = tcx.resolutions(()); + + // We hash the final, remapped names of all local source files so we + // don't have to include the path prefix remapping commandline args. + // If we included the full mapping in the SVH, we could only have + // reproducible builds by compiling from the same directory. So we just + // hash the result of the mapping instead of the mapping itself. + let mut source_file_names: Vec<_> = tcx + .sess + .source_map() + .files() + .iter() + .filter(|source_file| source_file.cnum == LOCAL_CRATE) + .map(|source_file| source_file.stable_id) + .collect(); + + source_file_names.sort_unstable(); + + // We have to take care of debugger visualizers explicitly. The HIR (and + // thus `hir_body_hash`) contains the #[debugger_visualizer] attributes but + // these attributes only store the file path to the visualizer file, not + // their content. Yet that content is exported into crate metadata, so any + // changes to it need to be reflected in the crate hash. + let debugger_visualizers: Vec<_> = tcx + .debugger_visualizers(LOCAL_CRATE) + .iter() + // We ignore the path to the visualizer file since it's not going to be + // encoded in crate metadata and we already hash the full contents of + // the file. + .map(DebuggerVisualizerFile::path_erased) + .collect(); + + let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); + upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); + source_file_names.hash_stable(&mut hcx, &mut stable_hasher); + debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher); + tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); + tcx.stable_crate_id(LOCAL_CRATE).hash_stable(&mut hcx, &mut stable_hasher); + // Hash visibility information since it does not appear in HIR. + // FIXME: Figure out how to remove `visibilities_for_hashing` by hashing visibilities on + // the fly in the resolver, storing only their accumulated hash in `ResolverGlobalCtxt`, + // and combining it with other hashes here. + resolutions.visibilities_for_hashing.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + }); + + Svh::new(crate_hash) +} + +fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { + let mut upstream_crates: Vec<_> = tcx + .crates(()) + .iter() + .map(|&cnum| { + let stable_crate_id = tcx.stable_crate_id(cnum); + let hash = tcx.crate_hash(cnum); + (stable_crate_id, hash) + }) + .collect(); + upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id); + upstream_crates +} + +fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> ModuleItems { + let mut collector = ItemCollector::new(tcx, false); + + let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); + collector.visit_mod(hir_mod, span, hir_id); + + let ItemCollector { + submodules, + items, + trait_items, + impl_items, + foreign_items, + body_owners, + .. + } = collector; + return ModuleItems { + add_root: false, + submodules: submodules.into_boxed_slice(), + free_items: items.into_boxed_slice(), + trait_items: trait_items.into_boxed_slice(), + impl_items: impl_items.into_boxed_slice(), + foreign_items: foreign_items.into_boxed_slice(), + body_owners: body_owners.into_boxed_slice(), + }; +} + +fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { + let mut collector = ItemCollector::new(tcx, true); + + // A "crate collector" and "module collector" start at a + // module item (the former starts at the crate root) but only + // the former needs to collect it. ItemCollector does not do this for us. + collector.submodules.push(CRATE_OWNER_ID); + tcx.hir().walk_toplevel_module(&mut collector); + + let ItemCollector { + submodules, + items, + trait_items, + impl_items, + foreign_items, + body_owners, + .. + } = collector; + + return ModuleItems { + add_root: true, + submodules: submodules.into_boxed_slice(), + free_items: items.into_boxed_slice(), + trait_items: trait_items.into_boxed_slice(), + impl_items: impl_items.into_boxed_slice(), + foreign_items: foreign_items.into_boxed_slice(), + body_owners: body_owners.into_boxed_slice(), + }; +} + +struct ItemCollector<'tcx> { + // When true, it collects all items in the create, + // otherwise it collects items in some module. + crate_collector: bool, + tcx: TyCtxt<'tcx>, + submodules: Vec, + items: Vec, + trait_items: Vec, + impl_items: Vec, + foreign_items: Vec, + body_owners: Vec, +} + +impl<'tcx> ItemCollector<'tcx> { + fn new(tcx: TyCtxt<'tcx>, crate_collector: bool) -> ItemCollector<'tcx> { + ItemCollector { + crate_collector, + tcx, + submodules: Vec::default(), + items: Vec::default(), + trait_items: Vec::default(), + impl_items: Vec::default(), + foreign_items: Vec::default(), + body_owners: Vec::default(), + } + } +} + +impl<'hir> Visitor<'hir> for ItemCollector<'hir> { + type NestedFilter = nested_filter::All; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + + fn visit_item(&mut self, item: &'hir Item<'hir>) { + if Node::Item(item).associated_body().is_some() { + self.body_owners.push(item.owner_id.def_id); + } + + self.items.push(item.item_id()); + + // Items that are modules are handled here instead of in visit_mod. + if let ItemKind::Mod(module) = &item.kind { + self.submodules.push(item.owner_id); + // A module collector does not recurse inside nested modules. + if self.crate_collector { + intravisit::walk_mod(self, module, item.hir_id()); + } + } else { + intravisit::walk_item(self, item) + } + } + + fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { + self.foreign_items.push(item.foreign_item_id()); + intravisit::walk_foreign_item(self, item) + } + + fn visit_anon_const(&mut self, c: &'hir AnonConst) { + self.body_owners.push(c.def_id); + intravisit::walk_anon_const(self, c) + } + + fn visit_inline_const(&mut self, c: &'hir ConstBlock) { + self.body_owners.push(c.def_id); + intravisit::walk_inline_const(self, c) + } + + fn visit_expr(&mut self, ex: &'hir Expr<'hir>) { + if let ExprKind::Closure(closure) = ex.kind { + self.body_owners.push(closure.def_id); + } + intravisit::walk_expr(self, ex) + } + + fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { + if Node::TraitItem(item).associated_body().is_some() { + self.body_owners.push(item.owner_id.def_id); + } + + self.trait_items.push(item.trait_item_id()); + intravisit::walk_trait_item(self, item) + } + + fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { + if Node::ImplItem(item).associated_body().is_some() { + self.body_owners.push(item.owner_id.def_id); + } + + self.impl_items.push(item.impl_item_id()); + intravisit::walk_impl_item(self, item) + } +} diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 31de0a747b24f..4b6e0f6083838 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -209,7 +209,7 @@ impl<'tcx> PrintExtra<'tcx> { { match self { PrintExtra::AfterParsing { krate, .. } => f(krate), - PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering().borrow().1), + PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering().1.borrow()), } } @@ -261,7 +261,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { } AstTreeExpanded => { debug!("pretty-printing expanded AST"); - format!("{:#?}", ex.tcx().resolver_for_lowering().borrow().1) + format!("{:#?}", ex.tcx().resolver_for_lowering().1.borrow()) } Hir(s) => { debug!("pretty printing HIR {:?}", s); @@ -293,7 +293,11 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { } HirTree => { debug!("pretty printing HIR tree"); - format!("{:#?}", ex.tcx().hir().krate()) + let tcx = ex.tcx(); + tcx.hir_crate_items(()) + .owners() + .map(|owner| format!("{:#?} => {:#?}\n", owner, tcx.lower_to_hir(owner))) + .collect() } Mir => { let mut out = Vec::new(); diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index b1854923247f8..2a55b4d43f25e 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -791,6 +791,15 @@ impl Res { } } +rustc_index::newtype_index! { + /// Identifies a fresh lifetime, for example desugared from `'_`. + #[encodable] + #[orderable] + #[debug_format = "FreshLifetimeResId({})"] + #[derive(HashStable_Generic)] + pub struct FreshLifetimeResId {} +} + /// Resolution for a lifetime appearing in a type. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum LifetimeRes { @@ -809,9 +818,9 @@ pub enum LifetimeRes { }, /// Created a generic parameter for an anonymous lifetime. Fresh { - /// Id of the generic parameter that introduced it. - /// - /// Creating the associated `LocalDefId` is the responsibility of lowering. + /// The id for tracking creating the associated `LocalDefId` + id: FreshLifetimeResId, + /// The `NodeId` for ast lowering to link to the `LocalDefId`. param: NodeId, /// Id of the introducing place. See `Param`. binder: NodeId, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6cccdec94c0b5..dab3095a52b0b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -11,6 +11,7 @@ pub use rustc_ast::{ImplPolarity, IsAuto, Movability, Mutability, UnOp}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; +use rustc_data_structures::unord::UnordMap; use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::hygiene::MacroKind; @@ -951,7 +952,9 @@ pub struct OwnerInfo<'hir> { pub attrs: AttributeMap<'hir>, /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. - pub trait_map: ItemLocalMap>, + pub trait_map: ItemLocalMap<&'hir [TraitCandidate]>, + /// Owners generated as side-effect by lowering. + pub children: UnordMap>, } impl<'tcx> OwnerInfo<'tcx> { @@ -965,15 +968,13 @@ impl<'tcx> OwnerInfo<'tcx> { pub enum MaybeOwner<'tcx> { Owner(&'tcx OwnerInfo<'tcx>), NonOwner(HirId), - /// Used as a placeholder for unused LocalDefId. - Phantom, } 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, + MaybeOwner::NonOwner(_) => None, } } @@ -982,19 +983,6 @@ impl<'tcx> MaybeOwner<'tcx> { } } -/// The top-level data structure that stores the entire contents of -/// the crate currently being compiled. -/// -/// For more details, see the [rustc dev guide]. -/// -/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html -#[derive(Debug)] -pub struct Crate<'hir> { - pub owners: IndexVec>, - // Only present when incr. comp. is enabled. - pub opt_hir_hash: Option, -} - #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Closure<'hir> { pub def_id: LocalDefId, diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index baa1635f7313f..b921f30122c5e 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -1,7 +1,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use crate::hir::{ - AttributeMap, BodyId, Crate, ForeignItemId, ImplItemId, ItemId, OwnerNodes, TraitItemId, + AttributeMap, BodyId, ForeignItemId, ImplItemId, ItemId, OwnerNodes, TraitItemId, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -106,10 +106,3 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap opt_hash.unwrap().hash_stable(hcx, hasher); } } - -impl HashStable for Crate<'_> { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - let Crate { owners: _, opt_hir_hash } = self; - opt_hir_hash.unwrap().hash_stable(hcx, hasher) - } -} diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index cad7870a0a1d8..588ae9bf73f93 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2080,7 +2080,11 @@ pub fn deny_non_region_late_bound( for (var, arg) in bound_vars { let Node::GenericParam(param) = tcx.hir_node_by_def_id(*var) else { - span_bug!(tcx.def_span(*var), "expected bound-var def-id to resolve to param"); + span_bug!( + tcx.def_span(*var), + "expected bound-var def-id to resolve to param: {:?}", + tcx.hir_node_by_def_id(*var) + ); }; let what = match param.kind { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 2951f50b1f598..b3de5ee924272 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -289,7 +289,8 @@ fn configure_and_expand( fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let sess = tcx.sess; - let (resolver, krate) = &*tcx.resolver_for_lowering().borrow(); + let (resolver, krate) = tcx.resolver_for_lowering(); + let krate = &*krate.borrow(); let mut lint_buffer = resolver.lint_buffer.steal(); if sess.opts.unstable_opts.input_stats { @@ -543,7 +544,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P fn resolver_for_lowering_raw<'tcx>( tcx: TyCtxt<'tcx>, (): (), -) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc)>, &'tcx ty::ResolverGlobalCtxt) { +) -> (&'tcx (ty::ResolverAstLowering, Steal>), &'tcx ty::ResolverGlobalCtxt) { let arenas = Resolver::arenas(); let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`. let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal(); @@ -559,7 +560,7 @@ fn resolver_for_lowering_raw<'tcx>( } = resolver.into_outputs(); let resolutions = tcx.arena.alloc(untracked_resolutions); - (tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions) + (tcx.arena.alloc((untracked_resolver_for_lowering, Steal::new(Lrc::new(krate)))), resolutions) } pub fn write_dep_info(tcx: TyCtxt<'_>) { @@ -614,12 +615,12 @@ pub fn write_dep_info(tcx: TyCtxt<'_>) { pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; - providers.hir_crate = rustc_ast_lowering::lower_to_hir; providers.resolver_for_lowering_raw = resolver_for_lowering_raw; providers.stripped_cfg_items = |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal()); providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1; providers.early_lint_checks = early_lint_checks; + rustc_ast_lowering::provide(providers); proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); @@ -740,6 +741,8 @@ pub(crate) fn create_global_ctxt<'tcx>( /// 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<'_>) { + tcx.ensure().early_lint_checks(()); + if tcx.sess.opts.unstable_opts.hir_stats { rustc_passes::hir_stats::print_hir_stats(tcx); } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index e3d7dff3c66bb..74ab330ee0d5e 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -29,10 +29,13 @@ macro_rules! arena_types { >, [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, [decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>, - [] resolver: rustc_data_structures::steal::Steal<( + [] resolver: ( rustc_middle::ty::ResolverAstLowering, - rustc_data_structures::sync::Lrc, - )>, + rustc_data_structures::steal::Steal> + ), + [] index_ast: rustc_index::IndexVec + >, [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, [decode] code_region: rustc_middle::mir::coverage::CodeRegion, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 305ba1ef3bbc8..dafd482cb92c6 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,21 +1,13 @@ -use crate::hir::ModuleItems; -use crate::middle::debugger_visualizer::DebuggerVisualizerFile; -use crate::query::LocalCrate; use crate::ty::TyCtxt; use rustc_ast as ast; use rustc_ast::visit::{walk_list, VisitorResult}; -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::{par_for_each_in, try_par_for_each_in, DynSend, DynSync}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::intravisit::Visitor; use rustc_hir::*; use rustc_hir_pretty as pprust_hir; -use rustc_middle::hir::nested_filter; -use rustc_span::def_id::StableCrateId; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ErrorGuaranteed, Span}; use rustc_target::spec::abi::Abi; @@ -151,11 +143,6 @@ impl<'tcx> TyCtxt<'tcx> { } impl<'hir> Map<'hir> { - #[inline] - pub fn krate(self) -> &'hir Crate<'hir> { - self.tcx.hir_crate(()) - } - #[inline] pub fn root_module(self) -> &'hir Mod<'hir> { match self.tcx.hir_owner_node(CRATE_OWNER_ID) { @@ -394,12 +381,11 @@ impl<'hir> Map<'hir> { where V: Visitor<'hir>, { - let krate = self.krate(); - for info in krate.owners.iter() { - if let MaybeOwner::Owner(info) = info { - for attrs in info.attrs.map.values() { - walk_list!(visitor, visit_attribute, *attrs); - } + let krate = self.tcx.hir_crate_items(()); + for owner in krate.owners() { + let attrs = self.tcx.hir_attrs(owner); + for attrs in attrs.map.values() { + walk_list!(visitor, visit_attribute, *attrs); } } V::Result::output() @@ -1014,93 +1000,6 @@ impl<'tcx> pprust_hir::PpAnn for TyCtxt<'tcx> { } } -pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { - let krate = tcx.hir_crate(()); - let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash"); - - let upstream_crates = upstream_crates(tcx); - - let resolutions = tcx.resolutions(()); - - // We hash the final, remapped names of all local source files so we - // don't have to include the path prefix remapping commandline args. - // If we included the full mapping in the SVH, we could only have - // reproducible builds by compiling from the same directory. So we just - // hash the result of the mapping instead of the mapping itself. - let mut source_file_names: Vec<_> = tcx - .sess - .source_map() - .files() - .iter() - .filter(|source_file| source_file.cnum == LOCAL_CRATE) - .map(|source_file| source_file.stable_id) - .collect(); - - source_file_names.sort_unstable(); - - // We have to take care of debugger visualizers explicitly. The HIR (and - // thus `hir_body_hash`) contains the #[debugger_visualizer] attributes but - // these attributes only store the file path to the visualizer file, not - // their content. Yet that content is exported into crate metadata, so any - // changes to it need to be reflected in the crate hash. - let debugger_visualizers: Vec<_> = tcx - .debugger_visualizers(LOCAL_CRATE) - .iter() - // We ignore the path to the visualizer file since it's not going to be - // encoded in crate metadata and we already hash the full contents of - // the file. - .map(DebuggerVisualizerFile::path_erased) - .collect(); - - let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| { - let mut stable_hasher = StableHasher::new(); - hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); - upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); - source_file_names.hash_stable(&mut hcx, &mut stable_hasher); - debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher); - if tcx.sess.opts.incremental.is_some() { - let definitions = tcx.untracked().definitions.freeze(); - let mut owner_spans: Vec<_> = krate - .owners - .iter_enumerated() - .filter_map(|(def_id, info)| { - let _ = info.as_owner()?; - let def_path_hash = definitions.def_path_hash(def_id); - let span = tcx.source_span(def_id); - debug_assert_eq!(span.parent(), None); - Some((def_path_hash, span)) - }) - .collect(); - owner_spans.sort_unstable_by_key(|bn| bn.0); - owner_spans.hash_stable(&mut hcx, &mut stable_hasher); - } - tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); - tcx.stable_crate_id(LOCAL_CRATE).hash_stable(&mut hcx, &mut stable_hasher); - // Hash visibility information since it does not appear in HIR. - // FIXME: Figure out how to remove `visibilities_for_hashing` by hashing visibilities on - // the fly in the resolver, storing only their accumulated hash in `ResolverGlobalCtxt`, - // and combining it with other hashes here. - resolutions.visibilities_for_hashing.hash_stable(&mut hcx, &mut stable_hasher); - stable_hasher.finish() - }); - - Svh::new(crate_hash) -} - -fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { - let mut upstream_crates: Vec<_> = tcx - .crates(()) - .iter() - .map(|&cnum| { - let stable_crate_id = tcx.stable_crate_id(cnum); - let hash = tcx.crate_hash(cnum); - (stable_crate_id, hash) - }) - .collect(); - upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id); - upstream_crates -} - fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id); @@ -1194,152 +1093,3 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"), } } - -pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> ModuleItems { - let mut collector = ItemCollector::new(tcx, false); - - let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); - collector.visit_mod(hir_mod, span, hir_id); - - let ItemCollector { - submodules, - items, - trait_items, - impl_items, - foreign_items, - body_owners, - .. - } = collector; - return ModuleItems { - submodules: submodules.into_boxed_slice(), - free_items: items.into_boxed_slice(), - trait_items: trait_items.into_boxed_slice(), - impl_items: impl_items.into_boxed_slice(), - foreign_items: foreign_items.into_boxed_slice(), - body_owners: body_owners.into_boxed_slice(), - }; -} - -pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { - let mut collector = ItemCollector::new(tcx, true); - - // A "crate collector" and "module collector" start at a - // module item (the former starts at the crate root) but only - // the former needs to collect it. ItemCollector does not do this for us. - collector.submodules.push(CRATE_OWNER_ID); - tcx.hir().walk_toplevel_module(&mut collector); - - let ItemCollector { - submodules, - items, - trait_items, - impl_items, - foreign_items, - body_owners, - .. - } = collector; - - return ModuleItems { - submodules: submodules.into_boxed_slice(), - free_items: items.into_boxed_slice(), - trait_items: trait_items.into_boxed_slice(), - impl_items: impl_items.into_boxed_slice(), - foreign_items: foreign_items.into_boxed_slice(), - body_owners: body_owners.into_boxed_slice(), - }; -} - -struct ItemCollector<'tcx> { - // When true, it collects all items in the create, - // otherwise it collects items in some module. - crate_collector: bool, - tcx: TyCtxt<'tcx>, - submodules: Vec, - items: Vec, - trait_items: Vec, - impl_items: Vec, - foreign_items: Vec, - body_owners: Vec, -} - -impl<'tcx> ItemCollector<'tcx> { - fn new(tcx: TyCtxt<'tcx>, crate_collector: bool) -> ItemCollector<'tcx> { - ItemCollector { - crate_collector, - tcx, - submodules: Vec::default(), - items: Vec::default(), - trait_items: Vec::default(), - impl_items: Vec::default(), - foreign_items: Vec::default(), - body_owners: Vec::default(), - } - } -} - -impl<'hir> Visitor<'hir> for ItemCollector<'hir> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_item(&mut self, item: &'hir Item<'hir>) { - if Node::Item(item).associated_body().is_some() { - self.body_owners.push(item.owner_id.def_id); - } - - self.items.push(item.item_id()); - - // Items that are modules are handled here instead of in visit_mod. - if let ItemKind::Mod(module) = &item.kind { - self.submodules.push(item.owner_id); - // A module collector does not recurse inside nested modules. - if self.crate_collector { - intravisit::walk_mod(self, module, item.hir_id()); - } - } else { - intravisit::walk_item(self, item) - } - } - - fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { - self.foreign_items.push(item.foreign_item_id()); - intravisit::walk_foreign_item(self, item) - } - - fn visit_anon_const(&mut self, c: &'hir AnonConst) { - self.body_owners.push(c.def_id); - intravisit::walk_anon_const(self, c) - } - - fn visit_inline_const(&mut self, c: &'hir ConstBlock) { - self.body_owners.push(c.def_id); - intravisit::walk_inline_const(self, c) - } - - fn visit_expr(&mut self, ex: &'hir Expr<'hir>) { - if let ExprKind::Closure(closure) = ex.kind { - self.body_owners.push(closure.def_id); - } - intravisit::walk_expr(self, ex) - } - - fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { - if Node::TraitItem(item).associated_body().is_some() { - self.body_owners.push(item.owner_id.def_id); - } - - self.trait_items.push(item.trait_item_id()); - intravisit::walk_trait_item(self, item) - } - - fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { - if Node::ImplItem(item).associated_body().is_some() { - self.body_owners.push(item.owner_id.def_id); - } - - self.impl_items.push(item.impl_item_id()); - intravisit::walk_impl_item(self, item) - } -} diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 57c8ba96a20a7..cd19d8a473793 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -22,12 +22,15 @@ use rustc_span::{ErrorGuaranteed, ExpnId}; /// bodies. The Ids are in visitor order. This is used to partition a pass between modules. #[derive(Debug, HashStable, Encodable, Decodable)] pub struct ModuleItems { - submodules: Box<[OwnerId]>, - free_items: Box<[ItemId]>, - trait_items: Box<[TraitItemId]>, - impl_items: Box<[ImplItemId]>, - foreign_items: Box<[ForeignItemId]>, - body_owners: Box<[LocalDefId]>, + /// Whether this represents the whole crate, in which case we need to add `CRATE_OWNER_ID` to + /// the iterators if we want to account for the crate root. + pub add_root: bool, + pub submodules: Box<[OwnerId]>, + pub free_items: Box<[ItemId]>, + pub trait_items: Box<[TraitItemId]>, + pub impl_items: Box<[ImplItemId]>, + pub foreign_items: Box<[ForeignItemId]>, + pub body_owners: Box<[LocalDefId]>, } impl ModuleItems { @@ -56,9 +59,10 @@ impl ModuleItems { } pub fn owners(&self) -> impl Iterator + '_ { - self.free_items - .iter() - .map(|id| id.owner_id) + self.add_root + .then_some(CRATE_OWNER_ID) + .into_iter() + .chain(self.free_items.iter().map(|id| id.owner_id)) .chain(self.trait_items.iter().map(|id| id.owner_id)) .chain(self.impl_items.iter().map(|id| id.owner_id)) .chain(self.foreign_items.iter().map(|id| id.owner_id)) @@ -160,22 +164,18 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn provide(providers: &mut Providers) { - providers.hir_crate_items = map::hir_crate_items; - providers.crate_hash = map::crate_hash; - providers.hir_module_items = map::hir_module_items; - providers.local_def_id_to_hir_id = |tcx, def_id| match tcx.hir_crate(()).owners[def_id] { + providers.local_def_id_to_hir_id = |tcx, def_id| match tcx.lower_to_hir(def_id) { MaybeOwner::Owner(_) => HirId::make_owner(def_id), MaybeOwner::NonOwner(hir_id) => hir_id, - MaybeOwner::Phantom => bug!("No HirId for {:?}", def_id), }; - providers.opt_hir_owner_nodes = - |tcx, id| tcx.hir_crate(()).owners.get(id)?.as_owner().map(|i| &i.nodes); + providers.opt_hir_owner_nodes = |tcx, id| tcx.lower_to_hir(id).as_owner().map(|i| &i.nodes); providers.hir_owner_parent = |tcx, owner_id| { tcx.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| { let parent_owner_id = tcx.local_def_id_to_hir_id(parent_def_id).owner; HirId { owner: parent_owner_id, - local_id: tcx.hir_crate(()).owners[parent_owner_id.def_id] + local_id: tcx + .lower_to_hir(parent_owner_id) .unwrap() .parenting .get(&owner_id.def_id) @@ -184,9 +184,8 @@ pub fn provide(providers: &mut Providers) { } }) }; - providers.hir_attrs = |tcx, id| { - tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) - }; + providers.hir_attrs = + |tcx, id| tcx.lower_to_hir(id.def_id).as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs); providers.def_span = |tcx, def_id| tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); providers.def_ident_span = |tcx, def_id| { let hir_id = tcx.local_def_id_to_hir_id(def_id); @@ -217,7 +216,6 @@ pub fn provide(providers: &mut Providers) { providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls; providers.expn_that_defined = |tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root()); - providers.in_scope_traits_map = |tcx, id| { - tcx.hir_crate(()).owners[id.def_id].as_owner().map(|owner_info| &owner_info.trait_map) - }; + providers.in_scope_traits_map = + |tcx, id| tcx.lower_to_hir(id.def_id).as_owner().map(|owner_info| &owner_info.trait_map); } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index add88491f8467..0c29009727a68 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -7,6 +7,7 @@ use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::{TyAndLayout, ValidityRequirement}; use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{GenericArg, GenericArgsRef}; +use rustc_hir::def::FreshLifetimeResId; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE}; use rustc_hir::hir_id::{HirId, OwnerId}; use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache}; @@ -563,6 +564,14 @@ impl Key for HirId { } } +impl Key for FreshLifetimeResId { + type Cache = DefaultCache; + + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl Key for (LocalDefId, HirId) { type Cache = DefaultCache; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d40a783358959..1de5e4555177e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -71,7 +71,7 @@ use rustc_hir::def_id::{ CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId, }; use rustc_hir::lang_items::{LangItem, LanguageItems}; -use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, TraitCandidate}; +use rustc_hir::{ItemLocalId, ItemLocalMap, TraitCandidate}; use rustc_index::IndexVec; use rustc_macros::rustc_queries; use rustc_query_system::ich::StableHashingContext; @@ -131,12 +131,18 @@ rustc_queries! { desc { "getting the resolver outputs" } } - query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc)>, &'tcx ty::ResolverGlobalCtxt) { + query resolver_for_lowering_raw(_: ()) -> (&'tcx (ty::ResolverAstLowering, Steal>), &'tcx ty::ResolverGlobalCtxt) { eval_always no_hash desc { "getting the resolver for lowering" } } + query index_ast(_: ()) -> &'tcx IndexVec> { + eval_always + no_hash + desc { "getting the AST for lowering" } + } + /// Return the span for a definition. /// Contrary to `def_span` below, this query returns the full absolute span of the definition. /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside @@ -147,16 +153,13 @@ rustc_queries! { desc { "getting the source span" } } - /// Represents crate as a whole (as distinct from the top-level crate module). - /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`), - /// we will have to assume that any change means that you need to be recompiled. - /// This is because the `hir_crate` query gives you access to all other items. - /// To avoid this fate, do not call `tcx.hir().krate()`; instead, - /// prefer wrappers like `tcx.visit_all_items_in_krate()`. - query hir_crate(key: ()) -> &'tcx Crate<'tcx> { - arena_cache + query fresh_lifetime_def_id(key: rustc_hir::def::FreshLifetimeResId) -> LocalDefId { + desc { "getting the DefId for a fresh lifetime created during resolution" } + } + + query lower_to_hir(key: LocalDefId) -> hir::MaybeOwner<'tcx> { eval_always - desc { "getting the crate HIR" } + desc { |tcx| "lowering HIR for `{}`", tcx.def_path_str(key.to_def_id()) } } /// All items in the crate. @@ -1530,8 +1533,7 @@ rustc_queries! { query specializes(_: (DefId, DefId)) -> bool { desc { "computing whether impls specialize one another" } } - query in_scope_traits_map(_: hir::OwnerId) - -> Option<&'tcx ItemLocalMap>> { + query in_scope_traits_map(_: hir::OwnerId) -> Option<&'tcx ItemLocalMap<&'tcx [TraitCandidate]>> { desc { "getting traits in scope at a block" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9225ae6300fc6..7fb72d2d31b87 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1835,7 +1835,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap { // Create a dependency to the crate to be sure we re-execute this when the amount of // definitions change. - self.ensure().hir_crate(()); + self.ensure().hir_crate_items(()); // Freeze definitions once we start iterating on them, to prevent adding new ones // while iterating. If some query needs to add definitions, it should be `ensure`d above. self.untracked.definitions.freeze().def_path_hash_to_def_index_map() @@ -3142,7 +3142,7 @@ impl<'tcx> TyCtxt<'tcx> { self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]) } - pub fn resolver_for_lowering(self) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { + pub fn resolver_for_lowering(self) -> &'tcx (ty::ResolverAstLowering, Steal>) { self.resolver_for_lowering_raw(()).0 } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7d57d88f40f4a..b878e3bfa0fab 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -43,7 +43,9 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_data_structures::unord::UnordMap; use rustc_errors::{Diag, ErrorGuaranteed, StashKey}; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; +use rustc_hir::def::{ + CtorKind, CtorOf, DefKind, DocLinkResMap, FreshLifetimeResId, LifetimeRes, Res, +}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; use rustc_index::IndexVec; use rustc_macros::{ @@ -212,6 +214,8 @@ pub struct ResolverAstLowering { pub lifetimes_res_map: NodeMap, /// Lifetime parameters that lowering will have to introduce. pub extra_lifetime_params_map: NodeMap>, + /// Lifetime parameters that resolver did not create `DefId`s for. + pub fresh_lifetime_res_info: IndexVec, pub next_node_id: ast::NodeId, diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 96893e585491f..f45255efc0616 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -87,11 +87,10 @@ impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> { /// Traverses and collects the debugger visualizers for a specific crate. fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec { - let resolver_and_krate = tcx.resolver_for_lowering().borrow(); - let krate = &*resolver_and_krate.1; + let krate = &tcx.resolver_for_lowering().1; let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() }; - rustc_ast::visit::Visitor::visit_crate(&mut visitor, krate); + rustc_ast::visit::Visitor::visit_crate(&mut visitor, &*krate.borrow()); // We are collecting visualizers in AST-order, which is deterministic, // so we don't need to do any explicit sorting in order to get a diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index b3722e99e1684..b21a68ca5a955 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -244,8 +244,8 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { /// Traverses and collects all the lang items in all crates. fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { - let resolver = tcx.resolver_for_lowering().borrow(); - let (resolver, krate) = &*resolver; + let (resolver, krate) = tcx.resolver_for_lowering(); + let krate = &*krate.borrow(); // Initialize the collector. let mut collector = LanguageItemCollector::new(tcx, resolver); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 66a1c05289b7d..36e3ca34562c9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -298,7 +298,7 @@ enum LifetimeRibKind { /// struct Foo<'a> { x: &'a () } /// async fn foo(Foo { x: _ }: Foo<'_>) {} /// ``` - AnonymousCreateParameter { binder: NodeId, report_in_path: bool }, + AnonymousCreateParameter { binder: NodeId, report_in_path: bool, binder_is_ast_owner: bool }, /// Replace all anonymous lifetimes by provided lifetime. Elided(LifetimeRes), @@ -696,6 +696,8 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Count the number of places a lifetime is used. lifetime_uses: FxHashMap, + + current_ast_owner: Option, } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. @@ -705,12 +707,14 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, // as they do not correspond to actual code. } fn visit_item(&mut self, item: &'ast Item) { - let prev = replace(&mut self.diag_metadata.current_item, Some(item)); + let prev_owner = self.current_ast_owner.replace(item.id); + let prev_item = self.diag_metadata.current_item.replace(item); // Always report errors in items we just entered. let old_ignore = replace(&mut self.in_func_body, false); self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item)); self.in_func_body = old_ignore; - self.diag_metadata.current_item = prev; + self.diag_metadata.current_item = prev_item; + self.current_ast_owner = prev_owner; } fn visit_arm(&mut self, arm: &'ast Arm) { self.resolve_arm(arm); @@ -825,6 +829,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, LifetimeRibKind::AnonymousCreateParameter { binder: ty.id, report_in_path: false, + binder_is_ast_owner: false, }, |this| { this.resolve_fn_signature( @@ -879,6 +884,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, ); } fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { + let prev = self.current_ast_owner.replace(foreign_item.id); self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id)); let def_kind = self.r.local_def_kind(foreign_item.id); match foreign_item.kind { @@ -913,6 +919,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, panic!("unexpanded macro in resolve!") } } + self.current_ast_owner = prev; } fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) { let previous_value = self.diag_metadata.current_function; @@ -927,6 +934,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, LifetimeRibKind::AnonymousCreateParameter { binder: fn_id, report_in_path: false, + binder_is_ast_owner: true, }, |this| { this.resolve_fn_signature( @@ -973,6 +981,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, LifetimeRibKind::AnonymousCreateParameter { binder: fn_id, report_in_path: coro_node_id.is_some(), + binder_is_ast_owner: true, }, |this| { this.resolve_fn_signature( @@ -1017,6 +1026,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, LifetimeRibKind::AnonymousCreateParameter { binder: fn_id, report_in_path: false, + binder_is_ast_owner: false, } } ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError, @@ -1193,6 +1203,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, LifetimeRibKind::AnonymousCreateParameter { binder, report_in_path: false, + binder_is_ast_owner: false, }, |this| { this.resolve_fn_signature( @@ -1332,6 +1343,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lifetime_ribs: Vec::new(), lifetime_elision_candidates: None, current_trait_ref: None, + current_ast_owner: None, diag_metadata: Default::default(), // errors at module scope should always be reported in_func_body: false, @@ -1673,8 +1685,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() { debug!(?rib.kind); match rib.kind { - LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { - let res = self.create_fresh_lifetime(lifetime.ident, binder, kind); + LifetimeRibKind::AnonymousCreateParameter { + binder, binder_is_ast_owner, .. + } => { + let res = self.create_fresh_lifetime( + lifetime.ident, + binder, + binder_is_ast_owner, + kind, + ); self.record_lifetime_res(lifetime.id, res, elision_candidate); return; } @@ -1803,14 +1822,17 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { &mut self, ident: Ident, binder: NodeId, + binder_is_ast_owner: bool, kind: MissingLifetimeKind, ) -> LifetimeRes { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); debug!(?ident.span); - // Leave the responsibility to create the `LocalDefId` to lowering. let param = self.r.next_node_id(); - let res = LifetimeRes::Fresh { param, binder, kind }; + let ast_owner = if binder_is_ast_owner { binder } else { self.current_ast_owner.unwrap() }; + let id = self.r.fresh_lifetime_res_info.push((ident.span, ast_owner)); + let res = LifetimeRes::Fresh { id, param, binder, kind }; + self.record_lifetime_param(param, res); // Record the created lifetime parameter so lowering can pick it up and add it to HIR. @@ -1950,11 +1972,20 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { break; } // Do not create a parameter for patterns and expressions. - LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { + LifetimeRibKind::AnonymousCreateParameter { + binder, + binder_is_ast_owner, + .. + } => { // Group all suggestions into the first record. let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime); for id in node_ids { - let res = self.create_fresh_lifetime(ident, binder, kind); + let res = self.create_fresh_lifetime( + ident, + binder, + binder_is_ast_owner, + kind, + ); self.record_lifetime_res( id, res, @@ -2847,6 +2878,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }; for item in trait_items { + let prev = self.current_ast_owner.replace(item.id); self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); match &item.kind { AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => { @@ -2906,6 +2938,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { panic!("unexpanded macro in resolve!") } }; + self.current_ast_owner = prev; } self.diag_metadata.current_trait_assoc_items = trait_assoc_items; @@ -2982,7 +3015,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { this.with_lifetime_rib( LifetimeRibKind::AnonymousCreateParameter { binder: item_id, - report_in_path: true + report_in_path: true, + binder_is_ast_owner: true, }, |this| { // Resolve the trait reference, if necessary. @@ -3045,6 +3079,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { seen_trait_items: &mut FxHashMap, trait_id: Option, ) { + let prev = self.current_ast_owner.replace(item.id); use crate::ResolutionError::*; self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis))); match &item.kind { @@ -3182,6 +3217,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { panic!("unexpanded macro in resolve!") } } + self.current_ast_owner = prev; } fn check_trait_item( diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 94cdce1025fe5..21edb7f6f9db9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -36,8 +36,8 @@ use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; -use rustc_hir::def::NonMacroAttrKind; use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS}; +use rustc_hir::def::{FreshLifetimeResId, NonMacroAttrKind}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{PrimTy, TraitCandidate}; @@ -1017,6 +1017,9 @@ pub struct Resolver<'a, 'tcx> { /// Lifetime parameters that lowering will have to introduce. extra_lifetime_params_map: NodeMap>, + /// The span and the node id of the parent item needed for generating the fresh lifetime. + fresh_lifetime_res_info: IndexVec, + /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: FxHashMap, module_children: LocalDefIdMap>, @@ -1417,6 +1420,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { label_res_map: Default::default(), lifetimes_res_map: Default::default(), extra_lifetime_params_map: Default::default(), + fresh_lifetime_res_info: IndexVec::default(), extern_crate_map: Default::default(), module_children: Default::default(), trait_map: NodeMap::default(), @@ -1631,6 +1635,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { lifetime_elision_allowed: self.lifetime_elision_allowed, lint_buffer: Steal::new(self.lint_buffer), delegation_fn_sigs: self.delegation_fn_sigs, + fresh_lifetime_res_info: self.fresh_lifetime_res_info, }; ResolverOutputs { global_ctxt, ast_lowering } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 5d8e61f9fa0d4..e2384c269169b 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -359,8 +359,6 @@ pub(crate) fn run_global_ctxt( ctxt.external_traits.borrow_mut().insert(sized_trait_did, sized_trait); } - debug!("crate: {:?}", tcx.hir().krate()); - let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt)); if krate.module.doc_value().is_empty() {