@@ -25,7 +25,12 @@ struct This {
2525 _in_token : Token ! [ in] ,
2626}
2727
28- enum InitializerField {
28+ struct InitializerField {
29+ attrs : Vec < Attribute > ,
30+ kind : InitializerKind ,
31+ }
32+
33+ enum InitializerKind {
2934 Value {
3035 ident : Ident ,
3136 value : Option < ( Token ! [ : ] , Expr ) > ,
@@ -42,7 +47,7 @@ enum InitializerField {
4247 } ,
4348}
4449
45- impl InitializerField {
50+ impl InitializerKind {
4651 fn ident ( & self ) -> Option < & Ident > {
4752 match self {
4853 Self :: Value { ident, .. } | Self :: Init { ident, .. } => Some ( ident) ,
@@ -224,10 +229,11 @@ fn init_fields(
224229 slot : & Ident ,
225230) -> TokenStream {
226231 let mut guards = vec ! [ ] ;
232+ let mut guard_attrs = vec ! [ ] ;
227233 let mut res = TokenStream :: new ( ) ;
228- for field in fields {
229- let init = match field {
230- InitializerField :: Value { ident, value } => {
234+ for InitializerField { attrs , kind } in fields {
235+ let init = match kind {
236+ InitializerKind :: Value { ident, value } => {
231237 let mut value_ident = ident. clone ( ) ;
232238 let value_prep = value. as_ref ( ) . map ( |value| & value. 1 ) . map ( |value| {
233239 // Setting the span of `value_ident` to `value`'s span improves error messages
@@ -250,21 +256,24 @@ fn init_fields(
250256 }
251257 } ;
252258 quote ! {
259+ #( #attrs) *
253260 {
254261 #value_prep
255262 // SAFETY: TODO
256263 unsafe { #write( :: core:: ptr:: addr_of_mut!( ( * #slot) . #ident) , #value_ident) } ;
257264 }
265+ #( #attrs) *
258266 #[ allow( unused_variables) ]
259267 let #ident = #accessor;
260268 }
261269 }
262- InitializerField :: Init { ident, value, .. } => {
270+ InitializerKind :: Init { ident, value, .. } => {
263271 // Again span for better diagnostics
264272 let init = format_ident ! ( "init" , span = value. span( ) ) ;
265273 if pinned {
266274 let project_ident = format_ident ! ( "__project_{ident}" ) ;
267275 quote ! {
276+ #( #attrs) *
268277 {
269278 let #init = #value;
270279 // SAFETY:
@@ -274,12 +283,14 @@ fn init_fields(
274283 // for `#ident`.
275284 unsafe { #data. #ident( :: core:: ptr:: addr_of_mut!( ( * #slot) . #ident) , #init) ? } ;
276285 }
286+ #( #attrs) *
277287 // SAFETY: TODO
278288 #[ allow( unused_variables) ]
279289 let #ident = unsafe { #data. #project_ident( & mut ( * #slot) . #ident) } ;
280290 }
281291 } else {
282292 quote ! {
293+ #( #attrs) *
283294 {
284295 let #init = #value;
285296 // SAFETY: `slot` is valid, because we are inside of an initializer
@@ -291,20 +302,25 @@ fn init_fields(
291302 ) ?
292303 } ;
293304 }
305+ #( #attrs) *
294306 // SAFETY: TODO
295307 #[ allow( unused_variables) ]
296308 let #ident = unsafe { & mut ( * #slot) . #ident } ;
297309 }
298310 }
299311 }
300- InitializerField :: Code { block : value, .. } => quote ! ( #[ allow( unused_braces) ] #value) ,
312+ InitializerKind :: Code { block : value, .. } => quote ! {
313+ #( #attrs) *
314+ #[ allow( unused_braces) ]
315+ #value
316+ } ,
301317 } ;
302318 res. extend ( init) ;
303- if let Some ( ident) = field . ident ( ) {
319+ if let Some ( ident) = kind . ident ( ) {
304320 // `mixed_site` ensures that the guard is not accessible to the user-controlled code.
305321 let guard = format_ident ! ( "__{ident}_guard" , span = Span :: mixed_site( ) ) ;
306- guards. push ( guard. clone ( ) ) ;
307322 res. extend ( quote ! {
323+ #( #attrs) *
308324 // Create the drop guard:
309325 //
310326 // We rely on macro hygiene to make it impossible for users to access this local
@@ -316,13 +332,18 @@ fn init_fields(
316332 )
317333 } ;
318334 } ) ;
335+ guards. push ( guard) ;
336+ guard_attrs. push ( attrs) ;
319337 }
320338 }
321339 quote ! {
322340 #res
323341 // If execution reaches this point, all fields have been initialized. Therefore we can now
324342 // dismiss the guards by forgetting them.
325- #( :: core:: mem:: forget( #guards) ; ) *
343+ #(
344+ #( #guard_attrs) *
345+ :: core:: mem:: forget( #guards) ;
346+ ) *
326347 }
327348}
328349
@@ -332,7 +353,10 @@ fn make_field_check(
332353 init_kind : InitKind ,
333354 path : & Path ,
334355) -> TokenStream {
335- let fields = fields. iter ( ) . filter_map ( |f| f. ident ( ) ) ;
356+ let field_attrs = fields
357+ . iter ( )
358+ . filter_map ( |f| f. kind . ident ( ) . map ( |_| & f. attrs ) ) ;
359+ let field_name = fields. iter ( ) . filter_map ( |f| f. kind . ident ( ) ) ;
336360 match init_kind {
337361 InitKind :: Normal => quote ! {
338362 // We use unreachable code to ensure that all fields have been mentioned exactly once,
@@ -343,7 +367,8 @@ fn make_field_check(
343367 let _ = || unsafe {
344368 :: core:: ptr:: write( slot, #path {
345369 #(
346- #fields: :: core:: panic!( ) ,
370+ #( #field_attrs) *
371+ #field_name: :: core:: panic!( ) ,
347372 ) *
348373 } )
349374 } ;
@@ -361,7 +386,8 @@ fn make_field_check(
361386 zeroed = :: core:: mem:: zeroed( ) ;
362387 :: core:: ptr:: write( slot, #path {
363388 #(
364- #fields: :: core:: panic!( ) ,
389+ #( #field_attrs) *
390+ #field_name: :: core:: panic!( ) ,
365391 ) *
366392 ..zeroed
367393 } )
@@ -382,7 +408,7 @@ impl Parse for Initializer {
382408 let lh = content. lookahead1 ( ) ;
383409 if lh. peek ( End ) || lh. peek ( Token ! [ ..] ) {
384410 break ;
385- } else if lh. peek ( Ident ) || lh. peek ( Token ! [ _] ) {
411+ } else if lh. peek ( Ident ) || lh. peek ( Token ! [ _] ) || lh . peek ( Token ! [ # ] ) {
386412 fields. push_value ( content. parse ( ) ?) ;
387413 let lh = content. lookahead1 ( ) ;
388414 if lh. peek ( End ) {
@@ -448,6 +474,16 @@ impl Parse for This {
448474}
449475
450476impl Parse for InitializerField {
477+ fn parse ( input : syn:: parse:: ParseStream ) -> syn:: Result < Self > {
478+ let attrs = input. call ( Attribute :: parse_outer) ?;
479+ Ok ( Self {
480+ attrs,
481+ kind : input. parse ( ) ?,
482+ } )
483+ }
484+ }
485+
486+ impl Parse for InitializerKind {
451487 fn parse ( input : syn:: parse:: ParseStream ) -> syn:: Result < Self > {
452488 let lh = input. lookahead1 ( ) ;
453489 if lh. peek ( Token ! [ _] ) {
0 commit comments