@@ -27,7 +27,12 @@ struct This {
2727 _in_token : Token ! [ in] ,
2828}
2929
30- enum InitializerField {
30+ struct InitializerField {
31+ attrs : Vec < Attribute > ,
32+ kind : InitializerKind ,
33+ }
34+
35+ enum InitializerKind {
3136 Value {
3237 ident : Ident ,
3338 value : Option < ( Token ! [ : ] , Expr ) > ,
@@ -44,7 +49,7 @@ enum InitializerField {
4449 } ,
4550}
4651
47- impl InitializerField {
52+ impl InitializerKind {
4853 fn ident ( & self ) -> Option < & Ident > {
4954 match self {
5055 Self :: Value { ident, .. } | Self :: Init { ident, .. } => Some ( ident) ,
@@ -229,10 +234,16 @@ fn init_fields(
229234 slot : & Ident ,
230235) -> TokenStream {
231236 let mut guards = vec ! [ ] ;
237+ let mut guard_attrs = vec ! [ ] ;
232238 let mut res = TokenStream :: new ( ) ;
233- for field in fields {
234- let init = match field {
235- InitializerField :: Value { ident, value } => {
239+ for InitializerField { attrs, kind } in fields {
240+ let cfgs = {
241+ let mut cfgs = attrs. clone ( ) ;
242+ cfgs. retain ( |attr| attr. path ( ) . is_ident ( "cfg" ) || attr. path ( ) . is_ident ( "cfg_attr" ) ) ;
243+ cfgs
244+ } ;
245+ let init = match kind {
246+ InitializerKind :: Value { ident, value } => {
236247 let mut value_ident = ident. clone ( ) ;
237248 let value_prep = value. as_ref ( ) . map ( |value| & value. 1 ) . map ( |value| {
238249 // Setting the span of `value_ident` to `value`'s span improves error messages
@@ -255,21 +266,24 @@ fn init_fields(
255266 }
256267 } ;
257268 quote ! {
269+ #( #attrs) *
258270 {
259271 #value_prep
260272 // SAFETY: TODO
261273 unsafe { #write( :: core:: ptr:: addr_of_mut!( ( * #slot) . #ident) , #value_ident) } ;
262274 }
275+ #( #cfgs) *
263276 #[ allow( unused_variables) ]
264277 let #ident = #accessor;
265278 }
266279 }
267- InitializerField :: Init { ident, value, .. } => {
280+ InitializerKind :: Init { ident, value, .. } => {
268281 // Again span for better diagnostics
269282 let init = format_ident ! ( "init" , span = value. span( ) ) ;
270283 if pinned {
271284 let project_ident = format_ident ! ( "__project_{ident}" ) ;
272285 quote ! {
286+ #( #attrs) *
273287 {
274288 let #init = #value;
275289 // SAFETY:
@@ -279,12 +293,14 @@ fn init_fields(
279293 // for `#ident`.
280294 unsafe { #data. #ident( :: core:: ptr:: addr_of_mut!( ( * #slot) . #ident) , #init) ? } ;
281295 }
296+ #( #cfgs) *
282297 // SAFETY: TODO
283298 #[ allow( unused_variables) ]
284299 let #ident = unsafe { #data. #project_ident( & mut ( * #slot) . #ident) } ;
285300 }
286301 } else {
287302 quote ! {
303+ #( #attrs) *
288304 {
289305 let #init = #value;
290306 // SAFETY: `slot` is valid, because we are inside of an initializer
@@ -296,20 +312,25 @@ fn init_fields(
296312 ) ?
297313 } ;
298314 }
315+ #( #cfgs) *
299316 // SAFETY: TODO
300317 #[ allow( unused_variables) ]
301318 let #ident = unsafe { & mut ( * #slot) . #ident } ;
302319 }
303320 }
304321 }
305- InitializerField :: Code { block : value, .. } => quote ! ( #[ allow( unused_braces) ] #value) ,
322+ InitializerKind :: Code { block : value, .. } => quote ! {
323+ #( #attrs) *
324+ #[ allow( unused_braces) ]
325+ #value
326+ } ,
306327 } ;
307328 res. extend ( init) ;
308- if let Some ( ident) = field . ident ( ) {
329+ if let Some ( ident) = kind . ident ( ) {
309330 // `mixed_site` ensures that the guard is not accessible to the user-controlled code.
310331 let guard = format_ident ! ( "__{ident}_guard" , span = Span :: mixed_site( ) ) ;
311- guards. push ( guard. clone ( ) ) ;
312332 res. extend ( quote ! {
333+ #( #cfgs) *
313334 // Create the drop guard:
314335 //
315336 // We rely on macro hygiene to make it impossible for users to access this local
@@ -321,13 +342,18 @@ fn init_fields(
321342 )
322343 } ;
323344 } ) ;
345+ guards. push ( guard) ;
346+ guard_attrs. push ( cfgs) ;
324347 }
325348 }
326349 quote ! {
327350 #res
328351 // If execution reaches this point, all fields have been initialized. Therefore we can now
329352 // dismiss the guards by forgetting them.
330- #( :: core:: mem:: forget( #guards) ; ) *
353+ #(
354+ #( #guard_attrs) *
355+ :: core:: mem:: forget( #guards) ;
356+ ) *
331357 }
332358}
333359
@@ -337,7 +363,10 @@ fn make_field_check(
337363 init_kind : InitKind ,
338364 path : & Path ,
339365) -> TokenStream {
340- let fields = fields. iter ( ) . filter_map ( |f| f. ident ( ) ) ;
366+ let field_attrs = fields
367+ . iter ( )
368+ . filter_map ( |f| f. kind . ident ( ) . map ( |_| & f. attrs ) ) ;
369+ let field_name = fields. iter ( ) . filter_map ( |f| f. kind . ident ( ) ) ;
341370 match init_kind {
342371 InitKind :: Normal => quote ! {
343372 // We use unreachable code to ensure that all fields have been mentioned exactly once,
@@ -348,7 +377,8 @@ fn make_field_check(
348377 let _ = || unsafe {
349378 :: core:: ptr:: write( slot, #path {
350379 #(
351- #fields: :: core:: panic!( ) ,
380+ #( #field_attrs) *
381+ #field_name: :: core:: panic!( ) ,
352382 ) *
353383 } )
354384 } ;
@@ -368,7 +398,8 @@ fn make_field_check(
368398 zeroed = :: core:: mem:: zeroed( ) ;
369399 :: core:: ptr:: write( slot, #path {
370400 #(
371- #fields: :: core:: panic!( ) ,
401+ #( #field_attrs) *
402+ #field_name: :: core:: panic!( ) ,
372403 ) *
373404 ..zeroed
374405 } )
@@ -389,7 +420,7 @@ impl Parse for Initializer {
389420 let lh = content. lookahead1 ( ) ;
390421 if lh. peek ( End ) || lh. peek ( Token ! [ ..] ) {
391422 break ;
392- } else if lh. peek ( Ident ) || lh. peek ( Token ! [ _] ) {
423+ } else if lh. peek ( Ident ) || lh. peek ( Token ! [ _] ) || lh . peek ( Token ! [ # ] ) {
393424 fields. push_value ( content. parse ( ) ?) ;
394425 let lh = content. lookahead1 ( ) ;
395426 if lh. peek ( End ) {
@@ -451,6 +482,16 @@ impl Parse for This {
451482}
452483
453484impl Parse for InitializerField {
485+ fn parse ( input : syn:: parse:: ParseStream < ' _ > ) -> syn:: Result < Self > {
486+ let attrs = input. call ( Attribute :: parse_outer) ?;
487+ Ok ( Self {
488+ attrs,
489+ kind : input. parse ( ) ?,
490+ } )
491+ }
492+ }
493+
494+ impl Parse for InitializerKind {
454495 fn parse ( input : syn:: parse:: ParseStream < ' _ > ) -> syn:: Result < Self > {
455496 let lh = input. lookahead1 ( ) ;
456497 if lh. peek ( Token ! [ _] ) {
0 commit comments