@@ -35,6 +35,11 @@ impl Parse for Args {
3535 }
3636}
3737
38+ struct FieldInfo < ' a > {
39+ field : & ' a Field ,
40+ pinned : bool ,
41+ }
42+
3843pub ( crate ) fn pin_data (
3944 args : Args ,
4045 input : Item ,
@@ -73,24 +78,30 @@ pub(crate) fn pin_data(
7378 replacer. visit_generics_mut ( & mut struct_. generics ) ;
7479 replacer. visit_fields_mut ( & mut struct_. fields ) ;
7580
76- let fields: Vec < ( bool , & Field ) > = struct_
81+ let fields: Vec < FieldInfo < ' _ > > = struct_
7782 . fields
7883 . iter_mut ( )
7984 . map ( |field| {
8085 let len = field. attrs . len ( ) ;
8186 field. attrs . retain ( |a| !a. path ( ) . is_ident ( "pin" ) ) ;
82- ( len != field. attrs . len ( ) , & * field)
87+ let pinned = len != field. attrs . len ( ) ;
88+
89+ FieldInfo {
90+ field : & * field,
91+ pinned,
92+ }
8393 } )
8494 . collect ( ) ;
8595
86- for ( pinned, field) in & fields {
87- if !pinned && is_phantom_pinned ( & field. ty ) {
96+ for field in & fields {
97+ let ident = field. field . ident . as_ref ( ) . unwrap ( ) ;
98+
99+ if !field. pinned && is_phantom_pinned ( & field. field . ty ) {
88100 dcx. warn (
89- field,
101+ field. field ,
90102 format ! (
91- "The field `{}` of type `PhantomPinned` only has an effect \
103+ "The field `{ident }` of type `PhantomPinned` only has an effect \
92104 if it has the `#[pin]` attribute",
93- field. ident. as_ref( ) . unwrap( ) ,
94105 ) ,
95106 ) ;
96107 }
@@ -143,7 +154,7 @@ fn is_phantom_pinned(ty: &Type) -> bool {
143154fn generate_unpin_impl (
144155 ident : & Ident ,
145156 generics : & Generics ,
146- fields : & [ ( bool , & Field ) ] ,
157+ fields : & [ FieldInfo < ' _ > ] ,
147158) -> TokenStream {
148159 let ( _, ty_generics, _) = generics. split_for_impl ( ) ;
149160 let mut generics_with_pin_lt = generics. clone ( ) ;
@@ -160,7 +171,7 @@ fn generate_unpin_impl(
160171 else {
161172 unreachable ! ( )
162173 } ;
163- let pinned_fields = fields. iter ( ) . filter_map ( | ( b , f ) | b . then_some ( f ) ) ;
174+ let pinned_fields = fields. iter ( ) . filter ( |f| f . pinned ) . map ( |f| f . field ) ;
164175 quote ! {
165176 // This struct will be used for the unpin analysis. It is needed, because only structurally
166177 // pinned fields are relevant whether the struct should implement `Unpin`.
@@ -238,7 +249,7 @@ fn generate_projections(
238249 vis : & Visibility ,
239250 ident : & Ident ,
240251 generics : & Generics ,
241- fields : & [ ( bool , & Field ) ] ,
252+ fields : & [ FieldInfo < ' _ > ] ,
242253) -> TokenStream {
243254 let ( impl_generics, ty_generics, _) = generics. split_for_impl ( ) ;
244255 let mut generics_with_pin_lt = generics. clone ( ) ;
@@ -249,21 +260,21 @@ fn generate_projections(
249260
250261 let ( fields_decl, fields_proj) : ( Vec < _ > , Vec < _ > ) = fields
251262 . iter ( )
252- . map ( |( pinned , field) | {
263+ . map ( |field| {
253264 let Field {
254265 vis,
255266 ident,
256267 ty,
257268 attrs,
258269 ..
259- } = field;
270+ } = & field . field ;
260271
261272 let mut no_doc_attrs = attrs. clone ( ) ;
262273 no_doc_attrs. retain ( |a| !a. path ( ) . is_ident ( "doc" ) ) ;
263274 let ident = ident
264275 . as_ref ( )
265276 . expect ( "only structs with named fields are supported" ) ;
266- if * pinned {
277+ if field . pinned {
267278 (
268279 quote ! (
269280 #( #attrs) *
@@ -291,12 +302,12 @@ fn generate_projections(
291302 . collect ( ) ;
292303 let structurally_pinned_fields_docs = fields
293304 . iter ( )
294- . filter_map ( | ( pinned , field ) | pinned . then_some ( field ) )
295- . map ( |Field { ident , .. } | format ! ( " - `{}`" , ident. as_ref( ) . unwrap( ) ) ) ;
305+ . filter ( |f| f . pinned )
306+ . map ( |f | format ! ( " - `{}`" , f . field . ident. as_ref( ) . unwrap( ) ) ) ;
296307 let not_structurally_pinned_fields_docs = fields
297308 . iter ( )
298- . filter_map ( | ( pinned , field ) | ( !pinned ) . then_some ( field ) )
299- . map ( |Field { ident , .. } | format ! ( " - `{}`" , ident. as_ref( ) . unwrap( ) ) ) ;
309+ . filter ( |f| !f . pinned )
310+ . map ( |f | format ! ( " - `{}`" , f . field . ident. as_ref( ) . unwrap( ) ) ) ;
300311 let docs = format ! ( " Pin-projections of [`{ident}`]" ) ;
301312 quote ! {
302313 #[ doc = #docs]
@@ -336,9 +347,9 @@ fn generate_projections(
336347
337348fn generate_the_pin_data (
338349 vis : & Visibility ,
339- ident : & Ident ,
350+ struct_name : & Ident ,
340351 generics : & Generics ,
341- fields : & [ ( bool , & Field ) ] ,
352+ fields : & [ FieldInfo < ' _ > ] ,
342353) -> TokenStream {
343354 let ( impl_generics, ty_generics, whr) = generics. split_for_impl ( ) ;
344355
@@ -347,78 +358,74 @@ fn generate_the_pin_data(
347358 // not structurally pinned, then it can be initialized via `Init`.
348359 //
349360 // The functions are `unsafe` to prevent accidentally calling them.
350- fn handle_field (
351- Field {
352- vis,
353- ident,
354- ty,
355- attrs,
356- ..
357- } : & Field ,
358- struct_ident : & Ident ,
359- pinned : bool ,
360- ) -> TokenStream {
361- let ident = ident
362- . as_ref ( )
363- . expect ( "only structs with named fields are supported" ) ;
364- let project_ident = format_ident ! ( "__project_{ident}" ) ;
365- let ( init_ty, init_fn, project_ty, project_body, pin_safety) = if pinned {
366- (
367- quote ! ( PinInit ) ,
368- quote ! ( __pinned_init) ,
369- quote ! ( :: core:: pin:: Pin <& ' __slot mut #ty>) ,
370- // SAFETY: this field is structurally pinned.
371- quote ! ( unsafe { :: core:: pin:: Pin :: new_unchecked( slot) } ) ,
372- quote ! (
373- /// - `slot` will not move until it is dropped, i.e. it will be pinned.
374- ) ,
375- )
376- } else {
377- (
378- quote ! ( Init ) ,
379- quote ! ( __init) ,
380- quote ! ( & ' __slot mut #ty) ,
381- quote ! ( slot) ,
382- quote ! ( ) ,
383- )
384- } ;
385- let slot_safety = format ! (
386- " `slot` points at the field `{ident}` inside of `{struct_ident}`, which is pinned." ,
387- ) ;
388- quote ! {
389- /// # Safety
390- ///
391- /// - `slot` is a valid pointer to uninitialized memory.
392- /// - the caller does not touch `slot` when `Err` is returned, they are only permitted
393- /// to deallocate.
394- #pin_safety
395- #( #attrs) *
396- #vis unsafe fn #ident<E >(
397- self ,
398- slot: * mut #ty,
399- init: impl :: pin_init:: #init_ty<#ty, E >,
400- ) -> :: core:: result:: Result <( ) , E > {
401- // SAFETY: this function has the same safety requirements as the __init function
402- // called below.
403- unsafe { :: pin_init:: #init_ty:: #init_fn( init, slot) }
404- }
405-
406- /// # Safety
407- ///
408- #[ doc = #slot_safety]
409- #( #attrs) *
410- #vis unsafe fn #project_ident<' __slot>(
411- self ,
412- slot: & ' __slot mut #ty,
413- ) -> #project_ty {
414- #project_body
415- }
416- }
417- }
418-
419361 let field_accessors = fields
420362 . iter ( )
421- . map ( |( pinned, field) | handle_field ( field, ident, * pinned) )
363+ . map ( |f| {
364+ let Field {
365+ vis,
366+ ident,
367+ ty,
368+ attrs,
369+ ..
370+ } = f. field ;
371+
372+ let field_name = ident
373+ . as_ref ( )
374+ . expect ( "only structs with named fields are supported" ) ;
375+ let project_ident = format_ident ! ( "__project_{field_name}" ) ;
376+ let ( init_ty, init_fn, project_ty, project_body, pin_safety) = if f. pinned {
377+ (
378+ quote ! ( PinInit ) ,
379+ quote ! ( __pinned_init) ,
380+ quote ! ( :: core:: pin:: Pin <& ' __slot mut #ty>) ,
381+ // SAFETY: this field is structurally pinned.
382+ quote ! ( unsafe { :: core:: pin:: Pin :: new_unchecked( slot) } ) ,
383+ quote ! (
384+ /// - `slot` will not move until it is dropped, i.e. it will be pinned.
385+ ) ,
386+ )
387+ } else {
388+ (
389+ quote ! ( Init ) ,
390+ quote ! ( __init) ,
391+ quote ! ( & ' __slot mut #ty) ,
392+ quote ! ( slot) ,
393+ quote ! ( ) ,
394+ )
395+ } ;
396+ let slot_safety = format ! (
397+ " `slot` points at the field `{field_name}` inside of `{struct_name}`, which is pinned." ,
398+ ) ;
399+ quote ! {
400+ /// # Safety
401+ ///
402+ /// - `slot` is a valid pointer to uninitialized memory.
403+ /// - the caller does not touch `slot` when `Err` is returned, they are only
404+ /// permitted to deallocate.
405+ #pin_safety
406+ #( #attrs) *
407+ #vis unsafe fn #field_name<E >(
408+ self ,
409+ slot: * mut #ty,
410+ init: impl :: pin_init:: #init_ty<#ty, E >,
411+ ) -> :: core:: result:: Result <( ) , E > {
412+ // SAFETY: this function has the same safety requirements as the __init function
413+ // called below.
414+ unsafe { :: pin_init:: #init_ty:: #init_fn( init, slot) }
415+ }
416+
417+ /// # Safety
418+ ///
419+ #[ doc = #slot_safety]
420+ #( #attrs) *
421+ #vis unsafe fn #project_ident<' __slot>(
422+ self ,
423+ slot: & ' __slot mut #ty,
424+ ) -> #project_ty {
425+ #project_body
426+ }
427+ }
428+ } )
422429 . collect :: < TokenStream > ( ) ;
423430 quote ! {
424431 // We declare this struct which will host all of the projection function for our type. It
@@ -428,7 +435,7 @@ fn generate_the_pin_data(
428435 #whr
429436 {
430437 __phantom: :: core:: marker:: PhantomData <
431- fn ( #ident #ty_generics) -> #ident #ty_generics
438+ fn ( #struct_name #ty_generics) -> #struct_name #ty_generics
432439 >,
433440 }
434441
@@ -452,7 +459,7 @@ fn generate_the_pin_data(
452459
453460 // SAFETY: We have added the correct projection functions above to `__ThePinData` and
454461 // we also use the least restrictive generics possible.
455- unsafe impl #impl_generics :: pin_init:: __internal:: HasPinData for #ident #ty_generics
462+ unsafe impl #impl_generics :: pin_init:: __internal:: HasPinData for #struct_name #ty_generics
456463 #whr
457464 {
458465 type PinData = __ThePinData #ty_generics;
@@ -466,7 +473,7 @@ fn generate_the_pin_data(
466473 unsafe impl #impl_generics :: pin_init:: __internal:: PinData for __ThePinData #ty_generics
467474 #whr
468475 {
469- type Datee = #ident #ty_generics;
476+ type Datee = #struct_name #ty_generics;
470477 }
471478 }
472479}
0 commit comments