diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 6f2d3e79d10ab..6884ed1891a3f 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -32,7 +32,7 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{SourceMap, Spanned}; -use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, SyntaxContext, kw, sym}; +use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym}; use thin_vec::{ThinVec, thin_vec}; use tracing::{debug, instrument}; @@ -41,6 +41,7 @@ use crate::errors::{ ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition, MaybeMissingMacroRulesName, }; +use crate::hygiene::Macros20NormalizedSyntaxContext; use crate::imports::{Import, ImportKind}; use crate::late::{DiagMetadata, PatternSource, Rib}; use crate::{ @@ -1163,11 +1164,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestions: &mut Vec, scope_set: ScopeSet<'ra>, ps: &ParentScope<'ra>, - ctxt: SyntaxContext, + sp: Span, filter_fn: &impl Fn(Res) -> bool, ) { - let ctxt = DUMMY_SP.with_ctxt(ctxt); - self.cm().visit_scopes(scope_set, ps, ctxt, None, |this, scope, use_prelude, _| { + let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt()); + self.cm().visit_scopes(scope_set, ps, ctxt, sp, None, |this, scope, use_prelude, _| { match scope { Scope::DeriveHelpers(expn_id) => { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); @@ -1269,8 +1270,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { filter_fn: &impl Fn(Res) -> bool, ) -> Option { let mut suggestions = Vec::new(); - let ctxt = ident.span.ctxt(); - self.add_scope_set_candidates(&mut suggestions, scope_set, parent_scope, ctxt, filter_fn); + self.add_scope_set_candidates( + &mut suggestions, + scope_set, + parent_scope, + ident.span, + filter_fn, + ); // Make sure error reporting is deterministic. suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 4fbde60d86792..0e73c349c8cdd 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -54,9 +54,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { mut self: CmResolver<'r, 'ra, 'tcx>, scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, - // Location of the span is not significant, but pass a `Span` instead of `SyntaxContext` - // to avoid extracting and re-packaging the syntax context unnecessarily. - orig_ctxt: Span, + mut ctxt: Macros20NormalizedSyntaxContext, + orig_ident_span: Span, derive_fallback_lint_id: Option, mut visitor: impl FnMut( CmResolver<'_, 'ra, 'tcx>, @@ -128,7 +127,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { TypeNS | ValueNS => Scope::ModuleNonGlobs(module, None), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; - let mut ctxt = Macros20NormalizedSyntaxContext::new(orig_ctxt.ctxt()); let mut use_prelude = !module.no_implicit_prelude; loop { @@ -153,7 +151,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { true } Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..) => true, - Scope::MacroUsePrelude => use_prelude || orig_ctxt.edition().is_rust_2015(), + Scope::MacroUsePrelude => use_prelude || orig_ident_span.is_rust_2015(), Scope::BuiltinAttrs => true, Scope::ExternPreludeItems | Scope::ExternPreludeFlags => { use_prelude || module_and_extern_prelude || extern_prelude @@ -396,9 +394,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize: Option, ignore_decl: Option>, ignore_import: Option>, + ) -> Result, Determinacy> { + self.resolve_ident_in_scope_set_inner( + IdentKey::new(orig_ident), + orig_ident.span, + scope_set, + parent_scope, + finalize, + ignore_decl, + ignore_import, + ) + } + + fn resolve_ident_in_scope_set_inner<'r>( + self: CmResolver<'r, 'ra, 'tcx>, + ident: IdentKey, + orig_ident_span: Span, + scope_set: ScopeSet<'ra>, + parent_scope: &ParentScope<'ra>, + finalize: Option, + ignore_decl: Option>, + ignore_import: Option>, ) -> Result, Determinacy> { // Make sure `self`, `super` etc produce an error when passed to here. - if !matches!(scope_set, ScopeSet::Module(..)) && orig_ident.is_path_segment_keyword() { + if !matches!(scope_set, ScopeSet::Module(..)) && ident.name.is_path_segment_keyword() { return Err(Determinacy::Determined); } @@ -432,13 +451,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let break_result = self.visit_scopes( scope_set, parent_scope, - orig_ident.span, + ident.ctxt, + orig_ident_span, derive_fallback_lint_id, |mut this, scope, use_prelude, ctxt| { - let ident = IdentKey { name: orig_ident.name, ctxt }; + let ident = IdentKey { name: ident.name, ctxt }; let res = match this.reborrow().resolve_ident_in_scope( ident, - orig_ident.span, + orig_ident_span, ns, scope, use_prelude, @@ -472,7 +492,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let Some(&(innermost_decl, _)) = innermost_results.first() { // Found another solution, if the first one was "weak", report an error. if this.get_mut().maybe_push_ambiguity( - orig_ident, + ident, + orig_ident_span, ns, scope_set, parent_scope, @@ -695,8 +716,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::StdLibPrelude => { let mut result = Err(Determinacy::Determined); if let Some(prelude) = self.prelude - && let Ok(decl) = self.reborrow().resolve_ident_in_scope_set( - ident.orig(orig_ident_span.with_ctxt(*ident.ctxt)), + && let Ok(decl) = self.reborrow().resolve_ident_in_scope_set_inner( + ident, + orig_ident_span, ScopeSet::Module(ns, prelude), parent_scope, None, @@ -749,7 +771,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn maybe_push_ambiguity( &mut self, - orig_ident: Ident, + ident: IdentKey, + orig_ident_span: Span, ns: Namespace, scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, @@ -775,7 +798,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else if innermost_res == derive_helper_compat { Some(AmbiguityKind::DeriveHelper) } else if res == derive_helper_compat && innermost_res != derive_helper { - span_bug!(orig_ident.span, "impossible inner resolution kind") + span_bug!(orig_ident_span, "impossible inner resolution kind") } else if matches!(innermost_scope, Scope::MacroRules(_)) && matches!(scope, Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..)) && !self.disambiguate_macro_rules_vs_modularized(innermost_decl, decl) @@ -790,7 +813,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // we visit all macro_rules scopes (e.g. textual scope macros) // before we visit any modules (e.g. path-based scope macros) span_bug!( - orig_ident.span, + orig_ident_span, "ambiguous scoped macro resolutions with path-based \ scope resolution as first candidate" ) @@ -839,8 +862,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else { // Turn ambiguity errors for core vs std panic into warnings. // FIXME: Remove with lang team approval. - let is_issue_147319_hack = orig_ident.span.edition() <= Edition::Edition2024 - && matches!(orig_ident.name, sym::panic) + let is_issue_147319_hack = orig_ident_span.edition() <= Edition::Edition2024 + && matches!(ident.name, sym::panic) && matches!(scope, Scope::StdLibPrelude) && matches!(innermost_scope, Scope::ModuleGlobs(_, _)) && ((self.is_specific_builtin_macro(res, sym::std_panic) @@ -852,7 +875,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.ambiguity_errors.push(AmbiguityError { kind, - ident: orig_ident, + ident: ident.orig(orig_ident_span), b1: innermost_decl, b2: decl, scope1: innermost_scope, @@ -880,46 +903,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { #[instrument(level = "debug", skip(self))] pub(crate) fn resolve_ident_in_module<'r>( - self: CmResolver<'r, 'ra, 'tcx>, - module: ModuleOrUniformRoot<'ra>, - mut ident: Ident, - ns: Namespace, - parent_scope: &ParentScope<'ra>, - finalize: Option, - ignore_decl: Option>, - ignore_import: Option>, - ) -> Result, Determinacy> { - let tmp_parent_scope; - let mut adjusted_parent_scope = parent_scope; - match module { - ModuleOrUniformRoot::Module(m) => { - if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(m.expansion) { - tmp_parent_scope = - ParentScope { module: self.expn_def_scope(def), ..*parent_scope }; - adjusted_parent_scope = &tmp_parent_scope; - } - } - ModuleOrUniformRoot::ExternPrelude => { - ident.span.normalize_to_macros_2_0_and_adjust(ExpnId::root()); - } - ModuleOrUniformRoot::ModuleAndExternPrelude(..) | ModuleOrUniformRoot::CurrentScope => { - // No adjustments - } - } - self.resolve_ident_in_virt_module_unadjusted( - module, - ident, - ns, - adjusted_parent_scope, - finalize, - ignore_decl, - ignore_import, - ) - } - - /// Attempts to resolve `ident` in namespace `ns` of `module`. - #[instrument(level = "debug", skip(self))] - fn resolve_ident_in_virt_module_unadjusted<'r>( self: CmResolver<'r, 'ra, 'tcx>, module: ModuleOrUniformRoot<'ra>, ident: Ident, @@ -930,14 +913,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ignore_import: Option>, ) -> Result, Determinacy> { match module { - ModuleOrUniformRoot::Module(module) => self.resolve_ident_in_scope_set( - ident, - ScopeSet::Module(ns, module), - parent_scope, - finalize, - ignore_decl, - ignore_import, - ), + ModuleOrUniformRoot::Module(module) => { + let (ident_key, def) = IdentKey::new_adjusted(ident, module.expansion); + let adjusted_parent_scope = match def { + Some(def) => ParentScope { module: self.expn_def_scope(def), ..*parent_scope }, + None => *parent_scope, + }; + self.resolve_ident_in_scope_set_inner( + ident_key, + ident.span, + ScopeSet::Module(ns, module), + &adjusted_parent_scope, + finalize, + ignore_decl, + ignore_import, + ) + } ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set( ident, ScopeSet::ModuleAndExternPrelude(ns, module), @@ -950,8 +941,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if ns != TypeNS { Err(Determined) } else { - self.resolve_ident_in_scope_set( - ident, + self.resolve_ident_in_scope_set_inner( + IdentKey::new_adjusted(ident, ExpnId::root()).0, + ident.span, ScopeSet::ExternPrelude, parent_scope, finalize, @@ -1145,8 +1137,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None => return Err(ControlFlow::Continue(Undetermined)), }; let tmp_parent_scope; - let (mut adjusted_parent_scope, mut ctxt) = (parent_scope, *ident.ctxt); - match ctxt.glob_adjust(module.expansion, glob_import.span) { + let (mut adjusted_parent_scope, mut adjusted_ident) = (parent_scope, ident); + match adjusted_ident + .ctxt + .update_unchecked(|ctxt| ctxt.glob_adjust(module.expansion, glob_import.span)) + { Some(Some(def)) => { tmp_parent_scope = ParentScope { module: self.expn_def_scope(def), ..*parent_scope }; @@ -1155,8 +1150,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Some(None) => {} None => continue, }; - let result = self.reborrow().resolve_ident_in_scope_set( - ident.orig(orig_ident_span.with_ctxt(ctxt)), + let result = self.reborrow().resolve_ident_in_scope_set_inner( + adjusted_ident, + orig_ident_span, ScopeSet::Module(ns, module), adjusted_parent_scope, None, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a3ee17ec4a9ac..8794c4ff8b025 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2677,7 +2677,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &mut names, ScopeSet::All(ns), parent_scope, - ctxt, + segment.ident.span.with_ctxt(ctxt), filter_fn, ); break; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 5fe1be039a881..75bd2c62f9b47 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -575,6 +575,12 @@ impl IdentKey { IdentKey { name: ident.name, ctxt: Macros20NormalizedSyntaxContext::new(ident.span.ctxt()) } } + #[inline] + fn new_adjusted(ident: Ident, expn_id: ExpnId) -> (IdentKey, Option) { + let (ctxt, def) = Macros20NormalizedSyntaxContext::new_adjusted(ident.span.ctxt(), expn_id); + (IdentKey { name: ident.name, ctxt }, def) + } + #[inline] fn with_root_ctxt(name: Symbol) -> Self { let ctxt = Macros20NormalizedSyntaxContext::new_unchecked(SyntaxContext::root()); @@ -1923,7 +1929,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &mut self, current_trait: Option>, parent_scope: &ParentScope<'ra>, - ctxt: Span, + sp: Span, assoc_item: Option<(Symbol, Namespace)>, ) -> Vec { let mut found_traits = Vec::new(); @@ -1940,7 +1946,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let scope_set = ScopeSet::All(TypeNS); - self.cm().visit_scopes(scope_set, parent_scope, ctxt, None, |mut this, scope, _, _| { + let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt()); + self.cm().visit_scopes(scope_set, parent_scope, ctxt, sp, None, |mut this, scope, _, _| { match scope { Scope::ModuleNonGlobs(module, _) => { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); @@ -2723,7 +2730,7 @@ mod ref_mut { } mod hygiene { - use rustc_span::SyntaxContext; + use rustc_span::{ExpnId, SyntaxContext}; /// A newtype around `SyntaxContext` that can only keep contexts produced by /// [SyntaxContext::normalize_to_macros_2_0]. @@ -2736,6 +2743,15 @@ mod hygiene { Macros20NormalizedSyntaxContext(ctxt.normalize_to_macros_2_0()) } + #[inline] + pub(crate) fn new_adjusted( + mut ctxt: SyntaxContext, + expn_id: ExpnId, + ) -> (Macros20NormalizedSyntaxContext, Option) { + let def = ctxt.normalize_to_macros_2_0_and_adjust(expn_id); + (Macros20NormalizedSyntaxContext(ctxt), def) + } + #[inline] pub(crate) fn new_unchecked(ctxt: SyntaxContext) -> Macros20NormalizedSyntaxContext { debug_assert_eq!(ctxt, ctxt.normalize_to_macros_2_0()); diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 2e8037b3f9e47..05f4c8e268a9c 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -804,7 +804,7 @@ impl SyntaxContext { /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0. #[inline] - pub(crate) fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { + pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { HygieneData::with(|data| { *self = data.normalize_to_macros_2_0(*self); data.adjust(self, expn_id)