1use std::ops::ControlFlow;23use Determinacy::*;4use Namespace::*;5use rustc_ast::{self as ast, NodeId};6use rustc_errors::ErrorGuaranteed;7use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS};8use rustc_middle::{bug, span_bug};9use rustc_session::errors::feature_err;10use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;11use rustc_span::edition::Edition;12use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};13use rustc_span::{Ident, Span, kw, sym};14use smallvec::SmallVec;15use tracing::{debug, instrument};1617use crate::diagnostics::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};18use crate::hygiene::Macros20NormalizedSyntaxContext;19use crate::imports::{Import, NameResolution};20use crate::late::{21 ConstantHasGenerics, DiagMetadata, NoConstantGenericsReason, PathSource, Rib, RibKind,22};23use crate::macros::{MacroRulesScope, sub_namespace_match};24use crate::{25 AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver, Decl, DeclKind,26 Determinacy, Finalize, IdentKey, ImportKind, ImportSummary, LateDecl, LocalModule, Module,27 ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError,28 Resolver, Scope, ScopeSet, Segment, Stage, Symbol, Used, diagnostics,29};3031#[derive(Copy, Clone)]32pub enum UsePrelude {33 No,34 Yes,35}3637impl From<UsePrelude> for bool {38 fn from(up: UsePrelude) -> bool {39 matches!(up, UsePrelude::Yes)40 }41}4243#[derive(Debug, PartialEq, Clone, Copy)]44enum Shadowing {45 Restricted,46 Unrestricted,47}4849impl<'ra, 'tcx> Resolver<'ra, 'tcx> {50 /// A generic scope visitor.51 /// Visits scopes in order to resolve some identifier in them or perform other actions.52 /// If the callback returns `Some` result, we stop visiting scopes and return it.53 pub(crate) fn visit_scopes<'r, T>(54 mut self: CmResolver<'r, 'ra, 'tcx>,55 scope_set: ScopeSet<'ra>,56 parent_scope: &ParentScope<'ra>,57 mut ctxt: Macros20NormalizedSyntaxContext,58 orig_ident_span: Span,59 derive_fallback_lint_id: Option<NodeId>,60 mut visitor: impl FnMut(61 CmResolver<'_, 'ra, 'tcx>,62 Scope<'ra>,63 UsePrelude,64 Macros20NormalizedSyntaxContext,65 ) -> ControlFlow<T>,66 ) -> Option<T> {67 // General principles:68 // 1. Not controlled (user-defined) names should have higher priority than controlled names69 // built into the language or standard library. This way we can add new names into the70 // language or standard library without breaking user code.71 // 2. "Closed set" below means new names cannot appear after the current resolution attempt.72 // Places to search (in order of decreasing priority):73 // (Type NS)74 // 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet75 // (open set, not controlled).76 // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents77 // (open, not controlled).78 // 3. Extern prelude (open, the open part is from macro expansions, not controlled).79 // 4. Tool modules (closed, controlled right now, but not in the future).80 // 5. Standard library prelude (de-facto closed, controlled).81 // 6. Language prelude (closed, controlled).82 // (Value NS)83 // 1. FIXME: Ribs (local variables), there's no necessary infrastructure yet84 // (open set, not controlled).85 // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents86 // (open, not controlled).87 // 3. Standard library prelude (de-facto closed, controlled).88 // (Macro NS)89 // 1-3. Derive helpers (open, not controlled). All ambiguities with other names90 // are currently reported as errors. They should be higher in priority than preludes91 // and probably even names in modules according to the "general principles" above. They92 // also should be subject to restricted shadowing because are effectively produced by93 // derives (you need to resolve the derive first to add helpers into scope), but they94 // should be available before the derive is expanded for compatibility.95 // It's mess in general, so we are being conservative for now.96 // 1-3. `macro_rules` (open, not controlled), loop through `macro_rules` scopes. Have higher97 // priority than prelude macros, but create ambiguities with macros in modules.98 // 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents99 // (open, not controlled). Have higher priority than prelude macros, but create100 // ambiguities with `macro_rules`.101 // 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).102 // 4a. User-defined prelude from macro-use103 // (open, the open part is from macro expansions, not controlled).104 // 4b. "Standard library prelude" part implemented through `macro-use` (closed, controlled).105 // 4c. Standard library prelude (de-facto closed, controlled).106 // 6. Language prelude: builtin attributes (closed, controlled).107108 let (ns, macro_kind) = match scope_set {109 ScopeSet::All(ns)110 | ScopeSet::Module(ns, _)111 | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),112 ScopeSet::ExternPrelude => (TypeNS, None),113 ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),114 };115 let module = match scope_set {116 // Start with the specified module.117 ScopeSet::Module(_, module) | ScopeSet::ModuleAndExternPrelude(_, module) => module,118 // Jump out of trait or enum modules, they do not act as scopes.119 _ => parent_scope.module.nearest_item_scope(),120 };121 let module_only = matches!(scope_set, ScopeSet::Module(..));122 let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..));123 let extern_prelude = matches!(scope_set, ScopeSet::ExternPrelude);124 let mut scope = match ns {125 _ if module_only || module_and_extern_prelude => Scope::ModuleNonGlobs(module, None),126 _ if extern_prelude => Scope::ExternPreludeItems,127 TypeNS | ValueNS => Scope::ModuleNonGlobs(module, None),128 MacroNS => Scope::DeriveHelpers(parent_scope.expansion),129 };130 let mut use_prelude = !module.no_implicit_prelude;131132 loop {133 let visit = match scope {134 // Derive helpers are not in scope when resolving derives in the same container.135 Scope::DeriveHelpers(expn_id) => {136 !(expn_id == parent_scope.expansion && macro_kind == Some(MacroKind::Derive))137 }138 Scope::DeriveHelpersCompat => true,139 Scope::MacroRules(macro_rules_scope) => {140 // Use "path compression" on `macro_rules` scope chains. This is an optimization141 // used to avoid long scope chains, see the comments on `MacroRulesScopeRef`.142 // As another consequence of this optimization visitors never observe invocation143 // scopes for macros that were already expanded.144 while let MacroRulesScope::Invocation(invoc_id) = macro_rules_scope.get() {145 if let Some(next_scope) = self.output_macro_rules_scopes.get(&invoc_id) {146 macro_rules_scope.set(next_scope.get());147 } else {148 break;149 }150 }151 true152 }153 Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..) => true,154 Scope::MacroUsePrelude => use_prelude || orig_ident_span.is_rust_2015(),155 Scope::BuiltinAttrs => true,156 Scope::ExternPreludeItems | Scope::ExternPreludeFlags => {157 use_prelude || module_and_extern_prelude || extern_prelude158 }159 Scope::ToolPrelude => use_prelude,160 Scope::StdLibPrelude => use_prelude || ns == MacroNS,161 Scope::BuiltinTypes => true,162 };163164 if visit {165 let use_prelude = if use_prelude { UsePrelude::Yes } else { UsePrelude::No };166 if let ControlFlow::Break(break_result) =167 visitor(self.reborrow(), scope, use_prelude, ctxt)168 {169 return Some(break_result);170 }171 }172173 scope = match scope {174 Scope::DeriveHelpers(LocalExpnId::ROOT) => Scope::DeriveHelpersCompat,175 Scope::DeriveHelpers(expn_id) => {176 // Derive helpers are not visible to code generated by bang or derive macros.177 let expn_data = expn_id.expn_data();178 match expn_data.kind {179 ExpnKind::Root180 | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {181 Scope::DeriveHelpersCompat182 }183 _ => Scope::DeriveHelpers(expn_data.parent.expect_local()),184 }185 }186 Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules),187 Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() {188 MacroRulesScope::Def(binding) => {189 Scope::MacroRules(binding.parent_macro_rules_scope)190 }191 MacroRulesScope::Invocation(invoc_id) => {192 Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules)193 }194 MacroRulesScope::Empty => Scope::ModuleNonGlobs(module, None),195 },196 Scope::ModuleNonGlobs(module, lint_id) => Scope::ModuleGlobs(module, lint_id),197 Scope::ModuleGlobs(..) if module_only => break,198 Scope::ModuleGlobs(..) if module_and_extern_prelude => match ns {199 TypeNS => {200 ctxt.update_unchecked(|ctxt| ctxt.adjust(ExpnId::root()));201 Scope::ExternPreludeItems202 }203 ValueNS | MacroNS => break,204 },205 Scope::ModuleGlobs(module, prev_lint_id) => {206 use_prelude = !module.no_implicit_prelude;207 match self.hygienic_lexical_parent(module, &mut ctxt, derive_fallback_lint_id) {208 Some((parent_module, lint_id)) => {209 Scope::ModuleNonGlobs(parent_module, lint_id.or(prev_lint_id))210 }211 None => {212 ctxt.update_unchecked(|ctxt| ctxt.adjust(ExpnId::root()));213 match ns {214 TypeNS => Scope::ExternPreludeItems,215 ValueNS => Scope::StdLibPrelude,216 MacroNS => Scope::MacroUsePrelude,217 }218 }219 }220 }221 Scope::MacroUsePrelude => Scope::StdLibPrelude,222 Scope::BuiltinAttrs => break, // nowhere else to search223 Scope::ExternPreludeItems => Scope::ExternPreludeFlags,224 Scope::ExternPreludeFlags if module_and_extern_prelude || extern_prelude => break,225 Scope::ExternPreludeFlags => Scope::ToolPrelude,226 Scope::ToolPrelude => Scope::StdLibPrelude,227 Scope::StdLibPrelude => match ns {228 TypeNS => Scope::BuiltinTypes,229 ValueNS => break, // nowhere else to search230 MacroNS => Scope::BuiltinAttrs,231 },232 Scope::BuiltinTypes => break, // nowhere else to search233 };234 }235236 None237 }238239 fn hygienic_lexical_parent(240 &self,241 module: Module<'ra>,242 ctxt: &mut Macros20NormalizedSyntaxContext,243 derive_fallback_lint_id: Option<NodeId>,244 ) -> Option<(Module<'ra>, Option<NodeId>)> {245 if !module.expansion.outer_expn_is_descendant_of(**ctxt) {246 let expn_id = ctxt.update_unchecked(|ctxt| ctxt.remove_mark());247 return Some((self.expn_def_scope(expn_id), None));248 }249250 if let ModuleKind::Block = module.kind {251 return Some((module.parent.unwrap().nearest_item_scope(), None));252 }253254 // We need to support the next case under a deprecation warning255 // ```256 // struct MyStruct;257 // ---- begin: this comes from a proc macro derive258 // mod implementation_details {259 // // Note that `MyStruct` is not in scope here.260 // impl SomeTrait for MyStruct { ... }261 // }262 // ---- end263 // ```264 // So we have to fall back to the module's parent during lexical resolution in this case.265 if derive_fallback_lint_id.is_some()266 && let Some(parent) = module.parent267 // Inner module is inside the macro268 && module.expansion != parent.expansion269 // Parent module is outside of the macro270 && module.expansion.is_descendant_of(parent.expansion)271 // The macro is a proc macro derive272 && let Some(def_id) = module.expansion.expn_data().macro_def_id273 {274 let ext = self.get_macro_by_def_id(def_id);275 if ext.builtin_name.is_none()276 && ext.macro_kinds() == MacroKinds::DERIVE277 && parent.expansion.outer_expn_is_descendant_of(**ctxt)278 {279 return Some((parent, derive_fallback_lint_id));280 }281 }282283 None284 }285286 /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.287 /// More specifically, we proceed up the hierarchy of scopes and return the binding for288 /// `ident` in the first scope that defines it (or None if no scopes define it).289 ///290 /// A block's items are above its local variables in the scope hierarchy, regardless of where291 /// the items are defined in the block. For example,292 /// ```rust293 /// fn f() {294 /// g(); // Since there are no local variables in scope yet, this resolves to the item.295 /// let g = || {};296 /// fn g() {}297 /// g(); // This resolves to the local variable `g` since it shadows the item.298 /// }299 /// ```300 ///301 /// Invariant: This must only be called during main resolution, not during302 /// import resolution.303 #[instrument(level = "debug", skip(self, ribs))]304 pub(crate) fn resolve_ident_in_lexical_scope(305 &mut self,306 mut ident: Ident,307 ns: Namespace,308 parent_scope: &ParentScope<'ra>,309 finalize: Option<Finalize>,310 ribs: &[Rib<'ra>],311 ignore_decl: Option<Decl<'ra>>,312 diag_metadata: Option<&DiagMetadata<'_>>,313 ) -> Option<LateDecl<'ra>> {314 let orig_ident = ident;315 let (general_span, normalized_span) = if ident.name == kw::SelfUpper {316 // FIXME(jseyfried) improve `Self` hygiene317 let empty_span = ident.span.with_ctxt(SyntaxContext::root());318 (empty_span, empty_span)319 } else if ns == TypeNS {320 let normalized_span = ident.span.normalize_to_macros_2_0();321 (normalized_span, normalized_span)322 } else {323 (ident.span.normalize_to_macro_rules(), ident.span.normalize_to_macros_2_0())324 };325 ident.span = general_span;326 let normalized_ident = Ident { span: normalized_span, ..ident };327328 // Walk backwards up the ribs in scope.329 for (i, rib) in ribs.iter().enumerate().rev() {330 debug!("walk rib\n{:?}", rib.bindings);331 // Use the rib kind to determine whether we are resolving parameters332 // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).333 let rib_ident = if rib.kind.contains_params() { normalized_ident } else { ident };334 if let Some((original_rib_ident_def, res)) = rib.bindings.get_key_value(&rib_ident) {335 // The ident resolves to a type parameter or local variable.336 return Some(LateDecl::RibDef(self.validate_res_from_ribs(337 i,338 rib_ident,339 *res,340 finalize.map(|_| general_span),341 *original_rib_ident_def,342 ribs,343 diag_metadata,344 )));345 } else if let RibKind::Block(Some(module)) = rib.kind346 && let Ok(binding) = self.cm().resolve_ident_in_scope_set(347 ident,348 ScopeSet::Module(ns, module.to_module()),349 parent_scope,350 finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),351 ignore_decl,352 None,353 )354 {355 // The ident resolves to an item in a block.356 return Some(LateDecl::Decl(binding));357 } else if let RibKind::Module(module) = rib.kind {358 // Encountered a module item, abandon ribs and look into that module and preludes.359 let parent_scope = &ParentScope { module: module.to_module(), ..*parent_scope };360 let finalize = finalize.map(|f| Finalize { stage: Stage::Late, ..f });361 return self362 .cm()363 .resolve_ident_in_scope_set(364 orig_ident,365 ScopeSet::All(ns),366 parent_scope,367 finalize,368 ignore_decl,369 None,370 )371 .ok()372 .map(LateDecl::Decl);373 }374375 if let RibKind::MacroDefinition(def) = rib.kind376 && def == self.macro_def(ident.span.ctxt())377 {378 // If an invocation of this macro created `ident`, give up on `ident`379 // and switch to `ident`'s source from the macro definition.380 ident.span.remove_mark();381 }382 }383384 unreachable!()385 }386387 /// Resolve an identifier in the specified set of scopes.388 pub(crate) fn resolve_ident_in_scope_set<'r>(389 self: CmResolver<'r, 'ra, 'tcx>,390 orig_ident: Ident,391 scope_set: ScopeSet<'ra>,392 parent_scope: &ParentScope<'ra>,393 finalize: Option<Finalize>,394 ignore_decl: Option<Decl<'ra>>,395 ignore_import: Option<Import<'ra>>,396 ) -> Result<Decl<'ra>, Determinacy> {397 self.resolve_ident_in_scope_set_inner(398 IdentKey::new(orig_ident),399 orig_ident.span,400 scope_set,401 parent_scope,402 finalize,403 ignore_decl,404 ignore_import,405 )406 }407408 fn resolve_ident_in_scope_set_inner<'r>(409 self: CmResolver<'r, 'ra, 'tcx>,410 ident: IdentKey,411 orig_ident_span: Span,412 scope_set: ScopeSet<'ra>,413 parent_scope: &ParentScope<'ra>,414 finalize: Option<Finalize>,415 ignore_decl: Option<Decl<'ra>>,416 ignore_import: Option<Import<'ra>>,417 ) -> Result<Decl<'ra>, Determinacy> {418 // Make sure `self`, `super` etc produce an error when passed to here.419 if !matches!(scope_set, ScopeSet::Module(..)) && ident.name.is_path_segment_keyword() {420 return Err(Determinacy::Determined);421 }422423 let (ns, macro_kind) = match scope_set {424 ScopeSet::All(ns)425 | ScopeSet::Module(ns, _)426 | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),427 ScopeSet::ExternPrelude => (TypeNS, None),428 ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),429 };430 let derive_fallback_lint_id = match finalize {431 Some(Finalize { node_id, stage: Stage::Late, .. }) => Some(node_id),432 _ => None,433 };434435 // This is *the* result, resolution from the scope closest to the resolved identifier.436 // However, sometimes this result is "weak" because it comes from a glob import or437 // a macro expansion, and in this case it cannot shadow names from outer scopes, e.g.438 // mod m { ... } // solution in outer scope439 // {440 // use prefix::*; // imports another `m` - innermost solution441 // // weak, cannot shadow the outer `m`, need to report ambiguity error442 // m::mac!();443 // }444 // So we have to save the innermost solution and continue searching in outer scopes445 // to detect potential ambiguities.446 let mut innermost_results: SmallVec<[(Decl<'_>, Scope<'_>); 2]> = SmallVec::new();447 let mut determinacy = Determinacy::Determined;448449 // Go through all the scopes and try to resolve the name.450 let break_result = self.visit_scopes(451 scope_set,452 parent_scope,453 ident.ctxt,454 orig_ident_span,455 derive_fallback_lint_id,456 |mut this, scope, use_prelude, ctxt| {457 let ident = IdentKey { name: ident.name, ctxt };458 let res = match this.reborrow().resolve_ident_in_scope(459 ident,460 orig_ident_span,461 ns,462 scope,463 use_prelude,464 scope_set,465 parent_scope,466 // Shadowed decls don't need to be marked as used or non-speculatively loaded.467 if innermost_results.is_empty() { finalize } else { None },468 ignore_decl,469 ignore_import,470 ) {471 Ok(decl) => Ok(decl),472 // We can break with an error at this step, it means we cannot determine the473 // resolution right now, but we must block and wait until we can, instead of474 // considering outer scopes. Although there's no need to do that if we already475 // have a better solution.476 Err(ControlFlow::Break(determinacy)) if innermost_results.is_empty() => {477 return ControlFlow::Break(Err(determinacy));478 }479 Err(determinacy) => Err(determinacy.into_value()),480 };481 match res {482 Ok(decl) if sub_namespace_match(decl.macro_kinds(), macro_kind) => {483 // Below we report various ambiguity errors.484 // We do not need to report them if we are either in speculative resolution,485 // or in late resolution when everything is already imported and expanded486 // and no ambiguities exist.487 let import = match finalize {488 None | Some(Finalize { stage: Stage::Late, .. }) => {489 return ControlFlow::Break(Ok(decl));490 }491 Some(Finalize { import, .. }) => import,492 };493 this.get_mut().maybe_push_glob_vs_glob_vis_ambiguity(494 ident,495 orig_ident_span,496 decl,497 import,498 );499500 if let Some(&(innermost_decl, _)) = innermost_results.first() {501 // Found another solution, if the first one was "weak", report an error.502 if this.get_mut().maybe_push_ambiguity(503 ident,504 orig_ident_span,505 ns,506 scope_set,507 parent_scope,508 decl,509 scope,510 &innermost_results,511 import,512 ) {513 // No need to search for more potential ambiguities, one is enough.514 return ControlFlow::Break(Ok(innermost_decl));515 }516 }517518 innermost_results.push((decl, scope));519 }520 Ok(_) | Err(Determinacy::Determined) => {}521 Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined,522 }523524 ControlFlow::Continue(())525 },526 );527528 // Scope visiting returned some result early.529 if let Some(break_result) = break_result {530 return break_result;531 }532533 // Scope visiting walked all the scopes and maybe found something in one of them.534 match innermost_results.first() {535 Some(&(decl, ..)) => Ok(decl),536 None => Err(determinacy),537 }538 }539540 fn resolve_ident_in_scope<'r>(541 mut self: CmResolver<'r, 'ra, 'tcx>,542 ident: IdentKey,543 orig_ident_span: Span,544 ns: Namespace,545 scope: Scope<'ra>,546 use_prelude: UsePrelude,547 scope_set: ScopeSet<'ra>,548 parent_scope: &ParentScope<'ra>,549 finalize: Option<Finalize>,550 ignore_decl: Option<Decl<'ra>>,551 ignore_import: Option<Import<'ra>>,552 ) -> Result<Decl<'ra>, ControlFlow<Determinacy, Determinacy>> {553 let ret = match scope {554 Scope::DeriveHelpers(expn_id) => {555 if let Some(decl) = self556 .helper_attrs557 .get(&expn_id)558 .and_then(|attrs| attrs.iter().rfind(|(i, ..)| ident == *i).map(|(.., d)| *d))559 {560 Ok(decl)561 } else {562 Err(Determinacy::Determined)563 }564 }565 Scope::DeriveHelpersCompat => {566 let mut result = Err(Determinacy::Determined);567 for derive in parent_scope.derives {568 let parent_scope = &ParentScope { derives: &[], ..*parent_scope };569 match self.reborrow().resolve_derive_macro_path(570 derive,571 parent_scope,572 false,573 ignore_import,574 ) {575 Ok((Some(ext), _)) => {576 if ext.helper_attrs.contains(&ident.name) {577 let decl = self.arenas.new_pub_def_decl(578 Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat),579 derive.span,580 LocalExpnId::ROOT,581 );582 result = Ok(decl);583 break;584 }585 }586 Ok(_) | Err(Determinacy::Determined) => {}587 Err(Determinacy::Undetermined) => result = Err(Determinacy::Undetermined),588 }589 }590 result591 }592 Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() {593 MacroRulesScope::Def(macro_rules_def) if ident == macro_rules_def.ident => {594 Ok(macro_rules_def.decl)595 }596 MacroRulesScope::Invocation(_) => Err(Determinacy::Undetermined),597 _ => Err(Determinacy::Determined),598 },599 Scope::ModuleNonGlobs(module, derive_fallback_lint_id) => {600 let (adjusted_parent_scope, adjusted_finalize) = if matches!(601 scope_set,602 ScopeSet::Module(..) | ScopeSet::ModuleAndExternPrelude(..)603 ) {604 (parent_scope, finalize)605 } else {606 (607 &ParentScope { module, ..*parent_scope },608 finalize.map(|f| Finalize { used: Used::Scope, ..f }),609 )610 };611 let decl = self.reborrow().resolve_ident_in_module_non_globs_unadjusted(612 module,613 ident,614 orig_ident_span,615 ns,616 adjusted_parent_scope,617 if matches!(scope_set, ScopeSet::Module(..)) {618 Shadowing::Unrestricted619 } else {620 Shadowing::Restricted621 },622 adjusted_finalize,623 ignore_decl,624 ignore_import,625 );626 match decl {627 Ok(decl) => {628 if let Some(lint_id) = derive_fallback_lint_id {629 self.get_mut().lint_buffer.buffer_lint(630 PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,631 lint_id,632 orig_ident_span,633 diagnostics::ProcMacroDeriveResolutionFallback {634 span: orig_ident_span,635 ns_descr: ns.descr(),636 ident: ident.name,637 },638 );639 }640 Ok(decl)641 }642 Err(ControlFlow::Continue(determinacy)) => Err(determinacy),643 Err(ControlFlow::Break(..)) => return decl,644 }645 }646 Scope::ModuleGlobs(module, _) if !module.is_local() => {647 // Fast path: external module decoding only creates non-glob declarations.648 Err(Determined)649 }650 Scope::ModuleGlobs(module, derive_fallback_lint_id) => {651 let (adjusted_parent_scope, adjusted_finalize) = if matches!(652 scope_set,653 ScopeSet::Module(..) | ScopeSet::ModuleAndExternPrelude(..)654 ) {655 (parent_scope, finalize)656 } else {657 (658 &ParentScope { module, ..*parent_scope },659 finalize.map(|f| Finalize { used: Used::Scope, ..f }),660 )661 };662 let binding = self.reborrow().resolve_ident_in_module_globs_unadjusted(663 module.expect_local(),664 ident,665 orig_ident_span,666 ns,667 adjusted_parent_scope,668 if matches!(scope_set, ScopeSet::Module(..)) {669 Shadowing::Unrestricted670 } else {671 Shadowing::Restricted672 },673 adjusted_finalize,674 ignore_decl,675 ignore_import,676 );677 match binding {678 Ok(binding) => {679 if let Some(lint_id) = derive_fallback_lint_id {680 self.get_mut().lint_buffer.buffer_lint(681 PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,682 lint_id,683 orig_ident_span,684 diagnostics::ProcMacroDeriveResolutionFallback {685 span: orig_ident_span,686 ns_descr: ns.descr(),687 ident: ident.name,688 },689 );690 }691 Ok(binding)692 }693 Err(ControlFlow::Continue(determinacy)) => Err(determinacy),694 Err(ControlFlow::Break(..)) => return binding,695 }696 }697 Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() {698 Some(decl) => Ok(decl),699 None => Err(Determinacy::determined(!self.graph_root.has_unexpanded_invocations())),700 },701 Scope::BuiltinAttrs => match self.builtin_attr_decls.get(&ident.name) {702 Some(decl) => Ok(*decl),703 None => Err(Determinacy::Determined),704 },705 Scope::ExternPreludeItems => {706 match self.reborrow().extern_prelude_get_item(707 ident,708 orig_ident_span,709 finalize.is_some(),710 ) {711 Some(decl) => Ok(decl),712 None => {713 Err(Determinacy::determined(!self.graph_root.has_unexpanded_invocations()))714 }715 }716 }717 Scope::ExternPreludeFlags => {718 match self.extern_prelude_get_flag(ident, orig_ident_span, finalize.is_some()) {719 Some(decl) => Ok(decl),720 None => Err(Determinacy::Determined),721 }722 }723 Scope::ToolPrelude => match self.registered_tool_decls.get(&ident) {724 Some(decl) => Ok(*decl),725 None => Err(Determinacy::Determined),726 },727 Scope::StdLibPrelude => {728 let mut result = Err(Determinacy::Determined);729 if let Some(prelude) = self.prelude730 && let Ok(decl) = self.reborrow().resolve_ident_in_scope_set_inner(731 ident,732 orig_ident_span,733 ScopeSet::Module(ns, prelude),734 parent_scope,735 None,736 ignore_decl,737 ignore_import,738 )739 && (matches!(use_prelude, UsePrelude::Yes) || self.is_builtin_macro(decl.res()))740 {741 result = Ok(decl)742 }743744 result745 }746 Scope::BuiltinTypes => match self.builtin_type_decls.get(&ident.name) {747 Some(decl) => {748 if matches!(ident.name, sym::f16)749 && !self.tcx.features().f16()750 && !orig_ident_span.allows_unstable(sym::f16)751 && finalize.is_some()752 {753 feature_err(754 self.tcx.sess,755 sym::f16,756 orig_ident_span,757 "the type `f16` is unstable",758 )759 .emit();760 }761 if matches!(ident.name, sym::f128)762 && !self.tcx.features().f128()763 && !orig_ident_span.allows_unstable(sym::f128)764 && finalize.is_some()765 {766 feature_err(767 self.tcx.sess,768 sym::f128,769 orig_ident_span,770 "the type `f128` is unstable",771 )772 .emit();773 }774 Ok(*decl)775 }776 None => Err(Determinacy::Determined),777 },778 };779780 ret.map_err(ControlFlow::Continue)781 }782783 fn maybe_push_glob_vs_glob_vis_ambiguity(784 &mut self,785 ident: IdentKey,786 orig_ident_span: Span,787 decl: Decl<'ra>,788 import: Option<ImportSummary>,789 ) {790 let Some(import) = import else { return };791 let vis1 = self.import_decl_vis(decl, import);792 let vis2 = self.import_decl_vis_ext(decl, import, true);793 if vis1 != vis2 {794 self.ambiguity_errors.push(AmbiguityError {795 kind: AmbiguityKind::GlobVsGlob,796 ambig_vis: Some((vis1, vis2)),797 ident: ident.orig(orig_ident_span),798 b1: decl.ambiguity_vis_max.get().unwrap_or(decl),799 b2: decl.ambiguity_vis_min.get().unwrap_or(decl),800 scope1: Scope::ModuleGlobs(decl.parent_module.unwrap(), None),801 scope2: Scope::ModuleGlobs(decl.parent_module.unwrap(), None),802 warning: Some(AmbiguityWarning::GlobImport),803 });804 }805 }806807 fn maybe_push_ambiguity(808 &mut self,809 ident: IdentKey,810 orig_ident_span: Span,811 ns: Namespace,812 scope_set: ScopeSet<'ra>,813 parent_scope: &ParentScope<'ra>,814 decl: Decl<'ra>,815 scope: Scope<'ra>,816 innermost_results: &[(Decl<'ra>, Scope<'ra>)],817 import: Option<ImportSummary>,818 ) -> bool {819 let (innermost_decl, innermost_scope) = innermost_results[0];820 let (res, innermost_res) = (decl.res(), innermost_decl.res());821 let ambig_vis = if res != innermost_res {822 None823 } else if let Some(import) = import824 && let vis1 = self.import_decl_vis(decl, import)825 && let vis2 = self.import_decl_vis(innermost_decl, import)826 && vis1 != vis2827 {828 Some((vis1, vis2))829 } else {830 return false;831 };832833 // FIXME: Use `scope` instead of `res` to detect built-in attrs and derive helpers,834 // it will exclude imports, make slightly more code legal, and will require lang approval.835 let module_only = matches!(scope_set, ScopeSet::Module(..));836 let is_builtin = |res| matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Builtin(..)));837 let derive_helper = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);838 let derive_helper_compat = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);839840 let ambiguity_error_kind = if is_builtin(innermost_res) || is_builtin(res) {841 Some(AmbiguityKind::BuiltinAttr)842 } else if innermost_res == derive_helper_compat {843 Some(AmbiguityKind::DeriveHelper)844 } else if res == derive_helper_compat && innermost_res != derive_helper {845 span_bug!(orig_ident_span, "impossible inner resolution kind")846 } else if matches!(innermost_scope, Scope::MacroRules(_))847 && matches!(scope, Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..))848 && !self.disambiguate_macro_rules_vs_modularized(innermost_decl, decl)849 {850 Some(AmbiguityKind::MacroRulesVsModularized)851 } else if matches!(scope, Scope::MacroRules(_))852 && matches!(innermost_scope, Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..))853 {854 // should be impossible because of visitation order in855 // visit_scopes856 //857 // we visit all macro_rules scopes (e.g. textual scope macros)858 // before we visit any modules (e.g. path-based scope macros)859 span_bug!(860 orig_ident_span,861 "ambiguous scoped macro resolutions with path-based \862 scope resolution as first candidate"863 )864 } else if innermost_decl.is_glob_import() {865 Some(AmbiguityKind::GlobVsOuter)866 } else if !module_only && innermost_decl.may_appear_after(parent_scope.expansion, decl) {867 Some(AmbiguityKind::MoreExpandedVsOuter)868 } else if innermost_decl.expansion != LocalExpnId::ROOT869 && (!module_only || ns == MacroNS)870 && let Scope::ModuleGlobs(m1, _) = scope871 && let Scope::ModuleNonGlobs(m2, _) = innermost_scope872 && m1 == m2873 {874 // FIXME: this error is too conservative and technically unnecessary now when module875 // scope is split into two scopes, at least when not resolving in `ScopeSet::Module`,876 // remove it with lang team approval.877 Some(AmbiguityKind::GlobVsExpanded)878 } else {879 None880 };881882 if let Some(kind) = ambiguity_error_kind {883 // Skip ambiguity errors for extern flag bindings "overridden"884 // by extern item bindings.885 // FIXME: Remove with lang team approval.886 let issue_145575_hack = matches!(scope, Scope::ExternPreludeFlags)887 && innermost_results[1..]888 .iter()889 .any(|(b, s)| matches!(s, Scope::ExternPreludeItems) && *b != innermost_decl);890 // Skip ambiguity errors for nonglob module bindings "overridden"891 // by glob module bindings in the same module.892 // FIXME: Remove with lang team approval.893 let issue_149681_hack = match scope {894 Scope::ModuleGlobs(m1, _)895 if innermost_results[1..]896 .iter()897 .any(|(_, s)| matches!(*s, Scope::ModuleNonGlobs(m2, _) if m1 == m2)) =>898 {899 true900 }901 _ => false,902 };903904 if issue_145575_hack || issue_149681_hack {905 self.issue_145575_hack_applied = true;906 } else {907 // Turn ambiguity errors for core vs std panic into warnings.908 // FIXME: Remove with lang team approval.909 let is_issue_147319_hack = orig_ident_span.edition() <= Edition::Edition2024910 && matches!(ident.name, sym::panic)911 && matches!(scope, Scope::StdLibPrelude)912 && matches!(innermost_scope, Scope::ModuleGlobs(_, _))913 && ((self.is_specific_builtin_macro(res, sym::std_panic)914 && self.is_specific_builtin_macro(innermost_res, sym::core_panic))915 || (self.is_specific_builtin_macro(res, sym::core_panic)916 && self.is_specific_builtin_macro(innermost_res, sym::std_panic)));917918 let warning = if ambig_vis.is_some() {919 Some(AmbiguityWarning::GlobImport)920 } else if is_issue_147319_hack {921 Some(AmbiguityWarning::PanicImport)922 } else {923 None924 };925926 self.ambiguity_errors.push(AmbiguityError {927 kind,928 ambig_vis,929 ident: ident.orig(orig_ident_span),930 b1: innermost_decl,931 b2: decl,932 scope1: innermost_scope,933 scope2: scope,934 warning,935 });936 return true;937 }938 }939940 false941 }942943 #[instrument(level = "debug", skip(self))]944 pub(crate) fn maybe_resolve_ident_in_module<'r>(945 self: CmResolver<'r, 'ra, 'tcx>,946 module: ModuleOrUniformRoot<'ra>,947 ident: Ident,948 ns: Namespace,949 parent_scope: &ParentScope<'ra>,950 ignore_import: Option<Import<'ra>>,951 ) -> Result<Decl<'ra>, Determinacy> {952 self.resolve_ident_in_module(module, ident, ns, parent_scope, None, None, ignore_import)953 }954955 fn resolve_super_in_module(956 &self,957 ident: Ident,958 module: Option<Module<'ra>>,959 parent_scope: &ParentScope<'ra>,960 ) -> Option<Module<'ra>> {961 let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();962 module963 .unwrap_or_else(|| self.resolve_self(&mut ctxt, parent_scope.module))964 .parent965 .map(|parent| self.resolve_self(&mut ctxt, parent))966 }967968 pub(crate) fn path_root_is_crate_root(&self, ident: Ident) -> bool {969 ident.name == kw::PathRoot && ident.span.is_rust_2015() && self.tcx.sess.is_rust_2015()970 }971972 #[instrument(level = "debug", skip(self))]973 pub(crate) fn resolve_ident_in_module<'r>(974 self: CmResolver<'r, 'ra, 'tcx>,975 module: ModuleOrUniformRoot<'ra>,976 ident: Ident,977 ns: Namespace,978 parent_scope: &ParentScope<'ra>,979 finalize: Option<Finalize>,980 ignore_decl: Option<Decl<'ra>>,981 ignore_import: Option<Import<'ra>>,982 ) -> Result<Decl<'ra>, Determinacy> {983 match module {984 ModuleOrUniformRoot::Module(module) => {985 if ns == TypeNS {986 if ident.name == kw::SelfLower {987 return Ok(module.self_decl.unwrap());988 }989 if ident.name == kw::Super990 && let Some(module) =991 self.resolve_super_in_module(ident, Some(module), parent_scope)992 {993 return Ok(module.self_decl.unwrap());994 }995 }996997 let (ident_key, def) = IdentKey::new_adjusted(ident, module.expansion);998 let adjusted_parent_scope = match def {999 Some(def) => ParentScope { module: self.expn_def_scope(def), ..*parent_scope },1000 None => *parent_scope,1001 };1002 self.resolve_ident_in_scope_set_inner(1003 ident_key,1004 ident.span,1005 ScopeSet::Module(ns, module),1006 &adjusted_parent_scope,1007 finalize,1008 ignore_decl,1009 ignore_import,1010 )1011 }1012 ModuleOrUniformRoot::OpenModule(sym) => {1013 let open_ns_name = format!("{}::{}", sym.as_str(), ident.name);1014 let ns_ident = IdentKey::with_root_ctxt(Symbol::intern(&open_ns_name));1015 match self.extern_prelude_get_flag(ns_ident, ident.span, finalize.is_some()) {1016 Some(decl) => Ok(decl),1017 None => Err(Determinacy::Determined),1018 }1019 }1020 ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set(1021 ident,1022 ScopeSet::ModuleAndExternPrelude(ns, module),1023 parent_scope,1024 finalize,1025 ignore_decl,1026 ignore_import,1027 ),1028 ModuleOrUniformRoot::ExternPrelude => {1029 if ns != TypeNS {1030 Err(Determined)1031 } else {1032 self.resolve_ident_in_scope_set_inner(1033 IdentKey::new_adjusted(ident, ExpnId::root()).0,1034 ident.span,1035 ScopeSet::ExternPrelude,1036 parent_scope,1037 finalize,1038 ignore_decl,1039 ignore_import,1040 )1041 }1042 }1043 ModuleOrUniformRoot::CurrentScope => {1044 if ns == TypeNS {1045 if ident.name == kw::SelfLower {1046 let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();1047 let module = self.resolve_self(&mut ctxt, parent_scope.module);1048 return Ok(module.self_decl.unwrap());1049 }1050 if ident.name == kw::Super1051 && let Some(module) =1052 self.resolve_super_in_module(ident, None, parent_scope)1053 {1054 return Ok(module.self_decl.unwrap());1055 }1056 if ident.name == kw::Crate1057 || ident.name == kw::DollarCrate1058 || self.path_root_is_crate_root(ident)1059 {1060 let module = self.resolve_crate_root(ident);1061 return Ok(module.self_decl.unwrap());1062 } else if ident.name == kw::Super {1063 // FIXME: Implement these with renaming requirements so that e.g.1064 // `use super;` doesn't work, but `use super as name;` does.1065 // Fall through here to get an error from `early_resolve_...`.1066 }1067 }10681069 self.resolve_ident_in_scope_set(1070 ident,1071 ScopeSet::All(ns),1072 parent_scope,1073 finalize,1074 ignore_decl,1075 ignore_import,1076 )1077 }1078 }1079 }10801081 /// Attempts to resolve `ident` in namespace `ns` of non-glob bindings in `module`.1082 fn resolve_ident_in_module_non_globs_unadjusted<'r>(1083 mut self: CmResolver<'r, 'ra, 'tcx>,1084 module: Module<'ra>,1085 ident: IdentKey,1086 orig_ident_span: Span,1087 ns: Namespace,1088 parent_scope: &ParentScope<'ra>,1089 shadowing: Shadowing,1090 finalize: Option<Finalize>,1091 // This binding should be ignored during in-module resolution, so that we don't get1092 // "self-confirming" import resolutions during import validation and checking.1093 ignore_decl: Option<Decl<'ra>>,1094 ignore_import: Option<Import<'ra>>,1095 ) -> Result<Decl<'ra>, ControlFlow<Determinacy, Determinacy>> {1096 let key = BindingKey::new(ident, ns);1097 // `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding1098 // doesn't need to be mutable. It will fail when there is a cycle of imports, and without1099 // the exclusive access infinite recursion will crash the compiler with stack overflow.1100 let resolution = &*self1101 .resolution_or_default(module, key, orig_ident_span)1102 .try_borrow_mut_unchecked()1103 .map_err(|_| ControlFlow::Continue(Determined))?;11041105 let binding = resolution.non_glob_decl.filter(|b| Some(*b) != ignore_decl);11061107 if let Some(finalize) = finalize {1108 return self.get_mut().finalize_module_binding(1109 ident,1110 orig_ident_span,1111 binding,1112 parent_scope,1113 finalize,1114 shadowing,1115 );1116 }11171118 // Items and single imports are not shadowable, if we have one, then it's determined.1119 if let Some(binding) = binding {1120 let accessible = self.is_accessible_from(binding.vis(), parent_scope.module);1121 return if accessible { Ok(binding) } else { Err(ControlFlow::Break(Determined)) };1122 }11231124 // In extern modules everything is determined from the start.1125 if !module.is_local() {1126 return Err(ControlFlow::Continue(Determined));1127 };11281129 // Check if one of single imports can still define the name, block if it can.1130 if self.reborrow().single_import_can_define_name(1131 &resolution,1132 None,1133 ns,1134 ignore_import,1135 ignore_decl,1136 parent_scope,1137 ) {1138 return Err(ControlFlow::Break(Undetermined));1139 }11401141 // Check if one of unexpanded macros can still define the name.1142 if module.has_unexpanded_invocations() {1143 return Err(ControlFlow::Continue(Undetermined));1144 }11451146 // No resolution and no one else can define the name - determinate error.1147 Err(ControlFlow::Continue(Determined))1148 }11491150 /// Attempts to resolve `ident` in namespace `ns` of glob bindings in `module`.1151 fn resolve_ident_in_module_globs_unadjusted<'r>(1152 mut self: CmResolver<'r, 'ra, 'tcx>,1153 module: LocalModule<'ra>,1154 ident: IdentKey,1155 orig_ident_span: Span,1156 ns: Namespace,1157 parent_scope: &ParentScope<'ra>,1158 shadowing: Shadowing,1159 finalize: Option<Finalize>,1160 ignore_decl: Option<Decl<'ra>>,1161 ignore_import: Option<Import<'ra>>,1162 ) -> Result<Decl<'ra>, ControlFlow<Determinacy, Determinacy>> {1163 let key = BindingKey::new(ident, ns);1164 // `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding1165 // doesn't need to be mutable. It will fail when there is a cycle of imports, and without1166 // the exclusive access infinite recursion will crash the compiler with stack overflow.1167 let resolution = &*self1168 .resolution_or_default(module.to_module(), key, orig_ident_span)1169 .try_borrow_mut_unchecked()1170 .map_err(|_| ControlFlow::Continue(Determined))?;11711172 let binding = resolution.glob_decl.filter(|b| Some(*b) != ignore_decl);11731174 if let Some(finalize) = finalize {1175 return self.get_mut().finalize_module_binding(1176 ident,1177 orig_ident_span,1178 binding,1179 parent_scope,1180 finalize,1181 shadowing,1182 );1183 }11841185 // Check if one of single imports can still define the name,1186 // if it can then our result is not determined and can be invalidated.1187 if self.reborrow().single_import_can_define_name(1188 &resolution,1189 binding,1190 ns,1191 ignore_import,1192 ignore_decl,1193 parent_scope,1194 ) {1195 return Err(ControlFlow::Break(Undetermined));1196 }11971198 // So we have a resolution that's from a glob import. This resolution is determined1199 // if it cannot be shadowed by some new item/import expanded from a macro.1200 // This happens either if there are no unexpanded macros, or expanded names cannot1201 // shadow globs (that happens in macro namespace or with restricted shadowing).1202 //1203 // Additionally, any macro in any module can plant names in the root module if it creates1204 // `macro_export` macros, so the root module effectively has unresolved invocations if any1205 // module has unresolved invocations.1206 // However, it causes resolution/expansion to stuck too often (#53144), so, to make1207 // progress, we have to ignore those potential unresolved invocations from other modules1208 // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted1209 // shadowing is enabled, see `macro_expanded_macro_export_errors`).1210 if let Some(binding) = binding {1211 return if binding.determined() || ns == MacroNS || shadowing == Shadowing::Restricted {1212 let accessible = self.is_accessible_from(binding.vis(), parent_scope.module);1213 if accessible { Ok(binding) } else { Err(ControlFlow::Break(Determined)) }1214 } else {1215 Err(ControlFlow::Break(Undetermined))1216 };1217 }12181219 // Now we are in situation when new item/import can appear only from a glob or a macro1220 // expansion. With restricted shadowing names from globs and macro expansions cannot1221 // shadow names from outer scopes, so we can freely fallback from module search to search1222 // in outer scopes. For `resolve_ident_in_scope_set` to continue search in outer1223 // scopes we return `Undetermined` with `ControlFlow::Continue`.1224 // Check if one of unexpanded macros can still define the name,1225 // if it can then our "no resolution" result is not determined and can be invalidated.1226 if module.has_unexpanded_invocations() {1227 return Err(ControlFlow::Continue(Undetermined));1228 }12291230 // Check if one of glob imports can still define the name,1231 // if it can then our "no resolution" result is not determined and can be invalidated.1232 for glob_import in module.globs.borrow().iter() {1233 if ignore_import == Some(*glob_import) {1234 continue;1235 }1236 if !self.is_accessible_from(glob_import.vis, parent_scope.module) {1237 continue;1238 }1239 let module = match glob_import.imported_module.get() {1240 Some(ModuleOrUniformRoot::Module(module)) => module,1241 Some(_) => continue,1242 None => return Err(ControlFlow::Continue(Undetermined)),1243 };1244 let tmp_parent_scope;1245 let (mut adjusted_parent_scope, mut adjusted_ident) = (parent_scope, ident);1246 match adjusted_ident1247 .ctxt1248 .update_unchecked(|ctxt| ctxt.glob_adjust(module.expansion, glob_import.span))1249 {1250 Some(Some(def)) => {1251 tmp_parent_scope =1252 ParentScope { module: self.expn_def_scope(def), ..*parent_scope };1253 adjusted_parent_scope = &tmp_parent_scope;1254 }1255 Some(None) => {}1256 None => continue,1257 };1258 let result = self.reborrow().resolve_ident_in_scope_set_inner(1259 adjusted_ident,1260 orig_ident_span,1261 ScopeSet::Module(ns, module),1262 adjusted_parent_scope,1263 None,1264 ignore_decl,1265 ignore_import,1266 );12671268 match result {1269 Err(Determined) => continue,1270 Ok(binding)1271 if !self.is_accessible_from(binding.vis(), glob_import.parent_scope.module) =>1272 {1273 continue;1274 }1275 Ok(_) | Err(Undetermined) => return Err(ControlFlow::Continue(Undetermined)),1276 }1277 }12781279 // No resolution and no one else can define the name - determinate error.1280 Err(ControlFlow::Continue(Determined))1281 }12821283 fn finalize_module_binding(1284 &mut self,1285 ident: IdentKey,1286 orig_ident_span: Span,1287 binding: Option<Decl<'ra>>,1288 parent_scope: &ParentScope<'ra>,1289 finalize: Finalize,1290 shadowing: Shadowing,1291 ) -> Result<Decl<'ra>, ControlFlow<Determinacy, Determinacy>> {1292 let Finalize { path_span, report_private, used, root_span, .. } = finalize;12931294 let Some(binding) = binding else {1295 return Err(ControlFlow::Continue(Determined));1296 };12971298 let ident = ident.orig(orig_ident_span);1299 if !self.is_accessible_from(binding.vis(), parent_scope.module) {1300 if report_private {1301 self.privacy_errors.push(PrivacyError {1302 ident,1303 decl: binding,1304 dedup_span: path_span,1305 outermost_res: None,1306 source: None,1307 parent_scope: *parent_scope,1308 single_nested: path_span != root_span,1309 });1310 } else {1311 return Err(ControlFlow::Break(Determined));1312 }1313 }13141315 if shadowing == Shadowing::Unrestricted1316 && binding.expansion != LocalExpnId::ROOT1317 && let DeclKind::Import { import, .. } = binding.kind1318 && matches!(import.kind, ImportKind::MacroExport)1319 {1320 self.macro_expanded_macro_export_errors.insert((path_span, binding.span));1321 }13221323 self.record_use(ident, binding, used);1324 return Ok(binding);1325 }13261327 // Checks if a single import can define the `Ident` corresponding to `binding`.1328 // This is used to check whether we can definitively accept a glob as a resolution.1329 fn single_import_can_define_name<'r>(1330 mut self: CmResolver<'r, 'ra, 'tcx>,1331 resolution: &NameResolution<'ra>,1332 binding: Option<Decl<'ra>>,1333 ns: Namespace,1334 ignore_import: Option<Import<'ra>>,1335 ignore_decl: Option<Decl<'ra>>,1336 parent_scope: &ParentScope<'ra>,1337 ) -> bool {1338 for single_import in &resolution.single_imports {1339 if let Some(decl) = resolution.non_glob_decl1340 && let DeclKind::Import { import, .. } = decl.kind1341 && import == *single_import1342 {1343 // Single import has already defined the name and we are aware of it,1344 // no need to block the globs.1345 continue;1346 }1347 if ignore_import == Some(*single_import) {1348 continue;1349 }1350 if !self.is_accessible_from(single_import.vis, parent_scope.module) {1351 continue;1352 }1353 if let Some(ignored) = ignore_decl1354 && let DeclKind::Import { import, .. } = ignored.kind1355 && import == *single_import1356 {1357 continue;1358 }13591360 let Some(module) = single_import.imported_module.get() else {1361 return true;1362 };1363 let ImportKind::Single { source, target, decls, .. } = &single_import.kind else {1364 unreachable!();1365 };1366 if source != target {1367 if decls.iter().all(|d| d.get().decl().is_none()) {1368 return true;1369 } else if decls[ns].get().decl().is_none() && binding.is_some() {1370 return true;1371 }1372 }13731374 match self.reborrow().resolve_ident_in_module(1375 module,1376 *source,1377 ns,1378 &single_import.parent_scope,1379 None,1380 ignore_decl,1381 None,1382 ) {1383 Err(Determined) => continue,1384 Ok(binding)1385 if !self1386 .is_accessible_from(binding.vis(), single_import.parent_scope.module) =>1387 {1388 continue;1389 }1390 Ok(_) | Err(Undetermined) => return true,1391 }1392 }13931394 false1395 }13961397 /// Validate a local resolution (from ribs).1398 #[instrument(level = "debug", skip(self, all_ribs))]1399 fn validate_res_from_ribs(1400 &mut self,1401 rib_index: usize,1402 rib_ident: Ident,1403 res: Res,1404 finalize: Option<Span>,1405 original_rib_ident_def: Ident,1406 all_ribs: &[Rib<'ra>],1407 diag_metadata: Option<&DiagMetadata<'_>>,1408 ) -> Res {1409 debug!("validate_res_from_ribs({:?})", res);1410 let ribs = &all_ribs[rib_index + 1..];14111412 // An invalid forward use of a generic parameter from a previous default1413 // or in a const param ty.1414 if let RibKind::ForwardGenericParamBan(reason) = all_ribs[rib_index].kind {1415 if let Some(span) = finalize {1416 let res_error = if rib_ident.name == kw::SelfUpper {1417 ResolutionError::ForwardDeclaredSelf(reason)1418 } else {1419 ResolutionError::ForwardDeclaredGenericParam(rib_ident.name, reason)1420 };1421 self.report_error(span, res_error);1422 }1423 assert_eq!(res, Res::Err);1424 return Res::Err;1425 }14261427 match res {1428 Res::Local(_) => {1429 use ResolutionError::*;1430 let mut res_err = None;14311432 for rib in ribs {1433 match rib.kind {1434 RibKind::Normal1435 | RibKind::Block(..)1436 | RibKind::FnOrCoroutine1437 | RibKind::Module(..)1438 | RibKind::MacroDefinition(..)1439 | RibKind::ForwardGenericParamBan(_) => {1440 // Nothing to do. Continue.1441 }1442 RibKind::Item(..) | RibKind::AssocItem => {1443 // This was an attempt to access an upvar inside a1444 // named function item. This is not allowed, so we1445 // report an error.1446 if let Some(span) = finalize {1447 // We don't immediately trigger a resolve error, because1448 // we want certain other resolution errors (namely those1449 // emitted for `ConstantItemRibKind` below) to take1450 // precedence.1451 res_err = Some((span, CannotCaptureDynamicEnvironmentInFnItem));1452 }1453 }1454 RibKind::ConstantItem(_, item) => {1455 // Still doesn't deal with upvars1456 if let Some(span) = finalize {1457 let (span, resolution_error) = match item {1458 None if rib_ident.name == kw::SelfLower => {1459 (span, LowercaseSelf)1460 }1461 None => {1462 // If we have a `let name = expr;`, we have the span for1463 // `name` and use that to see if it is followed by a type1464 // specifier. If not, then we know we need to suggest1465 // `const name: Ty = expr;`. This is a heuristic, it will1466 // break down in the presence of macros.1467 let sm = self.tcx.sess.source_map();1468 let type_span = match sm1469 .span_followed_by(original_rib_ident_def.span, ":")1470 {1471 None => {1472 Some(original_rib_ident_def.span.shrink_to_hi())1473 }1474 Some(_) => None,1475 };1476 (1477 rib_ident.span,1478 AttemptToUseNonConstantValueInConstant {1479 ident: original_rib_ident_def,1480 suggestion: "const",1481 current: "let",1482 type_span,1483 },1484 )1485 }1486 Some((ident, kind)) => (1487 span,1488 AttemptToUseNonConstantValueInConstant {1489 ident,1490 suggestion: "let",1491 current: kind.as_str(),1492 type_span: None,1493 },1494 ),1495 };1496 self.report_error(span, resolution_error);1497 }1498 return Res::Err;1499 }1500 RibKind::ConstParamTy => {1501 if let Some(span) = finalize {1502 self.report_error(1503 span,1504 ParamInTyOfConstParam { name: rib_ident.name },1505 );1506 }1507 return Res::Err;1508 }1509 RibKind::InlineAsmSym => {1510 if let Some(span) = finalize {1511 self.report_error(span, InvalidAsmSym);1512 }1513 return Res::Err;1514 }1515 }1516 }1517 if let Some((span, res_err)) = res_err {1518 self.report_error(span, res_err);1519 return Res::Err;1520 }1521 }1522 Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {1523 for rib in ribs {1524 let (has_generic_params, def_kind) = match rib.kind {1525 RibKind::Normal1526 | RibKind::Block(..)1527 | RibKind::FnOrCoroutine1528 | RibKind::Module(..)1529 | RibKind::MacroDefinition(..)1530 | RibKind::InlineAsmSym1531 | RibKind::AssocItem1532 | RibKind::ForwardGenericParamBan(_) => {1533 // Nothing to do. Continue.1534 continue;1535 }15361537 RibKind::ConstParamTy => {1538 if !self.tcx.features().generic_const_parameter_types() {1539 if let Some(span) = finalize {1540 self.report_error(1541 span,1542 ResolutionError::ParamInTyOfConstParam {1543 name: rib_ident.name,1544 },1545 );1546 }1547 return Res::Err;1548 } else {1549 continue;1550 }1551 }15521553 RibKind::ConstantItem(trivial, _) => {1554 if let ConstantHasGenerics::No(cause) = trivial1555 && !matches!(res, Res::SelfTyAlias { .. })1556 {1557 if let Some(span) = finalize {1558 let error = match cause {1559 NoConstantGenericsReason::IsEnumDiscriminant => {1560 ResolutionError::ParamInEnumDiscriminant {1561 name: rib_ident.name,1562 param_kind: ParamKindInEnumDiscriminant::Type,1563 }1564 }1565 NoConstantGenericsReason::NonTrivialConstArg => {1566 ResolutionError::ParamInNonTrivialAnonConst {1567 is_gca: self.tcx.features().generic_const_args(),1568 name: rib_ident.name,1569 param_kind: ParamKindInNonTrivialAnonConst::Type,1570 }1571 }1572 };1573 let _: ErrorGuaranteed = self.report_error(span, error);1574 }15751576 return Res::Err;1577 }15781579 continue;1580 }15811582 // This was an attempt to use a type parameter outside its scope.1583 RibKind::Item(has_generic_params, def_kind) => {1584 (has_generic_params, def_kind)1585 }1586 };15871588 if let Some(span) = finalize {1589 let item = if let Some(diag_metadata) = diag_metadata1590 && let Some(current_item) = diag_metadata.current_item1591 {1592 let label_span = current_item1593 .kind1594 .ident()1595 .map(|i| i.span)1596 .unwrap_or(current_item.span);1597 Some((label_span, current_item.span, current_item.kind.clone()))1598 } else {1599 None1600 };1601 self.report_error(1602 span,1603 ResolutionError::GenericParamsFromOuterItem {1604 outer_res: res,1605 has_generic_params,1606 def_kind,1607 inner_item: item,1608 current_self_ty: diag_metadata1609 .and_then(|m| m.current_self_type.as_ref())1610 .and_then(|ty| {1611 self.tcx.sess.source_map().span_to_snippet(ty.span).ok()1612 }),1613 },1614 );1615 }1616 return Res::Err;1617 }1618 }1619 Res::Def(DefKind::ConstParam, _) => {1620 for rib in ribs {1621 let (has_generic_params, def_kind) = match rib.kind {1622 RibKind::Normal1623 | RibKind::Block(..)1624 | RibKind::FnOrCoroutine1625 | RibKind::Module(..)1626 | RibKind::MacroDefinition(..)1627 | RibKind::InlineAsmSym1628 | RibKind::AssocItem1629 | RibKind::ForwardGenericParamBan(_) => continue,16301631 RibKind::ConstParamTy => {1632 if !self.tcx.features().generic_const_parameter_types() {1633 if let Some(span) = finalize {1634 self.report_error(1635 span,1636 ResolutionError::ParamInTyOfConstParam {1637 name: rib_ident.name,1638 },1639 );1640 }1641 return Res::Err;1642 } else {1643 continue;1644 }1645 }16461647 RibKind::ConstantItem(trivial, _) => {1648 if let ConstantHasGenerics::No(cause) = trivial {1649 if let Some(span) = finalize {1650 let error = match cause {1651 NoConstantGenericsReason::IsEnumDiscriminant => {1652 ResolutionError::ParamInEnumDiscriminant {1653 name: rib_ident.name,1654 param_kind: ParamKindInEnumDiscriminant::Const,1655 }1656 }1657 NoConstantGenericsReason::NonTrivialConstArg => {1658 ResolutionError::ParamInNonTrivialAnonConst {1659 is_gca: self.tcx.features().generic_const_args(),1660 name: rib_ident.name,1661 param_kind: ParamKindInNonTrivialAnonConst::Const {1662 name: rib_ident.name,1663 },1664 }1665 }1666 };1667 self.report_error(span, error);1668 }16691670 return Res::Err;1671 }16721673 continue;1674 }16751676 RibKind::Item(has_generic_params, def_kind) => {1677 (has_generic_params, def_kind)1678 }1679 };16801681 // This was an attempt to use a const parameter outside its scope.1682 if let Some(span) = finalize {1683 let item = if let Some(diag_metadata) = diag_metadata1684 && let Some(current_item) = diag_metadata.current_item1685 {1686 let label_span = current_item1687 .kind1688 .ident()1689 .map(|i| i.span)1690 .unwrap_or(current_item.span);1691 Some((label_span, current_item.span, current_item.kind.clone()))1692 } else {1693 None1694 };1695 self.report_error(1696 span,1697 ResolutionError::GenericParamsFromOuterItem {1698 outer_res: res,1699 has_generic_params,1700 def_kind,1701 inner_item: item,1702 current_self_ty: diag_metadata1703 .and_then(|m| m.current_self_type.as_ref())1704 .and_then(|ty| {1705 self.tcx.sess.source_map().span_to_snippet(ty.span).ok()1706 }),1707 },1708 );1709 }1710 return Res::Err;1711 }1712 }1713 _ => {}1714 }17151716 res1717 }17181719 #[instrument(level = "debug", skip(self))]1720 pub(crate) fn maybe_resolve_path<'r>(1721 self: CmResolver<'r, 'ra, 'tcx>,1722 path: &[Segment],1723 opt_ns: Option<Namespace>, // `None` indicates a module path in import1724 parent_scope: &ParentScope<'ra>,1725 ignore_import: Option<Import<'ra>>,1726 ) -> PathResult<'ra> {1727 self.resolve_path_with_ribs(1728 path,1729 opt_ns,1730 parent_scope,1731 None,1732 None,1733 None,1734 None,1735 ignore_import,1736 None,1737 )1738 }1739 #[instrument(level = "debug", skip(self))]1740 pub(crate) fn resolve_path<'r>(1741 self: CmResolver<'r, 'ra, 'tcx>,1742 path: &[Segment],1743 opt_ns: Option<Namespace>, // `None` indicates a module path in import1744 parent_scope: &ParentScope<'ra>,1745 finalize: Option<Finalize>,1746 ignore_decl: Option<Decl<'ra>>,1747 ignore_import: Option<Import<'ra>>,1748 ) -> PathResult<'ra> {1749 self.resolve_path_with_ribs(1750 path,1751 opt_ns,1752 parent_scope,1753 None,1754 finalize,1755 None,1756 ignore_decl,1757 ignore_import,1758 None,1759 )1760 }17611762 pub(crate) fn resolve_path_with_ribs<'r>(1763 mut self: CmResolver<'r, 'ra, 'tcx>,1764 path: &[Segment],1765 opt_ns: Option<Namespace>, // `None` indicates a module path in import1766 parent_scope: &ParentScope<'ra>,1767 source: Option<PathSource<'_, '_, '_>>,1768 finalize: Option<Finalize>,1769 ribs: Option<&PerNS<Vec<Rib<'ra>>>>,1770 ignore_decl: Option<Decl<'ra>>,1771 ignore_import: Option<Import<'ra>>,1772 diag_metadata: Option<&DiagMetadata<'_>>,1773 ) -> PathResult<'ra> {1774 let mut module = None;1775 let mut module_had_parse_errors = !self.mods_with_parse_errors.is_empty()1776 && self.mods_with_parse_errors.contains(&parent_scope.module.nearest_parent_mod());1777 let mut allow_super = true;1778 let mut second_binding = None;17791780 // We'll provide more context to the privacy errors later, up to `len`.1781 let privacy_errors_len = self.privacy_errors.len();1782 fn record_segment_res<'r, 'ra, 'tcx>(1783 mut this: CmResolver<'r, 'ra, 'tcx>,1784 finalize: Option<Finalize>,1785 res: Res,1786 id: Option<NodeId>,1787 ) {1788 if finalize.is_some()1789 && let Some(id) = id1790 && !this.partial_res_map.contains_key(&id)1791 {1792 assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id");1793 this.get_mut().record_partial_res(id, PartialRes::new(res));1794 }1795 }17961797 for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() {1798 debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id);17991800 let is_last = segment_idx + 1 == path.len();1801 let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };1802 let name = ident.name;18031804 allow_super &= ns == TypeNS && (name == kw::SelfLower || name == kw::Super);18051806 if ns == TypeNS {1807 if allow_super && name == kw::Super {1808 let parent = if segment_idx == 0 {1809 self.resolve_super_in_module(ident, None, parent_scope)1810 } else if let Some(ModuleOrUniformRoot::Module(module)) = module {1811 self.resolve_super_in_module(ident, Some(module), parent_scope)1812 } else {1813 None1814 };1815 if let Some(parent) = parent {1816 module = Some(ModuleOrUniformRoot::Module(parent));1817 continue;1818 }1819 return PathResult::failed(1820 ident,1821 false,1822 finalize.is_some(),1823 module_had_parse_errors,1824 module,1825 || {1826 (1827 "too many leading `super` keywords".to_string(),1828 "there are too many leading `super` keywords".to_string(),1829 None,1830 None,1831 )1832 },1833 );1834 }1835 if segment_idx == 0 {1836 if name == kw::SelfLower {1837 let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();1838 let self_mod = self.resolve_self(&mut ctxt, parent_scope.module);1839 if let Some(res) = self_mod.res() {1840 record_segment_res(self.reborrow(), finalize, res, id);1841 }1842 module = Some(ModuleOrUniformRoot::Module(self_mod));1843 continue;1844 }1845 if name == kw::PathRoot && ident.span.at_least_rust_2018() {1846 module = Some(ModuleOrUniformRoot::ExternPrelude);1847 continue;1848 }1849 if name == kw::PathRoot1850 && ident.span.is_rust_2015()1851 && self.tcx.sess.at_least_rust_2018()1852 {1853 // `::a::b` from 2015 macro on 2018 global edition1854 let crate_root = self.resolve_crate_root(ident);1855 module = Some(ModuleOrUniformRoot::ModuleAndExternPrelude(crate_root));1856 continue;1857 }1858 if name == kw::PathRoot || name == kw::Crate || name == kw::DollarCrate {1859 // `::a::b`, `crate::a::b` or `$crate::a::b`1860 let crate_root = self.resolve_crate_root(ident);1861 if let Some(res) = crate_root.res() {1862 record_segment_res(self.reborrow(), finalize, res, id);1863 }1864 module = Some(ModuleOrUniformRoot::Module(crate_root));1865 continue;1866 }1867 }1868 }18691870 let allow_trailing_self = is_last && name == kw::SelfLower;18711872 // Report special messages for path segment keywords in wrong positions.1873 if ident.is_path_segment_keyword() && segment_idx != 0 && !allow_trailing_self {1874 return PathResult::failed(1875 ident,1876 false,1877 finalize.is_some(),1878 module_had_parse_errors,1879 module,1880 || {1881 let name_str = if name == kw::PathRoot {1882 "the crate root".to_string()1883 } else {1884 format!("`{name}`")1885 };1886 let (message, label) = if segment_idx == 11887 && path[0].ident.name == kw::PathRoot1888 {1889 (1890 format!("global paths cannot start with {name_str}"),1891 "cannot start with this".to_string(),1892 )1893 } else if name == kw::SelfLower {1894 (1895 format!(1896 "`self` in paths can only be used in start position or last position"1897 ),1898 "can only be used in path start position or last position"1899 .to_string(),1900 )1901 } else {1902 (1903 format!("{name_str} in paths can only be used in start position"),1904 "can only be used in path start position".to_string(),1905 )1906 };1907 (message, label, None, None)1908 },1909 );1910 }19111912 let binding = if let Some(module) = module {1913 self.reborrow().resolve_ident_in_module(1914 module,1915 ident,1916 ns,1917 parent_scope,1918 finalize,1919 ignore_decl,1920 ignore_import,1921 )1922 } else if let Some(ribs) = ribs1923 && let Some(TypeNS | ValueNS) = opt_ns1924 {1925 assert!(ignore_import.is_none());1926 match self.get_mut().resolve_ident_in_lexical_scope(1927 ident,1928 ns,1929 parent_scope,1930 finalize,1931 &ribs[ns],1932 ignore_decl,1933 diag_metadata,1934 ) {1935 // we found a locally-imported or available item/module1936 Some(LateDecl::Decl(binding)) => Ok(binding),1937 // we found a local variable or type param1938 Some(LateDecl::RibDef(res)) => {1939 record_segment_res(self.reborrow(), finalize, res, id);1940 return PathResult::NonModule(PartialRes::with_unresolved_segments(1941 res,1942 path.len() - 1,1943 ));1944 }1945 _ => Err(Determinacy::determined(finalize.is_some())),1946 }1947 } else {1948 self.reborrow().resolve_ident_in_scope_set(1949 ident,1950 ScopeSet::All(ns),1951 parent_scope,1952 finalize,1953 ignore_decl,1954 ignore_import,1955 )1956 };19571958 match binding {1959 Ok(binding) => {1960 if segment_idx == 1 {1961 second_binding = Some(binding);1962 }1963 let res = binding.res();19641965 // Mark every privacy error in this path with the res to the last element. This allows us1966 // to detect the item the user cares about and either find an alternative import, or tell1967 // the user it is not accessible.1968 if finalize.is_some() {1969 for error in &mut self.get_mut().privacy_errors[privacy_errors_len..] {1970 error.outermost_res = Some((res, ident));1971 error.source = match source {1972 Some(PathSource::Struct(Some(expr)))1973 | Some(PathSource::Expr(Some(expr))) => Some(expr.clone()),1974 _ => None,1975 };1976 }1977 }19781979 let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);1980 if let Res::OpenMod(sym) = binding.res() {1981 module = Some(ModuleOrUniformRoot::OpenModule(sym));1982 record_segment_res(self.reborrow(), finalize, res, id);1983 } else if let Some(def_id) = binding.res().module_like_def_id() {1984 if self.mods_with_parse_errors.contains(&def_id) {1985 module_had_parse_errors = true;1986 }1987 module = Some(ModuleOrUniformRoot::Module(self.expect_module(def_id)));1988 record_segment_res(self.reborrow(), finalize, res, id);1989 } else if res == Res::ToolMod && !is_last && opt_ns.is_some() {1990 if binding.is_import() {1991 self.dcx().emit_err(diagnostics::ToolModuleImported {1992 span: ident.span,1993 import: binding.span,1994 });1995 }1996 let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);1997 return PathResult::NonModule(PartialRes::new(res));1998 } else if res == Res::Err {1999 return PathResult::NonModule(PartialRes::new(Res::Err));2000 } else if opt_ns.is_some() && (is_last || maybe_assoc) {
Findings
✓ No findings reported for this file.