diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 7277773334513..e6ceedddfa1be 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -6,10 +6,10 @@ //! Imports are also considered items and placed into modules here, but not resolved yet. use crate::def_collector::collect_definitions; -use crate::imports::{Import, ImportKind}; +use crate::imports::{ImportData, ImportKind}; use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; -use crate::{errors, BindingKey, MacroData}; +use crate::{errors, BindingKey, MacroData, NameBindingData}; use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError}; use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError}; @@ -31,15 +31,14 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use std::cell::Cell; -use std::ptr; type Res = def::Res; impl<'a, Id: Into> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, LocalExpnId) { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { - arenas.alloc_name_binding(NameBinding { + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> { + arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Module(self.0), ambiguity: None, vis: self.1.to_def_id(), @@ -50,8 +49,8 @@ impl<'a, Id: Into> ToNameBinding<'a> } impl<'a, Id: Into> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId) { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { - arenas.alloc_name_binding(NameBinding { + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> { + arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(self.0), ambiguity: None, vis: self.1.to_def_id(), @@ -71,7 +70,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let binding = def.to_name_binding(self.arenas); let key = self.new_disambiguated_key(ident, ns); if let Err(old_binding) = self.try_define(parent, key, binding) { - self.report_conflict(parent, ident, ns, old_binding, &binding); + self.report_conflict(parent, ident, ns, old_binding, binding); } } @@ -142,8 +141,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(def_id) => self.macro_def_scope(def_id), None => expn_id .as_local() - .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id)) - .unwrap_or(&self.graph_root), + .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id).copied()) + .unwrap_or(self.graph_root), } } @@ -354,7 +353,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { vis: ty::Visibility, ) { let current_module = self.parent_scope.module; - let import = self.r.arenas.alloc_import(Import { + let import = self.r.arenas.alloc_import(ImportData { kind, parent_scope: self.parent_scope, module_path, @@ -378,7 +377,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { if !type_ns_only || ns == TypeNS { let key = BindingKey::new(target, ns); let mut resolution = this.resolution(current_module, key).borrow_mut(); - resolution.add_single_import(import); + resolution.single_imports.insert(import); } }); } @@ -848,7 +847,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { (used, Some(ModuleOrUniformRoot::Module(module)), binding) }) .unwrap_or((true, None, self.r.dummy_binding)); - let import = self.r.arenas.alloc_import(Import { + let import = self.r.arenas.alloc_import(ImportData { kind: ImportKind::ExternCrate { source: orig_name, target: ident, id: item.id }, root_id: item.id, parent_scope: self.parent_scope, @@ -864,7 +863,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { }); self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); - if ptr::eq(parent, self.r.graph_root) { + if parent == self.r.graph_root { if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) { if expansion != LocalExpnId::ROOT && orig_name.is_some() @@ -996,7 +995,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn add_macro_use_binding( &mut self, name: Symbol, - binding: &'a NameBinding<'a>, + binding: NameBinding<'a>, span: Span, allow_shadowing: bool, ) { @@ -1058,7 +1057,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } let macro_use_import = |this: &Self, span| { - this.r.arenas.alloc_import(Import { + this.r.arenas.alloc_import(ImportData { kind: ImportKind::MacroUse, root_id: item.id, parent_scope: this.parent_scope, @@ -1228,7 +1227,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.set_binding_parent_module(binding, parent_scope.module); self.r.all_macro_rules.insert(ident.name, res); if is_macro_export { - let import = self.r.arenas.alloc_import(Import { + let import = self.r.arenas.alloc_import(ImportData { kind: ImportKind::MacroExport, root_id: item.id, parent_scope: self.parent_scope, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index d9e4974626d78..d3dcdfa427542 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1,5 +1,3 @@ -use std::ptr; - use rustc_ast::expand::StrippedCfgItem; use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; @@ -182,13 +180,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - pub(crate) fn report_conflict<'b>( + pub(crate) fn report_conflict( &mut self, parent: Module<'_>, ident: Ident, ns: Namespace, - new_binding: &NameBinding<'b>, - old_binding: &NameBinding<'b>, + new_binding: NameBinding<'a>, + old_binding: NameBinding<'a>, ) { // Error on the second of two conflicting names if old_binding.span.lo() > new_binding.span.lo() { @@ -262,7 +260,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; - let can_suggest = |binding: &NameBinding<'_>, import: &self::Import<'_>| { + let can_suggest = |binding: NameBinding<'_>, import: self::Import<'_>| { !binding.span.is_dummy() && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport) }; @@ -272,22 +270,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (Import { import: new, .. }, Import { import: old, .. }) if { (new.has_attributes || old.has_attributes) - && can_suggest(old_binding, old) - && can_suggest(new_binding, new) + && can_suggest(old_binding, *old) + && can_suggest(new_binding, *new) } => { if old.has_attributes { - Some((new, new_binding.span, true)) + Some((*new, new_binding.span, true)) } else { - Some((old, old_binding.span, true)) + Some((*old, old_binding.span, true)) } } // Otherwise prioritize the new binding. - (Import { import, .. }, other) if can_suggest(new_binding, import) => { - Some((import, new_binding.span, other.is_import())) + (Import { import, .. }, other) if can_suggest(new_binding, *import) => { + Some((*import, new_binding.span, other.is_import())) } - (other, Import { import, .. }) if can_suggest(old_binding, import) => { - Some((import, old_binding.span, other.is_import())) + (other, Import { import, .. }) if can_suggest(old_binding, *import) => { + Some((*import, old_binding.span, other.is_import())) } _ => None, }; @@ -341,7 +339,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &self, err: &mut Diagnostic, name: Symbol, - import: &Import<'_>, + import: Import<'_>, binding_span: Span, ) { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { @@ -413,7 +411,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn add_suggestion_for_duplicate_nested_use( &self, err: &mut Diagnostic, - import: &Import<'_>, + import: Import<'_>, binding_span: Span, ) { assert!(import.is_nested()); @@ -455,7 +453,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, finalize: Option, path: &[Segment], - second_binding: Option<&NameBinding<'_>>, + second_binding: Option>, ) { let Some(Finalize { node_id, root_span, .. }) = finalize else { return; @@ -1198,7 +1196,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // avoid suggesting anything with a hygienic name if ident.name == lookup_ident.name && ns == namespace - && !ptr::eq(in_module, parent_scope.module) + && in_module != parent_scope.module && !ident.span.normalize_to_macros_2_0().from_expansion() { let res = name_binding.res(); @@ -1515,7 +1513,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { true } - fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String { + fn binding_description(&self, b: NameBinding<'_>, ident: Ident, from_prelude: bool) -> String { let res = b.res(); if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) { // These already contain the "built-in" prefix or look bad with it. @@ -1555,7 +1553,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { err.span_label(ident.span, "ambiguous name"); err.note(format!("ambiguous because of {}", kind.descr())); - let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| { + let mut could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| { let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude); let note_msg = format!("`{ident}` could{also} refer to {what}"); @@ -1595,7 +1593,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// If the binding refers to a tuple struct constructor with fields, /// returns the span of its fields. - fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option { + fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option { if let NameBindingKind::Res(Res::Def( DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id, @@ -1622,7 +1620,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr }; let import_descr = nonimport_descr.clone() + " import"; let get_descr = - |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; + |b: NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; // Print the primary message. let descr = get_descr(binding); @@ -1702,7 +1700,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => None, }; - let first = ptr::eq(binding, first_binding); + let first = binding == first_binding; let msg = format!( "{and_refers_to}the {item} `{name}`{which} is defined here{dots}", and_refers_to = if first { "" } else { "...and refers to " }, @@ -1732,7 +1730,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn find_similarly_named_module_or_crate( &mut self, ident: Symbol, - current_module: &Module<'a>, + current_module: Module<'a>, ) -> Option { let mut candidates = self .extern_prelude @@ -1742,7 +1740,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.module_map .iter() .filter(|(_, module)| { - current_module.is_ancestor_of(module) && !ptr::eq(current_module, *module) + current_module.is_ancestor_of(**module) && current_module != **module }) .flat_map(|(_, module)| module.kind.name()), ) @@ -1762,7 +1760,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { opt_ns: Option, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, ribs: Option<&PerNS>>>, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option>, module: Option>, failed_segment_idx: usize, ident: Ident, @@ -1945,7 +1943,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } suggestion = suggestion.or_else(|| { - self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map( + self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map( |sugg| { ( vec![(ident.span, sugg.to_string())], @@ -2114,7 +2112,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// ``` pub(crate) fn check_for_module_export_macro( &mut self, - import: &'a Import<'a>, + import: Import<'a>, module: ModuleOrUniformRoot<'a>, ident: Ident, ) -> Option<(Option, Option)> { @@ -2126,9 +2124,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { crate_module = parent; } - if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) { - // Don't make a suggestion if the import was already from the root of the - // crate. + if module == ModuleOrUniformRoot::Module(crate_module) { + // Don't make a suggestion if the import was already from the root of the crate. return None; } diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 4863c9f479015..eb210532f51df 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -5,7 +5,6 @@ use rustc_ast::visit::Visitor; use rustc_ast::Crate; use rustc_ast::EnumDef; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::intern::Interned; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_middle::middle::privacy::Level; @@ -13,12 +12,10 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility}; use rustc_middle::ty::Visibility; use std::mem; -type ImportId<'a> = Interned<'a, NameBinding<'a>>; - #[derive(Clone, Copy)] enum ParentId<'a> { Def(LocalDefId), - Import(ImportId<'a>), + Import(NameBinding<'a>), } impl ParentId<'_> { @@ -36,7 +33,7 @@ pub(crate) struct EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { /// While walking import chains we need to track effective visibilities per-binding, and def id /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple /// bindings can correspond to a single def id in imports. So we keep a separate table. - import_effective_visibilities: EffectiveVisibilities>, + import_effective_visibilities: EffectiveVisibilities>, // It's possible to recalculate this at any point, but it's relatively expensive. current_private_vis: Visibility, changed: bool, @@ -47,7 +44,7 @@ impl Resolver<'_, '_> { self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local() } - fn private_vis_import(&mut self, binding: ImportId<'_>) -> Visibility { + fn private_vis_import(&mut self, binding: NameBinding<'_>) -> Visibility { let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() }; Visibility::Restricted( import @@ -75,7 +72,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { pub(crate) fn compute_effective_visibilities<'c>( r: &'r mut Resolver<'a, 'tcx>, krate: &'c Crate, - ) -> FxHashSet>> { + ) -> FxHashSet> { let mut visitor = EffectiveVisibilitiesVisitor { r, def_effective_visibilities: Default::default(), @@ -133,8 +130,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { // lint. For all bindings added to the table this way `is_ambiguity` returns true. let mut parent_id = ParentId::Def(module_id); while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind { - let binding_id = ImportId::new_unchecked(binding); - self.update_import(binding_id, parent_id); + self.update_import(binding, parent_id); if binding.ambiguity.is_some() { // Stop at the root ambiguity, further bindings in the chain should not @@ -143,7 +139,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { break; } - parent_id = ParentId::Import(binding_id); + parent_id = ParentId::Import(binding); binding = nested_binding; } @@ -192,7 +188,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } - fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) { + fn update_import(&mut self, binding: NameBinding<'a>, parent_id: ParentId<'a>) { let nominal_vis = binding.vis.expect_local(); let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 36f01676e7e09..520fab1f0c837 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -11,8 +11,6 @@ use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContex use rustc_span::symbol::{kw, Ident}; use rustc_span::{Span, DUMMY_SP}; -use std::ptr; - use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; use crate::late::{ ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind, @@ -20,7 +18,7 @@ use crate::late::{ use crate::macros::{sub_namespace_match, MacroRulesScope}; use crate::BindingKey; use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize}; -use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot}; +use crate::{ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res}; use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, Weak}; @@ -284,7 +282,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent_scope: &ParentScope<'a>, finalize: Option, ribs: &[Rib<'a>], - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option>, ) -> Option> { assert!(ns == TypeNS || ns == ValueNS); let orig_ident = ident; @@ -378,8 +376,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent_scope: &ParentScope<'a>, finalize: Option, force: bool, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ignore_binding: Option>, + ) -> Result, Determinacy> { bitflags::bitflags! { struct Flags: u8 { const MACRO_RULES = 1 << 0; @@ -415,7 +413,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // } // So we have to save the innermost solution and continue searching in outer scopes // to detect potential ambiguities. - let mut innermost_result: Option<(&NameBinding<'_>, Flags)> = None; + let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None; let mut determinacy = Determinacy::Determined; // Go through all the scopes and try to resolve the name. @@ -538,7 +536,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ), ); } - let misc_flags = if ptr::eq(module, this.graph_root) { + let misc_flags = if module == this.graph_root { Flags::MISC_SUGGEST_CRATE } else if module.is_normal() { Flags::MISC_SUGGEST_SELF @@ -717,7 +715,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ident: Ident, ns: Namespace, parent_scope: &ParentScope<'a>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ) -> Result, Determinacy> { self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None) .map_err(|(determinacy, _)| determinacy) } @@ -730,8 +728,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns: Namespace, parent_scope: &ParentScope<'a>, finalize: Option, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ignore_binding: Option>, + ) -> Result, Determinacy> { self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding) .map_err(|(determinacy, _)| determinacy) } @@ -744,8 +742,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns: Namespace, parent_scope: &ParentScope<'a>, finalize: Option, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { + ignore_binding: Option>, + ) -> Result, (Determinacy, Weak)> { let tmp_parent_scope; let mut adjusted_parent_scope = parent_scope; match module { @@ -782,8 +780,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns: Namespace, parent_scope: &ParentScope<'a>, finalize: Option, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ignore_binding: Option>, + ) -> Result, Determinacy> { self.resolve_ident_in_module_unadjusted_ext( module, ident, @@ -809,8 +807,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { finalize: Option, // This binding should be ignored during in-module resolution, so that we don't get // "self-confirming" import resolutions during import validation and checking. - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { + ignore_binding: Option>, + ) -> Result, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, ModuleOrUniformRoot::CrateRootAndExternPrelude => { @@ -873,13 +871,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // binding if it exists. What we really want here is having two separate scopes in // a module - one for non-globs and one for globs, but until that's done use this // hack to avoid inconsistent resolution ICEs during import validation. - let binding = - [resolution.binding, resolution.shadowed_glob].into_iter().find_map(|binding| { - match (binding, ignore_binding) { - (Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None, - _ => binding, - } - }); + let binding = [resolution.binding, resolution.shadowed_glob] + .into_iter() + .find_map(|binding| if binding == ignore_binding { None } else { binding }); if let Some(Finalize { path_span, report_private, .. }) = finalize { let Some(binding) = binding else { @@ -917,11 +911,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT { - if let NameBindingKind::Import { - import: Import { kind: ImportKind::MacroExport, .. }, - .. - } = binding.kind - { + if let NameBindingKind::Import { import, .. } = binding.kind + && matches!(import.kind, ImportKind::MacroExport) { self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); } } @@ -930,7 +921,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Ok(binding); } - let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { + let check_usable = |this: &mut Self, binding: NameBinding<'a>| { let usable = this.is_accessible_from(binding.vis, parent_scope.module); if usable { Ok(binding) } else { Err((Determined, Weak::No)) } }; @@ -955,7 +946,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let Some(ignored) = ignore_binding && let NameBindingKind::Import { import, .. } = ignored.kind && - ptr::eq(import, &**single_import) { + import == *single_import { // Ignore not just the binding itself, but if it has a shadowed_glob, // ignore that, too, because this loop is supposed to only process // named imports. @@ -1352,7 +1343,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { opt_ns: Option, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, finalize: Option, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option>, ) -> PathResult<'a> { self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding) } @@ -1364,7 +1355,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent_scope: &ParentScope<'a>, finalize: Option, ribs: Option<&PerNS>>>, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option>, ) -> PathResult<'a> { let mut module = None; let mut allow_super = true; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 074f761c53baa..d37fe783bbac2 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -12,7 +12,7 @@ use crate::{fluent_generated as fluent, Namespace::*}; use crate::{module_to_string, names_to_string, ImportSuggestion}; use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment}; use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet}; -use crate::{NameBinding, NameBindingKind, PathResult}; +use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult}; use rustc_ast::NodeId; use rustc_data_structures::fx::FxHashSet; @@ -35,7 +35,7 @@ use rustc_span::Span; use smallvec::SmallVec; use std::cell::Cell; -use std::{mem, ptr}; +use std::mem; type Res = def::Res; @@ -48,9 +48,9 @@ pub(crate) enum ImportKind<'a> { /// `target` in `use prefix::source as target`. target: Ident, /// Bindings to which `source` refers to. - source_bindings: PerNS, Determinacy>>>, + source_bindings: PerNS, Determinacy>>>, /// Bindings introduced by `target`. - target_bindings: PerNS>>>, + target_bindings: PerNS>>>, /// `true` for `...::{self [as target]}` imports, `false` otherwise. type_ns_only: bool, /// Did this import result from a nested import? ie. `use foo::{bar, baz};` @@ -135,7 +135,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> { /// One import. #[derive(Debug, Clone)] -pub(crate) struct Import<'a> { +pub(crate) struct ImportData<'a> { pub kind: ImportKind<'a>, /// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id` @@ -172,7 +172,11 @@ pub(crate) struct Import<'a> { pub used: Cell, } -impl<'a> Import<'a> { +/// All imports are unique and allocated on a same arena, +/// so we can use referential equality to compare them. +pub(crate) type Import<'a> = Interned<'a, ImportData<'a>>; + +impl<'a> ImportData<'a> { pub(crate) fn is_glob(&self) -> bool { matches!(self.kind, ImportKind::Glob { .. }) } @@ -214,15 +218,15 @@ impl<'a> Import<'a> { pub(crate) struct NameResolution<'a> { /// Single imports that may define the name in the namespace. /// Imports are arena-allocated, so it's ok to use pointers as keys. - pub single_imports: FxHashSet>>, + pub single_imports: FxHashSet>, /// The least shadowable known binding for this name, or None if there are no known bindings. - pub binding: Option<&'a NameBinding<'a>>, - pub shadowed_glob: Option<&'a NameBinding<'a>>, + pub binding: Option>, + pub shadowed_glob: Option>, } impl<'a> NameResolution<'a> { /// Returns the binding for the name if it is known or None if it not known. - pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> { + pub(crate) fn binding(&self) -> Option> { self.binding.and_then(|binding| { if !binding.is_glob_import() || self.single_imports.is_empty() { Some(binding) @@ -231,10 +235,6 @@ impl<'a> NameResolution<'a> { } }) } - - pub(crate) fn add_single_import(&mut self, import: &'a Import<'a>) { - self.single_imports.insert(Interned::new_unchecked(import)); - } } /// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved @@ -250,15 +250,12 @@ struct UnresolvedImportError { // Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;` // are permitted for backward-compatibility under a deprecation lint. -fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBinding<'_>) -> bool { +fn pub_use_of_private_extern_crate_hack(import: Import<'_>, binding: NameBinding<'_>) -> bool { match (&import.kind, &binding.kind) { - ( - ImportKind::Single { .. }, - NameBindingKind::Import { - import: Import { kind: ImportKind::ExternCrate { .. }, .. }, - .. - }, - ) => import.expect_vis().is_public(), + (ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. }) => { + matches!(binding_import.kind, ImportKind::ExternCrate { .. }) + && import.expect_vis().is_public() + } _ => false, } } @@ -266,11 +263,7 @@ fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBindi impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Given a binding and an import that resolves to it, /// return the corresponding binding defined by the import. - pub(crate) fn import( - &self, - binding: &'a NameBinding<'a>, - import: &'a Import<'a>, - ) -> &'a NameBinding<'a> { + pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> { let import_vis = import.expect_vis().to_def_id(); let vis = if binding.vis.is_at_least(import_vis, self.tcx) || pub_use_of_private_extern_crate_hack(import, binding) @@ -288,7 +281,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - self.arenas.alloc_name_binding(NameBinding { + self.arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Import { binding, import, used: Cell::new(false) }, ambiguity: None, span: import.span, @@ -302,8 +295,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, module: Module<'a>, key: BindingKey, - binding: &'a NameBinding<'a>, - ) -> Result<(), &'a NameBinding<'a>> { + binding: NameBinding<'a>, + ) -> Result<(), NameBinding<'a>> { let res = binding.res(); self.check_reserved_macro_name(key.ident, res); self.set_binding_parent_module(binding, module); @@ -372,12 +365,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn ambiguity( &self, kind: AmbiguityKind, - primary_binding: &'a NameBinding<'a>, - secondary_binding: &'a NameBinding<'a>, - ) -> &'a NameBinding<'a> { - self.arenas.alloc_name_binding(NameBinding { + primary_binding: NameBinding<'a>, + secondary_binding: NameBinding<'a>, + ) -> NameBinding<'a> { + self.arenas.alloc_name_binding(NameBindingData { ambiguity: Some((secondary_binding, kind)), - ..primary_binding.clone() + ..(*primary_binding).clone() }) } @@ -395,13 +388,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let t = f(self, resolution); - match resolution.binding() { - _ if old_binding.is_some() => return t, - None => return t, - Some(binding) => match old_binding { - Some(old_binding) if ptr::eq(old_binding, binding) => return t, - _ => (binding, t), - }, + if old_binding.is_none() && let Some(binding) = resolution.binding() { + (binding, t) + } else { + return t; } }; @@ -414,7 +404,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => continue, }; if self.is_accessible_from(binding.vis, scope) { - let imported_binding = self.import(binding, import); + let imported_binding = self.import(binding, *import); let key = BindingKey { ident, ..key }; let _ = self.try_define(import.parent_scope.module, key, imported_binding); } @@ -425,7 +415,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics. - fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) { + fn import_dummy_binding(&mut self, import: Import<'a>, is_indeterminate: bool) { if let ImportKind::Single { target, ref target_bindings, .. } = import.kind { if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none())) { @@ -463,7 +453,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { prev_indeterminate_count = indeterminate_count; indeterminate_count = 0; for import in mem::take(&mut self.indeterminate_imports) { - let import_indeterminate_count = self.resolve_import(&import); + let import_indeterminate_count = self.resolve_import(import); indeterminate_count += import_indeterminate_count; match import_indeterminate_count { 0 => self.determined_imports.push(import), @@ -475,7 +465,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn finalize_imports(&mut self) { for module in self.arenas.local_modules().iter() { - self.finalize_resolutions_in(module); + self.finalize_resolutions_in(*module); } let mut seen_spans = FxHashSet::default(); @@ -546,17 +536,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn check_hidden_glob_reexports( &mut self, - exported_ambiguities: FxHashSet>>, + exported_ambiguities: FxHashSet>, ) { for module in self.arenas.local_modules().iter() { - for (key, resolution) in self.resolutions(module).borrow().iter() { + for (key, resolution) in self.resolutions(*module).borrow().iter() { let resolution = resolution.borrow(); if let Some(binding) = resolution.binding { if let NameBindingKind::Import { import, .. } = binding.kind && let Some((amb_binding, _)) = binding.ambiguity && binding.res() != Res::Err - && exported_ambiguities.contains(&Interned::new_unchecked(binding)) + && exported_ambiguities.contains(&binding) { self.lint_buffer.buffer_lint_with_diagnostic( AMBIGUOUS_GLOB_REEXPORTS, @@ -612,7 +602,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn throw_unresolved_import_error(&mut self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) { + fn throw_unresolved_import_error(&mut self, errors: Vec<(Import<'_>, UnresolvedImportError)>) { if errors.is_empty() { return; } @@ -704,7 +694,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// /// Meanwhile, if resolve successful, the resolved bindings are written /// into the module. - fn resolve_import(&mut self, import: &'a Import<'a>) -> usize { + fn resolve_import(&mut self, import: Import<'a>) -> usize { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", Segment::names_to_string(&import.module_path), @@ -784,7 +774,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let key = BindingKey::new(target, ns); this.update_resolution(parent, key, |_, resolution| { - resolution.single_imports.remove(&Interned::new_unchecked(import)); + resolution.single_imports.remove(&import); }); } } @@ -798,7 +788,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// /// Optionally returns an unresolved import error. This error is buffered and used to /// consolidate multiple unresolved import errors into a single diagnostic. - fn finalize_import(&mut self, import: &'a Import<'a>) -> Option { + fn finalize_import(&mut self, import: Import<'a>) -> Option { let orig_vis = import.vis.take(); let ignore_binding = match &import.kind { ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(), @@ -824,7 +814,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathResult::Module(module) => { // Consistency checks, analogous to `finalize_macro_resolutions`. if let Some(initial_module) = import.imported_module.get() { - if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity { + if module != initial_module && no_ambiguity { span_bug!(import.span, "inconsistent resolution for an import"); } } else if self.privacy_errors.is_empty() { @@ -926,7 +916,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let ModuleOrUniformRoot::Module(module) = module { - if ptr::eq(module, import.parent_scope.module) { + if module == import.parent_scope.module { // Importing a module into itself is not allowed. return Some(UnresolvedImportError { span: import.span, @@ -1242,9 +1232,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn check_for_redundant_imports( &mut self, ident: Ident, - import: &'a Import<'a>, - source_bindings: &PerNS, Determinacy>>>, - target_bindings: &PerNS>>>, + import: Import<'a>, + source_bindings: &PerNS, Determinacy>>>, + target_bindings: &PerNS>>>, target: Ident, ) { // This function is only called for single imports. @@ -1305,7 +1295,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_glob_import(&mut self, import: &'a Import<'a>) { + fn resolve_glob_import(&mut self, import: Import<'a>) { // This function is only called for glob imports. let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() }; @@ -1319,7 +1309,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if module.is_trait() { self.tcx.sess.create_err(ItemsInTraitsAreNotImportable { span: import.span }).emit(); return; - } else if ptr::eq(module, import.parent_scope.module) { + } else if module == import.parent_scope.module { return; } else if is_prelude { self.prelude = Some(module); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index bca95ce54ad33..90cb312edd203 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1284,7 +1284,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ident: Ident, ns: Namespace, finalize: Option, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option>, ) -> Option> { self.r.resolve_ident_in_lexical_scope( ident, @@ -2972,7 +2972,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { F: FnOnce(Ident, String, Option) -> ResolutionError<'a>, { // If there is a TraitRef in scope for an impl, then the method must be in the trait. - let Some((module, _)) = &self.current_trait_ref else { return; }; + let Some((module, _)) = self.current_trait_ref else { return; }; ident.span.normalize_to_macros_2_0_and_adjust(module.expansion); let key = BindingKey::new(ident, ns); let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 9fec7cc3defb3..c0e3f1aaf01f0 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1593,7 +1593,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { return None; } - let resolutions = self.r.resolutions(module); + let resolutions = self.r.resolutions(*module); let targets = resolutions .borrow() .iter() diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index cc4cb9fa30cd9..da3d86a4718d7 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -14,6 +14,7 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(never_type)] +#![feature(rustc_attrs)] #![recursion_limit = "256"] #![allow(rustdoc::private_intra_doc_links)] #![allow(rustc::potential_query_instability)] @@ -61,10 +62,10 @@ use rustc_span::{Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; -use std::{fmt, ptr}; +use std::fmt; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; -use imports::{Import, ImportKind, NameResolution}; +use imports::{Import, ImportData, ImportKind, NameResolution}; use late::{HasGenericParams, PathSource, PatternSource}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; @@ -352,7 +353,7 @@ impl<'a> From<&'a ast::PathSegment> for Segment { /// forward. #[derive(Debug)] enum LexicalScopeBinding<'a> { - Item(&'a NameBinding<'a>), + Item(NameBinding<'a>), Res(Res), } @@ -365,7 +366,7 @@ impl<'a> LexicalScopeBinding<'a> { } } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] enum ModuleOrUniformRoot<'a> { /// Regular module. Module(Module<'a>), @@ -383,23 +384,6 @@ enum ModuleOrUniformRoot<'a> { CurrentScope, } -impl ModuleOrUniformRoot<'_> { - fn same_def(lhs: Self, rhs: Self) -> bool { - match (lhs, rhs) { - (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) => { - ptr::eq(lhs, rhs) - } - ( - ModuleOrUniformRoot::CrateRootAndExternPrelude, - ModuleOrUniformRoot::CrateRootAndExternPrelude, - ) - | (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) - | (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true, - _ => false, - } - } -} - #[derive(Debug)] enum PathResult<'a> { Module(ModuleOrUniformRoot<'a>), @@ -518,11 +502,11 @@ struct ModuleData<'a> { /// Whether `#[no_implicit_prelude]` is active. no_implicit_prelude: bool, - glob_importers: RefCell>>, - globs: RefCell>>, + glob_importers: RefCell>>, + globs: RefCell>>, /// Used to memoize the traits in this module for faster searches through all traits in scope. - traits: RefCell)]>>>, + traits: RefCell)]>>>, /// Span of the module itself. Used for error reporting. span: Span, @@ -530,7 +514,11 @@ struct ModuleData<'a> { expansion: ExpnId, } -type Module<'a> = &'a ModuleData<'a>; +/// All modules are unique and allocated on a same arena, +/// so we can use referential equality to compare them. +#[derive(Clone, Copy, PartialEq)] +#[rustc_pass_by_value] +struct Module<'a>(Interned<'a, ModuleData<'a>>); impl<'a> ModuleData<'a> { fn new( @@ -558,11 +546,13 @@ impl<'a> ModuleData<'a> { expansion, } } +} - fn for_each_child<'tcx, R, F>(&'a self, resolver: &mut R, mut f: F) +impl<'a> Module<'a> { + fn for_each_child<'tcx, R, F>(self, resolver: &mut R, mut f: F) where R: AsMut>, - F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>), + F: FnMut(&mut R, Ident, Namespace, NameBinding<'a>), { for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { if let Some(binding) = name_resolution.borrow().binding { @@ -572,7 +562,7 @@ impl<'a> ModuleData<'a> { } /// This modifies `self` in place. The traits will be stored in `self.traits`. - fn ensure_traits<'tcx, R>(&'a self, resolver: &mut R) + fn ensure_traits<'tcx, R>(self, resolver: &mut R) where R: AsMut>, { @@ -591,7 +581,7 @@ impl<'a> ModuleData<'a> { } } - fn res(&self) -> Option { + fn res(self) -> Option { match self.kind { ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)), _ => None, @@ -599,11 +589,11 @@ impl<'a> ModuleData<'a> { } // Public for rustdoc. - fn def_id(&self) -> DefId { + fn def_id(self) -> DefId { self.opt_def_id().expect("`ModuleData::def_id` is called on a block module") } - fn opt_def_id(&self) -> Option { + fn opt_def_id(self) -> Option { match self.kind { ModuleKind::Def(_, def_id, _) => Some(def_id), _ => None, @@ -611,15 +601,15 @@ impl<'a> ModuleData<'a> { } // `self` resolves to the first module ancestor that `is_normal`. - fn is_normal(&self) -> bool { + fn is_normal(self) -> bool { matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _)) } - fn is_trait(&self) -> bool { + fn is_trait(self) -> bool { matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _)) } - fn nearest_item_scope(&'a self) -> Module<'a> { + fn nearest_item_scope(self) -> Module<'a> { match self.kind { ModuleKind::Def(DefKind::Enum | DefKind::Trait, ..) => { self.parent.expect("enum or trait module without a parent") @@ -630,15 +620,15 @@ impl<'a> ModuleData<'a> { /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module). /// This may be the crate root. - fn nearest_parent_mod(&self) -> DefId { + fn nearest_parent_mod(self) -> DefId { match self.kind { ModuleKind::Def(DefKind::Mod, def_id, _) => def_id, _ => self.parent.expect("non-root module without parent").nearest_parent_mod(), } } - fn is_ancestor_of(&self, mut other: &Self) -> bool { - while !ptr::eq(self, other) { + fn is_ancestor_of(self, mut other: Self) -> bool { + while self != other { if let Some(parent) = other.parent { other = parent; } else { @@ -649,7 +639,15 @@ impl<'a> ModuleData<'a> { } } -impl<'a> fmt::Debug for ModuleData<'a> { +impl<'a> std::ops::Deref for Module<'a> { + type Target = ModuleData<'a>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a> fmt::Debug for Module<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.res()) } @@ -657,20 +655,24 @@ impl<'a> fmt::Debug for ModuleData<'a> { /// Records a possibly-private value, type, or module definition. #[derive(Clone, Debug)] -struct NameBinding<'a> { +struct NameBindingData<'a> { kind: NameBindingKind<'a>, - ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>, + ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>, expansion: LocalExpnId, span: Span, vis: ty::Visibility, } +/// All name bindings are unique and allocated on a same arena, +/// so we can use referential equality to compare them. +type NameBinding<'a> = Interned<'a, NameBindingData<'a>>; + trait ToNameBinding<'a> { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>; + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a>; } -impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { - fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { +impl<'a> ToNameBinding<'a> for NameBinding<'a> { + fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> NameBinding<'a> { self } } @@ -679,7 +681,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { enum NameBindingKind<'a> { Res(Res), Module(Module<'a>), - Import { binding: &'a NameBinding<'a>, import: &'a Import<'a>, used: Cell }, + Import { binding: NameBinding<'a>, import: Import<'a>, used: Cell }, } impl<'a> NameBindingKind<'a> { @@ -692,7 +694,7 @@ impl<'a> NameBindingKind<'a> { #[derive(Debug)] struct PrivacyError<'a> { ident: Ident, - binding: &'a NameBinding<'a>, + binding: NameBinding<'a>, dedup_span: Span, outermost_res: Option<(Res, Ident)>, parent_scope: ParentScope<'a>, @@ -761,13 +763,13 @@ enum AmbiguityErrorMisc { struct AmbiguityError<'a> { kind: AmbiguityKind, ident: Ident, - b1: &'a NameBinding<'a>, - b2: &'a NameBinding<'a>, + b1: NameBinding<'a>, + b2: NameBinding<'a>, misc1: AmbiguityErrorMisc, misc2: AmbiguityErrorMisc, } -impl<'a> NameBinding<'a> { +impl<'a> NameBindingData<'a> { fn module(&self) -> Option> { match self.kind { NameBindingKind::Module(module) => Some(module), @@ -805,14 +807,12 @@ impl<'a> NameBinding<'a> { fn is_extern_crate(&self) -> bool { match self.kind { - NameBindingKind::Import { - import: &Import { kind: ImportKind::ExternCrate { .. }, .. }, - .. - } => true, - NameBindingKind::Module(&ModuleData { - kind: ModuleKind::Def(DefKind::Mod, def_id, _), - .. - }) => def_id.is_crate_root(), + NameBindingKind::Import { import, .. } => { + matches!(import.kind, ImportKind::ExternCrate { .. }) + } + NameBindingKind::Module(module) + if let ModuleKind::Def(DefKind::Mod, def_id, _) = module.kind + => def_id.is_crate_root(), _ => false, } } @@ -855,7 +855,7 @@ impl<'a> NameBinding<'a> { fn may_appear_after( &self, invoc_parent_expansion: LocalExpnId, - binding: &NameBinding<'_>, + binding: NameBinding<'_>, ) -> bool { // self > max(invoc, binding) => !(self <= invoc || self <= binding) // Expansions are partially ordered, so "may appear after" is an inversion of @@ -872,7 +872,7 @@ impl<'a> NameBinding<'a> { #[derive(Default, Clone)] struct ExternPreludeEntry<'a> { - extern_crate_item: Option<&'a NameBinding<'a>>, + extern_crate_item: Option>, introduced_by_item: bool, } @@ -917,10 +917,10 @@ pub struct Resolver<'a, 'tcx> { field_visibility_spans: FxHashMap>, /// All imports known to succeed or fail. - determined_imports: Vec<&'a Import<'a>>, + determined_imports: Vec>, /// All non-determined imports. - indeterminate_imports: Vec<&'a Import<'a>>, + indeterminate_imports: Vec>, // Spans for local variables found during pattern resolution. // Used for suggestions during error reporting. @@ -962,7 +962,7 @@ pub struct Resolver<'a, 'tcx> { /// language items. empty_module: Module<'a>, module_map: FxHashMap>, - binding_parent_modules: FxHashMap>, Module<'a>>, + binding_parent_modules: FxHashMap, Module<'a>>, underscore_disambiguator: u32, @@ -984,7 +984,7 @@ pub struct Resolver<'a, 'tcx> { macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>, arenas: &'a ResolverArenas<'a>, - dummy_binding: &'a NameBinding<'a>, + dummy_binding: NameBinding<'a>, used_extern_options: FxHashSet, macro_names: FxHashSet, @@ -993,7 +993,7 @@ pub struct Resolver<'a, 'tcx> { /// the surface (`macro` items in libcore), but are actually attributes or derives. builtin_macro_kinds: FxHashMap, registered_tools: &'tcx RegisteredTools, - macro_use_prelude: FxHashMap>, + macro_use_prelude: FxHashMap>, macro_map: FxHashMap, dummy_ext_bang: Lrc, dummy_ext_derive: Lrc, @@ -1005,7 +1005,7 @@ pub struct Resolver<'a, 'tcx> { proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: - Vec<(Ident, MacroKind, ParentScope<'a>, Option<&'a NameBinding<'a>>)>, + Vec<(Ident, MacroKind, ParentScope<'a>, Option>)>, multi_segment_macro_resolutions: Vec<(Vec, Span, MacroKind, ParentScope<'a>, Option)>, builtin_attrs: Vec<(Ident, ParentScope<'a>)>, @@ -1030,7 +1030,7 @@ pub struct Resolver<'a, 'tcx> { /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, - potentially_unused_imports: Vec<&'a Import<'a>>, + potentially_unused_imports: Vec>, /// Table for mapping struct IDs into struct constructor IDs, /// it's not used during normal resolution, only for better error reporting. @@ -1085,7 +1085,7 @@ pub struct Resolver<'a, 'tcx> { pub struct ResolverArenas<'a> { modules: TypedArena>, local_modules: RefCell>>, - imports: TypedArena>, + imports: TypedArena>, name_resolutions: TypedArena>>, ast_paths: TypedArena, dropless: DroplessArena, @@ -1101,8 +1101,13 @@ impl<'a> ResolverArenas<'a> { no_implicit_prelude: bool, module_map: &mut FxHashMap>, ) -> Module<'a> { - let module = - self.modules.alloc(ModuleData::new(parent, kind, expn_id, span, no_implicit_prelude)); + let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new( + parent, + kind, + expn_id, + span, + no_implicit_prelude, + )))); let def_id = module.opt_def_id(); if def_id.map_or(true, |def_id| def_id.is_local()) { self.local_modules.borrow_mut().push(module); @@ -1115,11 +1120,11 @@ impl<'a> ResolverArenas<'a> { fn local_modules(&'a self) -> std::cell::Ref<'a, Vec>> { self.local_modules.borrow() } - fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> { - self.dropless.alloc(name_binding) + fn alloc_name_binding(&'a self, name_binding: NameBindingData<'a>) -> NameBinding<'a> { + Interned::new_unchecked(self.dropless.alloc(name_binding)) } - fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> { - self.imports.alloc(import) + fn alloc_import(&'a self, import: ImportData<'a>) -> Import<'a> { + Interned::new_unchecked(self.imports.alloc(import)) } fn alloc_name_resolution(&'a self) -> &'a RefCell> { self.name_resolutions.alloc(Default::default()) @@ -1314,7 +1319,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { macro_expanded_macro_export_errors: BTreeSet::new(), arenas, - dummy_binding: arenas.alloc_name_binding(NameBinding { + dummy_binding: arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(Res::Err), ambiguity: None, expansion: LocalExpnId::ROOT, @@ -1624,7 +1629,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.maybe_unused_trait_imports.insert(def_id); import_ids.push(def_id); } - self.add_to_glob_map(&import, trait_name); + self.add_to_glob_map(*import, trait_name); kind = &binding.kind; } import_ids @@ -1646,7 +1651,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module.populate_on_access.set(false); self.build_reduced_graph_external(module); } - &module.lazy_resolutions + &module.0.0.lazy_resolutions } fn resolution( @@ -1679,12 +1684,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { false } - fn record_use( - &mut self, - ident: Ident, - used_binding: &'a NameBinding<'a>, - is_lexical_scope: bool, - ) { + fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, is_lexical_scope: bool) { if let Some((b2, kind)) = used_binding.ambiguity { let ambiguity_error = AmbiguityError { kind, @@ -1704,10 +1704,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // but not introduce it, as used if they are accessed from lexical scope. if is_lexical_scope { if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) { - if let Some(crate_item) = entry.extern_crate_item { - if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item { - return; - } + if !entry.introduced_by_item && entry.extern_crate_item == Some(used_binding) { + return; } } } @@ -1716,13 +1714,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(id) = import.id() { self.used_imports.insert(id); } - self.add_to_glob_map(&import, ident); + self.add_to_glob_map(import, ident); self.record_use(ident, binding, false); } } #[inline] - fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) { + fn add_to_glob_map(&mut self, import: Import<'_>, ident: Ident) { if let ImportKind::Glob { id, .. } = import.kind { let def_id = self.local_def_id(id); self.glob_map.entry(def_id).or_default().insert(ident.name); @@ -1831,11 +1829,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { vis.is_accessible_from(module.nearest_parent_mod(), self.tcx) } - fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Module<'a>) { - if let Some(old_module) = - self.binding_parent_modules.insert(Interned::new_unchecked(binding), module) - { - if !ptr::eq(module, old_module) { + fn set_binding_parent_module(&mut self, binding: NameBinding<'a>, module: Module<'a>) { + if let Some(old_module) = self.binding_parent_modules.insert(binding, module) { + if module != old_module { span_bug!(binding.span, "parent module is reset for binding"); } } @@ -1843,25 +1839,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn disambiguate_macro_rules_vs_modularized( &self, - macro_rules: &'a NameBinding<'a>, - modularized: &'a NameBinding<'a>, + macro_rules: NameBinding<'a>, + modularized: NameBinding<'a>, ) -> bool { // Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules" // is disambiguated to mitigate regressions from macro modularization. // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general. match ( - self.binding_parent_modules.get(&Interned::new_unchecked(macro_rules)), - self.binding_parent_modules.get(&Interned::new_unchecked(modularized)), + self.binding_parent_modules.get(¯o_rules), + self.binding_parent_modules.get(&modularized), ) { (Some(macro_rules), Some(modularized)) => { macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod() - && modularized.is_ancestor_of(macro_rules) + && modularized.is_ancestor_of(*macro_rules) } _ => false, } } - fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<&'a NameBinding<'a>> { + fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option> { if ident.is_path_segment_keyword() { // Make sure `self`, `super` etc produce an error when passed to here. return None; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index d33e8d40b6383..d16b7902f6069 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -42,7 +42,7 @@ type Res = def::Res; /// Not modularized, can shadow previous `macro_rules` bindings, etc. #[derive(Debug)] pub(crate) struct MacroRulesBinding<'a> { - pub(crate) binding: &'a NameBinding<'a>, + pub(crate) binding: NameBinding<'a>, /// `macro_rules` scope into which the `macro_rules` item was planted. pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'a>, pub(crate) ident: Ident, @@ -870,7 +870,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn prohibit_imported_non_macro_attrs( &self, - binding: Option<&'a NameBinding<'a>>, + binding: Option>, res: Option, span: Span, ) {