@@ -5,7 +5,7 @@ use crate::errors::CannotDetermineMacroResolution;
55use crate :: errors:: { self , AddAsNonDerive , CannotFindIdentInThisScope } ;
66use crate :: errors:: { MacroExpectedFound , RemoveSurroundingDerive } ;
77use crate :: Namespace :: * ;
8- use crate :: { BindingKey , BuiltinMacroState , Determinacy , MacroData , Used } ;
8+ use crate :: { BindingKey , BuiltinMacroState , Determinacy , MacroData , NameBindingKind , Used } ;
99use crate :: { DeriveData , Finalize , ParentScope , ResolutionError , Resolver , ScopeSet } ;
1010use crate :: { ModuleKind , ModuleOrUniformRoot , NameBinding , PathResult , Segment , ToNameBinding } ;
1111use rustc_ast:: expand:: StrippedCfgItem ;
@@ -18,15 +18,18 @@ use rustc_errors::{Applicability, StashKey};
1818use rustc_expand:: base:: { Annotatable , DeriveResolution , Indeterminate , ResolverExpand } ;
1919use rustc_expand:: base:: { SyntaxExtension , SyntaxExtensionKind } ;
2020use rustc_expand:: compile_declarative_macro;
21- use rustc_expand:: expand:: { AstFragment , Invocation , InvocationKind , SupportsMacroExpansion } ;
21+ use rustc_expand:: expand:: {
22+ AstFragment , AstFragmentKind , Invocation , InvocationKind , SupportsMacroExpansion ,
23+ } ;
2224use rustc_hir:: def:: { self , DefKind , Namespace , NonMacroAttrKind } ;
2325use rustc_hir:: def_id:: { CrateNum , DefId , LocalDefId } ;
2426use rustc_middle:: middle:: stability;
2527use rustc_middle:: ty:: RegisteredTools ;
2628use rustc_middle:: ty:: { TyCtxt , Visibility } ;
27- use rustc_session:: lint:: builtin:: UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES ;
28- use rustc_session:: lint:: builtin:: { LEGACY_DERIVE_HELPERS , SOFT_UNSTABLE } ;
29- use rustc_session:: lint:: builtin:: { UNUSED_MACROS , UNUSED_MACRO_RULES } ;
29+ use rustc_session:: lint:: builtin:: {
30+ LEGACY_DERIVE_HELPERS , OUT_OF_SCOPE_MACRO_CALLS , SOFT_UNSTABLE ,
31+ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES , UNUSED_MACROS , UNUSED_MACRO_RULES ,
32+ } ;
3033use rustc_session:: lint:: BuiltinLintDiag ;
3134use rustc_session:: parse:: feature_err;
3235use rustc_span:: edit_distance:: edit_distance;
@@ -288,6 +291,16 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
288291 let parent_scope = & ParentScope { derives, ..parent_scope } ;
289292 let supports_macro_expansion = invoc. fragment_kind . supports_macro_expansion ( ) ;
290293 let node_id = invoc. expansion_data . lint_node_id ;
294+ // This is a heuristic, but it's good enough for the lint.
295+ let looks_like_invoc_in_mod_inert_attr = self
296+ . invocation_parents
297+ . get ( & invoc_id)
298+ . or_else ( || self . invocation_parents . get ( & eager_expansion_root) )
299+ . map ( |& ( mod_def_id, _) | mod_def_id)
300+ . filter ( |& mod_def_id| {
301+ invoc. fragment_kind == AstFragmentKind :: Expr
302+ && self . tcx . def_kind ( mod_def_id) == DefKind :: Mod
303+ } ) ;
291304 let ( ext, res) = self . smart_resolve_macro_path (
292305 path,
293306 kind,
@@ -298,6 +311,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
298311 force,
299312 soft_custom_inner_attributes_gate ( path, invoc) ,
300313 deleg_impl,
314+ looks_like_invoc_in_mod_inert_attr,
301315 ) ?;
302316
303317 let span = invoc. span ( ) ;
@@ -520,6 +534,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
520534 force : bool ,
521535 soft_custom_inner_attributes_gate : bool ,
522536 deleg_impl : Option < LocalDefId > ,
537+ invoc_in_mod_inert_attr : Option < LocalDefId > ,
523538 ) -> Result < ( Lrc < SyntaxExtension > , Res ) , Indeterminate > {
524539 let ( ext, res) = match self . resolve_macro_or_delegation_path (
525540 path,
@@ -528,6 +543,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
528543 true ,
529544 force,
530545 deleg_impl,
546+ invoc_in_mod_inert_attr. map ( |def_id| ( def_id, node_id) ) ,
531547 ) {
532548 Ok ( ( Some ( ext) , res) ) => ( ext, res) ,
533549 Ok ( ( None , res) ) => ( self . dummy_ext ( kind) , res) ,
@@ -682,20 +698,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
682698 trace : bool ,
683699 force : bool ,
684700 ) -> Result < ( Option < Lrc < SyntaxExtension > > , Res ) , Determinacy > {
685- self . resolve_macro_or_delegation_path ( path, kind, parent_scope, trace, force, None )
701+ self . resolve_macro_or_delegation_path ( path, kind, parent_scope, trace, force, None , None )
686702 }
687703
688704 fn resolve_macro_or_delegation_path (
689705 & mut self ,
690- path : & ast:: Path ,
706+ ast_path : & ast:: Path ,
691707 kind : Option < MacroKind > ,
692708 parent_scope : & ParentScope < ' a > ,
693709 trace : bool ,
694710 force : bool ,
695711 deleg_impl : Option < LocalDefId > ,
712+ invoc_in_mod_inert_attr : Option < ( LocalDefId , NodeId ) > ,
696713 ) -> Result < ( Option < Lrc < SyntaxExtension > > , Res ) , Determinacy > {
697- let path_span = path . span ;
698- let mut path = Segment :: from_path ( path ) ;
714+ let path_span = ast_path . span ;
715+ let mut path = Segment :: from_path ( ast_path ) ;
699716
700717 // Possibly apply the macro helper hack
701718 if deleg_impl. is_none ( )
@@ -761,6 +778,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
761778
762779 let res = binding. map ( |binding| binding. res ( ) ) ;
763780 self . prohibit_imported_non_macro_attrs ( binding. ok ( ) , res. ok ( ) , path_span) ;
781+ self . report_out_of_scope_macro_calls (
782+ ast_path,
783+ parent_scope,
784+ invoc_in_mod_inert_attr,
785+ binding. ok ( ) ,
786+ ) ;
764787 res
765788 } ;
766789
@@ -1013,6 +1036,45 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
10131036 }
10141037 }
10151038
1039+ fn report_out_of_scope_macro_calls (
1040+ & mut self ,
1041+ path : & ast:: Path ,
1042+ parent_scope : & ParentScope < ' a > ,
1043+ invoc_in_mod_inert_attr : Option < ( LocalDefId , NodeId ) > ,
1044+ binding : Option < NameBinding < ' a > > ,
1045+ ) {
1046+ if let Some ( ( mod_def_id, node_id) ) = invoc_in_mod_inert_attr
1047+ && let Some ( binding) = binding
1048+ // This is a `macro_rules` itself, not some import.
1049+ && let NameBindingKind :: Res ( res) = binding. kind
1050+ && let Res :: Def ( DefKind :: Macro ( MacroKind :: Bang ) , def_id) = res
1051+ // And the `macro_rules` is defined inside the attribute's module,
1052+ // so it cannot be in scope unless imported.
1053+ && self . tcx . is_descendant_of ( def_id, mod_def_id. to_def_id ( ) )
1054+ {
1055+ // Try to resolve our ident ignoring `macro_rules` scopes.
1056+ // If such resolution is successful and gives the same result
1057+ // (e.g. if the macro is re-imported), then silence the lint.
1058+ 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+ ) ;
1067+ if fallback_binding. ok ( ) . and_then ( |b| b. res ( ) . opt_def_id ( ) ) != Some ( def_id) {
1068+ self . tcx . sess . psess . buffer_lint (
1069+ OUT_OF_SCOPE_MACRO_CALLS ,
1070+ path. span ,
1071+ node_id,
1072+ BuiltinLintDiag :: OutOfScopeMacroCalls { path : pprust:: path_to_string ( path) } ,
1073+ ) ;
1074+ }
1075+ }
1076+ }
1077+
10161078 pub ( crate ) fn check_reserved_macro_name ( & mut self , ident : Ident , res : Res ) {
10171079 // Reserve some names that are not quite covered by the general check
10181080 // performed on `Resolver::builtin_attrs`.
0 commit comments