@@ -1049,38 +1049,56 @@ macro_rules! __pin_data {
10491049 @pinned( $( $( #[ $( $p_attr: tt) * ] ) * $pvis: vis $p_field: ident : $p_type: ty) ,* $( , ) ?) ,
10501050 @not_pinned( $( $( #[ $( $attr: tt) * ] ) * $fvis: vis $field: ident : $type: ty) ,* $( , ) ?) ,
10511051 ) => {
1052- // For every field, we create a projection function according to its projection type. If a
1053- // field is structurally pinned, then it must be initialized via `PinInit`, if it is not
1054- // structurally pinned, then it can be initialized via `Init`.
1055- //
1056- // The functions are `unsafe` to prevent accidentally calling them.
1057- #[ allow( dead_code) ]
1058- #[ expect( clippy:: missing_safety_doc) ]
1059- impl <$( $impl_generics) * > $pin_data<$( $ty_generics) * >
1060- where $( $whr) *
1061- {
1062- $(
1063- $( #[ $( $p_attr) * ] ) *
1064- $pvis unsafe fn $p_field<E >(
1065- self ,
1066- slot: * mut $p_type,
1067- init: impl $crate:: PinInit <$p_type, E >,
1068- ) -> :: core:: result:: Result <( ) , E > {
1069- // SAFETY: TODO.
1070- unsafe { $crate:: PinInit :: __pinned_init( init, slot) }
1071- }
1072- ) *
1073- $(
1074- $( #[ $( $attr) * ] ) *
1075- $fvis unsafe fn $field<E >(
1076- self ,
1077- slot: * mut $type,
1078- init: impl $crate:: Init <$type, E >,
1079- ) -> :: core:: result:: Result <( ) , E > {
1080- // SAFETY: TODO.
1081- unsafe { $crate:: Init :: __init( init, slot) }
1082- }
1083- ) *
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+ }
10841102 }
10851103 } ;
10861104}
@@ -1292,6 +1310,13 @@ macro_rules! __init_internal {
12921310 // return when an error/panic occurs.
12931311 // We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`.
12941312 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+
12951320 // Create the drop guard:
12961321 //
12971322 // We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1323,6 +1348,14 @@ macro_rules! __init_internal {
13231348 // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
13241349 // return when an error/panic occurs.
13251350 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+
13261359 // Create the drop guard:
13271360 //
13281361 // We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1341,7 +1374,48 @@ macro_rules! __init_internal {
13411374 ) ;
13421375 }
13431376 } ;
1344- ( 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) :
13451419 @data( $data: ident) ,
13461420 @slot( $slot: ident) ,
13471421 @guards( $( $guards: ident, ) * ) ,
@@ -1355,6 +1429,13 @@ macro_rules! __init_internal {
13551429 // SAFETY: The memory at `slot` is uninitialized.
13561430 unsafe { :: core:: ptr:: write( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) } ;
13571431 }
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+
13581439 // Create the drop guard:
13591440 //
13601441 // We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1365,7 +1446,7 @@ macro_rules! __init_internal {
13651446 $crate:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
13661447 } ;
13671448
1368- $crate:: __init_internal!( init_slot( $( $ use_data) ? ) :
1449+ $crate:: __init_internal!( init_slot( $use_data) :
13691450 @data( $data) ,
13701451 @slot( $slot) ,
13711452 @guards( [ < __ $field _guard >] , $( $guards, ) * ) ,
0 commit comments