@@ -831,6 +831,17 @@ macro_rules! __pin_data {
831831 $( $fields) *
832832 }
833833
834+ $crate:: __pin_data!( make_pin_projections:
835+ @vis( $vis) ,
836+ @name( $name) ,
837+ @impl_generics( $( $impl_generics) * ) ,
838+ @ty_generics( $( $ty_generics) * ) ,
839+ @decl_generics( $( $decl_generics) * ) ,
840+ @where ( $( $whr) * ) ,
841+ @pinned( $( $pinned) * ) ,
842+ @not_pinned( $( $not_pinned) * ) ,
843+ ) ;
844+
834845 // We put the rest into this const item, because it then will not be accessible to anything
835846 // outside.
836847 const _: ( ) = {
@@ -980,6 +991,56 @@ macro_rules! __pin_data {
980991 stringify!( $( $rest) * ) ,
981992 ) ;
982993 } ;
994+ ( make_pin_projections:
995+ @vis( $vis: vis) ,
996+ @name( $name: ident) ,
997+ @impl_generics( $( $impl_generics: tt) * ) ,
998+ @ty_generics( $( $ty_generics: tt) * ) ,
999+ @decl_generics( $( $decl_generics: tt) * ) ,
1000+ @where ( $( $whr: tt) * ) ,
1001+ @pinned( $( $( #[ $( $p_attr: tt) * ] ) * $pvis: vis $p_field: ident : $p_type: ty) ,* $( , ) ?) ,
1002+ @not_pinned( $( $( #[ $( $attr: tt) * ] ) * $fvis: vis $field: ident : $type: ty) ,* $( , ) ?) ,
1003+ ) => {
1004+ $crate:: macros:: paste! {
1005+ #[ doc( hidden) ]
1006+ $vis struct [ < $name Projection >] <' __pin, $( $decl_generics) * > {
1007+ $( $( #[ $( $p_attr) * ] ) * $pvis $p_field : :: core:: pin:: Pin <& ' __pin mut $p_type>, ) *
1008+ $( $( #[ $( $attr) * ] ) * $fvis $field : & ' __pin mut $type, ) *
1009+ ___pin_phantom_data: :: core:: marker:: PhantomData <& ' __pin mut ( ) >,
1010+ }
1011+
1012+ impl <$( $impl_generics) * > $name<$( $ty_generics) * >
1013+ where $( $whr) *
1014+ {
1015+ /// Pin-projects all fields of `Self`.
1016+ ///
1017+ /// These fields are structurally pinned:
1018+ $( #[ doc = :: core:: concat!( " - `" , :: core:: stringify!( $p_field) , "`" ) ] ) *
1019+ ///
1020+ /// These fields are **not** structurally pinned:
1021+ $( #[ doc = :: core:: concat!( " - `" , :: core:: stringify!( $field) , "`" ) ] ) *
1022+ #[ inline]
1023+ $vis fn project<' __pin>(
1024+ self : :: core:: pin:: Pin <& ' __pin mut Self >,
1025+ ) -> [ < $name Projection >] <' __pin, $( $ty_generics) * > {
1026+ // SAFETY: we only give access to `&mut` for fields not structurally pinned.
1027+ let this = unsafe { :: core:: pin:: Pin :: get_unchecked_mut( self ) } ;
1028+ [ < $name Projection >] {
1029+ $(
1030+ // SAFETY: `$p_field` is structurally pinned.
1031+ $( #[ $( $p_attr) * ] ) *
1032+ $p_field : unsafe { :: core:: pin:: Pin :: new_unchecked( & mut this. $p_field) } ,
1033+ ) *
1034+ $(
1035+ $( #[ $( $attr) * ] ) *
1036+ $field : & mut this. $field,
1037+ ) *
1038+ ___pin_phantom_data: :: core:: marker:: PhantomData ,
1039+ }
1040+ }
1041+ }
1042+ }
1043+ } ;
9831044 ( make_pin_data:
9841045 @pin_data( $pin_data: ident) ,
9851046 @impl_generics( $( $impl_generics: tt) * ) ,
@@ -988,38 +1049,56 @@ macro_rules! __pin_data {
9881049 @pinned( $( $( #[ $( $p_attr: tt) * ] ) * $pvis: vis $p_field: ident : $p_type: ty) ,* $( , ) ?) ,
9891050 @not_pinned( $( $( #[ $( $attr: tt) * ] ) * $fvis: vis $field: ident : $type: ty) ,* $( , ) ?) ,
9901051 ) => {
991- // For every field, we create a projection function according to its projection type. If a
992- // field is structurally pinned, then it must be initialized via `PinInit`, if it is not
993- // structurally pinned, then it can be initialized via `Init`.
994- //
995- // The functions are `unsafe` to prevent accidentally calling them.
996- #[ allow( dead_code) ]
997- #[ expect( clippy:: missing_safety_doc) ]
998- impl <$( $impl_generics) * > $pin_data<$( $ty_generics) * >
999- where $( $whr) *
1000- {
1001- $(
1002- $( #[ $( $p_attr) * ] ) *
1003- $pvis unsafe fn $p_field<E >(
1004- self ,
1005- slot: * mut $p_type,
1006- init: impl $crate:: PinInit <$p_type, E >,
1007- ) -> :: core:: result:: Result <( ) , E > {
1008- // SAFETY: TODO.
1009- unsafe { $crate:: PinInit :: __pinned_init( init, slot) }
1010- }
1011- ) *
1012- $(
1013- $( #[ $( $attr) * ] ) *
1014- $fvis unsafe fn $field<E >(
1015- self ,
1016- slot: * mut $type,
1017- init: impl $crate:: Init <$type, E >,
1018- ) -> :: core:: result:: Result <( ) , E > {
1019- // SAFETY: TODO.
1020- unsafe { $crate:: Init :: __init( init, slot) }
1021- }
1022- ) *
1052+ $crate:: macros:: paste! {
1053+ // For every field, we create a projection function according to its projection type. If a
1054+ // field is structurally pinned, then it must be initialized via `PinInit`, if it is not
1055+ // structurally pinned, then it can be initialized via `Init`.
1056+ //
1057+ // The functions are `unsafe` to prevent accidentally calling them.
1058+ #[ allow( dead_code) ]
1059+ #[ expect( clippy:: missing_safety_doc) ]
1060+ impl <$( $impl_generics) * > $pin_data<$( $ty_generics) * >
1061+ where $( $whr) *
1062+ {
1063+ $(
1064+ $( #[ $( $p_attr) * ] ) *
1065+ $pvis unsafe fn $p_field<E >(
1066+ self ,
1067+ slot: * mut $p_type,
1068+ init: impl $crate:: PinInit <$p_type, E >,
1069+ ) -> :: core:: result:: Result <( ) , E > {
1070+ // SAFETY: TODO.
1071+ unsafe { $crate:: PinInit :: __pinned_init( init, slot) }
1072+ }
1073+
1074+ $( #[ $( $p_attr) * ] ) *
1075+ $pvis unsafe fn [ <__project_ $p_field>] <' __slot>(
1076+ self ,
1077+ slot: & ' __slot mut $p_type,
1078+ ) -> :: core:: pin:: Pin <& ' __slot mut $p_type> {
1079+ :: core:: pin:: Pin :: new_unchecked( slot)
1080+ }
1081+ ) *
1082+ $(
1083+ $( #[ $( $attr) * ] ) *
1084+ $fvis unsafe fn $field<E >(
1085+ self ,
1086+ slot: * mut $type,
1087+ init: impl $crate:: Init <$type, E >,
1088+ ) -> :: core:: result:: Result <( ) , E > {
1089+ // SAFETY: TODO.
1090+ unsafe { $crate:: Init :: __init( init, slot) }
1091+ }
1092+
1093+ $( #[ $( $attr) * ] ) *
1094+ $fvis unsafe fn [ <__project_ $field>] <' __slot>(
1095+ self ,
1096+ slot: & ' __slot mut $type,
1097+ ) -> & ' __slot mut $type {
1098+ slot
1099+ }
1100+ ) *
1101+ }
10231102 }
10241103 } ;
10251104}
@@ -1202,6 +1281,21 @@ macro_rules! __init_internal {
12021281 // have been initialized. Therefore we can now dismiss the guards by forgetting them.
12031282 $( :: core:: mem:: forget( $guards) ; ) *
12041283 } ;
1284+ ( init_slot( $( $use_data: ident) ?) :
1285+ @data( $data: ident) ,
1286+ @slot( $slot: ident) ,
1287+ @guards( $( $guards: ident, ) * ) ,
1288+ // arbitrary code block
1289+ @munch_fields( _: { $( $code: tt) * } , $( $rest: tt) * ) ,
1290+ ) => {
1291+ { $( $code) * }
1292+ $crate:: __init_internal!( init_slot( $( $use_data) ?) :
1293+ @data( $data) ,
1294+ @slot( $slot) ,
1295+ @guards( $( $guards, ) * ) ,
1296+ @munch_fields( $( $rest) * ) ,
1297+ ) ;
1298+ } ;
12051299 ( init_slot( $use_data: ident) : // `use_data` is present, so we use the `data` to init fields.
12061300 @data( $data: ident) ,
12071301 @slot( $slot: ident) ,
@@ -1216,6 +1310,13 @@ macro_rules! __init_internal {
12161310 // return when an error/panic occurs.
12171311 // We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`.
12181312 unsafe { $data. $field( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , init) ? } ;
1313+ // SAFETY:
1314+ // - the project function does the correct field projection,
1315+ // - the field has been initialized,
1316+ // - the reference is only valid until the end of the initializer.
1317+ #[ allow( unused_variables) ]
1318+ let $field = $crate:: macros:: paste!( unsafe { $data. [ < __project_ $field >] ( & mut ( * $slot) . $field) } ) ;
1319+
12191320 // Create the drop guard:
12201321 //
12211322 // We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1247,6 +1348,14 @@ macro_rules! __init_internal {
12471348 // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
12481349 // return when an error/panic occurs.
12491350 unsafe { $crate:: Init :: __init( init, :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) ) ? } ;
1351+
1352+ // SAFETY:
1353+ // - the field is not structurally pinned, since the line above must compile,
1354+ // - the field has been initialized,
1355+ // - the reference is only valid until the end of the initializer.
1356+ #[ allow( unused_variables) ]
1357+ let $field = unsafe { & mut ( * $slot) . $field } ;
1358+
12501359 // Create the drop guard:
12511360 //
12521361 // We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1265,7 +1374,48 @@ macro_rules! __init_internal {
12651374 ) ;
12661375 }
12671376 } ;
1268- ( init_slot( $( $use_data: ident) ?) :
1377+ ( init_slot( ) : // No `use_data`, so all fields are not structurally pinned
1378+ @data( $data: ident) ,
1379+ @slot( $slot: ident) ,
1380+ @guards( $( $guards: ident, ) * ) ,
1381+ // Init by-value.
1382+ @munch_fields( $field: ident $( : $val: expr) ?, $( $rest: tt) * ) ,
1383+ ) => {
1384+ {
1385+ $( let $field = $val; ) ?
1386+ // Initialize the field.
1387+ //
1388+ // SAFETY: The memory at `slot` is uninitialized.
1389+ unsafe { :: core:: ptr:: write( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) } ;
1390+ }
1391+
1392+ #[ allow( unused_variables) ]
1393+ // SAFETY:
1394+ // - the field is not structurally pinned, since no `use_data` was required to create this
1395+ // initializer,
1396+ // - the field has been initialized,
1397+ // - the reference is only valid until the end of the initializer.
1398+ let $field = unsafe { & mut ( * $slot) . $field } ;
1399+
1400+ // Create the drop guard:
1401+ //
1402+ // We rely on macro hygiene to make it impossible for users to access this local variable.
1403+ // We use `paste!` to create new hygiene for `$field`.
1404+ $crate:: macros:: paste! {
1405+ // SAFETY: We forget the guard later when initialization has succeeded.
1406+ let [ < __ $field _guard >] = unsafe {
1407+ $crate:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
1408+ } ;
1409+
1410+ $crate:: __init_internal!( init_slot( ) :
1411+ @data( $data) ,
1412+ @slot( $slot) ,
1413+ @guards( [ < __ $field _guard >] , $( $guards, ) * ) ,
1414+ @munch_fields( $( $rest) * ) ,
1415+ ) ;
1416+ }
1417+ } ;
1418+ ( init_slot( $use_data: ident) :
12691419 @data( $data: ident) ,
12701420 @slot( $slot: ident) ,
12711421 @guards( $( $guards: ident, ) * ) ,
@@ -1279,6 +1429,13 @@ macro_rules! __init_internal {
12791429 // SAFETY: The memory at `slot` is uninitialized.
12801430 unsafe { :: core:: ptr:: write( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) } ;
12811431 }
1432+ // SAFETY:
1433+ // - the project function does the correct field projection,
1434+ // - the field has been initialized,
1435+ // - the reference is only valid until the end of the initializer.
1436+ #[ allow( unused_variables) ]
1437+ let $field = $crate:: macros:: paste!( unsafe { $data. [ < __project_ $field >] ( & mut ( * $slot) . $field) } ) ;
1438+
12821439 // Create the drop guard:
12831440 //
12841441 // We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1289,14 +1446,28 @@ macro_rules! __init_internal {
12891446 $crate:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
12901447 } ;
12911448
1292- $crate:: __init_internal!( init_slot( $( $ use_data) ? ) :
1449+ $crate:: __init_internal!( init_slot( $use_data) :
12931450 @data( $data) ,
12941451 @slot( $slot) ,
12951452 @guards( [ < __ $field _guard >] , $( $guards, ) * ) ,
12961453 @munch_fields( $( $rest) * ) ,
12971454 ) ;
12981455 }
12991456 } ;
1457+ ( make_initializer:
1458+ @slot( $slot: ident) ,
1459+ @type_name( $t: path) ,
1460+ @munch_fields( _: { $( $code: tt) * } , $( $rest: tt) * ) ,
1461+ @acc( $( $acc: tt) * ) ,
1462+ ) => {
1463+ // code blocks are ignored for the initializer check
1464+ $crate:: __init_internal!( make_initializer:
1465+ @slot( $slot) ,
1466+ @type_name( $t) ,
1467+ @munch_fields( $( $rest) * ) ,
1468+ @acc( $( $acc) * ) ,
1469+ ) ;
1470+ } ;
13001471 ( make_initializer:
13011472 @slot( $slot: ident) ,
13021473 @type_name( $t: path) ,
0 commit comments