1use std::cell::Cell;
5use std::mem;
6use std::sync::Arc;
7
8use rustc_ast::expand::StrippedCfgItem;
9use rustc_ast::{self as ast, Crate, NodeId, attr};
10use rustc_ast_pretty::pprust;
11use rustc_attr_parsing::{AttributeKind, StabilityLevel, find_attr};
12use rustc_data_structures::intern::Interned;
13use rustc_errors::{Applicability, StashKey};
14use rustc_expand::base::{
15 DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind,
16};
17use rustc_expand::compile_declarative_macro;
18use rustc_expand::expand::{
19 AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion,
20};
21use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind};
22use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
23use rustc_middle::middle::stability;
24use rustc_middle::ty::{RegisteredTools, TyCtxt, Visibility};
25use rustc_session::lint::BuiltinLintDiag;
26use rustc_session::lint::builtin::{
27 LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, UNKNOWN_OR_MALFORMED_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::errors::{
38 self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope,
39 MacroExpectedFound, RemoveSurroundingDerive,
40};
41use crate::imports::Import;
42use crate::{
43 BindingKey, DeriveData, Determinacy, Finalize, InvocationParent, MacroData, ModuleKind,
44 ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError,
45 Resolver, ScopeSet, Segment, ToNameBinding, Used,
46};
47
48type Res = def::Res<NodeId>;
49
50#[derive(Debug)]
53pub(crate) struct MacroRulesBinding<'ra> {
54 pub(crate) binding: NameBinding<'ra>,
55 pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'ra>,
57 pub(crate) ident: Ident,
58}
59
60#[derive(Copy, Clone, Debug)]
66pub(crate) enum MacroRulesScope<'ra> {
67 Empty,
69 Binding(&'ra MacroRulesBinding<'ra>),
71 Invocation(LocalExpnId),
74}
75
76pub(crate) type MacroRulesScopeRef<'ra> = Interned<'ra, Cell<MacroRulesScope<'ra>>>;
83
84pub(crate) fn sub_namespace_match(
88 candidate: Option<MacroKind>,
89 requirement: Option<MacroKind>,
90) -> bool {
91 #[derive(PartialEq)]
92 enum SubNS {
93 Bang,
94 AttrLike,
95 }
96 let sub_ns = |kind| match kind {
97 MacroKind::Bang => SubNS::Bang,
98 MacroKind::Attr | MacroKind::Derive => SubNS::AttrLike,
99 };
100 let candidate = candidate.map(sub_ns);
101 let requirement = requirement.map(sub_ns);
102 candidate.is_none() || requirement.is_none() || candidate == requirement
104}
105
106fn fast_print_path(path: &ast::Path) -> Symbol {
110 if let [segment] = path.segments.as_slice() {
111 segment.ident.name
112 } else {
113 let mut path_str = String::with_capacity(64);
114 for (i, segment) in path.segments.iter().enumerate() {
115 if i != 0 {
116 path_str.push_str("::");
117 }
118 if segment.ident.name != kw::PathRoot {
119 path_str.push_str(segment.ident.as_str())
120 }
121 }
122 Symbol::intern(&path_str)
123 }
124}
125
126pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
127 let mut registered_tools = RegisteredTools::default();
128 let (_, pre_configured_attrs) = &*tcx.crate_for_resolver(()).borrow();
129 for attr in attr::filter_by_name(pre_configured_attrs, sym::register_tool) {
130 for meta_item_inner in attr.meta_item_list().unwrap_or_default() {
131 match meta_item_inner.ident() {
132 Some(ident) => {
133 if let Some(old_ident) = registered_tools.replace(ident) {
134 tcx.dcx().emit_err(errors::ToolWasAlreadyRegistered {
135 span: ident.span,
136 tool: ident,
137 old_ident_span: old_ident.span,
138 });
139 }
140 }
141 None => {
142 tcx.dcx().emit_err(errors::ToolOnlyAcceptsIdentifiers {
143 span: meta_item_inner.span(),
144 tool: sym::register_tool,
145 });
146 }
147 }
148 }
149 }
150 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 resolve_dollar_crates(&mut self) {
168 hygiene::update_dollar_crate_names(|ctxt| {
169 let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
170 match self.resolve_crate_root(ident).kind {
171 ModuleKind::Def(.., name) if let Some(name) = name => name,
172 _ => kw::Crate,
173 }
174 });
175 }
176
177 fn visit_ast_fragment_with_placeholders(
178 &mut self,
179 expansion: LocalExpnId,
180 fragment: &AstFragment,
181 ) {
182 let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] };
185 let output_macro_rules_scope = self.build_reduced_graph(fragment, parent_scope);
186 self.output_macro_rules_scopes.insert(expansion, output_macro_rules_scope);
187
188 parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion);
189 if let Some(unexpanded_invocations) =
190 self.impl_unexpanded_invocations.get_mut(&self.invocation_parent(expansion))
191 {
192 unexpanded_invocations.remove(&expansion);
193 }
194 }
195
196 fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind) {
197 if self.builtin_macros.insert(name, ext).is_some() {
198 self.dcx().bug(format!("built-in macro `{name}` was already registered"));
199 }
200 }
201
202 fn expansion_for_ast_pass(
205 &mut self,
206 call_site: Span,
207 pass: AstPass,
208 features: &[Symbol],
209 parent_module_id: Option<NodeId>,
210 ) -> LocalExpnId {
211 let parent_module =
212 parent_module_id.map(|module_id| self.local_def_id(module_id).to_def_id());
213 let expn_id = LocalExpnId::fresh(
214 ExpnData::allow_unstable(
215 ExpnKind::AstPass(pass),
216 call_site,
217 self.tcx.sess.edition(),
218 features.into(),
219 None,
220 parent_module,
221 ),
222 self.create_stable_hashing_context(),
223 );
224
225 let parent_scope =
226 parent_module.map_or(self.empty_module, |def_id| self.expect_module(def_id));
227 self.ast_transform_scopes.insert(expn_id, parent_scope);
228
229 expn_id
230 }
231
232 fn resolve_imports(&mut self) {
233 self.resolve_imports()
234 }
235
236 fn resolve_macro_invocation(
237 &mut self,
238 invoc: &Invocation,
239 eager_expansion_root: LocalExpnId,
240 force: bool,
241 ) -> Result<Arc<SyntaxExtension>, Indeterminate> {
242 let invoc_id = invoc.expansion_data.id;
243 let parent_scope = match self.invocation_parent_scopes.get(&invoc_id) {
244 Some(parent_scope) => *parent_scope,
245 None => {
246 let parent_scope = *self
250 .invocation_parent_scopes
251 .get(&eager_expansion_root)
252 .expect("non-eager expansion without a parent scope");
253 self.invocation_parent_scopes.insert(invoc_id, parent_scope);
254 parent_scope
255 }
256 };
257
258 let (mut derives, mut inner_attr, mut deleg_impl) = (&[][..], false, None);
259 let (path, kind) = match invoc.kind {
260 InvocationKind::Attr { ref attr, derives: ref attr_derives, .. } => {
261 derives = self.arenas.alloc_ast_paths(attr_derives);
262 inner_attr = attr.style == ast::AttrStyle::Inner;
263 (&attr.get_normal_item().path, MacroKind::Attr)
264 }
265 InvocationKind::Bang { ref mac, .. } => (&mac.path, MacroKind::Bang),
266 InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive),
267 InvocationKind::GlobDelegation { ref item, .. } => {
268 let ast::AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() };
269 deleg_impl = Some(self.invocation_parent(invoc_id));
270 (&deleg.prefix, MacroKind::Bang)
272 }
273 };
274
275 let parent_scope = &ParentScope { derives, ..parent_scope };
277 let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion();
278 let node_id = invoc.expansion_data.lint_node_id;
279 let looks_like_invoc_in_mod_inert_attr = self
281 .invocation_parents
282 .get(&invoc_id)
283 .or_else(|| self.invocation_parents.get(&eager_expansion_root))
284 .filter(|&&InvocationParent { parent_def: mod_def_id, in_attr, .. }| {
285 in_attr
286 && invoc.fragment_kind == AstFragmentKind::Expr
287 && self.tcx.def_kind(mod_def_id) == DefKind::Mod
288 })
289 .map(|&InvocationParent { parent_def: mod_def_id, .. }| mod_def_id);
290 let (ext, res) = self.smart_resolve_macro_path(
291 path,
292 kind,
293 supports_macro_expansion,
294 inner_attr,
295 parent_scope,
296 node_id,
297 force,
298 deleg_impl,
299 looks_like_invoc_in_mod_inert_attr,
300 )?;
301
302 let span = invoc.span();
303 let def_id = if deleg_impl.is_some() { None } else { res.opt_def_id() };
304 invoc_id.set_expn_data(
305 ext.expn_data(
306 parent_scope.expansion,
307 span,
308 fast_print_path(path),
309 def_id,
310 def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()),
311 ),
312 self.create_stable_hashing_context(),
313 );
314
315 Ok(ext)
316 }
317
318 fn record_macro_rule_usage(&mut self, id: NodeId, rule_i: usize) {
319 let did = self.local_def_id(id);
320 if let Some(rules) = self.unused_macro_rules.get_mut(&did) {
321 rules.remove(&rule_i);
322 }
323 }
324
325 fn check_unused_macros(&mut self) {
326 for (_, &(node_id, ident)) in self.unused_macros.iter() {
327 self.lint_buffer.buffer_lint(
328 UNUSED_MACROS,
329 node_id,
330 ident.span,
331 BuiltinLintDiag::UnusedMacroDefinition(ident.name),
332 );
333 }
334
335 for (&def_id, unused_arms) in self.unused_macro_rules.iter() {
336 for (&arm_i, &(ident, rule_span)) in unused_arms.to_sorted_stable_ord() {
337 if self.unused_macros.contains_key(&def_id) {
338 continue;
340 }
341 let node_id = self.def_id_to_node_id[def_id];
342 self.lint_buffer.buffer_lint(
343 UNUSED_MACRO_RULES,
344 node_id,
345 rule_span,
346 BuiltinLintDiag::MacroRuleNeverUsed(arm_i, ident.name),
347 );
348 }
349 }
350 }
351
352 fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool {
353 self.containers_deriving_copy.contains(&expn_id)
354 }
355
356 fn resolve_derives(
357 &mut self,
358 expn_id: LocalExpnId,
359 force: bool,
360 derive_paths: &dyn Fn() -> Vec<DeriveResolution>,
361 ) -> Result<(), Indeterminate> {
362 let mut derive_data = mem::take(&mut self.derive_data);
370 let entry = derive_data.entry(expn_id).or_insert_with(|| DeriveData {
371 resolutions: derive_paths(),
372 helper_attrs: Vec::new(),
373 has_derive_copy: false,
374 });
375 let parent_scope = self.invocation_parent_scopes[&expn_id];
376 for (i, resolution) in entry.resolutions.iter_mut().enumerate() {
377 if resolution.exts.is_none() {
378 resolution.exts = Some(
379 match self.resolve_macro_path(
380 &resolution.path,
381 Some(MacroKind::Derive),
382 &parent_scope,
383 true,
384 force,
385 None,
386 ) {
387 Ok((Some(ext), _)) => {
388 if !ext.helper_attrs.is_empty() {
389 let last_seg = resolution.path.segments.last().unwrap();
390 let span = last_seg.ident.span.normalize_to_macros_2_0();
391 entry.helper_attrs.extend(
392 ext.helper_attrs
393 .iter()
394 .map(|name| (i, Ident::new(*name, span))),
395 );
396 }
397 entry.has_derive_copy |= ext.builtin_name == Some(sym::Copy);
398 ext
399 }
400 Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive),
401 Err(Determinacy::Undetermined) => {
402 assert!(self.derive_data.is_empty());
403 self.derive_data = derive_data;
404 return Err(Indeterminate);
405 }
406 },
407 );
408 }
409 }
410 entry.helper_attrs.sort_by_key(|(i, _)| *i);
412 let helper_attrs = entry
413 .helper_attrs
414 .iter()
415 .map(|(_, ident)| {
416 let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
417 let binding = (res, Visibility::<DefId>::Public, ident.span, expn_id)
418 .to_name_binding(self.arenas);
419 (*ident, binding)
420 })
421 .collect();
422 self.helper_attrs.insert(expn_id, helper_attrs);
423 if entry.has_derive_copy || self.has_derive_copy(parent_scope.expansion) {
426 self.containers_deriving_copy.insert(expn_id);
427 }
428 assert!(self.derive_data.is_empty());
429 self.derive_data = derive_data;
430 Ok(())
431 }
432
433 fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<Vec<DeriveResolution>> {
434 self.derive_data.remove(&expn_id).map(|data| data.resolutions)
435 }
436
437 fn cfg_accessible(
442 &mut self,
443 expn_id: LocalExpnId,
444 path: &ast::Path,
445 ) -> Result<bool, Indeterminate> {
446 self.path_accessible(expn_id, path, &[TypeNS, ValueNS, MacroNS])
447 }
448
449 fn macro_accessible(
450 &mut self,
451 expn_id: LocalExpnId,
452 path: &ast::Path,
453 ) -> Result<bool, Indeterminate> {
454 self.path_accessible(expn_id, path, &[MacroNS])
455 }
456
457 fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span {
458 self.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.tcx.sess)
459 }
460
461 fn declare_proc_macro(&mut self, id: NodeId) {
462 self.proc_macros.push(id)
463 }
464
465 fn append_stripped_cfg_item(&mut self, parent_node: NodeId, name: Ident, cfg: ast::MetaItem) {
466 self.stripped_cfg_items.push(StrippedCfgItem { parent_module: parent_node, name, cfg });
467 }
468
469 fn registered_tools(&self) -> &RegisteredTools {
470 self.registered_tools
471 }
472
473 fn register_glob_delegation(&mut self, invoc_id: LocalExpnId) {
474 self.glob_delegation_invoc_ids.insert(invoc_id);
475 }
476
477 fn glob_delegation_suffixes(
478 &mut self,
479 trait_def_id: DefId,
480 impl_def_id: LocalDefId,
481 ) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate> {
482 let target_trait = self.expect_module(trait_def_id);
483 if !target_trait.unexpanded_invocations.borrow().is_empty() {
484 return Err(Indeterminate);
485 }
486 if let Some(unexpanded_invocations) = self.impl_unexpanded_invocations.get(&impl_def_id)
493 && !unexpanded_invocations.is_empty()
494 {
495 return Err(Indeterminate);
496 }
497
498 let mut idents = Vec::new();
499 target_trait.for_each_child(self, |this, ident, ns, _binding| {
500 if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id)
502 && overriding_keys.contains(&BindingKey::new(ident.normalize_to_macros_2_0(), ns))
503 {
504 } else {
506 idents.push((ident, None));
507 }
508 });
509 Ok(idents)
510 }
511}
512
513impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
514 fn smart_resolve_macro_path(
518 &mut self,
519 path: &ast::Path,
520 kind: MacroKind,
521 supports_macro_expansion: SupportsMacroExpansion,
522 inner_attr: bool,
523 parent_scope: &ParentScope<'ra>,
524 node_id: NodeId,
525 force: bool,
526 deleg_impl: Option<LocalDefId>,
527 invoc_in_mod_inert_attr: Option<LocalDefId>,
528 ) -> Result<(Arc<SyntaxExtension>, Res), Indeterminate> {
529 let (ext, res) = match self.resolve_macro_or_delegation_path(
530 path,
531 Some(kind),
532 parent_scope,
533 true,
534 force,
535 deleg_impl,
536 invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)),
537 None,
538 ) {
539 Ok((Some(ext), res)) => (ext, res),
540 Ok((None, res)) => (self.dummy_ext(kind), res),
541 Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err),
542 Err(Determinacy::Undetermined) => return Err(Indeterminate),
543 };
544
545 if deleg_impl.is_some() {
547 if !matches!(res, Res::Err | Res::Def(DefKind::Trait, _)) {
548 self.dcx().emit_err(MacroExpectedFound {
549 span: path.span,
550 expected: "trait",
551 article: "a",
552 found: res.descr(),
553 macro_path: &pprust::path_to_string(path),
554 remove_surrounding_derive: None,
555 add_as_non_derive: None,
556 });
557 return Ok((self.dummy_ext(kind), Res::Err));
558 }
559
560 return Ok((ext, res));
561 }
562
563 for segment in &path.segments {
565 if let Some(args) = &segment.args {
566 self.dcx().emit_err(errors::GenericArgumentsInMacroPath { span: args.span() });
567 }
568 if kind == MacroKind::Attr && segment.ident.as_str().starts_with("rustc") {
569 self.dcx().emit_err(errors::AttributesStartingWithRustcAreReserved {
570 span: segment.ident.span,
571 });
572 }
573 }
574
575 match res {
576 Res::Def(DefKind::Macro(_), def_id) => {
577 if let Some(def_id) = def_id.as_local() {
578 self.unused_macros.swap_remove(&def_id);
579 if self.proc_macro_stubs.contains(&def_id) {
580 self.dcx().emit_err(errors::ProcMacroSameCrate {
581 span: path.span,
582 is_test: self.tcx.sess.is_test_crate(),
583 });
584 }
585 }
586 }
587 Res::NonMacroAttr(..) | Res::Err => {}
588 _ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
589 };
590
591 self.check_stability_and_deprecation(&ext, path, node_id);
592
593 let unexpected_res = if ext.macro_kind() != kind {
594 Some((kind.article(), kind.descr_expected()))
595 } else if matches!(res, Res::Def(..)) {
596 match supports_macro_expansion {
597 SupportsMacroExpansion::No => Some(("a", "non-macro attribute")),
598 SupportsMacroExpansion::Yes { supports_inner_attrs } => {
599 if inner_attr && !supports_inner_attrs {
600 Some(("a", "non-macro inner attribute"))
601 } else {
602 None
603 }
604 }
605 }
606 } else {
607 None
608 };
609 if let Some((article, expected)) = unexpected_res {
610 let path_str = pprust::path_to_string(path);
611
612 let mut err = MacroExpectedFound {
613 span: path.span,
614 expected,
615 article,
616 found: res.descr(),
617 macro_path: &path_str,
618 remove_surrounding_derive: None,
619 add_as_non_derive: None,
620 };
621
622 if !path.span.from_expansion()
624 && kind == MacroKind::Derive
625 && ext.macro_kind() != MacroKind::Derive
626 {
627 err.remove_surrounding_derive = Some(RemoveSurroundingDerive { span: path.span });
628 err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str });
629 }
630
631 self.dcx().emit_err(err);
632
633 return Ok((self.dummy_ext(kind), Res::Err));
634 }
635
636 if res != Res::Err && inner_attr && !self.tcx.features().custom_inner_attributes() {
638 let is_macro = match res {
639 Res::Def(..) => true,
640 Res::NonMacroAttr(..) => false,
641 _ => unreachable!(),
642 };
643 let msg = if is_macro {
644 "inner macro attributes are unstable"
645 } else {
646 "custom inner attributes are unstable"
647 };
648 feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit();
649 }
650
651 if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
652 && let [namespace, attribute, ..] = &*path.segments
653 && namespace.ident.name == sym::diagnostic
654 && ![sym::on_unimplemented, sym::do_not_recommend].contains(&attribute.ident.name)
655 {
656 let typo_name = find_best_match_for_name(
657 &[sym::on_unimplemented, sym::do_not_recommend],
658 attribute.ident.name,
659 Some(5),
660 );
661
662 self.tcx.sess.psess.buffer_lint(
663 UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
664 attribute.span(),
665 node_id,
666 BuiltinLintDiag::UnknownDiagnosticAttribute { span: attribute.span(), typo_name },
667 );
668 }
669
670 Ok((ext, res))
671 }
672
673 pub(crate) fn resolve_macro_path(
674 &mut self,
675 path: &ast::Path,
676 kind: Option<MacroKind>,
677 parent_scope: &ParentScope<'ra>,
678 trace: bool,
679 force: bool,
680 ignore_import: Option<Import<'ra>>,
681 ) -> Result<(Option<Arc<SyntaxExtension>>, Res), Determinacy> {
682 self.resolve_macro_or_delegation_path(
683 path,
684 kind,
685 parent_scope,
686 trace,
687 force,
688 None,
689 None,
690 ignore_import,
691 )
692 }
693
694 fn resolve_macro_or_delegation_path(
695 &mut self,
696 ast_path: &ast::Path,
697 kind: Option<MacroKind>,
698 parent_scope: &ParentScope<'ra>,
699 trace: bool,
700 force: bool,
701 deleg_impl: Option<LocalDefId>,
702 invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
703 ignore_import: Option<Import<'ra>>,
704 ) -> Result<(Option<Arc<SyntaxExtension>>, Res), Determinacy> {
705 let path_span = ast_path.span;
706 let mut path = Segment::from_path(ast_path);
707
708 if deleg_impl.is_none()
710 && kind == Some(MacroKind::Bang)
711 && let [segment] = path.as_slice()
712 && segment.ident.span.ctxt().outer_expn_data().local_inner_macros
713 {
714 let root = Ident::new(kw::DollarCrate, segment.ident.span);
715 path.insert(0, Segment::from_ident(root));
716 }
717
718 let res = if deleg_impl.is_some() || path.len() > 1 {
719 let ns = if deleg_impl.is_some() { TypeNS } else { MacroNS };
720 let res = match self.maybe_resolve_path(&path, Some(ns), parent_scope, ignore_import) {
721 PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => Ok(res),
722 PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
723 PathResult::NonModule(..)
724 | PathResult::Indeterminate
725 | PathResult::Failed { .. } => Err(Determinacy::Determined),
726 PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
727 Ok(module.res().unwrap())
728 }
729 PathResult::Module(..) => unreachable!(),
730 };
731
732 if trace {
733 let kind = kind.expect("macro kind must be specified if tracing is enabled");
734 self.multi_segment_macro_resolutions.push((
735 path,
736 path_span,
737 kind,
738 *parent_scope,
739 res.ok(),
740 ns,
741 ));
742 }
743
744 self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
745 res
746 } else {
747 let scope_set = kind.map_or(ScopeSet::All(MacroNS), ScopeSet::Macro);
748 let binding = self.early_resolve_ident_in_lexical_scope(
749 path[0].ident,
750 scope_set,
751 parent_scope,
752 None,
753 force,
754 None,
755 None,
756 );
757 if let Err(Determinacy::Undetermined) = binding {
758 return Err(Determinacy::Undetermined);
759 }
760
761 if trace {
762 let kind = kind.expect("macro kind must be specified if tracing is enabled");
763 self.single_segment_macro_resolutions.push((
764 path[0].ident,
765 kind,
766 *parent_scope,
767 binding.ok(),
768 ));
769 }
770
771 let res = binding.map(|binding| binding.res());
772 self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span);
773 self.report_out_of_scope_macro_calls(
774 ast_path,
775 parent_scope,
776 invoc_in_mod_inert_attr,
777 binding.ok(),
778 );
779 res
780 };
781
782 let res = res?;
783 let ext = match deleg_impl {
784 Some(impl_def_id) => match res {
785 def::Res::Def(DefKind::Trait, def_id) => {
786 let edition = self.tcx.sess.edition();
787 Some(Arc::new(SyntaxExtension::glob_delegation(def_id, impl_def_id, edition)))
788 }
789 _ => None,
790 },
791 None => self.get_macro(res).map(|macro_data| Arc::clone(¯o_data.ext)),
792 };
793 Ok((ext, res))
794 }
795
796 pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) {
797 let check_consistency = |this: &mut Self,
798 path: &[Segment],
799 span,
800 kind: MacroKind,
801 initial_res: Option<Res>,
802 res: Res| {
803 if let Some(initial_res) = initial_res {
804 if res != initial_res {
805 this.dcx().span_delayed_bug(span, "inconsistent resolution for a macro");
809 }
810 } else if this.tcx.dcx().has_errors().is_none() && this.privacy_errors.is_empty() {
811 let err = this.dcx().create_err(CannotDetermineMacroResolution {
820 span,
821 kind: kind.descr(),
822 path: Segment::names_to_string(path),
823 });
824 err.stash(span, StashKey::UndeterminedMacroResolution);
825 }
826 };
827
828 let macro_resolutions = mem::take(&mut self.multi_segment_macro_resolutions);
829 for (mut path, path_span, kind, parent_scope, initial_res, ns) in macro_resolutions {
830 for seg in &mut path {
832 seg.id = None;
833 }
834 match self.resolve_path(
835 &path,
836 Some(ns),
837 &parent_scope,
838 Some(Finalize::new(ast::CRATE_NODE_ID, path_span)),
839 None,
840 None,
841 ) {
842 PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => {
843 check_consistency(self, &path, path_span, kind, initial_res, res)
844 }
845 PathResult::Module(ModuleOrUniformRoot::Module(module)) => check_consistency(
847 self,
848 &path,
849 path_span,
850 kind,
851 initial_res,
852 module.res().unwrap(),
853 ),
854 path_res @ (PathResult::NonModule(..) | PathResult::Failed { .. }) => {
855 let mut suggestion = None;
856 let (span, label, module, segment) =
857 if let PathResult::Failed { span, label, module, segment_name, .. } =
858 path_res
859 {
860 if let PathResult::NonModule(partial_res) =
862 self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope, None)
863 && partial_res.unresolved_segments() == 0
864 {
865 let sm = self.tcx.sess.source_map();
866 let exclamation_span = sm.next_point(span);
867 suggestion = Some((
868 vec![(exclamation_span, "".to_string())],
869 format!(
870 "{} is not a macro, but a {}, try to remove `!`",
871 Segment::names_to_string(&path),
872 partial_res.base_res().descr()
873 ),
874 Applicability::MaybeIncorrect,
875 ));
876 }
877 (span, label, module, segment_name)
878 } else {
879 (
880 path_span,
881 format!(
882 "partially resolved path in {} {}",
883 kind.article(),
884 kind.descr()
885 ),
886 None,
887 path.last().map(|segment| segment.ident.name).unwrap(),
888 )
889 };
890 self.report_error(
891 span,
892 ResolutionError::FailedToResolve {
893 segment: Some(segment),
894 label,
895 suggestion,
896 module,
897 },
898 );
899 }
900 PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
901 }
902 }
903
904 let macro_resolutions = mem::take(&mut self.single_segment_macro_resolutions);
905 for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
906 match self.early_resolve_ident_in_lexical_scope(
907 ident,
908 ScopeSet::Macro(kind),
909 &parent_scope,
910 Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
911 true,
912 None,
913 None,
914 ) {
915 Ok(binding) => {
916 let initial_res = initial_binding.map(|initial_binding| {
917 self.record_use(ident, initial_binding, Used::Other);
918 initial_binding.res()
919 });
920 let res = binding.res();
921 let seg = Segment::from_ident(ident);
922 check_consistency(self, &[seg], ident.span, kind, initial_res, res);
923 if res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat) {
924 let node_id = self
925 .invocation_parents
926 .get(&parent_scope.expansion)
927 .map_or(ast::CRATE_NODE_ID, |parent| {
928 self.def_id_to_node_id[parent.parent_def]
929 });
930 self.lint_buffer.buffer_lint(
931 LEGACY_DERIVE_HELPERS,
932 node_id,
933 ident.span,
934 BuiltinLintDiag::LegacyDeriveHelpers(binding.span),
935 );
936 }
937 }
938 Err(..) => {
939 let expected = kind.descr_expected();
940
941 let mut err = self.dcx().create_err(CannotFindIdentInThisScope {
942 span: ident.span,
943 expected,
944 ident,
945 });
946 self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident, krate);
947 err.emit();
948 }
949 }
950 }
951
952 let builtin_attrs = mem::take(&mut self.builtin_attrs);
953 for (ident, parent_scope) in builtin_attrs {
954 let _ = self.early_resolve_ident_in_lexical_scope(
955 ident,
956 ScopeSet::Macro(MacroKind::Attr),
957 &parent_scope,
958 Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
959 true,
960 None,
961 None,
962 );
963 }
964 }
965
966 fn check_stability_and_deprecation(
967 &mut self,
968 ext: &SyntaxExtension,
969 path: &ast::Path,
970 node_id: NodeId,
971 ) {
972 let span = path.span;
973 if let Some(stability) = &ext.stability {
974 if let StabilityLevel::Unstable { reason, issue, is_soft, implied_by } = stability.level
975 {
976 let feature = stability.feature;
977
978 let is_allowed =
979 |feature| self.tcx.features().enabled(feature) || span.allows_unstable(feature);
980 let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
981 if !is_allowed(feature) && !allowed_by_implication {
982 let lint_buffer = &mut self.lint_buffer;
983 let soft_handler = |lint, span, msg: String| {
984 lint_buffer.buffer_lint(
985 lint,
986 node_id,
987 span,
988 BuiltinLintDiag::UnstableFeature(
989 msg.into(),
991 ),
992 )
993 };
994 stability::report_unstable(
995 self.tcx.sess,
996 feature,
997 reason.to_opt_reason(),
998 issue,
999 None,
1000 is_soft,
1001 span,
1002 soft_handler,
1003 stability::UnstableKind::Regular,
1004 );
1005 }
1006 }
1007 }
1008 if let Some(depr) = &ext.deprecation {
1009 let path = pprust::path_to_string(path);
1010 stability::early_report_macro_deprecation(
1011 &mut self.lint_buffer,
1012 depr,
1013 span,
1014 node_id,
1015 path,
1016 );
1017 }
1018 }
1019
1020 fn prohibit_imported_non_macro_attrs(
1021 &self,
1022 binding: Option<NameBinding<'ra>>,
1023 res: Option<Res>,
1024 span: Span,
1025 ) {
1026 if let Some(Res::NonMacroAttr(kind)) = res {
1027 if kind != NonMacroAttrKind::Tool && binding.is_none_or(|b| b.is_import()) {
1028 let binding_span = binding.map(|binding| binding.span);
1029 self.dcx().emit_err(errors::CannotUseThroughAnImport {
1030 span,
1031 article: kind.article(),
1032 descr: kind.descr(),
1033 binding_span,
1034 });
1035 }
1036 }
1037 }
1038
1039 fn report_out_of_scope_macro_calls(
1040 &mut self,
1041 path: &ast::Path,
1042 parent_scope: &ParentScope<'ra>,
1043 invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
1044 binding: Option<NameBinding<'ra>>,
1045 ) {
1046 if let Some((mod_def_id, node_id)) = invoc_in_mod_inert_attr
1047 && let Some(binding) = binding
1048 && let NameBindingKind::Res(res) = binding.kind
1050 && let Res::Def(DefKind::Macro(MacroKind::Bang), def_id) = res
1051 && self.tcx.is_descendant_of(def_id, mod_def_id.to_def_id())
1054 {
1055 let no_macro_rules = self.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty);
1059 let fallback_binding = self.early_resolve_ident_in_lexical_scope(
1060 path.segments[0].ident,
1061 ScopeSet::Macro(MacroKind::Bang),
1062 &ParentScope { macro_rules: no_macro_rules, ..*parent_scope },
1063 None,
1064 false,
1065 None,
1066 None,
1067 );
1068 if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
1069 let location = match parent_scope.module.kind {
1070 ModuleKind::Def(kind, def_id, name) => {
1071 if let Some(name) = name {
1072 format!("{} `{name}`", kind.descr(def_id))
1073 } else {
1074 "the crate root".to_string()
1075 }
1076 }
1077 ModuleKind::Block => "this scope".to_string(),
1078 };
1079 self.tcx.sess.psess.buffer_lint(
1080 OUT_OF_SCOPE_MACRO_CALLS,
1081 path.span,
1082 node_id,
1083 BuiltinLintDiag::OutOfScopeMacroCalls {
1084 span: path.span,
1085 path: pprust::path_to_string(path),
1086 location,
1087 },
1088 );
1089 }
1090 }
1091 }
1092
1093 pub(crate) fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) {
1094 if ident.name == sym::cfg || ident.name == sym::cfg_attr {
1097 let macro_kind = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kind());
1098 if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
1099 self.dcx()
1100 .emit_err(errors::NameReservedInAttributeNamespace { span: ident.span, ident });
1101 }
1102 }
1103 }
1104
1105 pub(crate) fn compile_macro(
1109 &mut self,
1110 macro_def: &ast::MacroDef,
1111 ident: Ident,
1112 attrs: &[rustc_hir::Attribute],
1113 span: Span,
1114 node_id: NodeId,
1115 edition: Edition,
1116 ) -> MacroData {
1117 let (mut ext, mut rule_spans) = compile_declarative_macro(
1118 self.tcx.sess,
1119 self.tcx.features(),
1120 macro_def,
1121 ident,
1122 attrs,
1123 span,
1124 node_id,
1125 edition,
1126 );
1127
1128 if find_attr!(attrs.iter(), AttributeKind::RustcMacroEdition2021) {
1132 ext.edition = Edition::Edition2021;
1133 }
1134
1135 if let Some(builtin_name) = ext.builtin_name {
1136 if let Some(builtin_ext_kind) = self.builtin_macros.get(&builtin_name) {
1138 ext.kind = builtin_ext_kind.clone();
1141 rule_spans = Vec::new();
1142 } else {
1143 self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { span, ident });
1144 }
1145 }
1146
1147 MacroData { ext: Arc::new(ext), rule_spans, macro_rules: macro_def.macro_rules }
1148 }
1149
1150 fn path_accessible(
1151 &mut self,
1152 expn_id: LocalExpnId,
1153 path: &ast::Path,
1154 namespaces: &[Namespace],
1155 ) -> Result<bool, Indeterminate> {
1156 let span = path.span;
1157 let path = &Segment::from_path(path);
1158 let parent_scope = self.invocation_parent_scopes[&expn_id];
1159
1160 let mut indeterminate = false;
1161 for ns in namespaces {
1162 match self.maybe_resolve_path(path, Some(*ns), &parent_scope, None) {
1163 PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
1164 PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
1165 return Ok(true);
1166 }
1167 PathResult::NonModule(..) |
1168 PathResult::Failed { is_error_from_last_segment: false, .. } => {
1170 self.dcx()
1171 .emit_err(errors::CfgAccessibleUnsure { span });
1172
1173 return Ok(false);
1176 }
1177 PathResult::Indeterminate => indeterminate = true,
1178 PathResult::Failed { .. } => {}
1181 PathResult::Module(_) => panic!("unexpected path resolution"),
1182 }
1183 }
1184
1185 if indeterminate {
1186 return Err(Indeterminate);
1187 }
1188
1189 Ok(false)
1190 }
1191}