diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index f4bfec24e3b1b..b915de481171d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -28,7 +28,7 @@ use crate::diagnostics::{ }; use crate::{ AllowReturnTypeNotation, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext, - ParamMode, ResolverAstLoweringExt, TryBlockScope, + ParamMode, TryBlockScope, }; pub(super) struct WillCreateDefIdsVisitor; @@ -267,7 +267,9 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), ExprKind::Call(f, args) => { - if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f, self.tcx) { + if let Some(legacy_args) = + self.curr_owner.owner.legacy_const_generic_args(f, self.tcx) + { self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args) } else { let f = self.lower_expr(f); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4bc61a22b3b3d..58b3cf663d3f8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -45,7 +45,6 @@ use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::node_id::NodeMap; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, *}; -use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; use rustc_attr_ir::target::Target; use rustc_attr_parsing::{AttributeParser, Recovery, ShouldEmit}; @@ -65,7 +64,6 @@ use rustc_hir::{ LifetimeSource, LifetimeSyntax, MissingLifetimeKind, ParamName, TraitCandidate, }; use rustc_index::{Idx, IndexSlice, IndexVec}; -use rustc_macros::extension; use rustc_middle::middle::resolve::{ AstOwner, LifetimeRes, PartialRes, PerOwnerResolverData, ResolverAstLowering, }; @@ -409,40 +407,6 @@ impl SpanLowerer { } } -#[extension(trait ResolverAstLoweringExt<'tcx>)] -impl<'tcx> ResolverAstLowering<'tcx> { - fn legacy_const_generic_args(&self, expr: &Expr, tcx: TyCtxt<'tcx>) -> Option> { - let ExprKind::Path(None, path) = &expr.kind else { - return None; - }; - - // Don't perform legacy const generics rewriting if the path already - // has generic arguments. - if path.segments.last().unwrap().args.is_some() { - return None; - } - - // We do not need to look at `partial_res_overrides`. That map only contains overrides for - // `self_param` locals. And here we are looking for the function definition that `expr` - // resolves to. - let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?; - - // We only support cross-crate argument rewriting. Uses - // within the same crate should be updated to use the new - // const generics style. - if def_id.is_local() { - return None; - } - - // we can use parsed attrs here since for other crates they're already available - find_attr!( - tcx, def_id, - RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes - ) - .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect()) - } -} - /// How relaxed bounds `?Trait` should be treated. /// /// Relaxed bounds should only be allowed in places where we later @@ -872,7 +836,29 @@ impl<'hir> LoweringContext<'_, 'hir> { fn get_partial_res(&self, id: NodeId) -> Option { match self.partial_res_overrides.get(&id) { Some(self_param_id) => Some(PartialRes::new(Res::Local(*self_param_id))), - None => self.resolver.partial_res_map.get(&id).copied(), + None => { + let new = self.curr_owner.owner.partial_res_map.get(&id).copied(); + let old = self.resolver.partial_res_map.get(&id).copied(); + if new.is_none() != old.is_none() { + let found = self + .resolver + .owners + .items() + .filter_map(|(_owner_id, owner)| { + owner.partial_res_map.get(&id)?; + Some(owner.def_id) + }) + .get_only() + .unwrap(); + debug!( + "owner_map: {new:?}\nglobal_map: {old:?}\n found in {found:?} {:?}\n current owner: {:?} {:?}", + self.tcx.source_span(found), + self.curr_owner.owner.def_id, + self.tcx.source_span(self.curr_owner.owner.def_id), + ); + } + old + } } } diff --git a/compiler/rustc_middle/src/middle/resolve.rs b/compiler/rustc_middle/src/middle/resolve.rs index c34758e6454e4..41da71670f7bd 100644 --- a/compiler/rustc_middle/src/middle/resolve.rs +++ b/compiler/rustc_middle/src/middle/resolve.rs @@ -3,7 +3,7 @@ use rustc_ast::node_id::NodeMap; use rustc_ast::{self as ast, NodeId}; -use rustc_attr_ir::StrippedCfgItem; +use rustc_attr_ir::{StrippedCfgItem, find_attr}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::steal::Steal; use rustc_data_structures::unord::{UnordMap, UnordSet}; @@ -17,7 +17,7 @@ use rustc_span::{ExpnId, Ident, Span, Symbol}; use smallvec::SmallVec; use crate::middle::privacy::EffectiveVisibilities; -use crate::ty::Visibility; +use crate::ty::{TyCtxt, Visibility}; /// The result of resolving a path before lowering to HIR, /// with "module" segments resolved and associated item @@ -216,6 +216,10 @@ pub struct PerOwnerResolverData<'tcx> { pub extra_lifetime_params_map: NodeMap> = Default::default(), + + /// Resolutions for nodes that have a single resolution. + pub partial_res_map: NodeMap = Default::default(), + /// The id of the owner pub id: NodeId, /// The `DefId` of the owner, can't be found in `node_id_to_def_id`. @@ -247,6 +251,41 @@ impl<'tcx> PerOwnerResolverData<'tcx> { pub fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, MissingLifetimeKind)] { self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) } + + pub fn legacy_const_generic_args( + &self, + expr: &ast::Expr, + tcx: TyCtxt<'tcx>, + ) -> Option> { + let ast::ExprKind::Path(None, path) = &expr.kind else { + return None; + }; + + // Don't perform legacy const generics rewriting if the path already + // has generic arguments. + if path.segments.last().unwrap().args.is_some() { + return None; + } + + // We do not need to look at `partial_res_overrides`. That map only contains overrides for + // `self_param` locals. And here we are looking for the function definition that `expr` + // resolves to. + let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?; + + // We only support cross-crate argument rewriting. Uses + // within the same crate should be updated to use the new + // const generics style. + if def_id.is_local() { + return None; + } + + // we can use parsed attrs here since for other crates they're already available + find_attr!( + tcx, def_id, + RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes + ) + .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect()) + } } /// Resolutions that should only be used for lowering. diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 09d7f5dd11006..a8949f2bbf461 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -497,6 +497,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { vis: vis.clone(), parent_scope: self.parent_scope, error, + owner: self.r.current_owner.id, }); Visibility::Public } diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 9defefee9637b..0588a94f7d31f 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -57,7 +57,7 @@ use crate::{ DelayedVisResolutionError, Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey, LateDecl, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used, - VisResolutionError, path_names_to_string, + VisResolutionError, path_names_to_string, with_owner, }; /// A vector of spans and replacements, a message and applicability. @@ -384,13 +384,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn report_delayed_vis_resolution_errors(&mut self) { - for DelayedVisResolutionError { vis, parent_scope, error } in + for DelayedVisResolutionError { vis, parent_scope, error, owner } in mem::take(&mut self.delayed_vis_resolution_errors) { - match self.try_resolve_visibility(&parent_scope, &vis, true) { - Ok(_) => self.report_vis_error(error), - Err(error) => self.report_vis_error(error), - }; + with_owner(self, owner, |this| { + match this.try_resolve_visibility(&parent_scope, &vis, true) { + Ok(_) => this.report_vis_error(error), + Err(error) => this.report_vis_error(error), + } + }); } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 5cd45c5de5230..354898780f245 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -36,7 +36,7 @@ use crate::{ AmbiguityError, BindingKey, Decl, DeclData, DeclKind, Determinacy, Finalize, IdentKey, ImportSuggestion, ImportSummary, LocalModule, ModuleOrUniformRoot, ParentScope, PathResult, PerNS, Res, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, - names_to_string, + names_to_string, with_owner, }; /// A potential import declaration in the process of being planted into a module. @@ -911,7 +911,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .expect("planting a glob cannot fail"); } - self.record_partial_res(*id, PartialRes::new(module.res().unwrap())); + with_owner(self, import.root_id, |this| { + this.record_partial_res(*id, PartialRes::new(module.res().unwrap())) + }); } // Something weird happened, which shouldn't have happened. @@ -941,7 +943,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .map(|i| (false, i)) .chain(indeterminate_imports.iter().map(|(i, _, _)| (true, i))) { - let unresolved_import_error = self.finalize_import(*import); + let unresolved_import_error = + with_owner(self, import.root_id, |this| this.finalize_import(*import)); // If this import is unresolved then create a dummy import // resolution for it so that later resolve stages won't complain. self.import_dummy_binding(*import, is_indeterminate); @@ -1645,12 +1648,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // purposes it's good enough to just favor one over the other. self.per_ns_mut(|this, ns| { if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) { - this.owners - .get_mut(&import.root_id) - .unwrap() - .import_res - .entry(import_id) - .or_default()[ns] = Some(binding.res()); + this.current_owner.import_res.entry(import_id).or_default()[ns] = + Some(binding.res()); } }); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e1787eadf5fb9..46f51de433483 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5089,7 +5089,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Fix up partial res of segment from `resolve_path` call. if let Some(id) = path[0].id { - self.r.partial_res_map.insert(id, PartialRes::new(Res::PrimTy(prim))); + let res = PartialRes::new(Res::PrimTy(prim)); + self.r.partial_res_map.insert(id, res); + self.r.current_owner.partial_res_map.insert(id, res); + assert_ne!(self.r.current_owner.id, DUMMY_NODE_ID); } PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1) @@ -5387,7 +5390,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ExprKind::Call(ref callee, ref arguments) => { self.resolve_expr(callee, Some(expr)); - let const_args = self.r.legacy_const_generic_args(callee).unwrap_or_default(); + let const_args = self + .r + .current_owner + .legacy_const_generic_args(callee, self.r.tcx) + .unwrap_or_default(); for (idx, argument) in arguments.iter().enumerate() { // Constant arguments need to be treated as AnonConst since // that is how they will be later lowered to HIR. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 0a96becf993e9..8b6b9d656a0fc 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -40,10 +40,10 @@ use macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef}; use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; use rustc_ast::{ - self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, Expr, ExprKind, - GenericArg, GenericArgs, Generics, NodeId, Path, attr, + self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, GenericArg, GenericArgs, + Generics, NodeId, Path, attr, }; -use rustc_attr_ir::{StrippedCfgItem, find_attr}; +use rustc_attr_ir::StrippedCfgItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, default}; use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; @@ -1088,6 +1088,7 @@ struct DelayedVisResolutionError<'ra> { vis: ast::Visibility, parent_scope: ParentScope<'ra>, error: VisResolutionError, + owner: NodeId, } #[derive(Clone, Copy, PartialEq, Debug)] @@ -2438,9 +2439,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn record_partial_res(&mut self, node_id: NodeId, resolution: PartialRes) { debug!("(recording res) recording {:?} for {}", resolution, node_id); + // We insert into both the global and the owner-local partial res map. + // The global one is needed for many diagnostics, and looking it up in the owner is not always feasible, + // as we regularly look at e.g. the parent's ast and resolve some ids there. + // We want to keep doing that lazily instead of eagerly, as we only need the information in the error path. if let Some(prev_res) = self.partial_res_map.insert(node_id, resolution) { panic!("path resolved multiple times ({prev_res:?} before, {resolution:?} now)"); } + assert_ne!(self.current_owner.id, DUMMY_NODE_ID); + if let Some(prev_res) = self.current_owner.partial_res_map.insert(node_id, resolution) { + panic!("path resolved multiple times ({prev_res:?} before, {resolution:?} now)"); + } } fn record_pat_span(&mut self, node: NodeId, span: Span) { @@ -2630,36 +2639,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - /// Checks if an expression refers to a function marked with - /// `#[rustc_legacy_const_generics]` and returns the argument index list - /// from the attribute. - fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option> { - let ExprKind::Path(None, path) = &expr.kind else { - return None; - }; - // Don't perform legacy const generics rewriting if the path already - // has generic arguments. - if path.segments.last().unwrap().args.is_some() { - return None; - } - - let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?; - - // We only support cross-crate argument rewriting. Uses - // within the same crate should be updated to use the new - // const generics style. - if def_id.is_local() { - return None; - } - - find_attr!( - // we can use parsed attrs here since for other crates they're already available - self.tcx, def_id, - RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes - ) - .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect()) - } - fn resolve_main(&mut self) { let any_exe = self.tcx.crate_types().contains(&CrateType::Executable); // Don't try to resolve main unless it's an executable