@@ -29,7 +29,12 @@ struct This {
2929 _in_token : Token ! [ in] ,
3030}
3131
32- enum InitializerField {
32+ struct InitializerField {
33+ attrs : Vec < Attribute > ,
34+ kind : InitializerKind ,
35+ }
36+
37+ enum InitializerKind {
3338 Value {
3439 ident : Ident ,
3540 value : Option < ( Token ! [ : ] , Expr ) > ,
@@ -46,7 +51,7 @@ enum InitializerField {
4651 } ,
4752}
4853
49- impl InitializerField {
54+ impl InitializerKind {
5055 fn ident ( & self ) -> Option < & Ident > {
5156 match self {
5257 Self :: Value { ident, .. } | Self :: Init { ident, .. } => Some ( ident) ,
@@ -227,10 +232,16 @@ fn init_fields(
227232 slot : & Ident ,
228233) -> TokenStream {
229234 let mut guards = vec ! [ ] ;
235+ let mut guard_attrs = vec ! [ ] ;
230236 let mut res = TokenStream :: new ( ) ;
231- for field in fields {
232- let init = match field {
233- InitializerField :: Value { ident, value } => {
237+ for InitializerField { attrs, kind } in fields {
238+ let cfgs = {
239+ let mut cfgs = attrs. clone ( ) ;
240+ cfgs. retain ( |attr| attr. path ( ) . is_ident ( "cfg" ) ) ;
241+ cfgs
242+ } ;
243+ let init = match kind {
244+ InitializerKind :: Value { ident, value } => {
234245 let mut value_ident = ident. clone ( ) ;
235246 let value_prep = value. as_ref ( ) . map ( |value| & value. 1 ) . map ( |value| {
236247 // Setting the span of `value_ident` to `value`'s span improves error messages
@@ -253,21 +264,24 @@ fn init_fields(
253264 }
254265 } ;
255266 quote ! {
267+ #( #attrs) *
256268 {
257269 #value_prep
258270 // SAFETY: TODO
259271 unsafe { #write( :: core:: ptr:: addr_of_mut!( ( * #slot) . #ident) , #value_ident) } ;
260272 }
273+ #( #cfgs) *
261274 #[ allow( unused_variables) ]
262275 let #ident = #accessor;
263276 }
264277 }
265- InitializerField :: Init { ident, value, .. } => {
278+ InitializerKind :: Init { ident, value, .. } => {
266279 // Again span for better diagnostics
267280 let init = format_ident ! ( "init" , span = value. span( ) ) ;
268281 if pinned {
269282 let project_ident = format_ident ! ( "__project_{ident}" ) ;
270283 quote ! {
284+ #( #attrs) *
271285 {
272286 let #init = #value;
273287 // SAFETY:
@@ -277,12 +291,14 @@ fn init_fields(
277291 // for `#ident`.
278292 unsafe { #data. #ident( :: core:: ptr:: addr_of_mut!( ( * #slot) . #ident) , #init) ? } ;
279293 }
294+ #( #cfgs) *
280295 // SAFETY: TODO
281296 #[ allow( unused_variables) ]
282297 let #ident = unsafe { #data. #project_ident( & mut ( * #slot) . #ident) } ;
283298 }
284299 } else {
285300 quote ! {
301+ #( #attrs) *
286302 {
287303 let #init = #value;
288304 // SAFETY: `slot` is valid, because we are inside of an initializer
@@ -294,20 +310,25 @@ fn init_fields(
294310 ) ?
295311 } ;
296312 }
313+ #( #cfgs) *
297314 // SAFETY: TODO
298315 #[ allow( unused_variables) ]
299316 let #ident = unsafe { & mut ( * #slot) . #ident } ;
300317 }
301318 }
302319 }
303- InitializerField :: Code { block : value, .. } => quote ! ( #[ allow( unused_braces) ] #value) ,
320+ InitializerKind :: Code { block : value, .. } => quote ! {
321+ #( #attrs) *
322+ #[ allow( unused_braces) ]
323+ #value
324+ } ,
304325 } ;
305326 res. extend ( init) ;
306- if let Some ( ident) = field . ident ( ) {
327+ if let Some ( ident) = kind . ident ( ) {
307328 // `mixed_site` ensures that the guard is not accessible to the user-controlled code.
308329 let guard = format_ident ! ( "__{ident}_guard" , span = Span :: mixed_site( ) ) ;
309- guards. push ( guard. clone ( ) ) ;
310330 res. extend ( quote ! {
331+ #( #cfgs) *
311332 // Create the drop guard:
312333 //
313334 // We rely on macro hygiene to make it impossible for users to access this local
@@ -319,13 +340,18 @@ fn init_fields(
319340 )
320341 } ;
321342 } ) ;
343+ guards. push ( guard) ;
344+ guard_attrs. push ( cfgs) ;
322345 }
323346 }
324347 quote ! {
325348 #res
326349 // If execution reaches this point, all fields have been initialized. Therefore we can now
327350 // dismiss the guards by forgetting them.
328- #( :: core:: mem:: forget( #guards) ; ) *
351+ #(
352+ #( #guard_attrs) *
353+ :: core:: mem:: forget( #guards) ;
354+ ) *
329355 }
330356}
331357
@@ -335,7 +361,10 @@ fn make_field_check(
335361 init_kind : InitKind ,
336362 path : & Path ,
337363) -> TokenStream {
338- let fields = fields. iter ( ) . filter_map ( |f| f. ident ( ) ) ;
364+ let field_attrs = fields
365+ . iter ( )
366+ . filter_map ( |f| f. kind . ident ( ) . map ( |_| & f. attrs ) ) ;
367+ let field_name = fields. iter ( ) . filter_map ( |f| f. kind . ident ( ) ) ;
339368 match init_kind {
340369 InitKind :: Normal => quote ! {
341370 // We use unreachable code to ensure that all fields have been mentioned exactly once,
@@ -346,7 +375,8 @@ fn make_field_check(
346375 let _ = || unsafe {
347376 :: core:: ptr:: write( slot, #path {
348377 #(
349- #fields: :: core:: panic!( ) ,
378+ #( #field_attrs) *
379+ #field_name: :: core:: panic!( ) ,
350380 ) *
351381 } )
352382 } ;
@@ -366,7 +396,8 @@ fn make_field_check(
366396 zeroed = :: core:: mem:: zeroed( ) ;
367397 :: core:: ptr:: write( slot, #path {
368398 #(
369- #fields: :: core:: panic!( ) ,
399+ #( #field_attrs) *
400+ #field_name: :: core:: panic!( ) ,
370401 ) *
371402 ..zeroed
372403 } )
@@ -387,7 +418,7 @@ impl Parse for Initializer {
387418 let lh = content. lookahead1 ( ) ;
388419 if lh. peek ( End ) || lh. peek ( Token ! [ ..] ) {
389420 break ;
390- } else if lh. peek ( Ident ) || lh. peek ( Token ! [ _] ) {
421+ } else if lh. peek ( Ident ) || lh. peek ( Token ! [ _] ) || lh . peek ( Token ! [ # ] ) {
391422 fields. push_value ( content. parse ( ) ?) ;
392423 let lh = content. lookahead1 ( ) ;
393424 if lh. peek ( End ) {
@@ -449,6 +480,16 @@ impl Parse for This {
449480}
450481
451482impl Parse for InitializerField {
483+ fn parse ( input : syn:: parse:: ParseStream < ' _ > ) -> syn:: Result < Self > {
484+ let attrs = input. call ( Attribute :: parse_outer) ?;
485+ Ok ( Self {
486+ attrs,
487+ kind : input. parse ( ) ?,
488+ } )
489+ }
490+ }
491+
492+ impl Parse for InitializerKind {
452493 fn parse ( input : syn:: parse:: ParseStream < ' _ > ) -> syn:: Result < Self > {
453494 let lh = input. lookahead1 ( ) ;
454495 if lh. peek ( Token ! [ _] ) {
0 commit comments