@@ -988,38 +988,56 @@ macro_rules! __pin_data {
988988 @pinned( $( $( #[ $( $p_attr: tt) * ] ) * $pvis: vis $p_field: ident : $p_type: ty) ,* $( , ) ?) ,
989989 @not_pinned( $( $( #[ $( $attr: tt) * ] ) * $fvis: vis $field: ident : $type: ty) ,* $( , ) ?) ,
990990 ) => {
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- ) *
991+ $crate:: macros:: paste! {
992+ // For every field, we create a projection function according to its projection type. If a
993+ // field is structurally pinned, then it must be initialized via `PinInit`, if it is not
994+ // structurally pinned, then it can be initialized via `Init`.
995+ //
996+ // The functions are `unsafe` to prevent accidentally calling them.
997+ #[ allow( dead_code) ]
998+ #[ expect( clippy:: missing_safety_doc) ]
999+ impl <$( $impl_generics) * > $pin_data<$( $ty_generics) * >
1000+ where $( $whr) *
1001+ {
1002+ $(
1003+ $( #[ $( $p_attr) * ] ) *
1004+ $pvis unsafe fn $p_field<E >(
1005+ self ,
1006+ slot: * mut $p_type,
1007+ init: impl $crate:: PinInit <$p_type, E >,
1008+ ) -> :: core:: result:: Result <( ) , E > {
1009+ // SAFETY: TODO.
1010+ unsafe { $crate:: PinInit :: __pinned_init( init, slot) }
1011+ }
1012+
1013+ $( #[ $( $p_attr) * ] ) *
1014+ $pvis unsafe fn [ <__project_ $p_field>] <' __slot>(
1015+ self ,
1016+ slot: & ' __slot mut $p_type,
1017+ ) -> :: core:: pin:: Pin <& ' __slot mut $p_type> {
1018+ :: core:: pin:: Pin :: new_unchecked( slot)
1019+ }
1020+ ) *
1021+ $(
1022+ $( #[ $( $attr) * ] ) *
1023+ $fvis unsafe fn $field<E >(
1024+ self ,
1025+ slot: * mut $type,
1026+ init: impl $crate:: Init <$type, E >,
1027+ ) -> :: core:: result:: Result <( ) , E > {
1028+ // SAFETY: TODO.
1029+ unsafe { $crate:: Init :: __init( init, slot) }
1030+ }
1031+
1032+ $( #[ $( $attr) * ] ) *
1033+ $fvis unsafe fn [ <__project_ $field>] <' __slot>(
1034+ self ,
1035+ slot: & ' __slot mut $type,
1036+ ) -> & ' __slot mut $type {
1037+ slot
1038+ }
1039+ ) *
1040+ }
10231041 }
10241042 } ;
10251043}
@@ -1216,6 +1234,13 @@ macro_rules! __init_internal {
12161234 // return when an error/panic occurs.
12171235 // We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`.
12181236 unsafe { $data. $field( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , init) ? } ;
1237+ // SAFETY:
1238+ // - the project function does the correct field projection,
1239+ // - the field has been initialized,
1240+ // - the reference is only valid until the end of the initializer.
1241+ #[ allow( unused_variables) ]
1242+ let $field = $crate:: macros:: paste!( unsafe { $data. [ < __project_ $field >] ( & mut ( * $slot) . $field) } ) ;
1243+
12191244 // Create the drop guard:
12201245 //
12211246 // We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1247,6 +1272,14 @@ macro_rules! __init_internal {
12471272 // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
12481273 // return when an error/panic occurs.
12491274 unsafe { $crate:: Init :: __init( init, :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) ) ? } ;
1275+
1276+ // SAFETY:
1277+ // - the field is not structurally pinned, since the line above must compile,
1278+ // - the field has been initialized,
1279+ // - the reference is only valid until the end of the initializer.
1280+ #[ allow( unused_variables) ]
1281+ let $field = unsafe { & mut ( * $slot) . $field } ;
1282+
12501283 // Create the drop guard:
12511284 //
12521285 // We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1265,7 +1298,48 @@ macro_rules! __init_internal {
12651298 ) ;
12661299 }
12671300 } ;
1268- ( init_slot( $( $use_data: ident) ?) :
1301+ ( init_slot( ) : // No `use_data`, so all fields are not structurally pinned
1302+ @data( $data: ident) ,
1303+ @slot( $slot: ident) ,
1304+ @guards( $( $guards: ident, ) * ) ,
1305+ // Init by-value.
1306+ @munch_fields( $field: ident $( : $val: expr) ?, $( $rest: tt) * ) ,
1307+ ) => {
1308+ {
1309+ $( let $field = $val; ) ?
1310+ // Initialize the field.
1311+ //
1312+ // SAFETY: The memory at `slot` is uninitialized.
1313+ unsafe { :: core:: ptr:: write( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) } ;
1314+ }
1315+
1316+ #[ allow( unused_variables) ]
1317+ // SAFETY:
1318+ // - the field is not structurally pinned, since no `use_data` was required to create this
1319+ // initializer,
1320+ // - the field has been initialized,
1321+ // - the reference is only valid until the end of the initializer.
1322+ let $field = unsafe { & mut ( * $slot) . $field } ;
1323+
1324+ // Create the drop guard:
1325+ //
1326+ // We rely on macro hygiene to make it impossible for users to access this local variable.
1327+ // We use `paste!` to create new hygiene for `$field`.
1328+ $crate:: macros:: paste! {
1329+ // SAFETY: We forget the guard later when initialization has succeeded.
1330+ let [ < __ $field _guard >] = unsafe {
1331+ $crate:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
1332+ } ;
1333+
1334+ $crate:: __init_internal!( init_slot( ) :
1335+ @data( $data) ,
1336+ @slot( $slot) ,
1337+ @guards( [ < __ $field _guard >] , $( $guards, ) * ) ,
1338+ @munch_fields( $( $rest) * ) ,
1339+ ) ;
1340+ }
1341+ } ;
1342+ ( init_slot( $use_data: ident) :
12691343 @data( $data: ident) ,
12701344 @slot( $slot: ident) ,
12711345 @guards( $( $guards: ident, ) * ) ,
@@ -1279,6 +1353,13 @@ macro_rules! __init_internal {
12791353 // SAFETY: The memory at `slot` is uninitialized.
12801354 unsafe { :: core:: ptr:: write( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) } ;
12811355 }
1356+ // SAFETY:
1357+ // - the project function does the correct field projection,
1358+ // - the field has been initialized,
1359+ // - the reference is only valid until the end of the initializer.
1360+ #[ allow( unused_variables) ]
1361+ let $field = $crate:: macros:: paste!( unsafe { $data. [ < __project_ $field >] ( & mut ( * $slot) . $field) } ) ;
1362+
12821363 // Create the drop guard:
12831364 //
12841365 // We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1289,7 +1370,7 @@ macro_rules! __init_internal {
12891370 $crate:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
12901371 } ;
12911372
1292- $crate:: __init_internal!( init_slot( $( $ use_data) ? ) :
1373+ $crate:: __init_internal!( init_slot( $use_data) :
12931374 @data( $data) ,
12941375 @slot( $slot) ,
12951376 @guards( [ < __ $field _guard >] , $( $guards, ) * ) ,
0 commit comments