Skip to main content

rustc_resolve/
macros.rs

1//! A bunch of methods and structures more or less related to resolving macros and
2//! interface provided by `Resolver` to macro expander.
3
4use std::mem;
5use std::sync::Arc;
6
7use rustc_ast::{self as ast, Crate, DelegationSuffixes, NodeId};
8use rustc_ast_pretty::pprust;
9use rustc_attr_parsing::AttributeParser;
10use rustc_errors::{Applicability, DiagCtxtHandle, StashKey};
11use rustc_expand::base::{
12    Annotatable, DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension,
13    SyntaxExtensionKind,
14};
15use rustc_expand::compile_declarative_macro;
16use rustc_expand::expand::{
17    AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion,
18};
19use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem};
20use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind};
21use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
22use rustc_hir::{Attribute, StabilityLevel};
23use rustc_middle::middle::stability;
24use rustc_middle::ty::{RegisteredTools, TyCtxt};
25use rustc_session::Session;
26use rustc_session::lint::builtin::{
27    LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, UNKNOWN_DIAGNOSTIC_ATTRIBUTES,
28    UNUSED_MACRO_RULES, UNUSED_MACROS,
29};
30use rustc_session::parse::feature_err;
31use rustc_span::edit_distance::find_best_match_for_name;
32use rustc_span::edition::Edition;
33use rustc_span::hygiene::{self, AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
34use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
35
36use crate::Namespace::*;
37use crate::def_collector::collect_definitions;
38use crate::errors::{
39    self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope,
40    MacroExpectedFound, RemoveSurroundingDerive,
41};
42use crate::hygiene::Macros20NormalizedSyntaxContext;
43use crate::imports::Import;
44use crate::{
45    BindingKey, CacheCell, CmResolver, Decl, DeclKind, DeriveData, Determinacy, Finalize, IdentKey,
46    InvocationParent, MacroData, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Res,
47    ResolutionError, Resolver, ScopeSet, Segment, Used,
48};
49
50/// Name declaration produced by a `macro_rules` item definition.
51/// Not modularized, can shadow previous `macro_rules` definitions, etc.
52#[derive(#[automatically_derived]
impl<'ra> ::core::fmt::Debug for MacroRulesDecl<'ra> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f,
            "MacroRulesDecl", "decl", &self.decl, "parent_macro_rules_scope",
            &self.parent_macro_rules_scope, "ident", &self.ident,
            "orig_ident_span", &&self.orig_ident_span)
    }
}Debug)]
53pub(crate) struct MacroRulesDecl<'ra> {
54    pub(crate) decl: Decl<'ra>,
55    /// `macro_rules` scope into which the `macro_rules` item was planted.
56    pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'ra>,
57    pub(crate) ident: IdentKey,
58    pub(crate) orig_ident_span: Span,
59}
60
61/// The scope introduced by a `macro_rules!` macro.
62/// This starts at the macro's definition and ends at the end of the macro's parent
63/// module (named or unnamed), or even further if it escapes with `#[macro_use]`.
64/// Some macro invocations need to introduce `macro_rules` scopes too because they
65/// can potentially expand into macro definitions.
66#[derive(#[automatically_derived]
impl<'ra> ::core::marker::Copy for MacroRulesScope<'ra> { }Copy, #[automatically_derived]
impl<'ra> ::core::clone::Clone for MacroRulesScope<'ra> {
    #[inline]
    fn clone(&self) -> MacroRulesScope<'ra> {
        let _: ::core::clone::AssertParamIsClone<&'ra MacroRulesDecl<'ra>>;
        let _: ::core::clone::AssertParamIsClone<LocalExpnId>;
        *self
    }
}Clone, #[automatically_derived]
impl<'ra> ::core::fmt::Debug for MacroRulesScope<'ra> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            MacroRulesScope::Empty =>
                ::core::fmt::Formatter::write_str(f, "Empty"),
            MacroRulesScope::Def(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Def",
                    &__self_0),
            MacroRulesScope::Invocation(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Invocation", &__self_0),
        }
    }
}Debug)]
67pub(crate) enum MacroRulesScope<'ra> {
68    /// Empty "root" scope at the crate start containing no names.
69    Empty,
70    /// The scope introduced by a `macro_rules!` macro definition.
71    Def(&'ra MacroRulesDecl<'ra>),
72    /// The scope introduced by a macro invocation that can potentially
73    /// create a `macro_rules!` macro definition.
74    Invocation(LocalExpnId),
75}
76
77/// `macro_rules!` scopes are always kept by reference and inside a cell.
78/// The reason is that we update scopes with value `MacroRulesScope::Invocation(invoc_id)`
79/// in-place after `invoc_id` gets expanded.
80/// This helps to avoid uncontrollable growth of `macro_rules!` scope chains,
81/// which usually grow linearly with the number of macro invocations
82/// in a module (including derives) and hurt performance.
83pub(crate) type MacroRulesScopeRef<'ra> = &'ra CacheCell<MacroRulesScope<'ra>>;
84
85/// Macro namespace is separated into two sub-namespaces, one for bang macros and
86/// one for attribute-like macros (attributes, derives).
87/// We ignore resolutions from one sub-namespace when searching names in scope for another.
88pub(crate) fn sub_namespace_match(
89    candidate: Option<MacroKinds>,
90    requirement: Option<MacroKind>,
91) -> bool {
92    // "No specific sub-namespace" means "matches anything" for both requirements and candidates.
93    let (Some(candidate), Some(requirement)) = (candidate, requirement) else {
94        return true;
95    };
96    match requirement {
97        MacroKind::Bang => candidate.contains(MacroKinds::BANG),
98        MacroKind::Attr | MacroKind::Derive => {
99            candidate.intersects(MacroKinds::ATTR | MacroKinds::DERIVE)
100        }
101    }
102}
103
104// We don't want to format a path using pretty-printing,
105// `format!("{}", path)`, because that tries to insert
106// line-breaks and is slow.
107fn fast_print_path(path: &ast::Path) -> Symbol {
108    if let [segment] = path.segments.as_slice() {
109        segment.ident.name
110    } else {
111        let mut path_str = String::with_capacity(64);
112        for (i, segment) in path.segments.iter().enumerate() {
113            if i != 0 {
114                path_str.push_str("::");
115            }
116            if segment.ident.name != kw::PathRoot {
117                path_str.push_str(segment.ident.as_str())
118            }
119        }
120        Symbol::intern(&path_str)
121    }
122}
123
124pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
125    let (_, pre_configured_attrs) = &*tcx.crate_for_resolver(()).borrow();
126    registered_tools_ast(tcx.dcx(), pre_configured_attrs, tcx.sess)
127}
128
129pub fn registered_tools_ast(
130    dcx: DiagCtxtHandle<'_>,
131    pre_configured_attrs: &[ast::Attribute],
132    sess: &Session,
133) -> RegisteredTools {
134    let mut registered_tools = RegisteredTools::default();
135
136    if let Some(Attribute::Parsed(AttributeKind::RegisterTool(tools, _))) =
137        AttributeParser::parse_limited(sess, pre_configured_attrs, &[sym::register_tool])
138    {
139        for tool in tools {
140            if let Some(old_tool) = registered_tools.replace(tool) {
141                dcx.emit_err(errors::ToolWasAlreadyRegistered {
142                    span: tool.span,
143                    tool,
144                    old_ident_span: old_tool.span,
145                });
146            }
147        }
148    }
149
150    // We implicitly add `rustfmt`, `clippy`, `diagnostic`, `miri` and `rust_analyzer` to known
151    // tools, but it's not an error to register them explicitly.
152    let predefined_tools =
153        [sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri, sym::rust_analyzer];
154    registered_tools.extend(predefined_tools.iter().cloned().map(Ident::with_dummy_span));
155    registered_tools
156}
157
158impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
159    fn next_node_id(&mut self) -> NodeId {
160        self.next_node_id()
161    }
162
163    fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId {
164        self.invocation_parents[&id].parent_def
165    }
166
167    fn mark_scope_with_compile_error(&mut self, id: NodeId) {
168        if let Some(id) = self.opt_local_def_id(id)
169            && self.tcx.def_kind(id).is_module_like()
170        {
171            self.mods_with_parse_errors.insert(id.to_def_id());
172        }
173    }
174
175    fn resolve_dollar_crates(&self) {
176        hygiene::update_dollar_crate_names(|ctxt| {
177            let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
178            match self.resolve_crate_root(ident).kind {
179                ModuleKind::Def(.., name) if let Some(name) = name => name,
180                _ => kw::Crate,
181            }
182        });
183    }
184
185    fn visit_ast_fragment_with_placeholders(
186        &mut self,
187        expansion: LocalExpnId,
188        fragment: &AstFragment,
189    ) {
190        // Integrate the new AST fragment into all the definition and module structures.
191        // We are inside the `expansion` now, but other parent scope components are still the same.
192        let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] };
193        let output_macro_rules_scope = collect_definitions(self, fragment, parent_scope);
194        self.output_macro_rules_scopes.insert(expansion, output_macro_rules_scope);
195
196        parent_scope.module.unexpanded_invocations.borrow_mut(self).remove(&expansion);
197        if let Some(unexpanded_invocations) =
198            self.impl_unexpanded_invocations.get_mut(&self.invocation_parent(expansion))
199        {
200            unexpanded_invocations.remove(&expansion);
201        }
202    }
203
204    fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind) {
205        if self.builtin_macros.insert(name, ext).is_some() {
206            self.dcx().bug(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("built-in macro `{0}` was already registered",
                name))
    })format!("built-in macro `{name}` was already registered"));
207        }
208    }
209
210    // Create a new Expansion with a definition site of the provided module, or
211    // a fake empty `#[no_implicit_prelude]` module if no module is provided.
212    fn expansion_for_ast_pass(
213        &mut self,
214        call_site: Span,
215        pass: AstPass,
216        features: &[Symbol],
217        parent_module_id: Option<NodeId>,
218    ) -> LocalExpnId {
219        let parent_module =
220            parent_module_id.map(|module_id| self.local_def_id(module_id).to_def_id());
221        let expn_id = self.tcx.with_stable_hashing_context(|hcx| {
222            LocalExpnId::fresh(
223                ExpnData::allow_unstable(
224                    ExpnKind::AstPass(pass),
225                    call_site,
226                    self.tcx.sess.edition(),
227                    features.into(),
228                    None,
229                    parent_module,
230                ),
231                hcx,
232            )
233        });
234
235        let parent_scope = parent_module
236            .map_or(self.empty_module, |def_id| self.expect_module(def_id).expect_local());
237        self.ast_transform_scopes.insert(expn_id, parent_scope);
238
239        expn_id
240    }
241
242    fn resolve_imports(&mut self) {
243        self.resolve_imports()
244    }
245
246    fn resolve_macro_invocation(
247        &mut self,
248        invoc: &Invocation,
249        eager_expansion_root: LocalExpnId,
250        force: bool,
251    ) -> Result<Arc<SyntaxExtension>, Indeterminate> {
252        let invoc_id = invoc.expansion_data.id;
253        let parent_scope = match self.invocation_parent_scopes.get(&invoc_id) {
254            Some(parent_scope) => *parent_scope,
255            None => {
256                // If there's no entry in the table, then we are resolving an eagerly expanded
257                // macro, which should inherit its parent scope from its eager expansion root -
258                // the macro that requested this eager expansion.
259                let parent_scope = *self
260                    .invocation_parent_scopes
261                    .get(&eager_expansion_root)
262                    .expect("non-eager expansion without a parent scope");
263                self.invocation_parent_scopes.insert(invoc_id, parent_scope);
264                parent_scope
265            }
266        };
267
268        let (mut derives, mut inner_attr, mut deleg_impl) = (&[][..], false, None);
269        let (path, kind) = match invoc.kind {
270            InvocationKind::Attr { ref attr, derives: ref attr_derives, .. } => {
271                derives = self.arenas.alloc_ast_paths(attr_derives);
272                inner_attr = attr.style == ast::AttrStyle::Inner;
273                (&attr.get_normal_item().path, MacroKind::Attr)
274            }
275            InvocationKind::Bang { ref mac, .. } => (&mac.path, MacroKind::Bang),
276            InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive),
277            InvocationKind::GlobDelegation { ref item, .. } => {
278                let ast::AssocItemKind::DelegationMac(deleg) = &item.kind else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
279                let DelegationSuffixes::Glob(star_span) = deleg.suffixes else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
280                deleg_impl = Some((self.invocation_parent(invoc_id), star_span));
281                // It is sufficient to consider glob delegation a bang macro for now.
282                (&deleg.prefix, MacroKind::Bang)
283            }
284        };
285
286        // Derives are not included when `invocations` are collected, so we have to add them here.
287        let parent_scope = &ParentScope { derives, ..parent_scope };
288        let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion();
289        let node_id = invoc.expansion_data.lint_node_id;
290        // This is a heuristic, but it's good enough for the lint.
291        let looks_like_invoc_in_mod_inert_attr = self
292            .invocation_parents
293            .get(&invoc_id)
294            .or_else(|| self.invocation_parents.get(&eager_expansion_root))
295            .filter(|&&InvocationParent { parent_def: mod_def_id, in_attr, .. }| {
296                in_attr
297                    && invoc.fragment_kind == AstFragmentKind::Expr
298                    && self.tcx.def_kind(mod_def_id) == DefKind::Mod
299            })
300            .map(|&InvocationParent { parent_def: mod_def_id, .. }| mod_def_id);
301        let sugg_span = match &invoc.kind {
302            InvocationKind::Attr { item: Annotatable::Item(item), .. }
303                if !item.span.from_expansion() =>
304            {
305                Some(item.span.shrink_to_lo())
306            }
307            _ => None,
308        };
309        let (ext, res) = self.smart_resolve_macro_path(
310            path,
311            kind,
312            supports_macro_expansion,
313            inner_attr,
314            parent_scope,
315            node_id,
316            force,
317            deleg_impl,
318            looks_like_invoc_in_mod_inert_attr,
319            sugg_span,
320        )?;
321
322        let span = invoc.span();
323        let def_id = if deleg_impl.is_some() { None } else { res.opt_def_id() };
324        self.tcx.with_stable_hashing_context(|hcx| {
325            invoc_id.set_expn_data(
326                ext.expn_data(
327                    parent_scope.expansion,
328                    span,
329                    fast_print_path(path),
330                    kind,
331                    def_id,
332                    def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()),
333                ),
334                hcx,
335            )
336        });
337
338        Ok(ext)
339    }
340
341    fn record_macro_rule_usage(&mut self, id: NodeId, rule_i: usize) {
342        if let Some(rules) = self.unused_macro_rules.get_mut(&id) {
343            rules.remove(rule_i);
344        }
345    }
346
347    fn check_unused_macros(&mut self) {
348        for (_, &(node_id, ident)) in self.unused_macros.iter() {
349            self.lint_buffer.buffer_lint(
350                UNUSED_MACROS,
351                node_id,
352                ident.span,
353                errors::UnusedMacroDefinition { name: ident.name },
354            );
355            // Do not report unused individual rules if the entire macro is unused
356            self.unused_macro_rules.swap_remove(&node_id);
357        }
358
359        for (&node_id, unused_arms) in self.unused_macro_rules.iter() {
360            if unused_arms.is_empty() {
361                continue;
362            }
363            let def_id = self.local_def_id(node_id);
364            let m = &self.local_macro_map[&def_id];
365            let SyntaxExtensionKind::MacroRules(ref m) = m.ext.kind else {
366                continue;
367            };
368            for arm_i in unused_arms.iter() {
369                if let Some((ident, rule_span)) = m.get_unused_rule(arm_i) {
370                    self.lint_buffer.buffer_lint(
371                        UNUSED_MACRO_RULES,
372                        node_id,
373                        rule_span,
374                        errors::MacroRuleNeverUsed { n: arm_i + 1, name: ident.name },
375                    );
376                }
377            }
378        }
379    }
380
381    fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool {
382        self.containers_deriving_copy.contains(&expn_id)
383    }
384
385    fn resolve_derives(
386        &mut self,
387        expn_id: LocalExpnId,
388        force: bool,
389        derive_paths: &dyn Fn() -> Vec<DeriveResolution>,
390    ) -> Result<(), Indeterminate> {
391        // Block expansion of the container until we resolve all derives in it.
392        // This is required for two reasons:
393        // - Derive helper attributes are in scope for the item to which the `#[derive]`
394        //   is applied, so they have to be produced by the container's expansion rather
395        //   than by individual derives.
396        // - Derives in the container need to know whether one of them is a built-in `Copy`.
397        //   (But see the comment mentioning #124794 below.)
398        // Temporarily take the data to avoid borrow checker conflicts.
399        let mut derive_data = mem::take(&mut self.derive_data);
400        let entry = derive_data.entry(expn_id).or_insert_with(|| DeriveData {
401            resolutions: derive_paths(),
402            helper_attrs: Vec::new(),
403            has_derive_copy: false,
404        });
405        let parent_scope = self.invocation_parent_scopes[&expn_id];
406        for (i, resolution) in entry.resolutions.iter_mut().enumerate() {
407            if resolution.exts.is_none() {
408                resolution.exts = Some(
409                    match self.cm().resolve_derive_macro_path(
410                        &resolution.path,
411                        &parent_scope,
412                        force,
413                        None,
414                    ) {
415                        Ok((Some(ext), _)) => {
416                            if !ext.helper_attrs.is_empty() {
417                                let span = resolution.path.segments.last().unwrap().ident.span;
418                                let ctxt = Macros20NormalizedSyntaxContext::new(span.ctxt());
419                                entry.helper_attrs.extend(
420                                    ext.helper_attrs
421                                        .iter()
422                                        .map(|&name| (i, IdentKey { name, ctxt }, span)),
423                                );
424                            }
425                            entry.has_derive_copy |= ext.builtin_name == Some(sym::Copy);
426                            ext
427                        }
428                        Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive),
429                        Err(Determinacy::Undetermined) => {
430                            if !self.derive_data.is_empty() {
    ::core::panicking::panic("assertion failed: self.derive_data.is_empty()")
};assert!(self.derive_data.is_empty());
431                            self.derive_data = derive_data;
432                            return Err(Indeterminate);
433                        }
434                    },
435                );
436            }
437        }
438        // Sort helpers in a stable way independent from the derive resolution order.
439        entry.helper_attrs.sort_by_key(|(i, ..)| *i);
440        let helper_attrs = entry
441            .helper_attrs
442            .iter()
443            .map(|&(_, ident, orig_ident_span)| {
444                let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
445                let decl = self.arenas.new_pub_def_decl(res, orig_ident_span, expn_id);
446                (ident, orig_ident_span, decl)
447            })
448            .collect();
449        self.helper_attrs.insert(expn_id, helper_attrs);
450        // Mark this derive as having `Copy` either if it has `Copy` itself or if its parent derive
451        // has `Copy`, to support `#[derive(Copy, Clone)]`, `#[derive(Clone, Copy)]`, or
452        // `#[derive(Copy)] #[derive(Clone)]`. We do this because the code generated for
453        // `derive(Clone)` changes if `derive(Copy)` is also present.
454        //
455        // FIXME(#124794): unfortunately this doesn't work with `#[derive(Clone)] #[derive(Copy)]`.
456        // When the `Clone` impl is generated the `#[derive(Copy)]` hasn't been processed and
457        // `has_derive_copy` hasn't been set yet.
458        if entry.has_derive_copy || self.has_derive_copy(parent_scope.expansion) {
459            self.containers_deriving_copy.insert(expn_id);
460        }
461        if !self.derive_data.is_empty() {
    ::core::panicking::panic("assertion failed: self.derive_data.is_empty()")
};assert!(self.derive_data.is_empty());
462        self.derive_data = derive_data;
463        Ok(())
464    }
465
466    fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<Vec<DeriveResolution>> {
467        self.derive_data.remove(&expn_id).map(|data| data.resolutions)
468    }
469
470    // The function that implements the resolution logic of `#[cfg_accessible(path)]`.
471    // Returns true if the path can certainly be resolved in one of three namespaces,
472    // returns false if the path certainly cannot be resolved in any of the three namespaces.
473    // Returns `Indeterminate` if we cannot give a certain answer yet.
474    fn cfg_accessible(
475        &mut self,
476        expn_id: LocalExpnId,
477        path: &ast::Path,
478    ) -> Result<bool, Indeterminate> {
479        self.path_accessible(expn_id, path, &[TypeNS, ValueNS, MacroNS])
480    }
481
482    fn macro_accessible(
483        &mut self,
484        expn_id: LocalExpnId,
485        path: &ast::Path,
486    ) -> Result<bool, Indeterminate> {
487        self.path_accessible(expn_id, path, &[MacroNS])
488    }
489
490    fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span {
491        self.cstore().get_proc_macro_quoted_span_untracked(self.tcx, krate, id)
492    }
493
494    fn declare_proc_macro(&mut self, id: NodeId) {
495        self.proc_macros.push(self.local_def_id(id))
496    }
497
498    fn append_stripped_cfg_item(
499        &mut self,
500        parent_node: NodeId,
501        ident: Ident,
502        cfg: CfgEntry,
503        cfg_span: Span,
504    ) {
505        self.stripped_cfg_items.push(StrippedCfgItem {
506            parent_scope: parent_node,
507            ident,
508            cfg: (cfg, cfg_span),
509        });
510    }
511
512    fn registered_tools(&self) -> &RegisteredTools {
513        self.registered_tools
514    }
515
516    fn register_glob_delegation(&mut self, invoc_id: LocalExpnId) {
517        self.glob_delegation_invoc_ids.insert(invoc_id);
518    }
519
520    fn glob_delegation_suffixes(
521        &self,
522        trait_def_id: DefId,
523        impl_def_id: LocalDefId,
524        star_span: Span,
525    ) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate> {
526        let target_trait = self.expect_module(trait_def_id);
527        if !target_trait.unexpanded_invocations.borrow().is_empty() {
528            return Err(Indeterminate);
529        }
530        // FIXME: Instead of waiting try generating all trait methods, and pruning
531        // the shadowed ones a bit later, e.g. when all macro expansion completes.
532        // Pros: expansion will be stuck less (but only in exotic cases), the implementation may be
533        // less hacky.
534        // Cons: More code is generated just to be deleted later, deleting already created `DefId`s
535        // may be nontrivial.
536        if let Some(unexpanded_invocations) = self.impl_unexpanded_invocations.get(&impl_def_id)
537            && !unexpanded_invocations.is_empty()
538        {
539            return Err(Indeterminate);
540        }
541
542        let mut idents = Vec::new();
543        target_trait.for_each_child(self, |this, ident, orig_ident_span, ns, _binding| {
544            if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id)
545                && overriding_keys.contains(&BindingKey::new(ident, ns))
546            {
547                // The name is overridden, do not produce it from the glob delegation.
548            } else {
549                // FIXME: Adjust hygiene for idents from globs, like for glob imports.
550                idents.push((ident.orig(star_span.with_ctxt(orig_ident_span.ctxt())), None));
551            }
552        });
553        Ok(idents)
554    }
555
556    fn insert_impl_trait_name(&mut self, id: NodeId, name: Symbol) {
557        self.impl_trait_names.insert(id, name);
558    }
559}
560
561impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
562    /// Resolve macro path with error reporting and recovery.
563    /// Uses dummy syntax extensions for unresolved macros or macros with unexpected resolutions
564    /// for better error recovery.
565    fn smart_resolve_macro_path(
566        &mut self,
567        path: &ast::Path,
568        kind: MacroKind,
569        supports_macro_expansion: SupportsMacroExpansion,
570        inner_attr: bool,
571        parent_scope: &ParentScope<'ra>,
572        node_id: NodeId,
573        force: bool,
574        deleg_impl: Option<(LocalDefId, Span)>,
575        invoc_in_mod_inert_attr: Option<LocalDefId>,
576        suggestion_span: Option<Span>,
577    ) -> Result<(Arc<SyntaxExtension>, Res), Indeterminate> {
578        let (ext, res) = match self.cm().resolve_macro_or_delegation_path(
579            path,
580            kind,
581            parent_scope,
582            force,
583            deleg_impl,
584            invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)),
585            None,
586            suggestion_span,
587        ) {
588            Ok((Some(ext), res)) => (ext, res),
589            Ok((None, res)) => (self.dummy_ext(kind), res),
590            Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err),
591            Err(Determinacy::Undetermined) => return Err(Indeterminate),
592        };
593
594        // Everything below is irrelevant to glob delegation, take a shortcut.
595        if deleg_impl.is_some() {
596            if !#[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Err | Res::Def(DefKind::Trait, _) => true,
    _ => false,
}matches!(res, Res::Err | Res::Def(DefKind::Trait, _)) {
597                self.dcx().emit_err(MacroExpectedFound {
598                    span: path.span,
599                    expected: "trait",
600                    article: "a",
601                    found: res.descr(),
602                    macro_path: &pprust::path_to_string(path),
603                    remove_surrounding_derive: None,
604                    add_as_non_derive: None,
605                });
606                return Ok((self.dummy_ext(kind), Res::Err));
607            }
608
609            return Ok((ext, res));
610        }
611
612        // Report errors for the resolved macro.
613        for (idx, segment) in path.segments.iter().enumerate() {
614            if let Some(args) = &segment.args {
615                self.dcx().emit_err(errors::GenericArgumentsInMacroPath { span: args.span() });
616            }
617            if kind == MacroKind::Attr && segment.ident.as_str().starts_with("rustc") {
618                if idx == 0 {
619                    self.dcx().emit_err(errors::AttributesStartingWithRustcAreReserved {
620                        span: segment.ident.span,
621                    });
622                } else {
623                    self.dcx().emit_err(errors::AttributesContainingRustcAreReserved {
624                        span: segment.ident.span,
625                    });
626                }
627            }
628        }
629
630        match res {
631            Res::Def(DefKind::Macro(_), def_id) => {
632                if let Some(def_id) = def_id.as_local() {
633                    self.unused_macros.swap_remove(&def_id);
634                    if self.proc_macro_stubs.contains(&def_id) {
635                        self.dcx().emit_err(errors::ProcMacroSameCrate {
636                            span: path.span,
637                            is_test: self.tcx.sess.is_test_crate(),
638                        });
639                    }
640                }
641            }
642            Res::NonMacroAttr(..) | Res::Err => {}
643            _ => {
    ::core::panicking::panic_fmt(format_args!("expected `DefKind::Macro` or `Res::NonMacroAttr`"));
}panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
644        };
645
646        self.check_stability_and_deprecation(&ext, path, node_id);
647
648        let unexpected_res = if !ext.macro_kinds().contains(kind.into()) {
649            Some((kind.article(), kind.descr_expected()))
650        } else if #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Def(..) => true,
    _ => false,
}matches!(res, Res::Def(..)) {
651            match supports_macro_expansion {
652                SupportsMacroExpansion::No => Some(("a", "non-macro attribute")),
653                SupportsMacroExpansion::Yes { supports_inner_attrs } => {
654                    if inner_attr && !supports_inner_attrs {
655                        Some(("a", "non-macro inner attribute"))
656                    } else {
657                        None
658                    }
659                }
660            }
661        } else {
662            None
663        };
664        if let Some((article, expected)) = unexpected_res {
665            let path_str = pprust::path_to_string(path);
666
667            let mut err = MacroExpectedFound {
668                span: path.span,
669                expected,
670                article,
671                found: res.descr(),
672                macro_path: &path_str,
673                remove_surrounding_derive: None,
674                add_as_non_derive: None,
675            };
676
677            // Suggest moving the macro out of the derive() if the macro isn't Derive
678            if !path.span.from_expansion()
679                && kind == MacroKind::Derive
680                && !ext.macro_kinds().contains(MacroKinds::DERIVE)
681                && ext.macro_kinds().contains(MacroKinds::ATTR)
682            {
683                err.remove_surrounding_derive = Some(RemoveSurroundingDerive { span: path.span });
684                err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str });
685            }
686
687            self.dcx().emit_err(err);
688
689            return Ok((self.dummy_ext(kind), Res::Err));
690        }
691
692        // We are trying to avoid reporting this error if other related errors were reported.
693        if res != Res::Err && inner_attr && !self.tcx.features().custom_inner_attributes() {
694            let is_macro = match res {
695                Res::Def(..) => true,
696                Res::NonMacroAttr(..) => false,
697                _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
698            };
699            let msg = if is_macro {
700                "inner macro attributes are unstable"
701            } else {
702                "custom inner attributes are unstable"
703            };
704            feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit();
705        }
706
707        const DIAGNOSTIC_ATTRIBUTES: &[(Symbol, Option<Symbol>)] = &[
708            (sym::on_unimplemented, None),
709            (sym::do_not_recommend, None),
710            (sym::on_move, Some(sym::diagnostic_on_move)),
711            (sym::on_const, Some(sym::diagnostic_on_const)),
712            (sym::on_unknown, Some(sym::diagnostic_on_unknown)),
713            (sym::on_unmatch_args, Some(sym::diagnostic_on_unmatch_args)),
714        ];
715
716        if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
717            && let [namespace, attribute, ..] = &*path.segments
718            && namespace.ident.name == sym::diagnostic
719            && !DIAGNOSTIC_ATTRIBUTES.iter().any(|(attr, feature)| {
720                attribute.ident.name == *attr
721                    && feature.is_none_or(|f| self.tcx.features().enabled(f))
722            })
723        {
724            let name = attribute.ident.name;
725            let span = attribute.span();
726
727            let help = 'help: {
728                if self.tcx.sess.is_nightly_build() {
729                    for (attr, feature) in DIAGNOSTIC_ATTRIBUTES {
730                        if let Some(feature) = *feature
731                            && *attr == name
732                        {
733                            break 'help Some(errors::UnknownDiagnosticAttributeHelp::UseFeature {
734                                feature,
735                            });
736                        }
737                    }
738                }
739
740                let candidates = DIAGNOSTIC_ATTRIBUTES
741                    .iter()
742                    .filter_map(|(attr, feature)| {
743                        feature.is_none_or(|f| self.tcx.features().enabled(f)).then_some(*attr)
744                    })
745                    .collect::<Vec<_>>();
746
747                find_best_match_for_name(&candidates, name, None).map(|typo_name| {
748                    errors::UnknownDiagnosticAttributeHelp::Typo { span, typo_name }
749                })
750            };
751
752            self.tcx.sess.psess.buffer_lint(
753                UNKNOWN_DIAGNOSTIC_ATTRIBUTES,
754                span,
755                node_id,
756                errors::UnknownDiagnosticAttribute { help },
757            );
758        }
759
760        Ok((ext, res))
761    }
762
763    pub(crate) fn resolve_derive_macro_path<'r>(
764        self: CmResolver<'r, 'ra, 'tcx>,
765        path: &ast::Path,
766        parent_scope: &ParentScope<'ra>,
767        force: bool,
768        ignore_import: Option<Import<'ra>>,
769    ) -> Result<(Option<Arc<SyntaxExtension>>, Res), Determinacy> {
770        self.resolve_macro_or_delegation_path(
771            path,
772            MacroKind::Derive,
773            parent_scope,
774            force,
775            None,
776            None,
777            ignore_import,
778            None,
779        )
780    }
781
782    fn resolve_macro_or_delegation_path<'r>(
783        mut self: CmResolver<'r, 'ra, 'tcx>,
784        ast_path: &ast::Path,
785        kind: MacroKind,
786        parent_scope: &ParentScope<'ra>,
787        force: bool,
788        deleg_impl: Option<(LocalDefId, Span)>,
789        invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
790        ignore_import: Option<Import<'ra>>,
791        suggestion_span: Option<Span>,
792    ) -> Result<(Option<Arc<SyntaxExtension>>, Res), Determinacy> {
793        let path_span = ast_path.span;
794        let mut path = Segment::from_path(ast_path);
795
796        // Possibly apply the macro helper hack
797        if deleg_impl.is_none()
798            && kind == MacroKind::Bang
799            && let [segment] = path.as_slice()
800            && segment.ident.span.ctxt().outer_expn_data().local_inner_macros
801        {
802            let root = Ident::new(kw::DollarCrate, segment.ident.span);
803            path.insert(0, Segment::from_ident(root));
804        }
805
806        let res = if deleg_impl.is_some() || path.len() > 1 {
807            let ns = if deleg_impl.is_some() { TypeNS } else { MacroNS };
808            let res = match self.reborrow().maybe_resolve_path(
809                &path,
810                Some(ns),
811                parent_scope,
812                ignore_import,
813            ) {
814                PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => Ok(res),
815                PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
816                PathResult::NonModule(..)
817                | PathResult::Indeterminate
818                | PathResult::Failed { .. } => Err(Determinacy::Determined),
819                PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
820                    Ok(module.res().unwrap())
821                }
822                PathResult::Module(..) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
823            };
824
825            self.multi_segment_macro_resolutions.borrow_mut(&self).push((
826                path,
827                path_span,
828                kind,
829                *parent_scope,
830                res.ok(),
831                ns,
832            ));
833
834            self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
835            res
836        } else {
837            let binding = self.reborrow().resolve_ident_in_scope_set(
838                path[0].ident,
839                ScopeSet::Macro(kind),
840                parent_scope,
841                None,
842                None,
843                None,
844            );
845            let binding = binding.map_err(|determinacy| {
846                Determinacy::determined(determinacy == Determinacy::Determined || force)
847            });
848            if let Err(Determinacy::Undetermined) = binding {
849                return Err(Determinacy::Undetermined);
850            }
851
852            self.single_segment_macro_resolutions.borrow_mut(&self).push((
853                path[0].ident,
854                kind,
855                *parent_scope,
856                binding.ok(),
857                suggestion_span,
858            ));
859
860            let res = binding.map(|binding| binding.res());
861            self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span);
862            self.reborrow().report_out_of_scope_macro_calls(
863                ast_path,
864                parent_scope,
865                invoc_in_mod_inert_attr,
866                binding.ok(),
867            );
868            res
869        };
870
871        let res = res?;
872        let ext = match deleg_impl {
873            Some((impl_def_id, star_span)) => match res {
874                Res::Def(DefKind::Trait, def_id) => {
875                    let edition = self.tcx.sess.edition();
876                    Some(Arc::new(SyntaxExtension::glob_delegation(
877                        def_id,
878                        impl_def_id,
879                        star_span,
880                        edition,
881                    )))
882                }
883                _ => None,
884            },
885            None => self.get_macro(res).map(|macro_data| Arc::clone(&macro_data.ext)),
886        };
887        Ok((ext, res))
888    }
889
890    pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) {
891        let check_consistency = |this: &Self,
892                                 path: &[Segment],
893                                 span,
894                                 kind: MacroKind,
895                                 initial_res: Option<Res>,
896                                 res: Res| {
897            if let Some(initial_res) = initial_res {
898                if res != initial_res {
899                    if this.ambiguity_errors.is_empty() {
900                        // Make sure compilation does not succeed if preferred macro resolution
901                        // has changed after the macro had been expanded. In theory all such
902                        // situations should be reported as errors, so this is a bug.
903                        this.dcx().span_delayed_bug(span, "inconsistent resolution for a macro");
904                    }
905                }
906            } else if this.tcx.dcx().has_errors().is_none() && this.privacy_errors.is_empty() {
907                // It's possible that the macro was unresolved (indeterminate) and silently
908                // expanded into a dummy fragment for recovery during expansion.
909                // Now, post-expansion, the resolution may succeed, but we can't change the
910                // past and need to report an error.
911                // However, non-speculative `resolve_path` can successfully return private items
912                // even if speculative `resolve_path` returned nothing previously, so we skip this
913                // less informative error if no other error is reported elsewhere.
914
915                let err = this.dcx().create_err(CannotDetermineMacroResolution {
916                    span,
917                    kind: kind.descr(),
918                    path: Segment::names_to_string(path),
919                });
920                err.stash(span, StashKey::UndeterminedMacroResolution);
921            }
922        };
923
924        let macro_resolutions = self.multi_segment_macro_resolutions.take(self);
925        for (mut path, path_span, kind, parent_scope, initial_res, ns) in macro_resolutions {
926            // FIXME: Path resolution will ICE if segment IDs present.
927            for seg in &mut path {
928                seg.id = None;
929            }
930            match self.cm().resolve_path(
931                &path,
932                Some(ns),
933                &parent_scope,
934                Some(Finalize::new(ast::CRATE_NODE_ID, path_span)),
935                None,
936                None,
937            ) {
938                PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => {
939                    check_consistency(self, &path, path_span, kind, initial_res, res)
940                }
941                // This may be a trait for glob delegation expansions.
942                PathResult::Module(ModuleOrUniformRoot::Module(module)) => check_consistency(
943                    self,
944                    &path,
945                    path_span,
946                    kind,
947                    initial_res,
948                    module.res().unwrap(),
949                ),
950                path_res @ (PathResult::NonModule(..) | PathResult::Failed { .. }) => {
951                    let mut suggestion = None;
952                    let (span, message, label, module, segment) = match path_res {
953                        PathResult::Failed {
954                            span, label, module, segment_name, message, ..
955                        } => {
956                            // try to suggest if it's not a macro, maybe a function
957                            if let PathResult::NonModule(partial_res) = self
958                                .cm()
959                                .maybe_resolve_path(&path, Some(ValueNS), &parent_scope, None)
960                                && partial_res.unresolved_segments() == 0
961                            {
962                                let sm = self.tcx.sess.source_map();
963                                let exclamation_span = sm.next_point(span);
964                                suggestion = Some((
965                                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(exclamation_span, "".to_string())]))vec![(exclamation_span, "".to_string())],
966                                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} is not a macro, but a {1}, try to remove `!`",
                Segment::names_to_string(&path),
                partial_res.base_res().descr()))
    })format!(
967                                        "{} is not a macro, but a {}, try to remove `!`",
968                                        Segment::names_to_string(&path),
969                                        partial_res.base_res().descr()
970                                    ),
971                                    Applicability::MaybeIncorrect,
972                                ));
973                            }
974                            (span, message, label, module, segment_name)
975                        }
976                        PathResult::NonModule(partial_res) => {
977                            let found_an = partial_res.base_res().article();
978                            let found_descr = partial_res.base_res().descr();
979                            let scope = match &path[..partial_res.unresolved_segments()] {
980                                [.., prev] => {
981                                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{1} `{0}`", prev.ident,
                found_descr))
    })format!("{found_descr} `{}`", prev.ident)
982                                }
983                                _ => found_descr.to_string(),
984                            };
985                            let expected_an = kind.article();
986                            let expected_descr = kind.descr();
987                            let expected_name = path[partial_res.unresolved_segments()].ident;
988
989                            (
990                                path_span,
991                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("cannot find {0} `{1}` in {2}",
                expected_descr, expected_name, scope))
    })format!(
992                                    "cannot find {expected_descr} `{expected_name}` in {scope}"
993                                ),
994                                match partial_res.base_res() {
995                                    Res::Def(
996                                        DefKind::Mod | DefKind::Macro(..) | DefKind::ExternCrate,
997                                        _,
998                                    ) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("partially resolved path in {0} {1}",
                expected_an, expected_descr))
    })format!(
999                                        "partially resolved path in {expected_an} {expected_descr}",
1000                                    ),
1001                                    _ => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} {1} can\'t exist within {2} {3}",
                expected_an, expected_descr, found_an, found_descr))
    })format!(
1002                                        "{expected_an} {expected_descr} can't exist within \
1003                                         {found_an} {found_descr}"
1004                                    ),
1005                                },
1006                                None,
1007                                path.last().map(|segment| segment.ident.name).unwrap(),
1008                            )
1009                        }
1010                        _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1011                    };
1012                    self.report_error(
1013                        span,
1014                        ResolutionError::FailedToResolve {
1015                            segment,
1016                            label,
1017                            suggestion,
1018                            module,
1019                            message,
1020                        },
1021                    );
1022                }
1023                PathResult::Module(..) | PathResult::Indeterminate => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1024            }
1025        }
1026
1027        let macro_resolutions = self.single_segment_macro_resolutions.take(self);
1028        for (ident, kind, parent_scope, initial_binding, sugg_span) in macro_resolutions {
1029            match self.cm().resolve_ident_in_scope_set(
1030                ident,
1031                ScopeSet::Macro(kind),
1032                &parent_scope,
1033                Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
1034                None,
1035                None,
1036            ) {
1037                Ok(binding) => {
1038                    let initial_res = initial_binding.map(|initial_binding| {
1039                        self.record_use(ident, initial_binding, Used::Other);
1040                        initial_binding.res()
1041                    });
1042                    let res = binding.res();
1043                    let seg = Segment::from_ident(ident);
1044                    check_consistency(self, &[seg], ident.span, kind, initial_res, res);
1045                    if res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat) {
1046                        let node_id = self
1047                            .invocation_parents
1048                            .get(&parent_scope.expansion)
1049                            .map_or(ast::CRATE_NODE_ID, |parent| {
1050                                self.def_id_to_node_id(parent.parent_def)
1051                            });
1052                        self.lint_buffer.buffer_lint(
1053                            LEGACY_DERIVE_HELPERS,
1054                            node_id,
1055                            ident.span,
1056                            errors::LegacyDeriveHelpers { span: binding.span },
1057                        );
1058                    }
1059                }
1060                Err(..) => {
1061                    let expected = kind.descr_expected();
1062
1063                    let mut err = self.dcx().create_err(CannotFindIdentInThisScope {
1064                        span: ident.span,
1065                        expected,
1066                        ident,
1067                    });
1068                    self.unresolved_macro_suggestions(
1069                        &mut err,
1070                        kind,
1071                        &parent_scope,
1072                        ident,
1073                        krate,
1074                        sugg_span,
1075                    );
1076                    err.emit();
1077                }
1078            }
1079        }
1080
1081        let builtin_attrs = mem::take(&mut self.builtin_attrs);
1082        for (ident, parent_scope) in builtin_attrs {
1083            let _ = self.cm().resolve_ident_in_scope_set(
1084                ident,
1085                ScopeSet::Macro(MacroKind::Attr),
1086                &parent_scope,
1087                Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
1088                None,
1089                None,
1090            );
1091        }
1092    }
1093
1094    fn check_stability_and_deprecation(
1095        &mut self,
1096        ext: &SyntaxExtension,
1097        path: &ast::Path,
1098        node_id: NodeId,
1099    ) {
1100        let span = path.span;
1101        if let Some(stability) = &ext.stability
1102            && let StabilityLevel::Unstable { reason, issue, implied_by, .. } = stability.level
1103        {
1104            let feature = stability.feature;
1105
1106            let is_allowed =
1107                |feature| self.tcx.features().enabled(feature) || span.allows_unstable(feature);
1108            let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
1109            if !is_allowed(feature) && !allowed_by_implication {
1110                stability::report_unstable(
1111                    self.tcx.sess,
1112                    feature,
1113                    reason.to_opt_reason(),
1114                    issue,
1115                    None,
1116                    span,
1117                    stability::UnstableKind::Regular,
1118                );
1119            }
1120        }
1121        if let Some(depr) = &ext.deprecation {
1122            let path = pprust::path_to_string(path);
1123            stability::early_report_macro_deprecation(
1124                &mut self.lint_buffer,
1125                depr,
1126                span,
1127                node_id,
1128                path,
1129            );
1130        }
1131    }
1132
1133    fn prohibit_imported_non_macro_attrs(
1134        &self,
1135        decl: Option<Decl<'ra>>,
1136        res: Option<Res>,
1137        span: Span,
1138    ) {
1139        if let Some(Res::NonMacroAttr(kind)) = res {
1140            if kind != NonMacroAttrKind::Tool && decl.is_none_or(|b| b.is_import()) {
1141                self.dcx().emit_err(errors::CannotUseThroughAnImport {
1142                    span,
1143                    article: kind.article(),
1144                    descr: kind.descr(),
1145                    binding_span: decl.map(|d| d.span),
1146                });
1147            }
1148        }
1149    }
1150
1151    fn report_out_of_scope_macro_calls<'r>(
1152        mut self: CmResolver<'r, 'ra, 'tcx>,
1153        path: &ast::Path,
1154        parent_scope: &ParentScope<'ra>,
1155        invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
1156        decl: Option<Decl<'ra>>,
1157    ) {
1158        if let Some((mod_def_id, node_id)) = invoc_in_mod_inert_attr
1159            && let Some(decl) = decl
1160            // This is a `macro_rules` itself, not some import.
1161            && let DeclKind::Def(res) = decl.kind
1162            && let Res::Def(DefKind::Macro(kinds), def_id) = res
1163            && kinds.contains(MacroKinds::BANG)
1164            // And the `macro_rules` is defined inside the attribute's module,
1165            // so it cannot be in scope unless imported.
1166            && self.tcx.is_descendant_of(def_id, mod_def_id.to_def_id())
1167        {
1168            // Try to resolve our ident ignoring `macro_rules` scopes.
1169            // If such resolution is successful and gives the same result
1170            // (e.g. if the macro is re-imported), then silence the lint.
1171            let no_macro_rules = self.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty);
1172            let ident = path.segments[0].ident;
1173            let fallback_binding = self.reborrow().resolve_ident_in_scope_set(
1174                ident,
1175                ScopeSet::Macro(MacroKind::Bang),
1176                &ParentScope { macro_rules: no_macro_rules, ..*parent_scope },
1177                None,
1178                None,
1179                None,
1180            );
1181            if let Ok(fallback_binding) = fallback_binding
1182                && fallback_binding.res().opt_def_id() == Some(def_id)
1183            {
1184                // Silence `unused_imports` on the fallback import as well.
1185                self.get_mut().record_use(ident, fallback_binding, Used::Other);
1186            } else {
1187                let location = match parent_scope.module.kind {
1188                    ModuleKind::Def(kind, def_id, name) => {
1189                        if let Some(name) = name {
1190                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} `{1}`", kind.descr(def_id),
                name))
    })format!("{} `{name}`", kind.descr(def_id))
1191                        } else {
1192                            "the crate root".to_string()
1193                        }
1194                    }
1195                    ModuleKind::Block => "this scope".to_string(),
1196                };
1197                self.tcx.sess.psess.buffer_lint(
1198                    OUT_OF_SCOPE_MACRO_CALLS,
1199                    path.span,
1200                    node_id,
1201                    errors::OutOfScopeMacroCalls {
1202                        span: path.span,
1203                        path: pprust::path_to_string(path),
1204                        location,
1205                    },
1206                );
1207            }
1208        }
1209    }
1210
1211    pub(crate) fn check_reserved_macro_name(&self, name: Symbol, span: Span, res: Res) {
1212        // Reserve some names that are not quite covered by the general check
1213        // performed on `Resolver::builtin_attrs`.
1214        if name == sym::cfg || name == sym::cfg_attr {
1215            let macro_kinds = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kinds());
1216            if macro_kinds.is_some() && sub_namespace_match(macro_kinds, Some(MacroKind::Attr)) {
1217                self.dcx().emit_err(errors::NameReservedInAttributeNamespace { span, ident: name });
1218            }
1219        }
1220    }
1221
1222    /// Compile the macro into a `SyntaxExtension` and its rule spans.
1223    ///
1224    /// Possibly replace its expander to a pre-defined one for built-in macros.
1225    pub(crate) fn compile_macro(
1226        &self,
1227        macro_def: &ast::MacroDef,
1228        ident: Ident,
1229        attrs: &[rustc_hir::Attribute],
1230        span: Span,
1231        node_id: NodeId,
1232        edition: Edition,
1233    ) -> MacroData {
1234        let (mut ext, mut nrules) = compile_declarative_macro(
1235            self.tcx.sess,
1236            self.tcx.features(),
1237            macro_def,
1238            ident,
1239            attrs,
1240            span,
1241            node_id,
1242            edition,
1243        );
1244
1245        if let Some(builtin_name) = ext.builtin_name {
1246            // The macro was marked with `#[rustc_builtin_macro]`.
1247            if let Some(builtin_ext_kind) = self.builtin_macros.get(&builtin_name) {
1248                // The macro is a built-in, replace its expander function
1249                // while still taking everything else from the source code.
1250                ext.kind = builtin_ext_kind.clone();
1251                nrules = 0;
1252            } else {
1253                self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { span, ident });
1254            }
1255        }
1256
1257        MacroData { ext: Arc::new(ext), nrules, macro_rules: macro_def.macro_rules }
1258    }
1259
1260    fn path_accessible(
1261        &mut self,
1262        expn_id: LocalExpnId,
1263        path: &ast::Path,
1264        namespaces: &[Namespace],
1265    ) -> Result<bool, Indeterminate> {
1266        let span = path.span;
1267        let path = &Segment::from_path(path);
1268        let parent_scope = self.invocation_parent_scopes[&expn_id];
1269
1270        let mut indeterminate = false;
1271        for ns in namespaces {
1272            match self.cm().maybe_resolve_path(path, Some(*ns), &parent_scope, None) {
1273                PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
1274                PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
1275                    return Ok(true);
1276                }
1277                PathResult::NonModule(..) |
1278                // HACK(Urgau): This shouldn't be necessary
1279                PathResult::Failed { is_error_from_last_segment: false, .. } => {
1280                    self.dcx()
1281                        .emit_err(errors::CfgAccessibleUnsure { span });
1282
1283                    // If we get a partially resolved NonModule in one namespace, we should get the
1284                    // same result in any other namespaces, so we can return early.
1285                    return Ok(false);
1286                }
1287                PathResult::Indeterminate => indeterminate = true,
1288                // We can only be sure that a path doesn't exist after having tested all the
1289                // possibilities, only at that time we can return false.
1290                PathResult::Failed { .. } => {}
1291                PathResult::Module(_) => { ::core::panicking::panic_fmt(format_args!("unexpected path resolution")); }panic!("unexpected path resolution"),
1292            }
1293        }
1294
1295        if indeterminate {
1296            return Err(Indeterminate);
1297        }
1298
1299        Ok(false)
1300    }
1301}