@@ -10,8 +10,8 @@ use crate::resolve_imports::ImportResolver;
1010use rustc:: hir:: def:: { self , DefKind , NonMacroAttrKind } ;
1111use rustc:: middle:: stability;
1212use rustc:: { ty, lint, span_bug} ;
13- use syntax:: ast:: { self , NodeId , Ident } ;
14- use syntax:: attr:: StabilityLevel ;
13+ use syntax:: ast:: { self , NodeId , Ident , Mac , Attribute } ;
14+ use syntax:: attr:: { self , StabilityLevel } ;
1515use syntax:: edition:: Edition ;
1616use syntax:: ext:: base:: { self , Indeterminate , SpecialDerives } ;
1717use syntax:: ext:: base:: { MacroKind , SyntaxExtension } ;
@@ -21,6 +21,7 @@ use syntax::ext::tt::macro_rules;
2121use syntax:: feature_gate:: { emit_feature_err, is_builtin_attr_name} ;
2222use syntax:: feature_gate:: GateIssue ;
2323use syntax:: symbol:: { Symbol , kw, sym} ;
24+ use syntax:: visit:: Visitor ;
2425use syntax_pos:: { Span , DUMMY_SP } ;
2526
2627use std:: { mem, ptr} ;
@@ -54,6 +55,21 @@ pub enum LegacyScope<'a> {
5455 Invocation ( ExpnId ) ,
5556}
5657
58+ struct MarkDeriveHelpers < ' a > ( & ' a [ ast:: Name ] ) ;
59+
60+ impl < ' a > Visitor < ' a > for MarkDeriveHelpers < ' a > {
61+ fn visit_attribute ( & mut self , attr : & Attribute ) {
62+ if let Some ( ident) = attr. ident ( ) {
63+ if self . 0 . contains ( & ident. name ) {
64+ attr:: mark_used ( attr) ;
65+ attr:: mark_known ( attr) ;
66+ }
67+ }
68+ }
69+
70+ fn visit_mac ( & mut self , _mac : & Mac ) { }
71+ }
72+
5773// Macro namespace is separated into two sub-namespaces, one for bang macros and
5874// one for attribute-like macros (attributes, derives).
5975// We ignore resolutions from one sub-namespace when searching names in scope for another.
@@ -164,26 +180,37 @@ impl<'a> base::Resolver for Resolver<'a> {
164180 ( & mac. path , MacroKind :: Bang , & [ ] [ ..] , false ) ,
165181 InvocationKind :: Derive { ref path, .. } =>
166182 ( path, MacroKind :: Derive , & [ ] [ ..] , false ) ,
167- InvocationKind :: DeriveContainer { ref derives, .. } => {
168- // Block expansion of derives in the container until we know whether one of them
169- // is a built-in `Copy`. Skip the resolution if there's only one derive - either
170- // it's not a `Copy` and we don't need to do anything, or it's a `Copy` and it
171- // will automatically knows about itself.
172- let mut result = Ok ( None ) ;
173- if derives. len ( ) > 1 {
174- for path in derives {
175- match self . resolve_macro_path ( path, Some ( MacroKind :: Derive ) ,
176- & parent_scope, true , force) {
177- Ok ( ( Some ( ref ext) , _) ) if ext. is_derive_copy => {
183+ InvocationKind :: DeriveContainer { ref derives, ref item } => {
184+ // Block expansion of the container until we resolve all derives in it.
185+ // This is required for two reasons:
186+ // - Derive helper attributes are in scope for the item to which the `#[derive]`
187+ // is applied, so they have to be produced by the container's expansion rather
188+ // than by individual derives.
189+ // - Derives in the container need to know whether one of them is a built-in `Copy`.
190+ // FIXME: Try to avoid repeated resolutions for derives here and in expansion.
191+ let mut derive_helpers = Vec :: new ( ) ;
192+ for path in derives {
193+ match self . resolve_macro_path (
194+ path, Some ( MacroKind :: Derive ) , & parent_scope, true , force
195+ ) {
196+ Ok ( ( Some ( ref ext) , _) ) => {
197+ derive_helpers. extend ( & ext. helper_attrs ) ;
198+ if ext. is_derive_copy {
178199 self . add_derives ( invoc_id, SpecialDerives :: COPY ) ;
179- return Ok ( None ) ;
180200 }
181- Err ( Determinacy :: Undetermined ) => result = Err ( Indeterminate ) ,
182- _ => { }
183201 }
202+ Ok ( _) | Err ( Determinacy :: Determined ) => { }
203+ Err ( Determinacy :: Undetermined ) => return Err ( Indeterminate ) ,
184204 }
185205 }
186- return result;
206+
207+ // Mark derive helpers inside this item as known and used.
208+ // FIXME: This is a hack, derive helpers should be integrated with regular name
209+ // resolution instead. For example, helpers introduced by a derive container
210+ // can be in scope for all code produced by that container's expansion.
211+ item. visit_with ( & mut MarkDeriveHelpers ( & derive_helpers) ) ;
212+
213+ return Ok ( None ) ;
187214 }
188215 } ;
189216
0 commit comments