@@ -31,7 +31,7 @@ impl<'a> DefCollector<'a> {
31
31
self . definitions . create_def_with_parent ( parent_def, node_id, data, self . expansion , span)
32
32
}
33
33
34
- pub fn with_parent < F : FnOnce ( & mut Self ) > ( & mut self , parent_def : DefIndex , f : F ) {
34
+ fn with_parent < F : FnOnce ( & mut Self ) > ( & mut self , parent_def : DefIndex , f : F ) {
35
35
let orig_parent_def = std:: mem:: replace ( & mut self . parent_def , parent_def) ;
36
36
f ( self ) ;
37
37
self . parent_def = orig_parent_def;
@@ -74,6 +74,22 @@ impl<'a> DefCollector<'a> {
74
74
} )
75
75
}
76
76
77
+ fn collect_field ( & mut self , field : & ' a StructField , index : Option < usize > ) {
78
+ if field. is_placeholder {
79
+ self . visit_macro_invoc ( field. id ) ;
80
+ } else {
81
+ let name = field. ident . map ( |ident| ident. name )
82
+ . or_else ( || index. map ( sym:: integer) )
83
+ . unwrap_or_else ( || {
84
+ let node_id = NodeId :: placeholder_from_expn_id ( self . expansion ) ;
85
+ sym:: integer ( self . definitions . placeholder_field_indices [ & node_id] )
86
+ } )
87
+ . as_interned_str ( ) ;
88
+ let def = self . create_def ( field. id , DefPathData :: ValueNs ( name) , field. span ) ;
89
+ self . with_parent ( def, |this| visit:: walk_struct_field ( this, field) ) ;
90
+ }
91
+ }
92
+
77
93
pub fn visit_macro_invoc ( & mut self , id : NodeId ) {
78
94
self . definitions . set_invocation_parent ( id. placeholder_to_expn_id ( ) , self . parent_def ) ;
79
95
}
@@ -170,17 +186,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
170
186
}
171
187
172
188
fn visit_variant_data ( & mut self , data : & ' a VariantData ) {
189
+ // The assumption here is that non-`cfg` macro expansion cannot change field indices.
190
+ // It currently holds because only inert attributes are accepted on fields,
191
+ // and every such attribute expands into a single field after it's resolved.
173
192
for ( index, field) in data. fields ( ) . iter ( ) . enumerate ( ) {
174
- if field . is_placeholder {
175
- self . visit_macro_invoc ( field. id ) ;
176
- continue ;
193
+ self . collect_field ( field , Some ( index ) ) ;
194
+ if field . is_placeholder && field. ident . is_none ( ) {
195
+ self . definitions . placeholder_field_indices . insert ( field . id , index ) ;
177
196
}
178
- let name = field. ident . map ( |ident| ident. name )
179
- . unwrap_or_else ( || sym:: integer ( index) ) ;
180
- let def = self . create_def ( field. id ,
181
- DefPathData :: ValueNs ( name. as_interned_str ( ) ) ,
182
- field. span ) ;
183
- self . with_parent ( def, |this| visit:: walk_struct_field ( this, field) ) ;
184
197
}
185
198
}
186
199
@@ -338,16 +351,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
338
351
}
339
352
}
340
353
341
- fn visit_struct_field ( & mut self , sf : & ' a StructField ) {
342
- if sf. is_placeholder {
343
- self . visit_macro_invoc ( sf. id )
344
- } else {
345
- let name = sf. ident . map ( |ident| ident. name )
346
- . unwrap_or_else ( || panic ! ( "don't know the field number in this context" ) ) ;
347
- let def = self . create_def ( sf. id ,
348
- DefPathData :: ValueNs ( name. as_interned_str ( ) ) ,
349
- sf. span ) ;
350
- self . with_parent ( def, |this| visit:: walk_struct_field ( this, sf) ) ;
351
- }
354
+ // This method is called only when we are visiting an individual field
355
+ // after expanding an attribute on it.
356
+ fn visit_struct_field ( & mut self , field : & ' a StructField ) {
357
+ self . collect_field ( field, None ) ;
352
358
}
353
359
}
0 commit comments