@@ -205,7 +205,6 @@ use crate::{
205205use alloc:: boxed:: Box ;
206206use core:: {
207207 alloc:: AllocError ,
208- cell:: Cell ,
209208 convert:: Infallible ,
210209 marker:: PhantomData ,
211210 mem:: MaybeUninit ,
@@ -636,6 +635,7 @@ macro_rules! try_pin_init {
636635 $crate:: try_pin_init!( init_slot:
637636 @data( data) ,
638637 @slot( slot) ,
638+ @guards( ) ,
639639 @munch_fields( $( $fields) * , ) ,
640640 ) ;
641641 // We use unreachable code to ensure that all fields have been mentioned exactly
@@ -650,10 +650,6 @@ macro_rules! try_pin_init {
650650 @acc( ) ,
651651 ) ;
652652 }
653- // Forget all guards, since initialization was a success.
654- $crate:: try_pin_init!( forget_guards:
655- @munch_fields( $( $fields) * , ) ,
656- ) ;
657653 }
658654 Ok ( __InitOk)
659655 }
@@ -667,13 +663,17 @@ macro_rules! try_pin_init {
667663 ( init_slot:
668664 @data( $data: ident) ,
669665 @slot( $slot: ident) ,
666+ @guards( $( $guards: ident, ) * ) ,
670667 @munch_fields( $( , ) ?) ,
671668 ) => {
672- // Endpoint of munching, no fields are left.
669+ // Endpoint of munching, no fields are left. If execution reaches this point, all fields
670+ // have been initialized. Therefore we can now dismiss the guards by forgetting them.
671+ $( :: core:: mem:: forget( $guards) ; ) *
673672 } ;
674673 ( init_slot:
675674 @data( $data: ident) ,
676675 @slot( $slot: ident) ,
676+ @guards( $( $guards: ident, ) * ) ,
677677 // In-place initialization syntax.
678678 @munch_fields( $field: ident <- $val: expr, $( $rest: tt) * ) ,
679679 ) => {
@@ -686,22 +686,24 @@ macro_rules! try_pin_init {
686686 unsafe { $data. $field( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) ? } ;
687687 // Create the drop guard.
688688 //
689- // We only give access to `&DropGuard`, so it cannot be forgotten via safe code .
689+ // Users cannot access this field due to macro hygiene .
690690 //
691691 // SAFETY: We forget the guard later when initialization has succeeded.
692- let $field = & unsafe {
692+ let guard = unsafe {
693693 $crate:: init:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
694694 } ;
695695
696696 $crate:: try_pin_init!( init_slot:
697697 @data( $data) ,
698698 @slot( $slot) ,
699+ @guards( guard, $( $guards, ) * ) ,
699700 @munch_fields( $( $rest) * ) ,
700701 ) ;
701702 } ;
702703 ( init_slot:
703704 @data( $data: ident) ,
704705 @slot( $slot: ident) ,
706+ @guards( $( $guards: ident, ) * ) ,
705707 // Direct value init, this is safe for every field.
706708 @munch_fields( $field: ident $( : $val: expr) ?, $( $rest: tt) * ) ,
707709 ) => {
@@ -712,16 +714,17 @@ macro_rules! try_pin_init {
712714 unsafe { :: core:: ptr:: write( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) } ;
713715 // Create the drop guard:
714716 //
715- // We only give access to `&DropGuard`, so it cannot be accidentally forgotten .
717+ // Users cannot access this field due to macro hygiene .
716718 //
717719 // SAFETY: We forget the guard later when initialization has succeeded.
718- let $field = & unsafe {
720+ let guard = unsafe {
719721 $crate:: init:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
720722 } ;
721723
722724 $crate:: try_pin_init!( init_slot:
723725 @data( $data) ,
724726 @slot( $slot) ,
727+ @guards( guard, $( $guards, ) * ) ,
725728 @munch_fields( $( $rest) * ) ,
726729 ) ;
727730 } ;
@@ -766,29 +769,6 @@ macro_rules! try_pin_init {
766769 @acc( $( $acc) * $field: :: core:: panic!( ) , ) ,
767770 ) ;
768771 } ;
769- ( forget_guards:
770- @munch_fields( $( , ) ?) ,
771- ) => {
772- // Munching finished.
773- } ;
774- ( forget_guards:
775- @munch_fields( $field: ident <- $val: expr, $( $rest: tt) * ) ,
776- ) => {
777- unsafe { $crate:: init:: __internal:: DropGuard :: forget( $field) } ;
778-
779- $crate:: try_pin_init!( forget_guards:
780- @munch_fields( $( $rest) * ) ,
781- ) ;
782- } ;
783- ( forget_guards:
784- @munch_fields( $field: ident $( : $val: expr) ?, $( $rest: tt) * ) ,
785- ) => {
786- unsafe { $crate:: init:: __internal:: DropGuard :: forget( $field) } ;
787-
788- $crate:: try_pin_init!( forget_guards:
789- @munch_fields( $( $rest) * ) ,
790- ) ;
791- } ;
792772}
793773
794774/// Construct an in-place initializer for `struct`s.
@@ -903,6 +883,7 @@ macro_rules! try_init {
903883 // Initialize every field.
904884 $crate:: try_init!( init_slot:
905885 @slot( slot) ,
886+ @guards( ) ,
906887 @munch_fields( $( $fields) * , ) ,
907888 ) ;
908889 // We use unreachable code to ensure that all fields have been mentioned exactly
@@ -917,10 +898,6 @@ macro_rules! try_init {
917898 @acc( ) ,
918899 ) ;
919900 }
920- // Forget all guards, since initialization was a success.
921- $crate:: try_init!( forget_guards:
922- @munch_fields( $( $fields) * , ) ,
923- ) ;
924901 }
925902 Ok ( __InitOk)
926903 }
@@ -933,57 +910,68 @@ macro_rules! try_init {
933910 } } ;
934911 ( init_slot:
935912 @slot( $slot: ident) ,
913+ @guards( $( $guards: ident, ) * ) ,
936914 @munch_fields( $( , ) ?) ,
937915 ) => {
938- // Endpoint of munching, no fields are left.
916+ // Endpoint of munching, no fields are left. If execution reaches this point, all fields
917+ // have been initialized. Therefore we can now dismiss the guards by forgetting them.
918+ $( :: core:: mem:: forget( $guards) ; ) *
939919 } ;
940920 ( init_slot:
941921 @slot( $slot: ident) ,
922+ @guards( $( $guards: ident, ) * ) ,
942923 @munch_fields( $field: ident <- $val: expr, $( $rest: tt) * ) ,
943924 ) => {
944- let $field = $val;
945- // Call the initializer.
946- //
947- // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
948- // return when an error/panic occurs.
949- unsafe {
950- $crate:: init:: Init :: __init( $field, :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) ) ?;
925+ {
926+ let $field = $val;
927+ // Call the initializer.
928+ //
929+ // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
930+ // return when an error/panic occurs.
931+ unsafe {
932+ $crate:: init:: Init :: __init( $field, :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) ) ?;
933+ }
951934 }
952935 // Create the drop guard.
953936 //
954- // We only give access to `&DropGuard`, so it cannot be accidentally forgotten .
937+ // Users cannot access this field due to macro hygiene .
955938 //
956939 // SAFETY: We forget the guard later when initialization has succeeded.
957- let $field = & unsafe {
940+ let guard = unsafe {
958941 $crate:: init:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
959942 } ;
960943
961944 $crate:: try_init!( init_slot:
962945 @slot( $slot) ,
946+ @guards( guard, $( $guards, ) * ) ,
963947 @munch_fields( $( $rest) * ) ,
964948 ) ;
965949 } ;
966950 ( init_slot:
967951 @slot( $slot: ident) ,
952+ @guards( $( $guards: ident, ) * ) ,
968953 // Direct value init.
969954 @munch_fields( $field: ident $( : $val: expr) ?, $( $rest: tt) * ) ,
970955 ) => {
971- $( let $field = $val; ) ?
972- // Call the initializer.
973- //
974- // SAFETY: The memory at `slot` is uninitialized.
975- unsafe { :: core:: ptr:: write( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) } ;
956+ {
957+ $( let $field = $val; ) ?
958+ // Call the initializer.
959+ //
960+ // SAFETY: The memory at `slot` is uninitialized.
961+ unsafe { :: core:: ptr:: write( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) , $field) } ;
962+ }
976963 // Create the drop guard.
977964 //
978- // We only give access to `&DropGuard`, so it cannot be accidentally forgotten .
965+ // Users cannot access this field due to macro hygiene .
979966 //
980967 // SAFETY: We forget the guard later when initialization has succeeded.
981- let $field = & unsafe {
968+ let guard = unsafe {
982969 $crate:: init:: __internal:: DropGuard :: new( :: core:: ptr:: addr_of_mut!( ( * $slot) . $field) )
983970 } ;
984971
985972 $crate:: try_init!( init_slot:
986973 @slot( $slot) ,
974+ @guards( guard, $( $guards, ) * ) ,
987975 @munch_fields( $( $rest) * ) ,
988976 ) ;
989977 } ;
@@ -1028,29 +1016,6 @@ macro_rules! try_init {
10281016 @acc( $( $acc) * $field: :: core:: panic!( ) , ) ,
10291017 ) ;
10301018 } ;
1031- ( forget_guards:
1032- @munch_fields( $( , ) ?) ,
1033- ) => {
1034- // Munching finished.
1035- } ;
1036- ( forget_guards:
1037- @munch_fields( $field: ident <- $val: expr, $( $rest: tt) * ) ,
1038- ) => {
1039- unsafe { $crate:: init:: __internal:: DropGuard :: forget( $field) } ;
1040-
1041- $crate:: try_init!( forget_guards:
1042- @munch_fields( $( $rest) * ) ,
1043- ) ;
1044- } ;
1045- ( forget_guards:
1046- @munch_fields( $field: ident $( : $val: expr) ?, $( $rest: tt) * ) ,
1047- ) => {
1048- unsafe { $crate:: init:: __internal:: DropGuard :: forget( $field) } ;
1049-
1050- $crate:: try_init!( forget_guards:
1051- @munch_fields( $( $rest) * ) ,
1052- ) ;
1053- } ;
10541019}
10551020
10561021/// A pin-initializer for the type `T`.
0 commit comments