Rollup merge of #113332 - petrochenkov:bindintern, r=cjgillot

resolve: Use `Interned` for some interned structures

Enough to get rid of all existing `ptr::eq`s and "partial" uses of `Interned`.
This commit is contained in:
fee1-dead 2023-07-06 09:20:32 +08:00 committed by GitHub
commit 01627265e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 224 additions and 255 deletions

View File

@ -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<NodeId>;
impl<'a, Id: Into<DefId>> ToNameBinding<'a>
for (Module<'a>, ty::Visibility<Id>, 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<DefId>> ToNameBinding<'a>
}
impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Res, ty::Visibility<Id>, 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,

View File

@ -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<Finalize>,
path: &[Segment],
second_binding: Option<&NameBinding<'_>>,
second_binding: Option<NameBinding<'_>>,
) {
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<Span> {
fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option<Span> {
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<Symbol> {
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<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'a>,
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
ignore_binding: Option<&'a NameBinding<'a>>,
ignore_binding: Option<NameBinding<'a>>,
module: Option<ModuleOrUniformRoot<'a>>,
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<Suggestion>, Option<String>)> {
@ -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;
}

View File

@ -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<ImportId<'a>>,
import_effective_visibilities: EffectiveVisibilities<NameBinding<'a>>,
// 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<Interned<'a, NameBinding<'a>>> {
) -> FxHashSet<NameBinding<'a>> {
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);

View File

@ -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<Finalize>,
ribs: &[Rib<'a>],
ignore_binding: Option<&'a NameBinding<'a>>,
ignore_binding: Option<NameBinding<'a>>,
) -> Option<LexicalScopeBinding<'a>> {
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<Finalize>,
force: bool,
ignore_binding: Option<&'a NameBinding<'a>>,
) -> Result<&'a NameBinding<'a>, Determinacy> {
ignore_binding: Option<NameBinding<'a>>,
) -> Result<NameBinding<'a>, 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<NameBinding<'a>, 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<Finalize>,
ignore_binding: Option<&'a NameBinding<'a>>,
) -> Result<&'a NameBinding<'a>, Determinacy> {
ignore_binding: Option<NameBinding<'a>>,
) -> Result<NameBinding<'a>, 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<Finalize>,
ignore_binding: Option<&'a NameBinding<'a>>,
) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
ignore_binding: Option<NameBinding<'a>>,
) -> Result<NameBinding<'a>, (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<Finalize>,
ignore_binding: Option<&'a NameBinding<'a>>,
) -> Result<&'a NameBinding<'a>, Determinacy> {
ignore_binding: Option<NameBinding<'a>>,
) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_unadjusted_ext(
module,
ident,
@ -809,8 +807,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
finalize: Option<Finalize>,
// 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<NameBinding<'a>>,
) -> Result<NameBinding<'a>, (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<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
ignore_binding: Option<&'a NameBinding<'a>>,
ignore_binding: Option<NameBinding<'a>>,
) -> 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<Finalize>,
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
ignore_binding: Option<&'a NameBinding<'a>>,
ignore_binding: Option<NameBinding<'a>>,
) -> PathResult<'a> {
let mut module = None;
let mut allow_super = true;

View File

@ -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<NodeId>;
@ -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<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
source_bindings: PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>,
/// Bindings introduced by `target`.
target_bindings: PerNS<Cell<Option<&'a NameBinding<'a>>>>,
target_bindings: PerNS<Cell<Option<NameBinding<'a>>>>,
/// `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<bool>,
}
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<Interned<'a, Import<'a>>>,
pub single_imports: FxHashSet<Import<'a>>,
/// 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<NameBinding<'a>>,
pub shadowed_glob: Option<NameBinding<'a>>,
}
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<NameBinding<'a>> {
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<Interned<'a, NameBinding<'a>>>,
exported_ambiguities: FxHashSet<NameBinding<'a>>,
) {
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<UnresolvedImportError> {
fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportError> {
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<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
target_bindings: &PerNS<Cell<Option<&'a NameBinding<'a>>>>,
import: Import<'a>,
source_bindings: &PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>,
target_bindings: &PerNS<Cell<Option<NameBinding<'a>>>>,
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);

View File

@ -1284,7 +1284,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
ident: Ident,
ns: Namespace,
finalize: Option<Finalize>,
ignore_binding: Option<&'a NameBinding<'a>>,
ignore_binding: Option<NameBinding<'a>>,
) -> Option<LexicalScopeBinding<'a>> {
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<Symbol>) -> 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);

View File

@ -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()

View File

@ -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<Vec<&'a Import<'a>>>,
globs: RefCell<Vec<&'a Import<'a>>>,
glob_importers: RefCell<Vec<Import<'a>>>,
globs: RefCell<Vec<Import<'a>>>,
/// Used to memoize the traits in this module for faster searches through all traits in scope.
traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
traits: RefCell<Option<Box<[(Ident, NameBinding<'a>)]>>>,
/// 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<Resolver<'a, 'tcx>>,
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<Resolver<'a, 'tcx>>,
{
@ -591,7 +581,7 @@ impl<'a> ModuleData<'a> {
}
}
fn res(&self) -> Option<Res> {
fn res(self) -> Option<Res> {
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<DefId> {
fn opt_def_id(self) -> Option<DefId> {
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<DefId>,
}
/// 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<bool> },
Import { binding: NameBinding<'a>, import: Import<'a>, used: Cell<bool> },
}
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<Module<'a>> {
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<NameBinding<'a>>,
introduced_by_item: bool,
}
@ -917,10 +917,10 @@ pub struct Resolver<'a, 'tcx> {
field_visibility_spans: FxHashMap<DefId, Vec<Span>>,
/// All imports known to succeed or fail.
determined_imports: Vec<&'a Import<'a>>,
determined_imports: Vec<Import<'a>>,
/// All non-determined imports.
indeterminate_imports: Vec<&'a Import<'a>>,
indeterminate_imports: Vec<Import<'a>>,
// 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<DefId, Module<'a>>,
binding_parent_modules: FxHashMap<Interned<'a, NameBinding<'a>>, Module<'a>>,
binding_parent_modules: FxHashMap<NameBinding<'a>, 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<Symbol>,
macro_names: FxHashSet<Ident>,
@ -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<LocalDefId, MacroKind>,
registered_tools: &'tcx RegisteredTools,
macro_use_prelude: FxHashMap<Symbol, &'a NameBinding<'a>>,
macro_use_prelude: FxHashMap<Symbol, NameBinding<'a>>,
macro_map: FxHashMap<DefId, MacroData>,
dummy_ext_bang: Lrc<SyntaxExtension>,
dummy_ext_derive: Lrc<SyntaxExtension>,
@ -1005,7 +1005,7 @@ pub struct Resolver<'a, 'tcx> {
proc_macro_stubs: FxHashSet<LocalDefId>,
/// 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<NameBinding<'a>>)>,
multi_segment_macro_resolutions:
Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>, Option<Res>)>,
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<Symbol, Span>,
potentially_unused_imports: Vec<&'a Import<'a>>,
potentially_unused_imports: Vec<Import<'a>>,
/// 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<ModuleData<'a>>,
local_modules: RefCell<Vec<Module<'a>>>,
imports: TypedArena<Import<'a>>,
imports: TypedArena<ImportData<'a>>,
name_resolutions: TypedArena<RefCell<NameResolution<'a>>>,
ast_paths: TypedArena<ast::Path>,
dropless: DroplessArena,
@ -1101,8 +1101,13 @@ impl<'a> ResolverArenas<'a> {
no_implicit_prelude: bool,
module_map: &mut FxHashMap<DefId, Module<'a>>,
) -> 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<Module<'a>>> {
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<NameResolution<'a>> {
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(&macro_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<NameBinding<'a>> {
if ident.is_path_segment_keyword() {
// Make sure `self`, `super` etc produce an error when passed to here.
return None;

View File

@ -42,7 +42,7 @@ type Res = def::Res<NodeId>;
/// 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<NameBinding<'a>>,
res: Option<Res>,
span: Span,
) {