11use super :: once:: ExclusiveState ;
22use crate :: cell:: UnsafeCell ;
33use crate :: mem:: ManuallyDrop ;
4- use crate :: ops:: Deref ;
4+ use crate :: ops:: { Deref , DerefMut } ;
55use crate :: panic:: { RefUnwindSafe , UnwindSafe } ;
66use crate :: sync:: Once ;
77use crate :: { fmt, ptr} ;
@@ -121,7 +121,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
121121 pub fn into_inner ( mut this : Self ) -> Result < T , F > {
122122 let state = this. once . state ( ) ;
123123 match state {
124- ExclusiveState :: Poisoned => panic ! ( "LazyLock instance has previously been poisoned" ) ,
124+ ExclusiveState :: Poisoned => panic_poisoned ( ) ,
125125 state => {
126126 let this = ManuallyDrop :: new ( this) ;
127127 let data = unsafe { ptr:: read ( & this. data ) } . into_inner ( ) ;
@@ -134,6 +134,63 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
134134 }
135135 }
136136
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+
137194 /// Forces the evaluation of this lazy value and returns a reference to
138195 /// result. This is equivalent to the `Deref` impl, but is explicit.
139196 ///
@@ -174,13 +231,58 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
174231}
175232
176233impl < 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 ( ) {
180282 // SAFETY:
181283 // The closure has been run successfully, so `value` has been initialized
182284 // and will not be modified again.
183- Some ( unsafe { & * ( * self . data . get ( ) ) . value } )
285+ Some ( unsafe { & ( * this . data . get ( ) ) . value } )
184286 } else {
185287 None
186288 }
@@ -215,6 +317,14 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
215317 }
216318}
217319
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+
218328#[ stable( feature = "lazy_cell" , since = "1.80.0" ) ]
219329impl < T : Default > Default for LazyLock < T > {
220330 /// Creates a new lazy value using `Default` as the initializing function.
@@ -228,14 +338,20 @@ impl<T: Default> Default for LazyLock<T> {
228338impl < T : fmt:: Debug , F > fmt:: Debug for LazyLock < T , F > {
229339 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
230340 let mut d = f. debug_tuple ( "LazyLock" ) ;
231- match self . get ( ) {
341+ match LazyLock :: get ( self ) {
232342 Some ( v) => d. field ( v) ,
233343 None => d. field ( & format_args ! ( "<uninit>" ) ) ,
234344 } ;
235345 d. finish ( )
236346 }
237347}
238348
349+ #[ cold]
350+ #[ inline( never) ]
351+ fn panic_poisoned ( ) -> ! {
352+ panic ! ( "LazyLock instance has previously been poisoned" )
353+ }
354+
239355// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
240356// to not impl `Sync` for `F`.
241357#[ stable( feature = "lazy_cell" , since = "1.80.0" ) ]
0 commit comments