diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 513d4e9b4a5..c8852a3a369 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -11,10 +11,13 @@ use std::fmt; use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_data_structures::sorted_map::SortedMap; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node}; +use rustc_hir::{ + GenericArg, GenericParam, GenericParamKind, HirId, ItemLocalMap, LifetimeName, Node, +}; use rustc_macros::extension; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::*; @@ -74,7 +77,7 @@ impl ResolvedArg { struct NamedVarMap { // maps from every use of a named (not anonymous) bound var to a // `ResolvedArg` describing how that variable is bound - defs: HirIdMap, + defs: ItemLocalMap, // Maps relevant hir items to the bound vars on them. These include: // - function defs @@ -82,7 +85,7 @@ struct NamedVarMap { // - closures // - trait refs // - bound types (like `T` in `for<'a> T<'a>: Foo`) - late_bound_vars: HirIdMap>, + late_bound_vars: ItemLocalMap>, } struct BoundVarContext<'a, 'tcx> { @@ -225,10 +228,10 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { resolve_bound_vars, - named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id), + named_variable_map: |tcx, id| &tcx.resolve_bound_vars(id).defs, is_late_bound_map, object_lifetime_default, - late_bound_vars_map: |tcx, id| tcx.resolve_bound_vars(id).late_bound_vars.get(&id), + late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars, ..*providers }; @@ -265,16 +268,12 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou hir::OwnerNode::Synthetic => unreachable!(), } - let mut rl = ResolveBoundVars::default(); - - for (hir_id, v) in named_variable_map.defs { - let map = rl.defs.entry(hir_id.owner).or_default(); - map.insert(hir_id.local_id, v); - } - for (hir_id, v) in named_variable_map.late_bound_vars { - let map = rl.late_bound_vars.entry(hir_id.owner).or_default(); - map.insert(hir_id.local_id, v); - } + let defs = named_variable_map.defs.into_sorted_stable_ord(); + let late_bound_vars = named_variable_map.late_bound_vars.into_sorted_stable_ord(); + let rl = ResolveBoundVars { + defs: SortedMap::from_presorted_elements(defs), + late_bound_vars: SortedMap::from_presorted_elements(late_bound_vars), + }; debug!(?rl.defs); debug!(?rl.late_bound_vars); @@ -340,7 +339,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { Scope::Binder { hir_id, .. } => { // Nested poly trait refs have the binders concatenated let mut full_binders = - self.map.late_bound_vars.entry(*hir_id).or_default().clone(); + self.map.late_bound_vars.entry(hir_id.local_id).or_default().clone(); full_binders.extend(supertrait_bound_vars); break (full_binders, BinderScopeType::Concatenating); } @@ -677,7 +676,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { hir::TyKind::Ref(lifetime_ref, ref mt) => { self.visit_lifetime(lifetime_ref); let scope = Scope::ObjectLifetimeDefault { - lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(), + lifetime: self.map.defs.get(&lifetime_ref.hir_id.local_id).cloned(), s: self.scope, }; self.with(scope, |this| this.visit_ty(mt.ty)); @@ -704,7 +703,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // and ban them. Type variables instantiated inside binders aren't // well-supported at the moment, so this doesn't work. // In the future, this should be fixed and this error should be removed. - let def = self.map.defs.get(&lifetime.hir_id).copied(); + let def = self.map.defs.get(&lifetime.hir_id.local_id).copied(); let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue }; let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id); @@ -841,7 +840,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let bound_vars: Vec<_> = self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect(); let hir_id = self.tcx.local_def_id_to_hir_id(def_id); - self.map.late_bound_vars.insert(hir_id, bound_vars); + self.map.late_bound_vars.insert(hir_id.local_id, bound_vars); } self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure)); intravisit::walk_fn_kind(self, fk); @@ -1019,10 +1018,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec) { - if let Some(old) = self.map.late_bound_vars.insert(hir_id, binder) { + if let Some(old) = self.map.late_bound_vars.insert(hir_id.local_id, binder) { bug!( "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}", - self.map.late_bound_vars[&hir_id] + self.map.late_bound_vars[&hir_id.local_id] ) } } @@ -1381,9 +1380,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { kind.descr(param_def_id.to_def_id()) ), }; - self.map.defs.insert(hir_id, ResolvedArg::Error(guar)); + self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar)); } else { - self.map.defs.insert(hir_id, def); + self.map.defs.insert(hir_id.local_id, def); } return; } @@ -1416,7 +1415,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id())) } }); - self.map.defs.insert(hir_id, ResolvedArg::Error(guar)); + self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar)); return; } Scope::Root { .. } => break, @@ -1526,7 +1525,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // This index can be used with `generic_args` since `parent_count == 0`. let index = generics.param_def_id_to_index[¶m_def_id] as usize; generic_args.args.get(index).and_then(|arg| match arg { - GenericArg::Lifetime(lt) => map.defs.get(<.hir_id).copied(), + GenericArg::Lifetime(lt) => map.defs.get(<.hir_id.local_id).copied(), _ => None, }) } @@ -1816,7 +1815,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) { debug!(span = ?lifetime_ref.ident.span); - self.map.defs.insert(lifetime_ref.hir_id, def); + self.map.defs.insert(lifetime_ref.hir_id.local_id, def); } /// Sometimes we resolve a lifetime, but later find that it is an @@ -1827,8 +1826,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { lifetime_ref: &'tcx hir::Lifetime, bad_def: ResolvedArg, ) { - // FIXME(#120456) - is `swap_remove` correct? - let old_value = self.map.defs.swap_remove(&lifetime_ref.hir_id); + let old_value = self.map.defs.remove(&lifetime_ref.hir_id.local_id); assert_eq!(old_value, Some(bad_def)); } @@ -1998,7 +1996,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`. // And this is exercised in: // `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`. - let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id).unwrap(); + let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id.local_id).unwrap(); let existing_bound_vars_saved = existing_bound_vars.clone(); existing_bound_vars.extend(bound_vars); self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved); diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index 32e2f3b4b16..13e35cd0909 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -1,9 +1,9 @@ //! Name resolution for lifetimes and late-bound type and const variables: type declarations. -use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::ErrorGuaranteed; +use rustc_hir::ItemLocalId; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{ItemLocalId, OwnerId}; use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable}; use crate::ty; @@ -47,11 +47,11 @@ pub enum ObjectLifetimeDefault { /// Maps the id of each lifetime reference to the lifetime decl /// that it corresponds to. -#[derive(Default, HashStable, Debug)] +#[derive(HashStable, Debug)] pub struct ResolveBoundVars { /// Maps from every use of a named (not anonymous) lifetime to a /// `Region` describing how that region is bound - pub defs: FxIndexMap>, + pub defs: SortedMap, - pub late_bound_vars: FxIndexMap>>, + pub late_bound_vars: SortedMap>, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bd6a7578a68..f0be70e00df 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -16,6 +16,7 @@ use rustc_ast::expand::StrippedCfgItem; use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; @@ -1742,8 +1743,7 @@ rustc_queries! { arena_cache desc { |tcx| "resolving lifetimes for `{}`", tcx.def_path_str(owner_id) } } - query named_variable_map(owner_id: hir::OwnerId) -> - Option<&'tcx FxIndexMap> { + query named_variable_map(owner_id: hir::OwnerId) -> &'tcx SortedMap { desc { |tcx| "looking up a named region inside `{}`", tcx.def_path_str(owner_id) } } query is_late_bound_map(owner_id: hir::OwnerId) -> Option<&'tcx FxIndexSet> { @@ -1759,7 +1759,7 @@ rustc_queries! { separate_provide_extern } query late_bound_vars_map(owner_id: hir::OwnerId) - -> Option<&'tcx FxIndexMap>> { + -> &'tcx SortedMap> { desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d6547b51186..27c1b88f93f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2996,7 +2996,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn named_bound_var(self, id: HirId) -> Option { debug!(?id, "named_region"); - self.named_variable_map(id.owner).and_then(|map| map.get(&id.local_id).cloned()) + self.named_variable_map(id.owner).get(&id.local_id).cloned() } pub fn is_late_bound(self, id: HirId) -> bool { @@ -3005,12 +3005,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn late_bound_vars(self, id: HirId) -> &'tcx List { self.mk_bound_variable_kinds( - &self - .late_bound_vars_map(id.owner) - .and_then(|map| map.get(&id.local_id).cloned()) - .unwrap_or_else(|| { - bug!("No bound vars found for {}", self.hir().node_to_string(id)) - }), + &self.late_bound_vars_map(id.owner).get(&id.local_id).cloned().unwrap_or_else(|| { + bug!("No bound vars found for {}", self.hir().node_to_string(id)) + }), ) }