1
1
use super :: once:: ExclusiveState ;
2
2
use crate :: cell:: UnsafeCell ;
3
3
use crate :: mem:: ManuallyDrop ;
4
- use crate :: ops:: Deref ;
4
+ use crate :: ops:: { Deref , DerefMut } ;
5
5
use crate :: panic:: { RefUnwindSafe , UnwindSafe } ;
6
6
use crate :: sync:: Once ;
7
7
use crate :: { fmt, ptr} ;
@@ -121,7 +121,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
121
121
pub fn into_inner ( mut this : Self ) -> Result < T , F > {
122
122
let state = this. once . state ( ) ;
123
123
match state {
124
- ExclusiveState :: Poisoned => panic ! ( "LazyLock instance has previously been poisoned" ) ,
124
+ ExclusiveState :: Poisoned => panic_poisoned ( ) ,
125
125
state => {
126
126
let this = ManuallyDrop :: new ( this) ;
127
127
let data = unsafe { ptr:: read ( & this. data ) } . into_inner ( ) ;
@@ -134,6 +134,63 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
134
134
}
135
135
}
136
136
137
+ /// Forces the evaluation of this lazy value and returns a mutable reference to
138
+ /// the result.
139
+ ///
140
+ /// This is equivalent to the `DerefMut` impl, but is explicit.
141
+ ///
142
+ /// # Examples
143
+ ///
144
+ /// ```
145
+ /// use std::sync::LazyLock;
146
+ ///
147
+ /// let mut lazy = LazyLock::new(|| 92);
148
+ ///
149
+ /// let p = LazyLock::force_mut(&mut lazy);
150
+ /// assert_eq!(*p, 92);
151
+ /// *p = 44;
152
+ /// assert_eq!(*lazy, 44);
153
+ /// *lazy = 55; // Using `DerefMut`
154
+ /// assert_eq!(*lazy, 55);
155
+ /// ```
156
+ #[ inline]
157
+ #[ stable( feature = "lazy_deref_mut" , since = "CURRENT_RUSTC_VERSION" ) ]
158
+ pub fn force_mut ( this : & mut LazyLock < T , F > ) -> & mut T {
159
+ #[ cold]
160
+ /// # Safety
161
+ /// May only be called when the state is `Incomplete`.
162
+ unsafe fn really_init < T , F : FnOnce ( ) -> T > ( this : & mut LazyLock < T , F > ) -> & mut T {
163
+ struct PoisonOnPanic < ' a , T , F > ( & ' a mut LazyLock < T , F > ) ;
164
+ impl < T , F > Drop for PoisonOnPanic < ' _ , T , F > {
165
+ #[ inline]
166
+ fn drop ( & mut self ) {
167
+ self . 0 . once . set_state ( ExclusiveState :: Poisoned ) ;
168
+ }
169
+ }
170
+
171
+ // SAFETY: We always poison if the initializer panics (then we never check the data),
172
+ // or set the data on success.
173
+ let f = unsafe { ManuallyDrop :: take ( & mut this. data . get_mut ( ) . f ) } ;
174
+ // INVARIANT: Initiated from mutable reference, don't drop because we read it.
175
+ let guard = PoisonOnPanic ( this) ;
176
+ let data = f ( ) ;
177
+ guard. 0 . data . get_mut ( ) . value = ManuallyDrop :: new ( data) ;
178
+ guard. 0 . once . set_state ( ExclusiveState :: Complete ) ;
179
+ core:: mem:: forget ( guard) ;
180
+ // SAFETY: We put the value there above.
181
+ unsafe { & mut this. data . get_mut ( ) . value }
182
+ }
183
+
184
+ let state = this. once . state ( ) ;
185
+ match state {
186
+ ExclusiveState :: Poisoned => panic_poisoned ( ) ,
187
+ // SAFETY: The `Once` states we completed the initialization.
188
+ ExclusiveState :: Complete => unsafe { & mut this. data . get_mut ( ) . value } ,
189
+ // SAFETY: The state is `Incomplete`.
190
+ ExclusiveState :: Incomplete => unsafe { really_init ( this) } ,
191
+ }
192
+ }
193
+
137
194
/// Forces the evaluation of this lazy value and returns a reference to
138
195
/// result. This is equivalent to the `Deref` impl, but is explicit.
139
196
///
@@ -174,13 +231,58 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
174
231
}
175
232
176
233
impl < T , F > LazyLock < T , F > {
177
- /// Gets the inner value if it has already been initialized.
178
- fn get ( & self ) -> Option < & T > {
179
- if self . once . is_completed ( ) {
234
+ /// Returns a reference to the value if initialized, or `None` if not.
235
+ ///
236
+ /// # Examples
237
+ ///
238
+ /// ```
239
+ /// #![feature(lazy_get)]
240
+ ///
241
+ /// use std::sync::LazyLock;
242
+ ///
243
+ /// let mut lazy = LazyLock::new(|| 92);
244
+ ///
245
+ /// assert_eq!(LazyLock::get_mut(&mut lazy), None);
246
+ /// let _ = LazyLock::force(&lazy);
247
+ /// *LazyLock::get_mut(&mut lazy).unwrap() = 44;
248
+ /// assert_eq!(*lazy, 44);
249
+ /// ```
250
+ #[ inline]
251
+ #[ unstable( feature = "lazy_get" , issue = "129333" ) ]
252
+ pub fn get_mut ( this : & mut LazyLock < T , F > ) -> Option < & mut T > {
253
+ // `state()` does not perform an atomic load, so prefer it over `is_complete()`.
254
+ let state = this. once . state ( ) ;
255
+ match state {
256
+ // SAFETY:
257
+ // The closure has been run successfully, so `value` has been initialized.
258
+ ExclusiveState :: Complete => Some ( unsafe { & mut this. data . get_mut ( ) . value } ) ,
259
+ _ => None ,
260
+ }
261
+ }
262
+
263
+ /// Returns a mutable reference to the value if initialized, or `None` if not.
264
+ ///
265
+ /// # Examples
266
+ ///
267
+ /// ```
268
+ /// #![feature(lazy_get)]
269
+ ///
270
+ /// use std::sync::LazyLock;
271
+ ///
272
+ /// let lazy = LazyLock::new(|| 92);
273
+ ///
274
+ /// assert_eq!(LazyLock::get(&lazy), None);
275
+ /// let _ = LazyLock::force(&lazy);
276
+ /// assert_eq!(LazyLock::get(&lazy), Some(&92));
277
+ /// ```
278
+ #[ inline]
279
+ #[ unstable( feature = "lazy_get" , issue = "129333" ) ]
280
+ pub fn get ( this : & LazyLock < T , F > ) -> Option < & T > {
281
+ if this. once . is_completed ( ) {
180
282
// SAFETY:
181
283
// The closure has been run successfully, so `value` has been initialized
182
284
// and will not be modified again.
183
- Some ( unsafe { & * ( * self . data . get ( ) ) . value } )
285
+ Some ( unsafe { & ( * this . data . get ( ) ) . value } )
184
286
} else {
185
287
None
186
288
}
@@ -215,6 +317,14 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
215
317
}
216
318
}
217
319
320
+ #[ stable( feature = "lazy_deref_mut" , since = "CURRENT_RUSTC_VERSION" ) ]
321
+ impl < T , F : FnOnce ( ) -> T > DerefMut for LazyLock < T , F > {
322
+ #[ inline]
323
+ fn deref_mut ( & mut self ) -> & mut T {
324
+ LazyLock :: force_mut ( self )
325
+ }
326
+ }
327
+
218
328
#[ stable( feature = "lazy_cell" , since = "1.80.0" ) ]
219
329
impl < T : Default > Default for LazyLock < T > {
220
330
/// Creates a new lazy value using `Default` as the initializing function.
@@ -228,14 +338,20 @@ impl<T: Default> Default for LazyLock<T> {
228
338
impl < T : fmt:: Debug , F > fmt:: Debug for LazyLock < T , F > {
229
339
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
230
340
let mut d = f. debug_tuple ( "LazyLock" ) ;
231
- match self . get ( ) {
341
+ match LazyLock :: get ( self ) {
232
342
Some ( v) => d. field ( v) ,
233
343
None => d. field ( & format_args ! ( "<uninit>" ) ) ,
234
344
} ;
235
345
d. finish ( )
236
346
}
237
347
}
238
348
349
+ #[ cold]
350
+ #[ inline( never) ]
351
+ fn panic_poisoned ( ) -> ! {
352
+ panic ! ( "LazyLock instance has previously been poisoned" )
353
+ }
354
+
239
355
// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
240
356
// to not impl `Sync` for `F`.
241
357
#[ stable( feature = "lazy_cell" , since = "1.80.0" ) ]
0 commit comments