Simplify bound var resolution.

This commit is contained in:
Camille GILLOT 2024-08-18 16:10:54 +00:00
parent c7cb45a791
commit 6ec58a44e2
4 changed files with 39 additions and 44 deletions

View File

@ -11,10 +11,13 @@ use std::fmt;
use rustc_ast::visit::walk_list; use rustc_ast::visit::walk_list;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::sorted_map::SortedMap;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{self, Visitor}; 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_macros::extension;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::*; use rustc_middle::middle::resolve_bound_vars::*;
@ -74,7 +77,7 @@ impl ResolvedArg {
struct NamedVarMap { struct NamedVarMap {
// maps from every use of a named (not anonymous) bound var to a // maps from every use of a named (not anonymous) bound var to a
// `ResolvedArg` describing how that variable is bound // `ResolvedArg` describing how that variable is bound
defs: HirIdMap<ResolvedArg>, defs: ItemLocalMap<ResolvedArg>,
// Maps relevant hir items to the bound vars on them. These include: // Maps relevant hir items to the bound vars on them. These include:
// - function defs // - function defs
@ -82,7 +85,7 @@ struct NamedVarMap {
// - closures // - closures
// - trait refs // - trait refs
// - bound types (like `T` in `for<'a> T<'a>: Foo`) // - bound types (like `T` in `for<'a> T<'a>: Foo`)
late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>, late_bound_vars: ItemLocalMap<Vec<ty::BoundVariableKind>>,
} }
struct BoundVarContext<'a, 'tcx> { struct BoundVarContext<'a, 'tcx> {
@ -225,10 +228,10 @@ pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { *providers = Providers {
resolve_bound_vars, 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, is_late_bound_map,
object_lifetime_default, 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 ..*providers
}; };
@ -265,16 +268,12 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
hir::OwnerNode::Synthetic => unreachable!(), hir::OwnerNode::Synthetic => unreachable!(),
} }
let mut rl = ResolveBoundVars::default(); let defs = named_variable_map.defs.into_sorted_stable_ord();
let late_bound_vars = named_variable_map.late_bound_vars.into_sorted_stable_ord();
for (hir_id, v) in named_variable_map.defs { let rl = ResolveBoundVars {
let map = rl.defs.entry(hir_id.owner).or_default(); defs: SortedMap::from_presorted_elements(defs),
map.insert(hir_id.local_id, v); late_bound_vars: SortedMap::from_presorted_elements(late_bound_vars),
} };
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);
}
debug!(?rl.defs); debug!(?rl.defs);
debug!(?rl.late_bound_vars); debug!(?rl.late_bound_vars);
@ -340,7 +339,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Binder { hir_id, .. } => { Scope::Binder { hir_id, .. } => {
// Nested poly trait refs have the binders concatenated // Nested poly trait refs have the binders concatenated
let mut full_binders = 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); full_binders.extend(supertrait_bound_vars);
break (full_binders, BinderScopeType::Concatenating); 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) => { hir::TyKind::Ref(lifetime_ref, ref mt) => {
self.visit_lifetime(lifetime_ref); self.visit_lifetime(lifetime_ref);
let scope = Scope::ObjectLifetimeDefault { 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, s: self.scope,
}; };
self.with(scope, |this| this.visit_ty(mt.ty)); 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 // and ban them. Type variables instantiated inside binders aren't
// well-supported at the moment, so this doesn't work. // well-supported at the moment, so this doesn't work.
// In the future, this should be fixed and this error should be removed. // 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 Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue };
let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id); 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<_> = let bound_vars: Vec<_> =
self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect(); 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); 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)); self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
intravisit::walk_fn_kind(self, fk); 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<ty::BoundVariableKind>) { fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
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!( bug!(
"overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}", "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()) 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 { } else {
self.map.defs.insert(hir_id, def); self.map.defs.insert(hir_id.local_id, def);
} }
return; return;
} }
@ -1416,7 +1415,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id())) 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; return;
} }
Scope::Root { .. } => break, 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`. // This index can be used with `generic_args` since `parent_count == 0`.
let index = generics.param_def_id_to_index[&param_def_id] as usize; let index = generics.param_def_id_to_index[&param_def_id] as usize;
generic_args.args.get(index).and_then(|arg| match arg { generic_args.args.get(index).and_then(|arg| match arg {
GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id).copied(), GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id.local_id).copied(),
_ => None, _ => None,
}) })
} }
@ -1816,7 +1815,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) { fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
debug!(span = ?lifetime_ref.ident.span); 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 /// 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, lifetime_ref: &'tcx hir::Lifetime,
bad_def: ResolvedArg, bad_def: ResolvedArg,
) { ) {
// FIXME(#120456) - is `swap_remove` correct? let old_value = self.map.defs.remove(&lifetime_ref.hir_id.local_id);
let old_value = self.map.defs.swap_remove(&lifetime_ref.hir_id);
assert_eq!(old_value, Some(bad_def)); 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`. // See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`.
// And this is exercised in: // And this is exercised in:
// `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`. // `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(); let existing_bound_vars_saved = existing_bound_vars.clone();
existing_bound_vars.extend(bound_vars); existing_bound_vars.extend(bound_vars);
self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved); self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);

View File

@ -1,9 +1,9 @@
//! Name resolution for lifetimes and late-bound type and const variables: type declarations. //! 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_errors::ErrorGuaranteed;
use rustc_hir::ItemLocalId;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{ItemLocalId, OwnerId};
use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable}; use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable};
use crate::ty; use crate::ty;
@ -47,11 +47,11 @@ pub enum ObjectLifetimeDefault {
/// Maps the id of each lifetime reference to the lifetime decl /// Maps the id of each lifetime reference to the lifetime decl
/// that it corresponds to. /// that it corresponds to.
#[derive(Default, HashStable, Debug)] #[derive(HashStable, Debug)]
pub struct ResolveBoundVars { pub struct ResolveBoundVars {
/// Maps from every use of a named (not anonymous) lifetime to a /// Maps from every use of a named (not anonymous) lifetime to a
/// `Region` describing how that region is bound /// `Region` describing how that region is bound
pub defs: FxIndexMap<OwnerId, FxIndexMap<ItemLocalId, ResolvedArg>>, pub defs: SortedMap<ItemLocalId, ResolvedArg>,
pub late_bound_vars: FxIndexMap<OwnerId, FxIndexMap<ItemLocalId, Vec<ty::BoundVariableKind>>>, pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>>,
} }

View File

@ -16,6 +16,7 @@ use rustc_ast::expand::StrippedCfgItem;
use rustc_ast::expand::allocator::AllocatorKind; use rustc_ast::expand::allocator::AllocatorKind;
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::steal::Steal; use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
@ -1742,8 +1743,7 @@ rustc_queries! {
arena_cache arena_cache
desc { |tcx| "resolving lifetimes for `{}`", tcx.def_path_str(owner_id) } desc { |tcx| "resolving lifetimes for `{}`", tcx.def_path_str(owner_id) }
} }
query named_variable_map(owner_id: hir::OwnerId) -> query named_variable_map(owner_id: hir::OwnerId) -> &'tcx SortedMap<ItemLocalId, ResolvedArg> {
Option<&'tcx FxIndexMap<ItemLocalId, ResolvedArg>> {
desc { |tcx| "looking up a named region inside `{}`", tcx.def_path_str(owner_id) } 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<ItemLocalId>> { query is_late_bound_map(owner_id: hir::OwnerId) -> Option<&'tcx FxIndexSet<ItemLocalId>> {
@ -1759,7 +1759,7 @@ rustc_queries! {
separate_provide_extern separate_provide_extern
} }
query late_bound_vars_map(owner_id: hir::OwnerId) query late_bound_vars_map(owner_id: hir::OwnerId)
-> Option<&'tcx FxIndexMap<ItemLocalId, Vec<ty::BoundVariableKind>>> { -> &'tcx SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>> {
desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) } desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) }
} }

View File

@ -2996,7 +2996,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> { pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
debug!(?id, "named_region"); 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 { 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<ty::BoundVariableKind> { pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
self.mk_bound_variable_kinds( self.mk_bound_variable_kinds(
&self &self.late_bound_vars_map(id.owner).get(&id.local_id).cloned().unwrap_or_else(|| {
.late_bound_vars_map(id.owner) bug!("No bound vars found for {}", self.hir().node_to_string(id))
.and_then(|map| map.get(&id.local_id).cloned()) }),
.unwrap_or_else(|| {
bug!("No bound vars found for {}", self.hir().node_to_string(id))
}),
) )
} }