From 4b55098307c8f8e46596606d24dd4eec52028bb8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 21 Jun 2025 14:44:59 +0000 Subject: [PATCH 1/5] Stop passing resolver disambiguator state to AST lowering. --- compiler/rustc_ast_lowering/src/expr.rs | 9 ++++++++- compiler/rustc_ast_lowering/src/lib.rs | 15 +++++++++++++-- compiler/rustc_ast_lowering/src/pat.rs | 4 +++- compiler/rustc_hir/src/definitions.rs | 13 ++++++++++++- compiler/rustc_middle/src/ty/mod.rs | 3 --- compiler/rustc_middle/src/ty/print/pretty.rs | 1 + compiler/rustc_resolve/src/lib.rs | 1 - .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 4 +++- compiler/rustc_symbol_mangling/src/v0.rs | 4 +++- ...emit-type-metadata-id-itanium-cxx-abi-paths.rs | 6 +++--- 10 files changed, 46 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 15e736261d583..5af7d11959518 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -9,6 +9,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; +use rustc_hir::definitions::DefPathData; use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; use rustc_session::errors::report_lit_error; @@ -488,7 +489,13 @@ impl<'hir> LoweringContext<'_, 'hir> { for (idx, arg) in args.iter().cloned().enumerate() { if legacy_args_idx.contains(&idx) { let node_id = self.next_node_id(); - self.create_def(node_id, None, DefKind::AnonConst, f.span); + self.create_def( + node_id, + None, + DefKind::AnonConst, + DefPathData::LateAnonConst, + f.span, + ); let mut visitor = WillCreateDefIdsVisitor {}; let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) { AstP(Expr { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1c96a375035aa..696f035f09ac1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -51,6 +51,7 @@ use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; +use rustc_hir::definitions::{DefPathData, DisambiguatorState}; use rustc_hir::lints::DelayedLint; use rustc_hir::{ self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, @@ -92,6 +93,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } struct LoweringContext<'a, 'hir> { tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering, + disambiguator: DisambiguatorState, /// Used to allocate HIR nodes. arena: &'hir hir::Arena<'hir>, @@ -154,6 +156,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Pseudo-globals. tcx, resolver, + disambiguator: DisambiguatorState::new(), arena: tcx.hir_arena, // HirId handling. @@ -525,6 +528,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id: ast::NodeId, name: Option, def_kind: DefKind, + def_path_data: DefPathData, span: Span, ) -> LocalDefId { let parent = self.current_hir_id_owner.def_id; @@ -540,7 +544,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let def_id = self .tcx .at(span) - .create_def(parent, name, def_kind, None, &mut self.resolver.disambiguator) + .create_def(parent, name, def_kind, Some(def_path_data), &mut self.disambiguator) .def_id(); debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); @@ -825,6 +829,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param, Some(kw::UnderscoreLifetime), DefKind::LifetimeParam, + DefPathData::DesugaredAnonymousLifetime, ident.span, ); debug!(?_def_id); @@ -2160,7 +2165,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // We're lowering a const argument that was originally thought to be a type argument, // so the def collector didn't create the def ahead of time. That's why we have to do // it here. - let def_id = self.create_def(node_id, None, DefKind::AnonConst, span); + let def_id = self.create_def( + node_id, + None, + DefKind::AnonConst, + DefPathData::LateAnonConst, + span, + ); let hir_id = self.lower_node_id(node_id); let path_expr = Expr { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index e444062104813..9d68234fc1a93 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -4,6 +4,7 @@ use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def::{DefKind, Res}; +use rustc_hir::definitions::DefPathData; use rustc_hir::{self as hir, LangItem}; use rustc_middle::span_bug; use rustc_span::source_map::{Spanned, respan}; @@ -524,7 +525,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // We're generating a range end that didn't exist in the AST, // so the def collector didn't create the def ahead of time. That's why we have to do // it here. - let def_id = self.create_def(node_id, None, DefKind::AnonConst, span); + let def_id = + self.create_def(node_id, None, DefKind::AnonConst, DefPathData::LateAnonConst, span); let hir_id = self.lower_node_id(node_id); let unstable_span = self.mark_span_with_reason( diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 698406d53a436..07d5bcdd6ee92 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -302,6 +302,10 @@ pub enum DefPathData { Ctor, /// A constant expression (see `{ast,hir}::AnonConst`). AnonConst, + /// A constant expression created during AST->HIR lowering.. + LateAnonConst, + /// A fresh anonymous lifetime created by desugaring elided lifetimes. + DesugaredAnonymousLifetime, /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. OpaqueTy, @@ -454,6 +458,8 @@ impl DefPathData { TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | OpaqueLifetime(name) => Some(name), + DesugaredAnonymousLifetime => Some(kw::UnderscoreLifetime), + Impl | ForeignMod | CrateRoot @@ -462,6 +468,7 @@ impl DefPathData { | Closure | Ctor | AnonConst + | LateAnonConst | OpaqueTy | AnonAssocTy(..) | SyntheticCoroutineBody @@ -475,6 +482,8 @@ impl DefPathData { TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) | OpaqueLifetime(name) => Some(name), + DesugaredAnonymousLifetime => Some(kw::UnderscoreLifetime), + Impl | ForeignMod | CrateRoot @@ -483,6 +492,7 @@ impl DefPathData { | Closure | Ctor | AnonConst + | LateAnonConst | OpaqueTy | SyntheticCoroutineBody | NestedStatic => None, @@ -502,7 +512,8 @@ impl DefPathData { GlobalAsm => DefPathDataName::Anon { namespace: sym::global_asm }, Closure => DefPathDataName::Anon { namespace: sym::closure }, Ctor => DefPathDataName::Anon { namespace: sym::constructor }, - AnonConst => DefPathDataName::Anon { namespace: sym::constant }, + AnonConst | LateAnonConst => DefPathDataName::Anon { namespace: sym::constant }, + DesugaredAnonymousLifetime => DefPathDataName::Named(kw::UnderscoreLifetime), OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, AnonAssocTy(..) => DefPathDataName::Anon { namespace: sym::anon_assoc }, SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic }, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a7cde2ad48547..42eeaac34c571 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -37,7 +37,6 @@ use rustc_errors::{Diag, ErrorGuaranteed}; use rustc_hir::LangItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; -use rustc_hir::definitions::DisambiguatorState; use rustc_index::IndexVec; use rustc_index::bit_set::BitMatrix; use rustc_macros::{ @@ -220,8 +219,6 @@ pub struct ResolverAstLowering { pub node_id_to_def_id: NodeMap, - pub disambiguator: DisambiguatorState, - pub trait_map: NodeMap>, /// List functions and methods for which lifetime elision was successful. pub lifetime_elision_allowed: FxHashSet, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 2eb530f328d39..c5ca86092b473 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2187,6 +2187,7 @@ fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace { DefPathData::ValueNs(..) | DefPathData::AnonConst + | DefPathData::LateAnonConst | DefPathData::Closure | DefPathData::Ctor => Namespace::ValueNS, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f38fee8dea5d9..a86a2cc5dd488 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1728,7 +1728,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .into_items() .map(|(k, f)| (k, f.key())) .collect(), - disambiguator: self.disambiguator, trait_map: self.trait_map, lifetime_elision_allowed: self.lifetime_elision_allowed, lint_buffer: Steal::new(self.lint_buffer), diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index f4a14b36ce5cf..b85dd73498135 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -713,7 +713,8 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { hir::definitions::DefPathData::ValueNs(..) => "v", hir::definitions::DefPathData::Closure => "C", hir::definitions::DefPathData::Ctor => "c", - hir::definitions::DefPathData::AnonConst => "k", + hir::definitions::DefPathData::AnonConst => "K", + hir::definitions::DefPathData::LateAnonConst => "k", hir::definitions::DefPathData::OpaqueTy => "i", hir::definitions::DefPathData::SyntheticCoroutineBody => "s", hir::definitions::DefPathData::NestedStatic => "n", @@ -723,6 +724,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { | hir::definitions::DefPathData::MacroNs(..) | hir::definitions::DefPathData::OpaqueLifetime(..) | hir::definitions::DefPathData::LifetimeNs(..) + | hir::definitions::DefPathData::DesugaredAnonymousLifetime | hir::definitions::DefPathData::AnonAssocTy(..) => { bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data); } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index fe0f8e6113ef7..eb679fb59790f 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -872,7 +872,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { DefPathData::ValueNs(_) => 'v', DefPathData::Closure => 'C', DefPathData::Ctor => 'c', - DefPathData::AnonConst => 'k', + DefPathData::AnonConst => 'K', + DefPathData::LateAnonConst => 'k', DefPathData::OpaqueTy => 'i', DefPathData::SyntheticCoroutineBody => 's', DefPathData::NestedStatic => 'n', @@ -884,6 +885,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { | DefPathData::Impl | DefPathData::MacroNs(_) | DefPathData::LifetimeNs(_) + | DefPathData::DesugaredAnonymousLifetime | DefPathData::OpaqueLifetime(_) | DefPathData::AnonAssocTy(..) => { bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data) diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs index a8ba8db1be3b4..e1527bf1edc2d 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs @@ -78,9 +78,9 @@ pub fn foo12(_: &Type4, _: &Type4, _: &Type4) {} // CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"} // CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"} // CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"} -// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"} -// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"} -// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"} +// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNKNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"} +// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNKNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"} +// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNKNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"} // CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"} // CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"} // CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"} From 50ae203104fc1ed2d21f1576ea80eb2aee2761b0 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 1 Jul 2024 10:27:01 +0000 Subject: [PATCH 2/5] Do not modify resolver outputs during lowering Co-authored-by: Camille Gillot --- compiler/rustc_ast_lowering/src/asm.rs | 5 +- compiler/rustc_ast_lowering/src/block.rs | 2 +- compiler/rustc_ast_lowering/src/delegation.rs | 27 +++---- compiler/rustc_ast_lowering/src/expr.rs | 8 +- compiler/rustc_ast_lowering/src/format.rs | 10 +-- compiler/rustc_ast_lowering/src/item.rs | 21 ++--- compiler/rustc_ast_lowering/src/lib.rs | 77 +++++++++++-------- compiler/rustc_ast_lowering/src/pat.rs | 9 ++- compiler/rustc_ast_lowering/src/path.rs | 5 +- compiler/rustc_driver_impl/src/pretty.rs | 4 +- compiler/rustc_hir/src/hir.rs | 3 +- compiler/rustc_interface/src/passes.rs | 10 ++- compiler/rustc_middle/src/arena.rs | 8 +- compiler/rustc_middle/src/query/mod.rs | 5 +- compiler/rustc_middle/src/ty/context.rs | 2 +- .../rustc_passes/src/debugger_visualizer.rs | 3 +- compiler/rustc_passes/src/lang_items.rs | 4 +- 17 files changed, 106 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index af279e07acc6e..c65860ddd1360 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -20,10 +20,10 @@ use super::errors::{ }; use crate::{ AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode, - ResolverAstLoweringExt, fluent_generated as fluent, + fluent_generated as fluent, }; -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { pub(crate) fn lower_inline_asm( &mut self, sp: Span, @@ -200,7 +200,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }, InlineAsmOperand::Sym { sym } => { let static_def_id = self - .resolver .get_partial_res(sym.id) .and_then(|res| res.full_res()) .and_then(|res| match res { diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index c3222b79e55c9..51bfd9f355019 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -5,7 +5,7 @@ use smallvec::SmallVec; use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext}; -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 9bfcd232221ba..575c2ff4b38a6 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -46,13 +46,15 @@ use rustc_ast::*; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_middle::span_bug; -use rustc_middle::ty::{Asyncness, ResolverAstLowering}; +use rustc_middle::ty::Asyncness; use rustc_span::symbol::kw; use rustc_span::{Ident, Span, Symbol}; use {rustc_ast as ast, rustc_hir as hir}; -use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode}; -use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt}; +use super::{ + AllowReturnTypeNotation, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext, + ParamMode, +}; pub(crate) struct DelegationResults<'hir> { pub body_id: hir::BodyId, @@ -61,7 +63,7 @@ pub(crate) struct DelegationResults<'hir> { pub generics: &'hir hir::Generics<'hir>, } -impl<'hir> LoweringContext<'_, 'hir> { +impl<'hir> LoweringContext<'hir> { fn is_method(&self, def_id: DefId, span: Span) -> bool { match self.tcx.def_kind(def_id) { DefKind::Fn => false, @@ -112,8 +114,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn get_resolution_id(&self, node_id: NodeId, span: Span) -> Result { - let def_id = - self.resolver.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id()); + let def_id = self.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id()); def_id.ok_or_else(|| { self.tcx.dcx().span_delayed_bug( span, @@ -292,7 +293,7 @@ impl<'hir> LoweringContext<'_, 'hir> { && idx == 0 { let mut self_resolver = SelfResolver { - resolver: this.resolver, + ctxt: this, path_id: delegation.id, self_param_id: pat_node_id, }; @@ -438,25 +439,25 @@ impl<'hir> LoweringContext<'_, 'hir> { } } -struct SelfResolver<'a> { - resolver: &'a mut ResolverAstLowering, +struct SelfResolver<'r, 'hir> { + ctxt: &'r mut LoweringContext<'hir>, path_id: NodeId, self_param_id: NodeId, } -impl<'a> SelfResolver<'a> { +impl SelfResolver<'_, '_> { fn try_replace_id(&mut self, id: NodeId) { - if let Some(res) = self.resolver.partial_res_map.get(&id) + if let Some(res) = self.ctxt.get_partial_res(id) && let Some(Res::Local(sig_id)) = res.full_res() && sig_id == self.path_id { let new_res = PartialRes::new(Res::Local(self.self_param_id)); - self.resolver.partial_res_map.insert(id, new_res); + self.ctxt.partial_res_overrides.insert(id, new_res); } } } -impl<'ast, 'a> Visitor<'ast> for SelfResolver<'a> { +impl<'ast> Visitor<'ast> for SelfResolver<'_, '_> { fn visit_id(&mut self, id: NodeId) { self.try_replace_id(id); } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5af7d11959518..b2b086e9cf00d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -53,7 +53,7 @@ impl<'v> rustc_ast::visit::Visitor<'v> for WillCreateDefIdsVisitor { } } -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))) } @@ -1229,7 +1229,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(..) @@ -1289,7 +1289,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> Option<(&'a Option>, &'a Path)> { if let ExprKind::Path(qself, path) = &expr.kind { // Does the path resolve to something disallowed in a tuple struct/variant pattern? - if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { + if let Some(partial_res) = self.get_partial_res(expr.id) { if let Some(res) = partial_res.full_res() && !res.expected_in_tuple_struct_pat() { @@ -1311,7 +1311,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> Option<(&'a Option>, &'a Path)> { if let ExprKind::Path(qself, path) = &expr.kind { // Does the path resolve to something disallowed in a unit struct/variant pattern? - if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { + if let Some(partial_res) = self.get_partial_res(expr.id) { if let Some(res) = partial_res.full_res() && !res.expected_in_unit_struct_pat() { diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 5b1dcab87b929..a2188d9e89d20 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -8,7 +8,7 @@ use rustc_span::{DesugaringKind, Ident, Span, Symbol, sym}; use super::LoweringContext; -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. @@ -236,7 +236,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, @@ -285,7 +285,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>, @@ -336,7 +336,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>, @@ -397,7 +397,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 abd70c7517c83..d0d3f175087c0 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -28,7 +28,7 @@ use super::{ pub(super) struct ItemLowerer<'a, 'hir> { pub(super) tcx: TyCtxt<'hir>, - pub(super) resolver: &'a mut ResolverAstLowering, + pub(super) resolver: &'hir ResolverAstLowering, pub(super) ast_index: &'a IndexSlice>, pub(super) owners: &'a mut IndexVec>, } @@ -58,7 +58,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { fn with_lctx( &mut self, owner: NodeId, - f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, + f: impl FnOnce(&mut LoweringContext<'hir>) -> hir::OwnerNode<'hir>, ) { let mut lctx = LoweringContext::new(self.tcx, self.resolver); lctx.with_hir_id_owner(owner, |lctx| f(lctx)); @@ -102,7 +102,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } } -impl<'hir> LoweringContext<'_, 'hir> { +impl<'hir> LoweringContext<'hir> { pub(super) fn lower_mod( &mut self, items: &[P], @@ -1106,7 +1106,6 @@ impl<'hir> LoweringContext<'_, 'hir> { defaultness, has_delayed_lints: !self.delayed_lints.is_empty(), trait_item_def_id: self - .resolver .get_partial_res(i.id) .map(|r| r.expect_full_res().opt_def_id()) .unwrap_or(None), @@ -1349,7 +1348,7 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(crate) 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, @@ -1486,7 +1485,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); @@ -1688,11 +1687,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let compute_is_param = || { // Check if the where clause type is a plain type parameter. - match self - .resolver - .get_partial_res(bound_pred.bounded_ty.id) - .and_then(|r| r.full_res()) - { + match self.get_partial_res(bound_pred.bounded_ty.id).and_then(|r| r.full_res()) { Some(Res::Def(DefKind::TyParam, def_id)) if bound_pred.bound_generic_params.is_empty() => { @@ -1759,7 +1754,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Introduce extra lifetimes if late resolution tells us to. let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id); - params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| { + params.extend(extra_lifetimes.into_iter().filter_map(|&(ident, node_id, res)| { self.lifetime_res_to_generic_param( ident, node_id, @@ -1801,7 +1796,7 @@ impl<'hir> LoweringContext<'_, 'hir> { return; }; let define_opaque = define_opaque.iter().filter_map(|(id, path)| { - let res = self.resolver.get_partial_res(*id); + let res = self.get_partial_res(*id); let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) else { self.dcx().span_delayed_bug(path.span, "should have errored in resolve"); return None; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 696f035f09ac1..2c3de16ad5bd9 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -90,9 +90,9 @@ pub mod stability; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } -struct LoweringContext<'a, 'hir> { +struct LoweringContext<'hir> { tcx: TyCtxt<'hir>, - resolver: &'a mut ResolverAstLowering, + resolver: &'hir ResolverAstLowering, disambiguator: DisambiguatorState, /// Used to allocate HIR nodes. @@ -126,7 +126,7 @@ 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>, @@ -136,6 +136,14 @@ struct LoweringContext<'a, 'hir> { /// NodeIds that are lowered inside the current HIR owner. Only used for duplicate lowering check. #[cfg(debug_assertions)] 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, + /// Overlay over resolver's `partial_res_map` used by delegation. + partial_res_overrides: NodeMap, allow_try_trait: Arc<[Symbol]>, allow_gen_future: Arc<[Symbol]>, @@ -149,8 +157,8 @@ struct LoweringContext<'a, 'hir> { attribute_parser: AttributeParser<'hir>, } -impl<'a, 'hir> LoweringContext<'a, 'hir> { - fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self { +impl<'hir> LoweringContext<'hir> { + fn new(tcx: TyCtxt<'hir>, resolver: &'hir ResolverAstLowering) -> Self { let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect(); Self { // Pseudo-globals. @@ -171,6 +179,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { #[cfg(debug_assertions)] node_id_to_local_id: Default::default(), trait_map: Default::default(), + next_node_id: resolver.next_node_id, + node_id_to_def_id: NodeMap::default(), + partial_res_overrides: NodeMap::default(), // Lowering state. catch_scope: None, @@ -253,10 +264,6 @@ impl ResolverAstLowering { None } - fn get_partial_res(&self, id: NodeId) -> Option { - self.partial_res_map.get(&id).copied() - } - /// Obtains per-namespace resolutions for `use` statement with the given `NodeId`. fn get_import_res(&self, id: NodeId) -> PerNS>> { self.import_res_map.get(&id).copied().unwrap_or_default() @@ -279,8 +286,8 @@ impl ResolverAstLowering { /// /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring /// should appear at the enclosing `PolyTraitRef`. - fn extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> { - self.extra_lifetime_params_map.get(&id).cloned().unwrap_or_default() + fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, LifetimeRes)] { + self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) } } @@ -462,7 +469,8 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { tcx.ensure_done().early_lint_checks(()); tcx.ensure_done().debugger_visualizers(LOCAL_CRATE); tcx.ensure_done().get_lang_items(()); - let (mut resolver, krate) = tcx.resolver_for_lowering().steal(); + let (resolver, krate) = tcx.resolver_for_lowering(); + let krate = krate.steal(); let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); let mut owners = IndexVec::from_fn_n( @@ -470,12 +478,8 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { tcx.definitions_untracked().def_index_count(), ); - let mut lowerer = item::ItemLowerer { - tcx, - resolver: &mut resolver, - ast_index: &ast_index, - owners: &mut owners, - }; + let mut lowerer = + item::ItemLowerer { tcx, resolver, ast_index: &ast_index, owners: &mut owners }; for def_id in ast_index.indices() { lowerer.lower_node(def_id); } @@ -522,7 +526,7 @@ enum GenericArgsMode { Silence, } -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { fn create_def( &mut self, node_id: ast::NodeId, @@ -548,28 +552,38 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .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 opt_local_def_id(&self, node: NodeId) -> Option { - self.resolver.node_id_to_def_id.get(&node).copied() + self.node_id_to_def_id + .get(&node) + .or_else(|| self.resolver.node_id_to_def_id.get(&node)) + .copied() } fn local_def_id(&self, node: NodeId) -> LocalDefId { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) } + fn get_partial_res(&self, id: NodeId) -> Option { + self.partial_res_overrides + .get(&id) + .or_else(|| self.resolver.partial_res_map.get(&id)) + .copied() + } + /// Given the id of an owner node in the AST, returns the corresponding `OwnerId`. fn owner_id(&self, node: NodeId) -> hir::OwnerId { hir::OwnerId { def_id: self.local_def_id(node) } @@ -692,8 +706,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.children.push((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[..]); } // Check whether the same `NodeId` is lowered more than once. @@ -734,7 +748,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn expect_full_res(&mut self, id: NodeId) -> Res { - self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res()) + self.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res()) } fn lower_import_res(&mut self, id: NodeId, span: Span) -> PerNS> { @@ -873,7 +887,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .collect(); 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); @@ -1162,7 +1176,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // FIXME: Should we be handling `(PATH_TO_CONST)`? TyKind::Path(None, path) => { if let Some(res) = self - .resolver .get_partial_res(ty.id) .and_then(|partial_res| partial_res.full_res()) { @@ -1209,7 +1222,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // The other cases when a qpath should be opportunistically made a trait object are handled // by `ty_path`. if qself.is_none() - && let Some(partial_res) = self.resolver.get_partial_res(t.id) + && let Some(partial_res) = self.get_partial_res(t.id) && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res() { let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { @@ -1550,7 +1563,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let [segment] = path.segments.as_slice() else { panic!(); }; - let res = self.resolver.get_partial_res(*id).map_or(Res::Err, |partial_res| { + let res = self.get_partial_res(*id).map_or(Res::Err, |partial_res| { partial_res.full_res().expect("no partial res expected for precise capture arg") }); hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg { @@ -2217,7 +2230,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &anon.value }; let maybe_res = - self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); + self.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); if let ExprKind::Path(qself, path) = &expr.kind && path.is_potential_trivial_const_arg(tcx.features().min_generic_const_args()) && (tcx.features().min_generic_const_args() @@ -2511,7 +2524,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 9d68234fc1a93..7b0ab6df232e7 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -13,10 +13,11 @@ use rustc_span::{DesugaringKind, Ident, Span}; use super::errors::{ ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding, }; -use super::{ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt}; -use crate::{AllowReturnTypeNotation, ImplTraitPosition}; +use super::{ + AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, +}; -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)) } @@ -284,7 +285,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir_id: hir::HirId, lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>, ) -> hir::PatKind<'hir> { - match self.resolver.get_partial_res(p.id).map(|d| d.expect_full_res()) { + match self.get_partial_res(p.id).map(|d| d.expect_full_res()) { // `None` can occur in body-less function signatures res @ (None | Some(Res::Local(_))) => { let binding_id = match res { diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index c80ef275c801a..0969a82784a1f 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -19,7 +19,7 @@ use super::{ LifetimeRes, LoweringContext, ParamMode, ResolverAstLoweringExt, }; -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { #[instrument(level = "trace", skip(self))] pub(crate) fn lower_qpath( &mut self, @@ -38,8 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Reject cases like `::Assoc` and `::Assoc`. .map(|q| self.lower_ty(&q.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Path))); - let partial_res = - self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err)); + let partial_res = self.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err)); let base_res = partial_res.base_res(); let unresolved_segments = partial_res.unresolved_segments(); diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 1604b704033bd..37b9cfffff3b3 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -211,7 +211,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); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e7898648c2b05..b644d47bae13a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1530,8 +1530,7 @@ 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]>, /// Lints delayed during ast lowering to be emitted /// after hir has completely built pub delayed_lints: DelayedLints, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index fb6897c7d8958..dabeaee4d00e5 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -387,7 +387,8 @@ fn print_macro_stats(ecx: &ExtCtxt<'_>) { 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 { @@ -773,7 +774,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, Arc)>, &'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(); @@ -795,7 +796,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, Arc::new(krate)))), resolutions) + (tcx.arena.alloc((untracked_resolver_for_lowering, Steal::new(Arc::new(krate)))), resolutions) } pub fn write_dep_info(tcx: TyCtxt<'_>) { @@ -852,7 +853,8 @@ pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) { return; } let _timer = tcx.sess.timer("write_interface"); - let (_, krate) = &*tcx.resolver_for_lowering().borrow(); + let (_, krate) = tcx.resolver_for_lowering(); + let krate = &*krate.borrow(); let krate = rustc_ast_pretty::pprust::print_crate_as_interface( krate, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 43a7af9ce3809..35f73d17440f1 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -28,10 +28,12 @@ macro_rules! arena_types { >, [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, [decode] borrowck_result: rustc_middle::mir::ConcreteOpaqueTypes<'tcx>, - [] resolver: rustc_data_structures::steal::Steal<( + [] resolver: ( rustc_middle::ty::ResolverAstLowering, - std::sync::Arc, - )>, + rustc_data_structures::steal::Steal< + std::sync::Arc + > + ), [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, [] const_allocs: rustc_middle::mir::interpret::Allocation, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ae8c8259be4ca..074c601f6cfbf 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -198,7 +198,7 @@ rustc_queries! { desc { "getting the resolver outputs" } } - query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Arc)>, &'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" } @@ -1851,8 +1851,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 7e6bcfee02541..cbc4d0b70a3f7 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3373,7 +3373,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, Arc)> { + pub fn resolver_for_lowering(self) -> &'tcx (ty::ResolverAstLowering, Steal>) { self.resolver_for_lowering_raw(()).0 } diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 7a7a8175e5569..725d47cb2ec4b 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -82,8 +82,7 @@ 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.borrow(); let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() }; rustc_ast::visit::Visitor::visit_crate(&mut visitor, krate); diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 6fac01827a499..61be2994f00be 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -247,8 +247,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); From c1357611324ef452070daec532d10a66007aa66b Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 1 Jul 2024 15:46:24 +0000 Subject: [PATCH 3/5] Make lowering incremental. Co-authored-by: Camille Gillot --- compiler/rustc_ast/src/ast.rs | 11 + compiler/rustc_ast_lowering/src/item.rs | 126 +++++------ compiler/rustc_ast_lowering/src/lib.rs | 207 +++++++++--------- compiler/rustc_driver_impl/src/pretty.rs | 4 +- compiler/rustc_hir/src/hir.rs | 22 +- compiler/rustc_hir/src/stable_hash_impls.rs | 9 +- compiler/rustc_interface/src/passes.rs | 13 +- compiler/rustc_middle/src/arena.rs | 8 +- compiler/rustc_middle/src/hir/map.rs | 12 +- compiler/rustc_middle/src/hir/mod.rs | 21 +- compiler/rustc_middle/src/query/mod.rs | 22 +- compiler/rustc_middle/src/ty/context.rs | 2 +- .../rustc_passes/src/debugger_visualizer.rs | 2 +- compiler/rustc_passes/src/lang_items.rs | 1 - 14 files changed, 223 insertions(+), 237 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8c2b521c560d9..aa69dcfdcff17 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -4108,6 +4108,17 @@ impl TryFrom for ForeignItemKind { pub type ForeignItem = Item; +#[derive(Debug)] +pub enum AstOwner<'a> { + NonOwner, + Synthetic(rustc_span::def_id::LocalDefId), + Crate(&'a Crate), + Item(&'a Item), + TraitItem(&'a AssocItem), + ImplItem(&'a AssocItem), + ForeignItem(&'a ForeignItem), +} + // Some nodes are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d0d3f175087c0..b1c95fe5e1d69 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,17 +1,15 @@ use rustc_abi::ExternAbi; use rustc_ast::ptr::P; -use rustc_ast::visit::AssocCtxt; use rustc_ast::*; use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; use rustc_hir::def::{DefKind, PerNS, Res}; -use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; +use rustc_hir::def_id::CRATE_DEF_ID; use rustc_hir::{self as hir, HirId, LifetimeSource, 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::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym}; +use rustc_span::{DesugaringKind, Ident, Span, Symbol, kw, sym}; use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; use tracing::instrument; @@ -22,15 +20,13 @@ use super::errors::{ }; use super::stability::{enabled_names, gate_unstable_abi}; use super::{ - AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, + FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, ResolverAstLoweringExt, }; -pub(super) struct ItemLowerer<'a, 'hir> { +pub(super) struct ItemLowerer<'hir> { pub(super) tcx: TyCtxt<'hir>, pub(super) resolver: &'hir ResolverAstLowering, - pub(super) ast_index: &'a IndexSlice>, - pub(super) owners: &'a mut IndexVec>, } /// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span @@ -54,51 +50,47 @@ 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); - 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); - assert!( - matches!(owner, hir::MaybeOwner::Phantom), - "duplicate copy of {def_id:?} in lctx.children" - ); - *owner = info; - } + ) -> hir::MaybeOwner<'hir> { + let mut lctx = LoweringContext::new(self.tcx, self.resolver, owner); + + let item = f(&mut lctx); + debug_assert_eq!(lctx.current_hir_id_owner, item.def_id()); + + let info = lctx.make_owner_info(item); + + hir::MaybeOwner::Owner(lctx.arena.alloc(info)) } - pub(super) fn lower_node(&mut self, def_id: LocalDefId) { - 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) => { - 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); - // FIXME(jdonszelman): is dummy span ever a problem here? - lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP); - hir::OwnerNode::Crate(module) - }) - } - AstOwner::Item(item) => { - self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) - } - AstOwner::AssocItem(item, ctxt) => { - self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt)) - } - AstOwner::ForeignItem(item) => self.with_lctx(item.id, |lctx| { - hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)) - }), - } - } + #[instrument(level = "debug", skip(self, c))] + 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); + lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, c.spans.inner_span); + hir::OwnerNode::Crate(module) + }) + } + + #[instrument(level = "debug", skip(self))] + 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))) + } + + 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))) + } + + 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))) } } @@ -138,12 +130,13 @@ impl<'hir> LoweringContext<'hir> { } fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { + let owner_id = self.current_hir_id_owner; + let hir_id: HirId = owner_id.into(); let vis_span = self.lower_span(i.vis.span); - let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind); let item = hir::Item { - owner_id: hir_id.expect_owner(), + owner_id, kind, vis_span, span: self.lower_span(i.span), @@ -635,21 +628,9 @@ impl<'hir> LoweringContext<'hir> { } } - fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) -> 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. - match ctxt { - AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)), - AssocCtxt::Impl { of_trait } => { - hir::OwnerNode::ImplItem(self.lower_impl_item(item, of_trait)) - } - } - } - fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { - let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); - let owner_id = hir_id.expect_owner(); + let owner_id = self.current_hir_id_owner; + let hir_id: HirId = owner_id.into(); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let (ident, kind) = match &i.kind { ForeignItemKind::Fn(box Fn { sig, ident, generics, define_opaque, .. }) => { @@ -820,9 +801,9 @@ impl<'hir> LoweringContext<'hir> { } fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { - let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); + let trait_item_def_id = self.current_hir_id_owner; + let hir_id: HirId = trait_item_def_id.into(); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); - let trait_item_def_id = hir_id.expect_owner(); let (ident, generics, kind, has_default) = match &i.kind { AssocItemKind::Const(box ConstItem { @@ -982,15 +963,16 @@ impl<'hir> LoweringContext<'hir> { self.expr(span, hir::ExprKind::Err(guar)) } - fn lower_impl_item( - &mut self, - i: &AssocItem, - is_in_trait_impl: bool, - ) -> &'hir hir::ImplItem<'hir> { + fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { + let owner_id = self.current_hir_id_owner; + let hir_id: HirId = owner_id.into(); + let parent_id = self.tcx.local_parent(owner_id.def_id); + let is_in_trait_impl = + matches!(self.tcx.def_kind(parent_id), DefKind::Impl { of_trait: true }); + // 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); - let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let (ident, (generics, kind)) = match &i.kind { @@ -1097,7 +1079,7 @@ impl<'hir> LoweringContext<'hir> { }; let item = hir::ImplItem { - owner_id: hir_id.expect_owner(), + owner_id, ident: self.lower_ident(ident), generics, kind, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2c3de16ad5bd9..a38e23b79ce61 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -41,23 +41,22 @@ use std::sync::Arc; use rustc_ast::node_id::NodeMap; +use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, *}; use rustc_attr_parsing::{AttributeParser, Late, OmitDoc}; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::spawn; use rustc_data_structures::tagged_ptr::TaggedRef; +use rustc_data_structures::unord::ExtendUnord; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; -use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; +use rustc_hir::def_id::{LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::{DefPathData, DisambiguatorState}; use rustc_hir::lints::DelayedLint; use rustc_hir::{ self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, LifetimeSource, LifetimeSyntax, 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}; @@ -105,7 +104,7 @@ struct LoweringContext<'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>, contract_ensures: Option<(Span, Ident, HirId)>, @@ -158,8 +157,9 @@ struct LoweringContext<'hir> { } impl<'hir> LoweringContext<'hir> { - fn new(tcx: TyCtxt<'hir>, resolver: &'hir ResolverAstLowering) -> Self { + fn new(tcx: TyCtxt<'hir>, resolver: &'hir ResolverAstLowering, owner: NodeId) -> Self { let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect(); + let current_hir_id_owner = hir::OwnerId { def_id: resolver.node_id_to_def_id[&owner] }; Self { // Pseudo-globals. tcx, @@ -171,13 +171,13 @@ impl<'hir> LoweringContext<'hir> { bodies: Vec::new(), define_opaque: None, attrs: SortedMap::default(), - children: Vec::default(), + children: LocalDefIdMap::default(), contract_ensures: None, - current_hir_id_owner: hir::CRATE_OWNER_ID, - item_local_id_counter: hir::ItemLocalId::ZERO, + current_hir_id_owner, + item_local_id_counter: hir::ItemLocalId::new(1), ident_and_label_to_local_id: Default::default(), #[cfg(debug_assertions)] - node_id_to_local_id: Default::default(), + 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(), @@ -387,116 +387,115 @@ 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), -} +pub fn index_ast<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexVec> { + let (resolver, krate) = tcx.resolver_for_lowering(); + + let mut indexer = + Indexer { node_id_to_def_id: &resolver.node_id_to_def_id, index: IndexVec::new() }; + indexer.visit_crate(&krate); + indexer.insert(CRATE_NODE_ID, AstOwner::Crate(&*krate)); + return tcx.arena.alloc(indexer.index); -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> { + struct Indexer<'s, 'ast> { node_id_to_def_id: &'s NodeMap, - index: IndexVec>, + index: IndexVec>, } - impl<'a> visit::Visitor<'a> for Indexer<'_, 'a> { - fn visit_attribute(&mut self, _: &'a Attribute) { + impl<'ast> Indexer<'_, 'ast> { + fn insert(&mut self, id: NodeId, node: AstOwner<'ast>) { + let def_id = self.node_id_to_def_id[&id]; + self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); + self.index[def_id] = 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, AstOwner::Synthetic(parent)); + + let def_id = self.node_id_to_def_id[&id]; + self.visit_item_id_use_tree(nested, def_id); + } + } + } + } + } + + impl<'ast> visit::Visitor<'ast> for Indexer<'_, 'ast> { + fn visit_attribute(&mut self, _: &'ast 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, AstOwner::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); + fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: visit::AssocCtxt) { visit::walk_assoc_item(self, item, ctxt); + let owner_ref = match ctxt { + visit::AssocCtxt::Trait => AstOwner::TraitItem(item), + visit::AssocCtxt::Impl { .. } => AstOwner::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, AstOwner::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; +#[instrument(level = "trace", skip(tcx))] +pub fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> { // Queries that borrow `resolver_for_lowering`. tcx.ensure_done().output_filenames(()); tcx.ensure_done().early_lint_checks(()); tcx.ensure_done().debugger_visualizers(LOCAL_CRATE); tcx.ensure_done().get_lang_items(()); - let (resolver, krate) = tcx.resolver_for_lowering(); - let krate = krate.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 (resolver, _) = tcx.resolver_for_lowering(); + let ast_index = tcx.index_ast(()); + let node = ast_index.get(def_id); + + let mut item_lowerer = item::ItemLowerer { tcx, resolver }; + + // The item existed in the AST. + let parent_id = match node { + Some(AstOwner::Crate(c)) => return item_lowerer.lower_crate(&c), + Some(AstOwner::Item(item)) => return item_lowerer.lower_item(&item), + Some(AstOwner::TraitItem(item)) => { + return item_lowerer.lower_trait_item(&item); + } + Some(AstOwner::ImplItem(item)) => { + return item_lowerer.lower_impl_item(&item); + } + Some(AstOwner::ForeignItem(item)) => return item_lowerer.lower_foreign_item(&item), + Some(AstOwner::Synthetic(parent_id)) => *parent_id, + Some(AstOwner::NonOwner) | None => tcx.local_parent(def_id), + }; - let mut lowerer = - item::ItemLowerer { tcx, resolver, ast_index: &ast_index, owners: &mut owners }; - for def_id in ast_index.indices() { - lowerer.lower_node(def_id); + // 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); } - drop(ast_index); - - // Drop AST to free memory. It can be expensive so try to drop it on a separate thread. - let prof = sess.prof.clone(); - spawn(move || { - let _timer = prof.verbose_generic_activity("drop_ast"); - drop(krate); - }); - - // 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)] @@ -566,6 +565,7 @@ impl<'hir> LoweringContext<'hir> { /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name /// resolver (if any). + #[instrument(level = "trace", skip(self), ret)] fn opt_local_def_id(&self, node: NodeId) -> Option { self.node_id_to_def_id .get(&node) @@ -617,6 +617,7 @@ impl<'hir> LoweringContext<'hir> { 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_delayed_lints = std::mem::take(&mut self.delayed_lints); + 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. @@ -651,9 +652,11 @@ impl<'hir> LoweringContext<'hir> { self.impl_trait_defs = current_impl_trait_defs; self.impl_trait_bounds = current_impl_trait_bounds; self.delayed_lints = current_delayed_lints; + 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 == &owner_id.def_id)); - self.children.push((owner_id.def_id, hir::MaybeOwner::Owner(info))); + debug_assert!(!self.children.contains_key(&owner_id.def_id)); + self.children.insert(owner_id.def_id, hir::MaybeOwner::Owner(info)); } fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> { @@ -662,6 +665,7 @@ impl<'hir> LoweringContext<'hir> { let define_opaque = std::mem::take(&mut self.define_opaque); let trait_map = std::mem::take(&mut self.trait_map); let delayed_lints = std::mem::take(&mut self.delayed_lints).into_boxed_slice(); + let children = std::mem::take(&mut self.children); #[cfg(debug_assertions)] for (id, attrs) in attrs.iter() { @@ -684,7 +688,14 @@ impl<'hir> LoweringContext<'hir> { let delayed_lints = hir::lints::DelayedLints { lints: delayed_lints, opt_hash: delayed_lints_hash }; - self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map, delayed_lints }) + self.arena.alloc(hir::OwnerInfo { + nodes, + parenting, + attrs, + trait_map, + delayed_lints, + children, + }) } /// This method allocates a new `HirId` for the given `NodeId`. @@ -703,7 +714,7 @@ impl<'hir> LoweringContext<'hir> { let hir_id = HirId { owner, local_id }; 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.get(&ast_node_id) { diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 37b9cfffff3b3..6b9124334eceb 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -211,7 +211,7 @@ impl<'tcx> PrintExtra<'tcx> { { match self { PrintExtra::AfterParsing { krate, .. } => f(krate), - PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering().1.borrow()), + PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering().1), } } @@ -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().1.borrow()) + format!("{:#?}", &ex.tcx().resolver_for_lowering().1) } Hir(s) => { debug!("pretty printing HIR {:?}", s); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b644d47bae13a..5c96edacf70f3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -18,6 +18,7 @@ use rustc_attr_data_structures::AttributeKind; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::tagged_ptr::TaggedRef; +use rustc_data_structures::unord::UnordMap; use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::LocalDefId; @@ -1534,6 +1535,8 @@ pub struct OwnerInfo<'hir> { /// Lints delayed during ast lowering to be emitted /// after hir has completely built pub delayed_lints: DelayedLints, + /// Owners generated as side-effect by lowering. + pub children: UnordMap>, } impl<'tcx> OwnerInfo<'tcx> { @@ -1547,36 +1550,23 @@ 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> { + #[inline] pub fn as_owner(self) -> Option<&'tcx OwnerInfo<'tcx>> { match self { MaybeOwner::Owner(i) => Some(i), - MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => None, + MaybeOwner::NonOwner(_) => None, } } + #[inline] pub fn unwrap(self) -> &'tcx OwnerInfo<'tcx> { self.as_owner().unwrap_or_else(|| panic!("Not a HIR owner")) } } -/// 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 6acf1524b608f..080eff0cc7a47 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -3,7 +3,7 @@ use rustc_span::def_id::DefPathHash; use crate::HashIgnoredAttrId; 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 crate::lints::DelayedLints; @@ -119,13 +119,6 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap } } -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) - } -} - impl HashStable for HashIgnoredAttrId { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { hcx.hash_attr_id(self, hasher) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index dabeaee4d00e5..1b6aec7813d5b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -388,7 +388,6 @@ fn print_macro_stats(ecx: &ExtCtxt<'_>) { fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let sess = tcx.sess; 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 { @@ -464,7 +463,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { tcx.registered_tools(()), Some(lint_buffer), rustc_lint::BuiltinCombinedEarlyLintPass::new(), - (&**krate, &*krate.attrs), + (krate, &*krate.attrs), ) } @@ -774,7 +773,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P fn resolver_for_lowering_raw<'tcx>( tcx: TyCtxt<'tcx>, (): (), -) -> (&'tcx (ty::ResolverAstLowering, Steal>), &'tcx ty::ResolverGlobalCtxt) { +) -> (&'tcx (ty::ResolverAstLowering, ast::Crate), &'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(); @@ -796,7 +795,7 @@ fn resolver_for_lowering_raw<'tcx>( } = resolver.into_outputs(); let resolutions = tcx.arena.alloc(untracked_resolutions); - (tcx.arena.alloc((untracked_resolver_for_lowering, Steal::new(Arc::new(krate)))), resolutions) + (tcx.arena.alloc((untracked_resolver_for_lowering, krate)), resolutions) } pub fn write_dep_info(tcx: TyCtxt<'_>) { @@ -854,7 +853,6 @@ pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) { } let _timer = tcx.sess.timer("write_interface"); let (_, krate) = tcx.resolver_for_lowering(); - let krate = &*krate.borrow(); let krate = rustc_ast_pretty::pprust::print_crate_as_interface( krate, @@ -871,7 +869,8 @@ pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) { 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.index_ast = rustc_ast_lowering::index_ast; + providers.lower_to_hir = rustc_ast_lowering::lower_to_hir; providers.resolver_for_lowering_raw = resolver_for_lowering_raw; providers.stripped_cfg_items = |tcx, _| &tcx.resolutions(()).stripped_cfg_items[..]; providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1; @@ -1023,6 +1022,8 @@ pub fn create_and_enter_global_ctxt 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<'_>) { + tcx.ensure_done().early_lint_checks(()); + if tcx.sess.opts.unstable_opts.input_stats { rustc_passes::input_stats::print_hir_stats(tcx); } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 35f73d17440f1..d0ac440f21075 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -30,10 +30,12 @@ macro_rules! arena_types { [decode] borrowck_result: rustc_middle::mir::ConcreteOpaqueTypes<'tcx>, [] resolver: ( rustc_middle::ty::ResolverAstLowering, - rustc_data_structures::steal::Steal< - std::sync::Arc - > + rustc_ast::Crate ), + [] index_ast: rustc_index::IndexVec< + rustc_span::def_id::LocalDefId, + rustc_ast::AstOwner<'tcx> + >, [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, [] const_allocs: rustc_middle::mir::interpret::Allocation, diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 42a1e7377f4ba..733c0d5e8873e 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -1118,11 +1118,8 @@ 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 krate = tcx.hir_crate_items(()); let upstream_crates = upstream_crates(tcx); - let resolutions = tcx.resolutions(()); // We hash the final, remapped names of all local source files so we @@ -1157,7 +1154,12 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { 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); + // hir_body_hash + for owner in krate.owners() { + if let Some(info) = tcx.lower_to_hir(owner.def_id).as_owner() { + info.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); diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 6c07e49734ab0..f55f4813b8fab 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -208,19 +208,18 @@ 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) @@ -229,11 +228,10 @@ pub fn provide(providers: &mut Providers) { } }) }; - providers.hir_attr_map = |tcx, id| { - tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) - }; + providers.hir_attr_map = + |tcx, id| tcx.lower_to_hir(id.def_id).as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs); providers.opt_ast_lowering_delayed_lints = - |tcx, id| tcx.hir_crate(()).owners[id.def_id].as_owner().map(|o| &o.delayed_lints); + |tcx, id| tcx.lower_to_hir(id.def_id).as_owner().map(|o| &o.delayed_lints); 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); @@ -273,7 +271,6 @@ pub fn provide(providers: &mut Providers) { |tcx, trait_id| tcx.resolutions(()).trait_impls.get(&trait_id).map_or(&[], |xs| &xs[..]); 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/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 074c601f6cfbf..16b9f624b876a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -83,7 +83,7 @@ use rustc_hir::def_id::{ CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId, }; use rustc_hir::lang_items::{LangItem, LanguageItems}; -use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate}; +use rustc_hir::{ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate}; use rustc_index::IndexVec; use rustc_lint_defs::LintId; use rustc_macros::rustc_queries; @@ -198,12 +198,18 @@ rustc_queries! { desc { "getting the resolver outputs" } } - query resolver_for_lowering_raw(_: ()) -> (&'tcx (ty::ResolverAstLowering, Steal>), &'tcx ty::ResolverGlobalCtxt) { + query resolver_for_lowering_raw(_: ()) -> (&'tcx (ty::ResolverAstLowering, ast::Crate), &'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. @@ -215,17 +221,9 @@ rustc_queries! { desc { "getting the source span" } } - /// Represents crate as a whole (as distinct from the top-level crate module). - /// - /// If you call `tcx.hir_crate(())` 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_crate(())`; instead, prefer wrappers like - /// [`TyCtxt::hir_visit_all_item_likes_in_crate`]. - query hir_crate(key: ()) -> &'tcx Crate<'tcx> { - arena_cache + query lower_to_hir(key: LocalDefId) -> hir::MaybeOwner<'tcx> { eval_always - desc { "getting the crate HIR" } + desc { |tcx| "lower HIR for `{}`", tcx.def_path_str(key.to_def_id()) } } /// All items in the crate. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index cbc4d0b70a3f7..423b6b5ae29be 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3373,7 +3373,7 @@ impl<'tcx> TyCtxt<'tcx> { self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]) } - pub fn resolver_for_lowering(self) -> &'tcx (ty::ResolverAstLowering, Steal>) { + pub fn resolver_for_lowering(self) -> &'tcx (ty::ResolverAstLowering, ast::Crate) { self.resolver_for_lowering_raw(()).0 } diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 725d47cb2ec4b..9b41203bd19e3 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -82,7 +82,7 @@ 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 krate = &*tcx.resolver_for_lowering().1.borrow(); + 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); diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 61be2994f00be..40ef4ca842eb2 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -248,7 +248,6 @@ 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, krate) = tcx.resolver_for_lowering(); - let krate = &*krate.borrow(); // Initialize the collector. let mut collector = LanguageItemCollector::new(tcx, resolver); From 5e1c6cf941b48a1ba016fcb3d4f1eb45b69dcf40 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 22 Jun 2025 15:50:17 +0000 Subject: [PATCH 4/5] Precompute hash for OwnerInfo too. --- compiler/rustc_ast_lowering/src/lib.rs | 21 +++++++++++++-- compiler/rustc_hir/src/hir.rs | 8 +++--- compiler/rustc_hir/src/stable_hash_impls.rs | 26 +++++++++++++------ compiler/rustc_middle/src/ty/context.rs | 4 +-- .../rustc_mir_transform/src/coverage/mod.rs | 2 +- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a38e23b79ce61..1425cbc98238a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -45,6 +45,7 @@ use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, *}; use rustc_attr_parsing::{AttributeParser, Late, OmitDoc}; use rustc_data_structures::sorted_map::SortedMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_data_structures::unord::ExtendUnord; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle}; @@ -679,16 +680,32 @@ impl<'hir> LoweringContext<'hir> { let bodies = SortedMap::from_presorted_elements(bodies); // Don't hash unless necessary, because it's expensive. - let (opt_hash_including_bodies, attrs_hash, delayed_lints_hash) = + let (bodies_hash, attrs_hash, delayed_lints_hash) = self.tcx.hash_owner_nodes(node, &bodies, &attrs, &delayed_lints, define_opaque); let num_nodes = self.item_local_id_counter.as_usize(); let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes); - let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies }; + let nodes = hir::OwnerNodes { opt_hash: bodies_hash, nodes, bodies }; let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque }; let delayed_lints = hir::lints::DelayedLints { lints: delayed_lints, opt_hash: delayed_lints_hash }; + let opt_hash = if self.tcx.needs_crate_hash() { + Some(self.tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + nodes.hash_stable(&mut hcx, &mut stable_hasher); + parenting.hash_stable(&mut hcx, &mut stable_hasher); + attrs.hash_stable(&mut hcx, &mut stable_hasher); + trait_map.hash_stable(&mut hcx, &mut stable_hasher); + delayed_lints.hash_stable(&mut hcx, &mut stable_hasher); + children.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + })) + } else { + None + }; + self.arena.alloc(hir::OwnerInfo { + opt_hash, nodes, parenting, attrs, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 5c96edacf70f3..47624ff45114b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1482,7 +1482,7 @@ impl<'tcx> AttributeMap<'tcx> { pub struct OwnerNodes<'tcx> { /// Pre-computed hash of the full HIR. Used in the crate hash. Only present /// when incr. comp. is enabled. - pub opt_hash_including_bodies: Option, + pub opt_hash: Option, /// Full HIR for the current owner. // The zeroth node's parent should never be accessed: the owner's parent is computed by the // hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally @@ -1515,13 +1515,13 @@ impl fmt::Debug for OwnerNodes<'_> { }), ) .field("bodies", &self.bodies) - .field("opt_hash_including_bodies", &self.opt_hash_including_bodies) + .field("opt_hash", &self.opt_hash) .finish() } } /// Full information resulting from lowering an AST node. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug)] pub struct OwnerInfo<'hir> { /// Contents of the HIR. pub nodes: OwnerNodes<'hir>, @@ -1537,6 +1537,8 @@ pub struct OwnerInfo<'hir> { pub delayed_lints: DelayedLints, /// Owners generated as side-effect by lowering. pub children: UnordMap>, + // Only present when the crate hash is needed. + pub opt_hash: Option, } impl<'tcx> OwnerInfo<'tcx> { diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 080eff0cc7a47..c20cb81d6ed2d 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -3,7 +3,7 @@ use rustc_span::def_id::DefPathHash; use crate::HashIgnoredAttrId; use crate::hir::{ - AttributeMap, BodyId, ForeignItemId, ImplItemId, ItemId, OwnerNodes, TraitItemId, + AttributeMap, BodyId, ForeignItemId, ImplItemId, ItemId, OwnerInfo, OwnerNodes, TraitItemId, }; use crate::hir_id::{HirId, ItemLocalId}; use crate::lints::DelayedLints; @@ -92,18 +92,17 @@ impl ToStableHashKey for ForeignItemId // in "DefPath Mode". impl<'tcx, HirCtx: crate::HashStableContext> HashStable for OwnerNodes<'tcx> { + #[inline] fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - // We ignore the `nodes` and `bodies` fields since these refer to information included in - // `hash` which is hashed in the collector and used for the crate hash. - // `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing - // the body satisfies the condition of two nodes being different have different - // `hash_stable` results. - let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _ } = *self; - opt_hash_including_bodies.unwrap().hash_stable(hcx, hasher); + // We ignore the other fields since these refer to information included in + // `opt_hash` which is hashed in the collector and used for the crate hash. + let OwnerNodes { opt_hash, .. } = *self; + opt_hash.unwrap().hash_stable(hcx, hasher); } } impl HashStable for DelayedLints { + #[inline] fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { let DelayedLints { opt_hash, .. } = *self; opt_hash.unwrap().hash_stable(hcx, hasher); @@ -111,6 +110,7 @@ impl HashStable for DelayedLints { } impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap<'tcx> { + #[inline] fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { // We ignore the `map` since it refers to information included in `opt_hash` which is // hashed in the collector and used for the crate hash. @@ -119,6 +119,16 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap } } +impl<'tcx, HirCtx: crate::HashStableContext> HashStable for OwnerInfo<'tcx> { + #[inline] + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + // We ignore the rest since it refers to information included in `opt_hash` which is + // hashed in the collector and used for the crate hash. + let OwnerInfo { opt_hash, .. } = *self; + opt_hash.unwrap().hash_stable(hcx, hasher); + } +} + impl HashStable for HashIgnoredAttrId { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { hcx.hash_attr_id(self, hasher) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 423b6b5ae29be..d2ece77f8c4ae 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1360,11 +1360,11 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> { let bodies = Default::default(); let attrs = hir::AttributeMap::EMPTY; - let (opt_hash_including_bodies, _, _) = + let (opt_hash, _, _) = self.tcx.hash_owner_nodes(node, &bodies, &attrs.map, &[], attrs.define_opaque); let node = node.into(); self.opt_hir_owner_nodes(Some(self.tcx.arena.alloc(hir::OwnerNodes { - opt_hash_including_bodies, + opt_hash, nodes: IndexVec::from_elem_n( hir::ParentedNode { parent: hir::ItemLocalId::INVALID, node }, 1, diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index f253d1662cac8..221bd7516732e 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -327,7 +327,7 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx hir::Body<'tcx>) -> u64 { // FIXME(cjgillot) Stop hashing HIR manually here. let owner = hir_body.id().hir_id.owner; - tcx.hir_owner_nodes(owner).opt_hash_including_bodies.unwrap().to_smaller_hash().as_u64() + tcx.hir_owner_nodes(owner).opt_hash.unwrap().to_smaller_hash().as_u64() } fn extract_hole_spans_from_hir<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &hir::Body<'tcx>) -> Vec { From 971544de9920f8d2edc2c5eaca7556f9c829de3d Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 2 Jul 2025 16:49:49 +0000 Subject: [PATCH 5/5] Split-up the AST to index it. --- Cargo.lock | 1 - compiler/rustc_ast/src/ast.rs | 12 +- compiler/rustc_ast/src/mut_visit.rs | 5 +- compiler/rustc_ast_lowering/Cargo.toml | 1 - compiler/rustc_ast_lowering/src/block.rs | 16 +- compiler/rustc_ast_lowering/src/expr.rs | 12 +- compiler/rustc_ast_lowering/src/item.rs | 27 +-- compiler/rustc_ast_lowering/src/lib.rs | 168 ++++++++++++++---- compiler/rustc_driver_impl/src/pretty.rs | 4 +- compiler/rustc_interface/src/passes.rs | 9 +- compiler/rustc_middle/src/arena.rs | 12 +- compiler/rustc_middle/src/query/mod.rs | 5 +- compiler/rustc_middle/src/ty/context.rs | 2 +- .../rustc_passes/src/debugger_visualizer.rs | 2 +- compiler/rustc_passes/src/lang_items.rs | 1 + ..._legacy_const_generics-issue-123077.stderr | 7 +- 16 files changed, 182 insertions(+), 102 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d2fca8bb3f48..000975979c874 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3242,7 +3242,6 @@ version = "0.0.0" dependencies = [ "rustc_abi", "rustc_ast", - "rustc_ast_pretty", "rustc_attr_data_structures", "rustc_attr_parsing", "rustc_data_structures", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index aa69dcfdcff17..2bee4384d8120 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -4109,14 +4109,14 @@ impl TryFrom for ForeignItemKind { pub type ForeignItem = Item; #[derive(Debug)] -pub enum AstOwner<'a> { +pub enum AstOwner { NonOwner, Synthetic(rustc_span::def_id::LocalDefId), - Crate(&'a Crate), - Item(&'a Item), - TraitItem(&'a AssocItem), - ImplItem(&'a AssocItem), - ForeignItem(&'a ForeignItem), + Crate(P), + Item(P), + TraitItem(P), + ImplItem(P), + ForeignItem(P), } // Some nodes are used a lot. Make sure they don't unintentionally get bigger. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 3eae19f4daa11..f9c018da90992 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -142,7 +142,10 @@ pub fn walk_flat_map_stmt( stmts } -fn walk_flat_map_stmt_kind(vis: &mut T, kind: StmtKind) -> SmallVec<[StmtKind; 1]> { +pub fn walk_flat_map_stmt_kind( + vis: &mut T, + kind: StmtKind, +) -> SmallVec<[StmtKind; 1]> { match kind { StmtKind::Let(mut local) => smallvec![StmtKind::Let({ vis.visit_local(&mut local); diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index dc571f5c3671a..6e23549047f1f 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -10,7 +10,6 @@ doctest = false # tidy-alphabetical-start rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } -rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr_data_structures = { path = "../rustc_attr_data_structures" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 51bfd9f355019..3bc05b22a408b 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -43,17 +43,11 @@ impl<'hir> LoweringContext<'hir> { stmts.push(hir::Stmt { hir_id, kind, span }); } StmtKind::Item(it) => { - stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map( - |(i, item_id)| { - let hir_id = match i { - 0 => self.lower_node_id(s.id), - _ => self.next_id(), - }; - let kind = hir::StmtKind::Item(item_id); - let span = self.lower_span(s.span); - hir::Stmt { hir_id, kind, span } - }, - )); + let item_id = self.lower_item_ref(it); + let hir_id = self.lower_node_id(s.id); + let kind = hir::StmtKind::Item(item_id); + let span = self.lower_span(s.span); + stmts.push(hir::Stmt { hir_id, kind, span }); } StmtKind::Expr(e) => { let e = self.lower_expr(e); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b2b086e9cf00d..6f5357a5e56f4 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use rustc_ast::ptr::P as AstP; use rustc_ast::*; -use rustc_ast_pretty::pprust::expr_to_string; use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; @@ -463,13 +462,16 @@ impl<'hir> LoweringContext<'hir> { let mut invalid_expr_error = |tcx: TyCtxt<'_>, span| { // Avoid emitting the error multiple times. if error.is_none() { + let sm = tcx.sess.source_map(); let mut const_args = vec![]; let mut other_args = vec![]; for (idx, arg) in args.iter().enumerate() { - if legacy_args_idx.contains(&idx) { - const_args.push(format!("{{ {} }}", expr_to_string(arg))); - } else { - other_args.push(expr_to_string(arg)); + if let Ok(arg) = sm.span_to_snippet(arg.span) { + if legacy_args_idx.contains(&idx) { + const_args.push(format!("{{ {} }}", arg)); + } else { + other_args.push(arg); + } } } let suggestion = UseConstGenericArg { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b1c95fe5e1d69..325a1f9e22984 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -10,7 +10,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{DesugaringKind, Ident, Span, Symbol, kw, sym}; -use smallvec::{SmallVec, smallvec}; +use smallvec::SmallVec; use thin_vec::ThinVec; use tracing::instrument; @@ -27,6 +27,7 @@ use super::{ pub(super) struct ItemLowerer<'hir> { pub(super) tcx: TyCtxt<'hir>, pub(super) resolver: &'hir ResolverAstLowering, + pub(super) next_node_id: NodeId, } /// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span @@ -56,7 +57,7 @@ impl<'hir> ItemLowerer<'hir> { owner: NodeId, f: impl FnOnce(&mut LoweringContext<'hir>) -> hir::OwnerNode<'hir>, ) -> hir::MaybeOwner<'hir> { - let mut lctx = LoweringContext::new(self.tcx, self.resolver, owner); + let mut lctx = LoweringContext::new(self.tcx, self.resolver, owner, self.next_node_id); let item = f(&mut lctx); debug_assert_eq!(lctx.current_hir_id_owner, item.def_id()); @@ -105,28 +106,12 @@ impl<'hir> LoweringContext<'hir> { inner_span: self.lower_span(spans.inner_span), inject_use_span: self.lower_span(spans.inject_use_span), }, - item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))), + item_ids: self.arena.alloc_from_iter(items.iter().map(|x| self.lower_item_ref(x))), }) } - pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { - let mut node_ids = smallvec![hir::ItemId { owner_id: self.owner_id(i.id) }]; - if let ItemKind::Use(use_tree) = &i.kind { - self.lower_item_id_use_tree(use_tree, &mut node_ids); - } - node_ids - } - - fn lower_item_id_use_tree(&mut self, tree: &UseTree, vec: &mut SmallVec<[hir::ItemId; 1]>) { - match &tree.kind { - UseTreeKind::Nested { items, .. } => { - for &(ref nested, id) in items { - vec.push(hir::ItemId { owner_id: self.owner_id(id) }); - self.lower_item_id_use_tree(nested, vec); - } - } - UseTreeKind::Simple(..) | UseTreeKind::Glob => {} - } + pub(super) fn lower_item_ref(&mut self, i: &Item) -> hir::ItemId { + hir::ItemId { owner_id: self.owner_id(i.id) } } fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1425cbc98238a..8b18ae31d6c10 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -40,12 +40,14 @@ use std::sync::Arc; +use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::node_id::NodeMap; -use rustc_ast::visit::{self, Visitor}; +use rustc_ast::ptr::P; use rustc_ast::{self as ast, *}; use rustc_attr_parsing::{AttributeParser, Late, OmitDoc}; 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::tagged_ptr::TaggedRef; use rustc_data_structures::unord::ExtendUnord; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle}; @@ -64,7 +66,7 @@ use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::add_feature_diagnostics; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; -use smallvec::SmallVec; +use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; use tracing::{debug, instrument, trace}; @@ -158,7 +160,12 @@ struct LoweringContext<'hir> { } impl<'hir> LoweringContext<'hir> { - fn new(tcx: TyCtxt<'hir>, resolver: &'hir ResolverAstLowering, owner: NodeId) -> Self { + fn new( + tcx: TyCtxt<'hir>, + resolver: &'hir ResolverAstLowering, + owner: NodeId, + next_node_id: NodeId, + ) -> Self { let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect(); let current_hir_id_owner = hir::OwnerId { def_id: resolver.node_id_to_def_id[&owner] }; Self { @@ -180,7 +187,7 @@ impl<'hir> LoweringContext<'hir> { #[cfg(debug_assertions)] node_id_to_local_id: [(owner, hir::ItemLocalId::ZERO)].into_iter().collect(), trait_map: Default::default(), - next_node_id: resolver.next_node_id, + next_node_id, node_id_to_def_id: NodeMap::default(), partial_res_overrides: NodeMap::default(), @@ -388,69 +395,152 @@ enum FnDeclKind { Impl, } -pub fn index_ast<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexVec> { +pub fn index_ast<'tcx>( + tcx: TyCtxt<'tcx>, + (): (), +) -> (IndexVec>, NodeId) { + // Queries that borrow `resolver_for_lowering`. + tcx.ensure_done().output_filenames(()); + tcx.ensure_done().early_lint_checks(()); + tcx.ensure_done().get_lang_items(()); + tcx.ensure_done().debugger_visualizers(LOCAL_CRATE); + let (resolver, krate) = tcx.resolver_for_lowering(); + let mut krate = krate.steal(); - let mut indexer = - Indexer { node_id_to_def_id: &resolver.node_id_to_def_id, index: IndexVec::new() }; - indexer.visit_crate(&krate); - indexer.insert(CRATE_NODE_ID, AstOwner::Crate(&*krate)); - return tcx.arena.alloc(indexer.index); + let mut indexer = Indexer { + node_id_to_def_id: &resolver.node_id_to_def_id, + index: IndexVec::new(), + next_node_id: resolver.next_node_id, + }; + indexer.visit_crate(&mut krate); + indexer.insert(CRATE_NODE_ID, AstOwner::Crate(P(krate))); + return (indexer.index, indexer.next_node_id); - struct Indexer<'s, 'ast> { + struct Indexer<'s> { node_id_to_def_id: &'s NodeMap, - index: IndexVec>, + index: IndexVec>, + next_node_id: NodeId, } - impl<'ast> Indexer<'_, 'ast> { - fn insert(&mut self, id: NodeId, node: AstOwner<'ast>) { + impl Indexer<'_> { + fn insert(&mut self, id: NodeId, node: AstOwner) { let def_id = self.node_id_to_def_id[&id]; - self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); - self.index[def_id] = node; + self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner)); + self.index[def_id] = Steal::new(node); + } + + fn make_dummy( + &mut self, + id: NodeId, + span: Span, + dummy: impl FnOnce(P) -> K, + ) -> P> { + use rustc_ast::token::Delimiter; + use rustc_ast::tokenstream::{DelimSpan, TokenStream}; + use thin_vec::thin_vec; + + P(Item { + attrs: AttrVec::default(), + id, + span, + vis: Visibility { kind: VisibilityKind::Public, span, tokens: None }, + // Lacking a better choice, we replace the contents with a macro call. + // Unexpanded macros should never reach lowering, so this is not confusing. + kind: dummy(P(MacCall { + path: Path { span, segments: thin_vec![], tokens: None }, + args: P(DelimArgs { + dspan: DelimSpan::from_single(span), + delim: Delimiter::Parenthesis, + tokens: TokenStream::new(Vec::new()), + }), + })), + tokens: None, + }) } - fn visit_item_id_use_tree(&mut self, tree: &UseTree, parent: LocalDefId) { + fn replace_with_dummy( + &mut self, + item: &mut ast::Item, + dummy: impl FnOnce(P) -> K, + node: impl FnOnce(P>) -> AstOwner, + ) { + let dummy = self.make_dummy(item.id, item.span, dummy); + let item = std::mem::replace(item, *dummy); + self.insert(item.id, node(P(item))); + } + + #[tracing::instrument(level = "trace", skip(self))] + fn visit_item_id_use_tree( + &mut self, + tree: &UseTree, + parent: LocalDefId, + items: &mut SmallVec<[P; 1]>, + ) { match tree.kind { UseTreeKind::Glob | UseTreeKind::Simple(_) => {} - UseTreeKind::Nested { items: ref nested_vec, span: _ } => { + UseTreeKind::Nested { items: ref nested_vec, span } => { for &(ref nested, id) in nested_vec { self.insert(id, AstOwner::Synthetic(parent)); + items.push(self.make_dummy(id, span, ItemKind::MacCall)); let def_id = self.node_id_to_def_id[&id]; - self.visit_item_id_use_tree(nested, def_id); + self.visit_item_id_use_tree(nested, def_id, items); } } } } } - impl<'ast> visit::Visitor<'ast> for Indexer<'_, 'ast> { - fn visit_attribute(&mut self, _: &'ast Attribute) { + impl MutVisitor for Indexer<'_> { + fn visit_attribute(&mut self, _: &mut 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: &'ast Item) { + fn flat_map_item(&mut self, mut item: P) -> SmallVec<[P; 1]> { let def_id = self.node_id_to_def_id[&item.id]; + mut_visit::walk_item(self, &mut *item); + let dummy = self.make_dummy(item.id, item.span, ItemKind::MacCall); + let mut items = smallvec![dummy]; if let ItemKind::Use(ref use_tree) = item.kind { - self.visit_item_id_use_tree(use_tree, def_id); + self.visit_item_id_use_tree(use_tree, def_id, &mut items); } - visit::walk_item(self, item); self.insert(item.id, AstOwner::Item(item)); + items } - fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: visit::AssocCtxt) { - visit::walk_assoc_item(self, item, ctxt); - let owner_ref = match ctxt { - visit::AssocCtxt::Trait => AstOwner::TraitItem(item), - visit::AssocCtxt::Impl { .. } => AstOwner::ImplItem(item), - }; - self.insert(item.id, owner_ref); + fn flat_map_stmt(&mut self, stmt: Stmt) -> SmallVec<[Stmt; 1]> { + let Stmt { id, span, kind } = stmt; + let mut id = Some(id); + mut_visit::walk_flat_map_stmt_kind(self, kind) + .into_iter() + .map(|kind| { + let id = id.take().unwrap_or_else(|| { + let next = self.next_node_id; + self.next_node_id.increment_by(1); + next + }); + Stmt { id, kind, span } + }) + .collect() } - fn visit_foreign_item(&mut self, item: &'ast ForeignItem) { - visit::walk_item(self, item); - self.insert(item.id, AstOwner::ForeignItem(item)); + fn visit_assoc_item(&mut self, item: &mut AssocItem, ctxt: visit::AssocCtxt) { + mut_visit::walk_assoc_item(self, item, ctxt); + match ctxt { + visit::AssocCtxt::Trait => { + self.replace_with_dummy(item, AssocItemKind::MacCall, AstOwner::TraitItem) + } + visit::AssocCtxt::Impl { .. } => { + self.replace_with_dummy(item, AssocItemKind::MacCall, AstOwner::ImplItem) + } + } + } + + fn visit_foreign_item(&mut self, item: &mut ForeignItem) { + mut_visit::walk_item(self, item); + self.replace_with_dummy(item, ForeignItemKind::MacCall, AstOwner::ForeignItem); } } } @@ -463,13 +553,13 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> tcx.ensure_done().debugger_visualizers(LOCAL_CRATE); tcx.ensure_done().get_lang_items(()); let (resolver, _) = tcx.resolver_for_lowering(); - let ast_index = tcx.index_ast(()); - let node = ast_index.get(def_id); + let (ast_index, next_node_id) = tcx.index_ast(()); + let node = ast_index.get(def_id).map(Steal::steal); - let mut item_lowerer = item::ItemLowerer { tcx, resolver }; + let mut item_lowerer = item::ItemLowerer { tcx, resolver, next_node_id: *next_node_id }; // The item existed in the AST. - let parent_id = match node { + let parent_id = match node.as_ref() { Some(AstOwner::Crate(c)) => return item_lowerer.lower_crate(&c), Some(AstOwner::Item(item)) => return item_lowerer.lower_item(&item), Some(AstOwner::TraitItem(item)) => { @@ -483,6 +573,8 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> Some(AstOwner::NonOwner) | None => tcx.local_parent(def_id), }; + tcx.sess.time("drop_ast", || std::mem::drop(node)); + // 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 { diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 6b9124334eceb..37b9cfffff3b3 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -211,7 +211,7 @@ impl<'tcx> PrintExtra<'tcx> { { match self { PrintExtra::AfterParsing { krate, .. } => f(krate), - PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering().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().1) + format!("{:#?}", ex.tcx().resolver_for_lowering().1.borrow()) } Hir(s) => { debug!("pretty printing HIR {:?}", s); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 1b6aec7813d5b..7907b8b62216c 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -388,6 +388,7 @@ fn print_macro_stats(ecx: &ExtCtxt<'_>) { fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let sess = tcx.sess; 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 { @@ -463,7 +464,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { tcx.registered_tools(()), Some(lint_buffer), rustc_lint::BuiltinCombinedEarlyLintPass::new(), - (krate, &*krate.attrs), + (&*krate, &*krate.attrs), ) } @@ -773,7 +774,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P fn resolver_for_lowering_raw<'tcx>( tcx: TyCtxt<'tcx>, (): (), -) -> (&'tcx (ty::ResolverAstLowering, ast::Crate), &'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(); @@ -795,7 +796,7 @@ fn resolver_for_lowering_raw<'tcx>( } = resolver.into_outputs(); let resolutions = tcx.arena.alloc(untracked_resolutions); - (tcx.arena.alloc((untracked_resolver_for_lowering, krate)), resolutions) + (tcx.arena.alloc((untracked_resolver_for_lowering, Steal::new(krate))), resolutions) } pub fn write_dep_info(tcx: TyCtxt<'_>) { @@ -855,7 +856,7 @@ pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) { let (_, krate) = tcx.resolver_for_lowering(); let krate = rustc_ast_pretty::pprust::print_crate_as_interface( - krate, + &*krate.borrow(), tcx.sess.psess.edition, &tcx.sess.psess.attr_id_generator, ); diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index d0ac440f21075..8273fd5e8de8c 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -30,12 +30,14 @@ macro_rules! arena_types { [decode] borrowck_result: rustc_middle::mir::ConcreteOpaqueTypes<'tcx>, [] resolver: ( rustc_middle::ty::ResolverAstLowering, - rustc_ast::Crate + rustc_data_structures::steal::Steal + ), + [] index_ast: ( + rustc_index::IndexVec + >, + rustc_ast::NodeId, ), - [] index_ast: rustc_index::IndexVec< - rustc_span::def_id::LocalDefId, - rustc_ast::AstOwner<'tcx> - >, [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, [] const_allocs: rustc_middle::mir::interpret::Allocation, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 16b9f624b876a..77e7f8703d7c9 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -198,13 +198,14 @@ rustc_queries! { desc { "getting the resolver outputs" } } - query resolver_for_lowering_raw(_: ()) -> (&'tcx (ty::ResolverAstLowering, ast::Crate), &'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> { + query index_ast(_: ()) -> &'tcx (IndexVec>, ast::NodeId) { + arena_cache eval_always no_hash desc { "getting the AST for lowering" } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d2ece77f8c4ae..ab535fc1f66d5 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3373,7 +3373,7 @@ impl<'tcx> TyCtxt<'tcx> { self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]) } - pub fn resolver_for_lowering(self) -> &'tcx (ty::ResolverAstLowering, ast::Crate) { + pub fn resolver_for_lowering(self) -> &'tcx (ty::ResolverAstLowering, Steal) { self.resolver_for_lowering_raw(()).0 } diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 9b41203bd19e3..067b28e141f6a 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -85,7 +85,7 @@ fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec LanguageItemCollector<'ast, 'tcx> { /// Traverses and collects all the lang items in all crates. fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { let (resolver, krate) = tcx.resolver_for_lowering(); + let krate = &*krate.borrow(); // Initialize the collector. let mut collector = LanguageItemCollector::new(tcx, resolver); diff --git a/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr b/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr index 6f5d719006d8f..111d6d524e5fb 100644 --- a/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr +++ b/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr @@ -67,9 +67,10 @@ LL | struct F(); help: try using a const generic argument instead | LL ~ std::arch::x86_64::_mm_blend_ps::<{ { -LL + struct F(); -LL + 1 -LL ~ } }>(loop {}, loop {}); +LL + struct F(); +LL + +LL + 1 +LL ~ } }>(loop {}, loop {}); | error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items