@@ -22,7 +22,6 @@ unsafe impl DestroyedState for () {
22
22
#[ derive( Copy , Clone ) ]
23
23
enum State < D > {
24
24
Uninitialized ,
25
- Initializing ,
26
25
Alive ,
27
26
Destroyed ( D ) ,
28
27
}
@@ -64,36 +63,31 @@ where
64
63
65
64
#[ cold]
66
65
fn get_or_init_slow ( & self , i : Option < & mut Option < T > > , f : impl FnOnce ( ) -> T ) -> * const T {
67
- // Ensure we have unique access to an uninitialized value.
68
66
match self . state . get ( ) {
69
- State :: Uninitialized => self . state . set ( State :: Initializing ) ,
70
- State :: Initializing => panic ! ( "thread_local initializer recursively depends on itself" ) ,
67
+ State :: Uninitialized => { }
71
68
State :: Alive => return self . value . get ( ) . cast ( ) ,
72
69
State :: Destroyed ( _) => return ptr:: null ( ) ,
73
70
}
74
71
75
- struct BackToUninitOnPanic < ' a , D > ( & ' a Cell < State < D > > ) ;
76
- impl < ' a , D > Drop for BackToUninitOnPanic < ' a , D > {
77
- fn drop ( & mut self ) {
78
- self . 0 . set ( State :: Uninitialized ) ;
79
- }
80
- }
81
-
82
- // Get the initial value, making sure that we restore the state to uninitialized
83
- // should f panic.
84
- let on_panic = BackToUninitOnPanic ( & self . state ) ;
85
72
let v = i. and_then ( Option :: take) . unwrap_or_else ( f) ;
86
- crate :: mem:: forget ( on_panic) ;
87
73
88
- // SAFETY: we are !Sync so we have exclusive access to self.value. We also ensured
89
- // that the state was uninitialized so we aren't replacing a value we must keep alive.
90
- unsafe {
91
- self . value . get ( ) . write ( MaybeUninit :: new ( v) ) ;
74
+ match self . state . replace ( State :: Alive ) {
75
+ State :: Uninitialized => D :: register_dtor ( self ) ,
76
+
77
+ State :: Alive => {
78
+ // An init occurred during a recursive call, this could be a panic in the future.
79
+
80
+ // SAFETY: we cannot be inside a `LocalKey::with` scope, as the initializer
81
+ // has already returned and the next scope only starts after we return
82
+ // the pointer. Therefore, there can be no references to the old value.
83
+ unsafe { ( * self . value . get ( ) ) . assume_init_drop ( ) }
84
+ }
85
+
86
+ State :: Destroyed ( _) => unreachable ! ( ) ,
92
87
}
93
88
94
- self . state . set ( State :: Alive ) ;
95
- D :: register_dtor ( self ) ;
96
- self . value . get ( ) . cast ( )
89
+ // SAFETY: we are !Sync so we have exclusive access to self.value.
90
+ unsafe { ( * self . value . get ( ) ) . write ( v) }
97
91
}
98
92
}
99
93
@@ -113,9 +107,7 @@ unsafe extern "C" fn destroy<T>(ptr: *mut u8) {
113
107
// We also updated the state to Destroyed to prevent the destructor
114
108
// from accessing the thread-local variable, as this would violate
115
109
// the exclusive access provided by &mut T in Drop::drop.
116
- unsafe {
117
- crate :: ptr:: drop_in_place ( storage. value . get ( ) . cast :: < T > ( ) ) ;
118
- }
110
+ unsafe { ( * storage. value . get ( ) ) . assume_init_drop ( ) }
119
111
}
120
112
} )
121
113
}
0 commit comments