@@ -45,7 +45,7 @@ use syntax::symbol::{kw, sym};
4545use syntax:: source_map:: Spanned ;
4646use syntax:: visit:: { self , Visitor } ;
4747use syntax_expand:: base:: SyntaxExtension ;
48- use syntax_pos:: hygiene:: { MacroKind , ExpnId , Transparency , SyntaxContext } ;
48+ use syntax_pos:: hygiene:: { MacroKind , ExpnId , ExpnKind , Transparency , SyntaxContext } ;
4949use syntax_pos:: { Span , DUMMY_SP } ;
5050use errors:: { Applicability , DiagnosticBuilder } ;
5151
@@ -97,6 +97,7 @@ impl Determinacy {
9797/// but not for late resolution yet.
9898#[ derive( Clone , Copy ) ]
9999enum Scope < ' a > {
100+ DeriveHelpers ( ExpnId ) ,
100101 DeriveHelpersCompat ,
101102 MacroRules ( LegacyScope < ' a > ) ,
102103 CrateRoot ,
@@ -942,6 +943,8 @@ pub struct Resolver<'a> {
942943 /// Legacy scopes *produced* by expanding the macro invocations,
943944 /// include all the `macro_rules` items and other invocations generated by them.
944945 output_legacy_scopes : FxHashMap < ExpnId , LegacyScope < ' a > > ,
946+ /// Helper attributes that are in scope for the given expansion.
947+ helper_attrs : FxHashMap < ExpnId , Vec < Ident > > ,
945948
946949 /// Avoid duplicated errors for "name already defined".
947950 name_already_seen : FxHashMap < Name , Span > ,
@@ -1219,6 +1222,7 @@ impl<'a> Resolver<'a> {
12191222 non_macro_attrs : [ non_macro_attr ( false ) , non_macro_attr ( true ) ] ,
12201223 invocation_parent_scopes,
12211224 output_legacy_scopes : Default :: default ( ) ,
1225+ helper_attrs : Default :: default ( ) ,
12221226 macro_defs,
12231227 local_macro_def_scopes : FxHashMap :: default ( ) ,
12241228 name_already_seen : FxHashMap :: default ( ) ,
@@ -1467,23 +1471,26 @@ impl<'a> Resolver<'a> {
14671471 // in prelude, not sure where exactly (creates ambiguities with any other prelude names).
14681472
14691473 let rust_2015 = ident. span . rust_2015 ( ) ;
1470- let ( ns, is_absolute_path) = match scope_set {
1471- ScopeSet :: All ( ns, _) => ( ns, false ) ,
1472- ScopeSet :: AbsolutePath ( ns) => ( ns, true ) ,
1473- ScopeSet :: Macro ( _ ) => ( MacroNS , false ) ,
1474+ let ( ns, macro_kind , is_absolute_path) = match scope_set {
1475+ ScopeSet :: All ( ns, _) => ( ns, None , false ) ,
1476+ ScopeSet :: AbsolutePath ( ns) => ( ns, None , true ) ,
1477+ ScopeSet :: Macro ( macro_kind ) => ( MacroNS , Some ( macro_kind ) , false ) ,
14741478 } ;
14751479 // Jump out of trait or enum modules, they do not act as scopes.
14761480 let module = parent_scope. module . nearest_item_scope ( ) ;
14771481 let mut scope = match ns {
14781482 _ if is_absolute_path => Scope :: CrateRoot ,
14791483 TypeNS | ValueNS => Scope :: Module ( module) ,
1480- MacroNS => Scope :: DeriveHelpersCompat ,
1484+ MacroNS => Scope :: DeriveHelpers ( parent_scope . expansion ) ,
14811485 } ;
14821486 let mut ident = ident. modern ( ) ;
14831487 let mut use_prelude = !module. no_implicit_prelude ;
14841488
14851489 loop {
14861490 let visit = match scope {
1491+ // Derive helpers are not in scope when resolving derives in the same container.
1492+ Scope :: DeriveHelpers ( expn_id) =>
1493+ !( expn_id == parent_scope. expansion && macro_kind == Some ( MacroKind :: Derive ) ) ,
14871494 Scope :: DeriveHelpersCompat => true ,
14881495 Scope :: MacroRules ( ..) => true ,
14891496 Scope :: CrateRoot => true ,
@@ -1505,6 +1512,17 @@ impl<'a> Resolver<'a> {
15051512 }
15061513
15071514 scope = match scope {
1515+ Scope :: DeriveHelpers ( expn_id) if expn_id != ExpnId :: root ( ) => {
1516+ // Derive helpers are not visible to code generated by bang or derive macros.
1517+ let expn_data = expn_id. expn_data ( ) ;
1518+ match expn_data. kind {
1519+ ExpnKind :: Root |
1520+ ExpnKind :: Macro ( MacroKind :: Bang , _) |
1521+ ExpnKind :: Macro ( MacroKind :: Derive , _) => Scope :: DeriveHelpersCompat ,
1522+ _ => Scope :: DeriveHelpers ( expn_data. parent ) ,
1523+ }
1524+ }
1525+ Scope :: DeriveHelpers ( ..) => Scope :: DeriveHelpersCompat ,
15081526 Scope :: DeriveHelpersCompat =>
15091527 Scope :: MacroRules ( parent_scope. legacy ) ,
15101528 Scope :: MacroRules ( legacy_scope) => match legacy_scope {
0 commit comments