@@ -994,7 +994,6 @@ macro_rules! __pin_data {
994
994
/// - `init_slot`: recursively creates the code that initializes all fields in `slot`.
995
995
/// - `make_initializer`: recursively create the struct initializer that guarantees that every
996
996
/// field has been initialized exactly once.
997
- /// - `forget_guards`: recursively forget the drop guards for every field.
998
997
#[ doc( hidden) ]
999
998
#[ macro_export]
1000
999
macro_rules! __init_internal {
@@ -1034,6 +1033,7 @@ macro_rules! __init_internal {
1034
1033
$crate:: __init_internal!( init_slot( $( $use_data) ?) :
1035
1034
@data( data) ,
1036
1035
@slot( slot) ,
1036
+ @guards( ) ,
1037
1037
@munch_fields( $( $fields) * , ) ,
1038
1038
) ;
1039
1039
// We use unreachable code to ensure that all fields have been mentioned exactly
@@ -1048,10 +1048,6 @@ macro_rules! __init_internal {
1048
1048
@acc( ) ,
1049
1049
) ;
1050
1050
}
1051
- // Forget all guards, since initialization was a success.
1052
- $crate:: __init_internal!( forget_guards:
1053
- @munch_fields( $( $fields) * , ) ,
1054
- ) ;
1055
1051
}
1056
1052
Ok ( __InitOk)
1057
1053
}
@@ -1065,13 +1061,17 @@ macro_rules! __init_internal {
1065
1061
( init_slot( $( $use_data: ident) ?) :
1066
1062
@data( $data: ident) ,
1067
1063
@slot( $slot: ident) ,
1064
+ @guards( $( $guards: ident, ) * ) ,
1068
1065
@munch_fields( $( , ) ?) ,
1069
1066
) => {
1070
- // Endpoint of munching, no fields are left.
1067
+ // Endpoint of munching, no fields are left. If execution reaches this point, all fields
1068
+ // have been initialized. Therefore we can now dismiss the guards by forgetting them.
1069
+ $( :: core:: mem:: forget( $guards) ; ) *
1071
1070
} ;
1072
1071
( init_slot( $use_data: ident) : // `use_data` is present, so we use the `data` to init fields.
1073
1072
@data( $data: ident) ,
1074
1073
@slot( $slot: ident) ,
1074
+ @guards( $( $guards: ident, ) * ) ,
1075
1075
// In-place initialization syntax.
1076
1076
@munch_fields( $field: ident <- $val: expr, $( $rest: tt) * ) ,
1077
1077
) => {
@@ -1082,24 +1082,28 @@ macro_rules! __init_internal {
1082
1082
// return when an error/panic occurs.
1083
1083
// We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`.
1084
1084
unsafe { $data. $field( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) ? } ;
1085
- // Create the drop guard.
1086
- //
1087
- // We only give access to `&DropGuard`, so it cannot be forgotten via safe code.
1085
+ // Create the drop guard:
1088
1086
//
1089
- // SAFETY: We forget the guard later when initialization has succeeded.
1090
- let $field = & unsafe {
1091
- $crate:: init:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
1092
- } ;
1087
+ // We rely on macro hygiene to make it impossible for users to access this local variable.
1088
+ // We use `paste!` to create new hygiene for `$field`.
1089
+ :: kernel:: macros:: paste! {
1090
+ // SAFETY: We forget the guard later when initialization has succeeded.
1091
+ let [ <$field>] = unsafe {
1092
+ $crate:: init:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
1093
+ } ;
1093
1094
1094
- $crate:: __init_internal!( init_slot( $use_data) :
1095
- @data( $data) ,
1096
- @slot( $slot) ,
1097
- @munch_fields( $( $rest) * ) ,
1098
- ) ;
1095
+ $crate:: __init_internal!( init_slot( $use_data) :
1096
+ @data( $data) ,
1097
+ @slot( $slot) ,
1098
+ @guards( [ <$field>] , $( $guards, ) * ) ,
1099
+ @munch_fields( $( $rest) * ) ,
1100
+ ) ;
1101
+ }
1099
1102
} ;
1100
1103
( init_slot( ) : // No `use_data`, so we use `Init::__init` directly.
1101
1104
@data( $data: ident) ,
1102
1105
@slot( $slot: ident) ,
1106
+ @guards( $( $guards: ident, ) * ) ,
1103
1107
// In-place initialization syntax.
1104
1108
@munch_fields( $field: ident <- $val: expr, $( $rest: tt) * ) ,
1105
1109
) => {
@@ -1109,24 +1113,28 @@ macro_rules! __init_internal {
1109
1113
// SAFETY: `slot` is valid, because we are inside of an initializer closure, we
1110
1114
// return when an error/panic occurs.
1111
1115
unsafe { $crate:: init:: Init :: __init( $field, :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) ) ? } ;
1112
- // Create the drop guard.
1113
- //
1114
- // We only give access to `&DropGuard`, so it cannot be forgotten via safe code.
1116
+ // Create the drop guard:
1115
1117
//
1116
- // SAFETY: We forget the guard later when initialization has succeeded.
1117
- let $field = & unsafe {
1118
- $crate:: init:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
1119
- } ;
1118
+ // We rely on macro hygiene to make it impossible for users to access this local variable.
1119
+ // We use `paste!` to create new hygiene for `$field`.
1120
+ :: kernel:: macros:: paste! {
1121
+ // SAFETY: We forget the guard later when initialization has succeeded.
1122
+ let [ <$field>] = unsafe {
1123
+ $crate:: init:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
1124
+ } ;
1120
1125
1121
- $crate:: __init_internal!( init_slot( ) :
1122
- @data( $data) ,
1123
- @slot( $slot) ,
1124
- @munch_fields( $( $rest) * ) ,
1125
- ) ;
1126
+ $crate:: __init_internal!( init_slot( ) :
1127
+ @data( $data) ,
1128
+ @slot( $slot) ,
1129
+ @guards( [ <$field>] , $( $guards, ) * ) ,
1130
+ @munch_fields( $( $rest) * ) ,
1131
+ ) ;
1132
+ }
1126
1133
} ;
1127
1134
( init_slot( $( $use_data: ident) ?) :
1128
1135
@data( $data: ident) ,
1129
1136
@slot( $slot: ident) ,
1137
+ @guards( $( $guards: ident, ) * ) ,
1130
1138
// Init by-value.
1131
1139
@munch_fields( $field: ident $( : $val: expr) ?, $( $rest: tt) * ) ,
1132
1140
) => {
@@ -1137,18 +1145,21 @@ macro_rules! __init_internal {
1137
1145
unsafe { :: core:: ptr:: write( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) } ;
1138
1146
// Create the drop guard:
1139
1147
//
1140
- // We only give access to `&DropGuard`, so it cannot be accidentally forgotten.
1141
- //
1142
- // SAFETY: We forget the guard later when initialization has succeeded.
1143
- let $field = & unsafe {
1144
- $crate:: init:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
1145
- } ;
1148
+ // We rely on macro hygiene to make it impossible for users to access this local variable.
1149
+ // We use `paste!` to create new hygiene for `$field`.
1150
+ :: kernel:: macros:: paste! {
1151
+ // SAFETY: We forget the guard later when initialization has succeeded.
1152
+ let [ <$field>] = unsafe {
1153
+ $crate:: init:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
1154
+ } ;
1146
1155
1147
- $crate:: __init_internal!( init_slot( $( $use_data) ?) :
1148
- @data( $data) ,
1149
- @slot( $slot) ,
1150
- @munch_fields( $( $rest) * ) ,
1151
- ) ;
1156
+ $crate:: __init_internal!( init_slot( $( $use_data) ?) :
1157
+ @data( $data) ,
1158
+ @slot( $slot) ,
1159
+ @guards( [ <$field>] , $( $guards, ) * ) ,
1160
+ @munch_fields( $( $rest) * ) ,
1161
+ ) ;
1162
+ }
1152
1163
} ;
1153
1164
( make_initializer:
1154
1165
@slot( $slot: ident) ,
@@ -1191,29 +1202,6 @@ macro_rules! __init_internal {
1191
1202
@acc( $( $acc) * $field: :: core:: panic!( ) , ) ,
1192
1203
) ;
1193
1204
} ;
1194
- ( forget_guards:
1195
- @munch_fields( $( , ) ?) ,
1196
- ) => {
1197
- // Munching finished.
1198
- } ;
1199
- ( forget_guards:
1200
- @munch_fields( $field: ident <- $val: expr, $( $rest: tt) * ) ,
1201
- ) => {
1202
- unsafe { $crate:: init:: __internal:: DropGuard :: forget( $field) } ;
1203
-
1204
- $crate:: __init_internal!( forget_guards:
1205
- @munch_fields( $( $rest) * ) ,
1206
- ) ;
1207
- } ;
1208
- ( forget_guards:
1209
- @munch_fields( $field: ident $( : $val: expr) ?, $( $rest: tt) * ) ,
1210
- ) => {
1211
- unsafe { $crate:: init:: __internal:: DropGuard :: forget( $field) } ;
1212
-
1213
- $crate:: __init_internal!( forget_guards:
1214
- @munch_fields( $( $rest) * ) ,
1215
- ) ;
1216
- } ;
1217
1205
}
1218
1206
1219
1207
#[ doc( hidden) ]
0 commit comments