@@ -7,9 +7,12 @@ use syn::{
77 parse_quote, parse_quote_spanned,
88 spanned:: Spanned ,
99 visit_mut:: VisitMut ,
10- Error , Field , Ident , Item , ItemStruct , PathSegment , Result , Type , TypePath , WhereClause ,
10+ Error , Field , Fields , Ident , Item , ItemStruct , PathSegment , Result , Type , TypePath ,
11+ WhereClause ,
1112} ;
1213
14+ use crate :: member:: Member ;
15+
1316pub ( crate ) mod kw {
1417 syn:: custom_keyword!( PinnedDrop ) ;
1518}
@@ -171,8 +174,13 @@ fn generate_unpin_impl(
171174 let ( _, ty_generics, _) = generics. split_for_impl ( ) ;
172175 let mut pinned_fields = fields
173176 . iter ( )
174- . filter ( |f| is_field_structurally_pinned ( f) )
175- . cloned ( )
177+ . enumerate ( )
178+ . filter ( |( _, f) | is_field_structurally_pinned ( f) )
179+ . map ( |( i, f) | {
180+ let mut f = f. clone ( ) ;
181+ f. ident . get_or_insert_with ( || format_ident ! ( "_{i}" ) ) ;
182+ f
183+ } )
176184 . collect :: < Vec < _ > > ( ) ;
177185 for field in & mut pinned_fields {
178186 field. attrs . retain ( |a| !a. path ( ) . is_ident ( "pin" ) ) ;
@@ -271,42 +279,55 @@ fn generate_projections(
271279 let projection = format_ident ! ( "{ident}Projection" ) ;
272280 let this = format_ident ! ( "this" ) ;
273281
274- let ( fields_decl, fields_proj) = collect_tuple ( fields. iter ( ) . map (
275- |f @ Field {
276- vis,
277- ident,
278- ty,
279- attrs,
280- ..
281- } | {
282+ let ( fields_decl, fields_proj) = collect_tuple ( fields. iter ( ) . enumerate ( ) . map (
283+ |(
284+ idx,
285+ f @ Field {
286+ vis,
287+ ident,
288+ ty,
289+ attrs,
290+ ..
291+ } ,
292+ ) | {
282293 let mut attrs = attrs. clone ( ) ;
283294 attrs. retain ( |a| !a. path ( ) . is_ident ( "pin" ) ) ;
284295 let mut no_doc_attrs = attrs. clone ( ) ;
285296 no_doc_attrs. retain ( |a| !a. path ( ) . is_ident ( "doc" ) ) ;
286- let ident = ident
287- . as_ref ( )
288- . expect ( "only structs with named fields are supported" ) ;
289- if is_field_structurally_pinned ( f) {
297+ let ty = if is_field_structurally_pinned ( f) {
298+ quote ! ( :: core:: pin:: Pin <& ' __pin mut #ty>)
299+ } else {
300+ quote ! ( & ' __pin mut #ty)
301+ } ;
302+ let m = Member :: new ( idx, ident. as_ref ( ) ) ;
303+ let access = if is_field_structurally_pinned ( f) {
304+ quote ! (
305+ // SAFETY: this field is structurally pinned.
306+ unsafe { :: core:: pin:: Pin :: new_unchecked( & mut #this. #m) }
307+ )
308+ } else {
309+ quote ! ( & mut #this. #m)
310+ } ;
311+ if ident. is_some ( ) {
290312 (
291313 quote ! (
292314 #( #attrs) *
293- #vis #ident: :: core :: pin :: Pin < & ' __pin mut #ty> ,
315+ #vis #ident: #ty,
294316 ) ,
295317 quote ! (
296318 #( #no_doc_attrs) *
297- // SAFETY: this field is structurally pinned.
298- #ident: unsafe { :: core:: pin:: Pin :: new_unchecked( & mut #this. #ident) } ,
319+ #ident: #access,
299320 ) ,
300321 )
301322 } else {
302323 (
303324 quote ! (
304325 #( #attrs) *
305- #vis #ident : & ' __pin mut # ty,
326+ #vis #ty,
306327 ) ,
307328 quote ! (
308329 #( #no_doc_attrs) *
309- #ident : & mut #this . #ident ,
330+ #access ,
310331 ) ,
311332 )
312333 }
@@ -315,49 +336,91 @@ fn generate_projections(
315336 let structurally_pinned_fields_docs = fields
316337 . iter ( )
317338 . filter ( |f| is_field_structurally_pinned ( f) )
318- . map ( |Field { ident, .. } | {
319- let doc = format ! ( " - `{}`" , ident. as_ref( ) . expect( "" ) ) ;
339+ . enumerate ( )
340+ . map ( |( i, Field { ident, .. } ) | {
341+ let doc = match ident. as_ref ( ) {
342+ Some ( ident) => format ! ( " - `{ident}`" ) ,
343+ None => format ! ( "- `{i}`" ) ,
344+ } ;
320345 quote ! ( #[ doc = #doc] )
321346 } ) ;
322347 let not_structurally_pinned_fields_docs = fields
323348 . iter ( )
324349 . filter ( |f| !is_field_structurally_pinned ( f) )
325- . map ( |Field { ident, .. } | {
326- let doc = format ! ( " - `{}`" , ident. as_ref( ) . expect( "" ) ) ;
350+ . enumerate ( )
351+ . map ( |( i, Field { ident, .. } ) | {
352+ let doc = match ident. as_ref ( ) {
353+ Some ( ident) => format ! ( " - `{ident}`" ) ,
354+ None => format ! ( "- `{i}`" ) ,
355+ } ;
327356 quote ! ( #[ doc = #doc] )
328357 } ) ;
329358 let docs = format ! ( " Pin-projections of [`{ident}`]" ) ;
330- quote ! {
331- #[ doc = #docs]
332- #[ allow( dead_code) ]
333- #[ doc( hidden) ]
334- #vis struct #projection #generics {
335- #( #fields_decl) *
336- ___pin_phantom_data: :: core:: marker:: PhantomData <& ' __pin mut ( ) >,
337- }
359+ match fields {
360+ Fields :: Unit | Fields :: Named ( _) => quote ! {
361+ #[ doc = #docs]
362+ #[ allow( dead_code) ]
363+ #[ doc( hidden) ]
364+ #vis struct #projection #generics {
365+ #( #fields_decl) *
366+ ___pin_phantom_data: :: core:: marker:: PhantomData <& ' __pin mut ( ) >,
367+ }
338368
339- impl #og_impl_gen #ident #og_ty_gen
340- #whr
341- {
342- /// Pin-projects all fields of `Self`.
343- ///
344- /// These fields are structurally pinned:
345- #( #structurally_pinned_fields_docs) *
346- ///
347- /// These fields are **not** structurally pinned:
348- #( #not_structurally_pinned_fields_docs) *
349- #[ inline]
350- #vis fn project<' __pin>(
351- self : :: core:: pin:: Pin <& ' __pin mut Self >,
352- ) -> #projection #ty_gen {
353- // SAFETY: we only give access to `&mut` for fields not structurally pinned.
354- let #this = unsafe { :: core:: pin:: Pin :: get_unchecked_mut( self ) } ;
355- #projection {
356- #( #fields_proj) *
357- ___pin_phantom_data: :: core:: marker:: PhantomData ,
369+ impl #og_impl_gen #ident #og_ty_gen
370+ #whr
371+ {
372+ /// Pin-projects all fields of `Self`.
373+ ///
374+ /// These fields are structurally pinned:
375+ #( #structurally_pinned_fields_docs) *
376+ ///
377+ /// These fields are **not** structurally pinned:
378+ #( #not_structurally_pinned_fields_docs) *
379+ #[ inline]
380+ #vis fn project<' __pin>(
381+ self : :: core:: pin:: Pin <& ' __pin mut Self >,
382+ ) -> #projection #ty_gen {
383+ // SAFETY: we only give access to `&mut` for fields not structurally pinned.
384+ let #this = unsafe { :: core:: pin:: Pin :: get_unchecked_mut( self ) } ;
385+ #projection {
386+ #( #fields_proj) *
387+ ___pin_phantom_data: :: core:: marker:: PhantomData ,
388+ }
358389 }
359390 }
360- }
391+ } ,
392+ Fields :: Unnamed ( _) => quote ! {
393+ #[ doc = #docs]
394+ #[ allow( dead_code) ]
395+ #[ doc( hidden) ]
396+ #vis struct #projection #generics (
397+ #( #fields_decl) *
398+ :: core:: marker:: PhantomData <& ' __pin mut ( ) >,
399+ ) ;
400+
401+ impl #og_impl_gen #ident #og_ty_gen
402+ #whr
403+ {
404+ /// Pin-projects all fields of `Self`.
405+ ///
406+ /// These fields are structurally pinned:
407+ #( #structurally_pinned_fields_docs) *
408+ ///
409+ /// These fields are **not** structurally pinned:
410+ #( #not_structurally_pinned_fields_docs) *
411+ #[ inline]
412+ #vis fn project<' __pin>(
413+ self : :: core:: pin:: Pin <& ' __pin mut Self >,
414+ ) -> #projection #ty_gen {
415+ // SAFETY: we only give access to `&mut` for fields not structurally pinned.
416+ let #this = unsafe { :: core:: pin:: Pin :: get_unchecked_mut( self ) } ;
417+ #projection(
418+ #( #fields_proj) *
419+ :: core:: marker:: PhantomData ,
420+ )
421+ }
422+ }
423+ } ,
361424 }
362425}
363426
@@ -378,6 +441,7 @@ fn generate_the_pin_data(
378441 //
379442 // The functions are `unsafe` to prevent accidentally calling them.
380443 fn handle_field (
444+ idx : usize ,
381445 Field {
382446 vis,
383447 ident,
@@ -390,10 +454,12 @@ fn generate_the_pin_data(
390454 ) -> TokenStream {
391455 let mut attrs = attrs. clone ( ) ;
392456 attrs. retain ( |a| !a. path ( ) . is_ident ( "pin" ) ) ;
393- let ident = ident
394- . as_ref ( )
395- . expect ( "only structs with named fields are supported" ) ;
396- let project_ident = format_ident ! ( "__project_{ident}" ) ;
457+ let m = Member :: new ( idx, ident. as_ref ( ) ) ;
458+ let fun_ident = match & m {
459+ Member :: Named ( ident) => ident. clone ( ) ,
460+ Member :: Unnamed ( idx) => format_ident ! ( "_{}" , idx) ,
461+ } ;
462+ let project_ident = format_ident ! ( "__project_{}" , m) ;
397463 let ( init_ty, init_fn, project_ty, project_body, pin_safety) = if pinned {
398464 (
399465 quote ! ( PinInit ) ,
@@ -415,7 +481,7 @@ fn generate_the_pin_data(
415481 )
416482 } ;
417483 let slot_safety = format ! (
418- " `slot` points at the field `{ident }` inside of `{struct_ident}`, which is pinned." ,
484+ " `slot` points at the field `{m }` inside of `{struct_ident}`, which is pinned." ,
419485 ) ;
420486 quote ! {
421487 /// # Safety
@@ -425,7 +491,7 @@ fn generate_the_pin_data(
425491 /// to deallocate.
426492 #pin_safety
427493 #( #attrs) *
428- #vis unsafe fn #ident <E >(
494+ #vis unsafe fn #fun_ident <E >(
429495 self ,
430496 slot: * mut #ty,
431497 init: impl :: pin_init:: #init_ty<#ty, E >,
@@ -439,6 +505,7 @@ fn generate_the_pin_data(
439505 ///
440506 #[ doc = #slot_safety]
441507 #( #attrs) *
508+ #[ allow( non_snake_case) ]
442509 #vis unsafe fn #project_ident<' __slot>(
443510 self ,
444511 slot: & ' __slot mut #ty,
@@ -450,7 +517,8 @@ fn generate_the_pin_data(
450517
451518 let field_accessors = fields
452519 . iter ( )
453- . map ( |f| handle_field ( f, ident, is_field_structurally_pinned ( f) ) )
520+ . enumerate ( )
521+ . map ( |( i, f) | handle_field ( i, f, ident, is_field_structurally_pinned ( f) ) )
454522 . collect :: < TokenStream > ( ) ;
455523 quote ! {
456524 // We declare this struct which will host all of the projection function for our type. It
0 commit comments