@@ -50,6 +50,7 @@ unsafe impl<T> Sync for Storage<T> {}
5050
5151struct Value < T : ' static > {
5252 value : T ,
53+ // INVARIANT: if this value is stored under a TLS key, `key` must be that `key`.
5354 key : Key ,
5455}
5556
@@ -73,10 +74,14 @@ impl<T: 'static> Storage<T> {
7374 // is not running) + it is coming from a trusted source (self).
7475 unsafe { & ( * ptr) . value }
7576 } else {
77+ // SAFETY: trivially correct.
7678 unsafe { Self :: try_initialize ( key, ptr, i, f) }
7779 }
7880 }
7981
82+ /// # Safety
83+ /// * `key` must be the result of calling `self.key.force()`
84+ /// * `ptr` must be the current value associated with `key`.
8085 unsafe fn try_initialize (
8186 key : Key ,
8287 ptr : * mut Value < T > ,
@@ -91,11 +96,16 @@ impl<T: 'static> Storage<T> {
9196 let value = Box :: new ( Value { value : i. and_then ( Option :: take) . unwrap_or_else ( f) , key } ) ;
9297 let ptr = Box :: into_raw ( value) ;
9398
94- let old = unsafe { get ( key) as * mut Value < T > } ;
95- // SAFETY: `ptr` is a correct pointer that can be destroyed by the key destructor.
96- unsafe {
99+ // SAFETY:
100+ // * key came from a `LazyKey` and is thus correct.
101+ // * `ptr` is a correct pointer that can be destroyed by the key destructor.
102+ // * the value is stored under the key that it contains.
103+ let old = unsafe {
104+ let old = get ( key) as * mut Value < T > ;
97105 set ( key, ptr as * mut u8 ) ;
98- }
106+ old
107+ } ;
108+
99109 if !old. is_null ( ) {
100110 // If the variable was recursively initialized, drop the old value.
101111 // SAFETY: We cannot be inside a `LocalKey::with` scope, as the
@@ -123,8 +133,10 @@ unsafe extern "C" fn destroy_value<T: 'static>(ptr: *mut u8) {
123133 abort_on_dtor_unwind ( || {
124134 let ptr = unsafe { Box :: from_raw ( ptr as * mut Value < T > ) } ;
125135 let key = ptr. key ;
136+ // SAFETY: `key` is the TLS key `ptr` was stored under.
126137 unsafe { set ( key, ptr:: without_provenance_mut ( 1 ) ) } ;
127138 drop ( ptr) ;
139+ // SAFETY: `key` is the TLS key `ptr` was stored under.
128140 unsafe { set ( key, ptr:: null_mut ( ) ) } ;
129141 } ) ;
130142}
0 commit comments