1 | #[cfg (all(test, not(target_os = "emscripten" )))] |
2 | mod tests; |
3 | |
4 | use crate::cell::UnsafeCell; |
5 | use crate::fmt; |
6 | use crate::marker::PhantomData; |
7 | use crate::mem::ManuallyDrop; |
8 | use crate::ops::{Deref, DerefMut}; |
9 | use crate::ptr::NonNull; |
10 | use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; |
11 | use crate::sys::sync as sys; |
12 | |
13 | /// A reader-writer lock |
14 | /// |
15 | /// This type of lock allows a number of readers or at most one writer at any |
16 | /// point in time. The write portion of this lock typically allows modification |
17 | /// of the underlying data (exclusive access) and the read portion of this lock |
18 | /// typically allows for read-only access (shared access). |
19 | /// |
20 | /// In comparison, a [`Mutex`] does not distinguish between readers or writers |
21 | /// that acquire the lock, therefore blocking any threads waiting for the lock to |
22 | /// become available. An `RwLock` will allow any number of readers to acquire the |
23 | /// lock as long as a writer is not holding the lock. |
24 | /// |
25 | /// The priority policy of the lock is dependent on the underlying operating |
26 | /// system's implementation, and this type does not guarantee that any |
27 | /// particular policy will be used. In particular, a writer which is waiting to |
28 | /// acquire the lock in `write` might or might not block concurrent calls to |
29 | /// `read`, e.g.: |
30 | /// |
31 | /// <details><summary>Potential deadlock example</summary> |
32 | /// |
33 | /// ```text |
34 | /// // Thread 1 | // Thread 2 |
35 | /// let _rg1 = lock.read(); | |
36 | /// | // will block |
37 | /// | let _wg = lock.write(); |
38 | /// // may deadlock | |
39 | /// let _rg2 = lock.read(); | |
40 | /// ``` |
41 | /// |
42 | /// </details> |
43 | /// |
44 | /// The type parameter `T` represents the data that this lock protects. It is |
45 | /// required that `T` satisfies [`Send`] to be shared across threads and |
46 | /// [`Sync`] to allow concurrent access through readers. The RAII guards |
47 | /// returned from the locking methods implement [`Deref`] (and [`DerefMut`] |
48 | /// for the `write` methods) to allow access to the content of the lock. |
49 | /// |
50 | /// # Poisoning |
51 | /// |
52 | /// An `RwLock`, like [`Mutex`], will become poisoned on a panic. Note, however, |
53 | /// that an `RwLock` may only be poisoned if a panic occurs while it is locked |
54 | /// exclusively (write mode). If a panic occurs in any reader, then the lock |
55 | /// will not be poisoned. |
56 | /// |
57 | /// # Examples |
58 | /// |
59 | /// ``` |
60 | /// use std::sync::RwLock; |
61 | /// |
62 | /// let lock = RwLock::new(5); |
63 | /// |
64 | /// // many reader locks can be held at once |
65 | /// { |
66 | /// let r1 = lock.read().unwrap(); |
67 | /// let r2 = lock.read().unwrap(); |
68 | /// assert_eq!(*r1, 5); |
69 | /// assert_eq!(*r2, 5); |
70 | /// } // read locks are dropped at this point |
71 | /// |
72 | /// // only one write lock may be held, however |
73 | /// { |
74 | /// let mut w = lock.write().unwrap(); |
75 | /// *w += 1; |
76 | /// assert_eq!(*w, 6); |
77 | /// } // write lock is dropped here |
78 | /// ``` |
79 | /// |
80 | /// [`Mutex`]: super::Mutex |
81 | #[stable (feature = "rust1" , since = "1.0.0" )] |
82 | #[cfg_attr (not(test), rustc_diagnostic_item = "RwLock" )] |
83 | pub struct RwLock<T: ?Sized> { |
84 | inner: sys::RwLock, |
85 | poison: poison::Flag, |
86 | data: UnsafeCell<T>, |
87 | } |
88 | |
89 | #[stable (feature = "rust1" , since = "1.0.0" )] |
90 | unsafe impl<T: ?Sized + Send> Send for RwLock<T> {} |
91 | #[stable (feature = "rust1" , since = "1.0.0" )] |
92 | unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {} |
93 | |
94 | /// RAII structure used to release the shared read access of a lock when |
95 | /// dropped. |
96 | /// |
97 | /// This structure is created by the [`read`] and [`try_read`] methods on |
98 | /// [`RwLock`]. |
99 | /// |
100 | /// [`read`]: RwLock::read |
101 | /// [`try_read`]: RwLock::try_read |
102 | #[must_use = "if unused the RwLock will immediately unlock" ] |
103 | #[must_not_suspend = "holding a RwLockReadGuard across suspend \ |
104 | points can cause deadlocks, delays, \ |
105 | and cause Futures to not implement `Send`" ] |
106 | #[stable (feature = "rust1" , since = "1.0.0" )] |
107 | #[clippy::has_significant_drop] |
108 | #[cfg_attr (not(test), rustc_diagnostic_item = "RwLockReadGuard" )] |
109 | pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { |
110 | // NB: we use a pointer instead of `&'a T` to avoid `noalias` violations, because a |
111 | // `RwLockReadGuard` argument doesn't hold immutability for its whole scope, only until it drops. |
112 | // `NonNull` is also covariant over `T`, just like we would have with `&T`. `NonNull` |
113 | // is preferable over `const* T` to allow for niche optimization. |
114 | data: NonNull<T>, |
115 | inner_lock: &'a sys::RwLock, |
116 | } |
117 | |
118 | #[stable (feature = "rust1" , since = "1.0.0" )] |
119 | impl<T: ?Sized> !Send for RwLockReadGuard<'_, T> {} |
120 | |
121 | #[stable (feature = "rwlock_guard_sync" , since = "1.23.0" )] |
122 | unsafe impl<T: ?Sized + Sync> Sync for RwLockReadGuard<'_, T> {} |
123 | |
124 | /// RAII structure used to release the exclusive write access of a lock when |
125 | /// dropped. |
126 | /// |
127 | /// This structure is created by the [`write`] and [`try_write`] methods |
128 | /// on [`RwLock`]. |
129 | /// |
130 | /// [`write`]: RwLock::write |
131 | /// [`try_write`]: RwLock::try_write |
132 | #[must_use = "if unused the RwLock will immediately unlock" ] |
133 | #[must_not_suspend = "holding a RwLockWriteGuard across suspend \ |
134 | points can cause deadlocks, delays, \ |
135 | and cause Future's to not implement `Send`" ] |
136 | #[stable (feature = "rust1" , since = "1.0.0" )] |
137 | #[clippy::has_significant_drop] |
138 | #[cfg_attr (not(test), rustc_diagnostic_item = "RwLockWriteGuard" )] |
139 | pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> { |
140 | lock: &'a RwLock<T>, |
141 | poison: poison::Guard, |
142 | } |
143 | |
144 | #[stable (feature = "rust1" , since = "1.0.0" )] |
145 | impl<T: ?Sized> !Send for RwLockWriteGuard<'_, T> {} |
146 | |
147 | #[stable (feature = "rwlock_guard_sync" , since = "1.23.0" )] |
148 | unsafe impl<T: ?Sized + Sync> Sync for RwLockWriteGuard<'_, T> {} |
149 | |
150 | /// RAII structure used to release the shared read access of a lock when |
151 | /// dropped, which can point to a subfield of the protected data. |
152 | /// |
153 | /// This structure is created by the [`map`] and [`try_map`] methods |
154 | /// on [`RwLockReadGuard`]. |
155 | /// |
156 | /// [`map`]: RwLockReadGuard::map |
157 | /// [`try_map`]: RwLockReadGuard::try_map |
158 | #[must_use = "if unused the RwLock will immediately unlock" ] |
159 | #[must_not_suspend = "holding a MappedRwLockReadGuard across suspend \ |
160 | points can cause deadlocks, delays, \ |
161 | and cause Futures to not implement `Send`" ] |
162 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
163 | #[clippy::has_significant_drop] |
164 | pub struct MappedRwLockReadGuard<'a, T: ?Sized + 'a> { |
165 | // NB: we use a pointer instead of `&'a T` to avoid `noalias` violations, because a |
166 | // `MappedRwLockReadGuard` argument doesn't hold immutability for its whole scope, only until it drops. |
167 | // `NonNull` is also covariant over `T`, just like we would have with `&T`. `NonNull` |
168 | // is preferable over `const* T` to allow for niche optimization. |
169 | data: NonNull<T>, |
170 | inner_lock: &'a sys::RwLock, |
171 | } |
172 | |
173 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
174 | impl<T: ?Sized> !Send for MappedRwLockReadGuard<'_, T> {} |
175 | |
176 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
177 | unsafe impl<T: ?Sized + Sync> Sync for MappedRwLockReadGuard<'_, T> {} |
178 | |
179 | /// RAII structure used to release the exclusive write access of a lock when |
180 | /// dropped, which can point to a subfield of the protected data. |
181 | /// |
182 | /// This structure is created by the [`map`] and [`try_map`] methods |
183 | /// on [`RwLockWriteGuard`]. |
184 | /// |
185 | /// [`map`]: RwLockWriteGuard::map |
186 | /// [`try_map`]: RwLockWriteGuard::try_map |
187 | #[must_use = "if unused the RwLock will immediately unlock" ] |
188 | #[must_not_suspend = "holding a MappedRwLockWriteGuard across suspend \ |
189 | points can cause deadlocks, delays, \ |
190 | and cause Future's to not implement `Send`" ] |
191 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
192 | #[clippy::has_significant_drop] |
193 | pub struct MappedRwLockWriteGuard<'a, T: ?Sized + 'a> { |
194 | // NB: we use a pointer instead of `&'a mut T` to avoid `noalias` violations, because a |
195 | // `MappedRwLockWriteGuard` argument doesn't hold uniqueness for its whole scope, only until it drops. |
196 | // `NonNull` is covariant over `T`, so we add a `PhantomData<&'a mut T>` field |
197 | // below for the correct variance over `T` (invariance). |
198 | data: NonNull<T>, |
199 | inner_lock: &'a sys::RwLock, |
200 | poison_flag: &'a poison::Flag, |
201 | poison: poison::Guard, |
202 | _variance: PhantomData<&'a mut T>, |
203 | } |
204 | |
205 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
206 | impl<T: ?Sized> !Send for MappedRwLockWriteGuard<'_, T> {} |
207 | |
208 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
209 | unsafe impl<T: ?Sized + Sync> Sync for MappedRwLockWriteGuard<'_, T> {} |
210 | |
211 | impl<T> RwLock<T> { |
212 | /// Creates a new instance of an `RwLock<T>` which is unlocked. |
213 | /// |
214 | /// # Examples |
215 | /// |
216 | /// ``` |
217 | /// use std::sync::RwLock; |
218 | /// |
219 | /// let lock = RwLock::new(5); |
220 | /// ``` |
221 | #[stable (feature = "rust1" , since = "1.0.0" )] |
222 | #[rustc_const_stable (feature = "const_locks" , since = "1.63.0" )] |
223 | #[inline ] |
224 | pub const fn new(t: T) -> RwLock<T> { |
225 | RwLock { inner: sys::RwLock::new(), poison: poison::Flag::new(), data: UnsafeCell::new(t) } |
226 | } |
227 | } |
228 | |
229 | impl<T: ?Sized> RwLock<T> { |
230 | /// Locks this `RwLock` with shared read access, blocking the current thread |
231 | /// until it can be acquired. |
232 | /// |
233 | /// The calling thread will be blocked until there are no more writers which |
234 | /// hold the lock. There may be other readers currently inside the lock when |
235 | /// this method returns. This method does not provide any guarantees with |
236 | /// respect to the ordering of whether contentious readers or writers will |
237 | /// acquire the lock first. |
238 | /// |
239 | /// Returns an RAII guard which will release this thread's shared access |
240 | /// once it is dropped. |
241 | /// |
242 | /// # Errors |
243 | /// |
244 | /// This function will return an error if the `RwLock` is poisoned. An |
245 | /// `RwLock` is poisoned whenever a writer panics while holding an exclusive |
246 | /// lock. The failure will occur immediately after the lock has been |
247 | /// acquired. |
248 | /// |
249 | /// # Panics |
250 | /// |
251 | /// This function might panic when called if the lock is already held by the current thread. |
252 | /// |
253 | /// # Examples |
254 | /// |
255 | /// ``` |
256 | /// use std::sync::{Arc, RwLock}; |
257 | /// use std::thread; |
258 | /// |
259 | /// let lock = Arc::new(RwLock::new(1)); |
260 | /// let c_lock = Arc::clone(&lock); |
261 | /// |
262 | /// let n = lock.read().unwrap(); |
263 | /// assert_eq!(*n, 1); |
264 | /// |
265 | /// thread::spawn(move || { |
266 | /// let r = c_lock.read(); |
267 | /// assert!(r.is_ok()); |
268 | /// }).join().unwrap(); |
269 | /// ``` |
270 | #[inline ] |
271 | #[stable (feature = "rust1" , since = "1.0.0" )] |
272 | pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> { |
273 | unsafe { |
274 | self.inner.read(); |
275 | RwLockReadGuard::new(self) |
276 | } |
277 | } |
278 | |
279 | /// Attempts to acquire this `RwLock` with shared read access. |
280 | /// |
281 | /// If the access could not be granted at this time, then `Err` is returned. |
282 | /// Otherwise, an RAII guard is returned which will release the shared access |
283 | /// when it is dropped. |
284 | /// |
285 | /// This function does not block. |
286 | /// |
287 | /// This function does not provide any guarantees with respect to the ordering |
288 | /// of whether contentious readers or writers will acquire the lock first. |
289 | /// |
290 | /// # Errors |
291 | /// |
292 | /// This function will return the [`Poisoned`] error if the `RwLock` is |
293 | /// poisoned. An `RwLock` is poisoned whenever a writer panics while holding |
294 | /// an exclusive lock. `Poisoned` will only be returned if the lock would |
295 | /// have otherwise been acquired. |
296 | /// |
297 | /// This function will return the [`WouldBlock`] error if the `RwLock` could |
298 | /// not be acquired because it was already locked exclusively. |
299 | /// |
300 | /// [`Poisoned`]: TryLockError::Poisoned |
301 | /// [`WouldBlock`]: TryLockError::WouldBlock |
302 | /// |
303 | /// # Examples |
304 | /// |
305 | /// ``` |
306 | /// use std::sync::RwLock; |
307 | /// |
308 | /// let lock = RwLock::new(1); |
309 | /// |
310 | /// match lock.try_read() { |
311 | /// Ok(n) => assert_eq!(*n, 1), |
312 | /// Err(_) => unreachable!(), |
313 | /// }; |
314 | /// ``` |
315 | #[inline ] |
316 | #[stable (feature = "rust1" , since = "1.0.0" )] |
317 | pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>> { |
318 | unsafe { |
319 | if self.inner.try_read() { |
320 | Ok(RwLockReadGuard::new(self)?) |
321 | } else { |
322 | Err(TryLockError::WouldBlock) |
323 | } |
324 | } |
325 | } |
326 | |
327 | /// Locks this `RwLock` with exclusive write access, blocking the current |
328 | /// thread until it can be acquired. |
329 | /// |
330 | /// This function will not return while other writers or other readers |
331 | /// currently have access to the lock. |
332 | /// |
333 | /// Returns an RAII guard which will drop the write access of this `RwLock` |
334 | /// when dropped. |
335 | /// |
336 | /// # Errors |
337 | /// |
338 | /// This function will return an error if the `RwLock` is poisoned. An |
339 | /// `RwLock` is poisoned whenever a writer panics while holding an exclusive |
340 | /// lock. An error will be returned when the lock is acquired. |
341 | /// |
342 | /// # Panics |
343 | /// |
344 | /// This function might panic when called if the lock is already held by the current thread. |
345 | /// |
346 | /// # Examples |
347 | /// |
348 | /// ``` |
349 | /// use std::sync::RwLock; |
350 | /// |
351 | /// let lock = RwLock::new(1); |
352 | /// |
353 | /// let mut n = lock.write().unwrap(); |
354 | /// *n = 2; |
355 | /// |
356 | /// assert!(lock.try_read().is_err()); |
357 | /// ``` |
358 | #[inline ] |
359 | #[stable (feature = "rust1" , since = "1.0.0" )] |
360 | pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> { |
361 | unsafe { |
362 | self.inner.write(); |
363 | RwLockWriteGuard::new(self) |
364 | } |
365 | } |
366 | |
367 | /// Attempts to lock this `RwLock` with exclusive write access. |
368 | /// |
369 | /// If the lock could not be acquired at this time, then `Err` is returned. |
370 | /// Otherwise, an RAII guard is returned which will release the lock when |
371 | /// it is dropped. |
372 | /// |
373 | /// This function does not block. |
374 | /// |
375 | /// This function does not provide any guarantees with respect to the ordering |
376 | /// of whether contentious readers or writers will acquire the lock first. |
377 | /// |
378 | /// # Errors |
379 | /// |
380 | /// This function will return the [`Poisoned`] error if the `RwLock` is |
381 | /// poisoned. An `RwLock` is poisoned whenever a writer panics while holding |
382 | /// an exclusive lock. `Poisoned` will only be returned if the lock would |
383 | /// have otherwise been acquired. |
384 | /// |
385 | /// This function will return the [`WouldBlock`] error if the `RwLock` could |
386 | /// not be acquired because it was already locked exclusively. |
387 | /// |
388 | /// [`Poisoned`]: TryLockError::Poisoned |
389 | /// [`WouldBlock`]: TryLockError::WouldBlock |
390 | /// |
391 | /// |
392 | /// # Examples |
393 | /// |
394 | /// ``` |
395 | /// use std::sync::RwLock; |
396 | /// |
397 | /// let lock = RwLock::new(1); |
398 | /// |
399 | /// let n = lock.read().unwrap(); |
400 | /// assert_eq!(*n, 1); |
401 | /// |
402 | /// assert!(lock.try_write().is_err()); |
403 | /// ``` |
404 | #[inline ] |
405 | #[stable (feature = "rust1" , since = "1.0.0" )] |
406 | pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> { |
407 | unsafe { |
408 | if self.inner.try_write() { |
409 | Ok(RwLockWriteGuard::new(self)?) |
410 | } else { |
411 | Err(TryLockError::WouldBlock) |
412 | } |
413 | } |
414 | } |
415 | |
416 | /// Determines whether the lock is poisoned. |
417 | /// |
418 | /// If another thread is active, the lock can still become poisoned at any |
419 | /// time. You should not trust a `false` value for program correctness |
420 | /// without additional synchronization. |
421 | /// |
422 | /// # Examples |
423 | /// |
424 | /// ``` |
425 | /// use std::sync::{Arc, RwLock}; |
426 | /// use std::thread; |
427 | /// |
428 | /// let lock = Arc::new(RwLock::new(0)); |
429 | /// let c_lock = Arc::clone(&lock); |
430 | /// |
431 | /// let _ = thread::spawn(move || { |
432 | /// let _lock = c_lock.write().unwrap(); |
433 | /// panic!(); // the lock gets poisoned |
434 | /// }).join(); |
435 | /// assert_eq!(lock.is_poisoned(), true); |
436 | /// ``` |
437 | #[inline ] |
438 | #[stable (feature = "sync_poison" , since = "1.2.0" )] |
439 | pub fn is_poisoned(&self) -> bool { |
440 | self.poison.get() |
441 | } |
442 | |
443 | /// Clear the poisoned state from a lock. |
444 | /// |
445 | /// If the lock is poisoned, it will remain poisoned until this function is called. This allows |
446 | /// recovering from a poisoned state and marking that it has recovered. For example, if the |
447 | /// value is overwritten by a known-good value, then the lock can be marked as un-poisoned. Or |
448 | /// possibly, the value could be inspected to determine if it is in a consistent state, and if |
449 | /// so the poison is removed. |
450 | /// |
451 | /// # Examples |
452 | /// |
453 | /// ``` |
454 | /// use std::sync::{Arc, RwLock}; |
455 | /// use std::thread; |
456 | /// |
457 | /// let lock = Arc::new(RwLock::new(0)); |
458 | /// let c_lock = Arc::clone(&lock); |
459 | /// |
460 | /// let _ = thread::spawn(move || { |
461 | /// let _lock = c_lock.write().unwrap(); |
462 | /// panic!(); // the lock gets poisoned |
463 | /// }).join(); |
464 | /// |
465 | /// assert_eq!(lock.is_poisoned(), true); |
466 | /// let guard = lock.write().unwrap_or_else(|mut e| { |
467 | /// **e.get_mut() = 1; |
468 | /// lock.clear_poison(); |
469 | /// e.into_inner() |
470 | /// }); |
471 | /// assert_eq!(lock.is_poisoned(), false); |
472 | /// assert_eq!(*guard, 1); |
473 | /// ``` |
474 | #[inline ] |
475 | #[stable (feature = "mutex_unpoison" , since = "1.77.0" )] |
476 | pub fn clear_poison(&self) { |
477 | self.poison.clear(); |
478 | } |
479 | |
480 | /// Consumes this `RwLock`, returning the underlying data. |
481 | /// |
482 | /// # Errors |
483 | /// |
484 | /// This function will return an error if the `RwLock` is poisoned. An |
485 | /// `RwLock` is poisoned whenever a writer panics while holding an exclusive |
486 | /// lock. An error will only be returned if the lock would have otherwise |
487 | /// been acquired. |
488 | /// |
489 | /// # Examples |
490 | /// |
491 | /// ``` |
492 | /// use std::sync::RwLock; |
493 | /// |
494 | /// let lock = RwLock::new(String::new()); |
495 | /// { |
496 | /// let mut s = lock.write().unwrap(); |
497 | /// *s = "modified" .to_owned(); |
498 | /// } |
499 | /// assert_eq!(lock.into_inner().unwrap(), "modified" ); |
500 | /// ``` |
501 | #[stable (feature = "rwlock_into_inner" , since = "1.6.0" )] |
502 | pub fn into_inner(self) -> LockResult<T> |
503 | where |
504 | T: Sized, |
505 | { |
506 | let data = self.data.into_inner(); |
507 | poison::map_result(self.poison.borrow(), |()| data) |
508 | } |
509 | |
510 | /// Returns a mutable reference to the underlying data. |
511 | /// |
512 | /// Since this call borrows the `RwLock` mutably, no actual locking needs to |
513 | /// take place -- the mutable borrow statically guarantees no locks exist. |
514 | /// |
515 | /// # Errors |
516 | /// |
517 | /// This function will return an error if the `RwLock` is poisoned. An |
518 | /// `RwLock` is poisoned whenever a writer panics while holding an exclusive |
519 | /// lock. An error will only be returned if the lock would have otherwise |
520 | /// been acquired. |
521 | /// |
522 | /// # Examples |
523 | /// |
524 | /// ``` |
525 | /// use std::sync::RwLock; |
526 | /// |
527 | /// let mut lock = RwLock::new(0); |
528 | /// *lock.get_mut().unwrap() = 10; |
529 | /// assert_eq!(*lock.read().unwrap(), 10); |
530 | /// ``` |
531 | #[stable (feature = "rwlock_get_mut" , since = "1.6.0" )] |
532 | pub fn get_mut(&mut self) -> LockResult<&mut T> { |
533 | let data = self.data.get_mut(); |
534 | poison::map_result(self.poison.borrow(), |()| data) |
535 | } |
536 | } |
537 | |
538 | #[stable (feature = "rust1" , since = "1.0.0" )] |
539 | impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> { |
540 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
541 | let mut d: DebugStruct<'_, '_> = f.debug_struct(name:"RwLock" ); |
542 | match self.try_read() { |
543 | Ok(guard: RwLockReadGuard<'_, T>) => { |
544 | d.field(name:"data" , &&*guard); |
545 | } |
546 | Err(TryLockError::Poisoned(err: PoisonError>)) => { |
547 | d.field(name:"data" , &&**err.get_ref()); |
548 | } |
549 | Err(TryLockError::WouldBlock) => { |
550 | d.field(name:"data" , &format_args!("<locked>" )); |
551 | } |
552 | } |
553 | d.field(name:"poisoned" , &self.poison.get()); |
554 | d.finish_non_exhaustive() |
555 | } |
556 | } |
557 | |
558 | #[stable (feature = "rw_lock_default" , since = "1.10.0" )] |
559 | impl<T: Default> Default for RwLock<T> { |
560 | /// Creates a new `RwLock<T>`, with the `Default` value for T. |
561 | fn default() -> RwLock<T> { |
562 | RwLock::new(Default::default()) |
563 | } |
564 | } |
565 | |
566 | #[stable (feature = "rw_lock_from" , since = "1.24.0" )] |
567 | impl<T> From<T> for RwLock<T> { |
568 | /// Creates a new instance of an `RwLock<T>` which is unlocked. |
569 | /// This is equivalent to [`RwLock::new`]. |
570 | fn from(t: T) -> Self { |
571 | RwLock::new(t) |
572 | } |
573 | } |
574 | |
575 | impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { |
576 | /// Create a new instance of `RwLockReadGuard<T>` from a `RwLock<T>`. |
577 | // SAFETY: if and only if `lock.inner.read()` (or `lock.inner.try_read()`) has been |
578 | // successfully called from the same thread before instantiating this object. |
579 | unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockReadGuard<'rwlock, T>> { |
580 | poison::map_result(result:lock.poison.borrow(), |()| RwLockReadGuard { |
581 | data: NonNull::new_unchecked(ptr:lock.data.get()), |
582 | inner_lock: &lock.inner, |
583 | }) |
584 | } |
585 | } |
586 | |
587 | impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { |
588 | /// Create a new instance of `RwLockWriteGuard<T>` from a `RwLock<T>`. |
589 | // SAFETY: if and only if `lock.inner.write()` (or `lock.inner.try_write()`) has been |
590 | // successfully called from the same thread before instantiating this object. |
591 | unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockWriteGuard<'rwlock, T>> { |
592 | poison::map_result(result:lock.poison.guard(), |guard: Guard| RwLockWriteGuard { lock, poison: guard }) |
593 | } |
594 | } |
595 | |
596 | #[stable (feature = "std_debug" , since = "1.16.0" )] |
597 | impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> { |
598 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
599 | (**self).fmt(f) |
600 | } |
601 | } |
602 | |
603 | #[stable (feature = "std_guard_impls" , since = "1.20.0" )] |
604 | impl<T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'_, T> { |
605 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
606 | (**self).fmt(f) |
607 | } |
608 | } |
609 | |
610 | #[stable (feature = "std_debug" , since = "1.16.0" )] |
611 | impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> { |
612 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
613 | (**self).fmt(f) |
614 | } |
615 | } |
616 | |
617 | #[stable (feature = "std_guard_impls" , since = "1.20.0" )] |
618 | impl<T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'_, T> { |
619 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
620 | (**self).fmt(f) |
621 | } |
622 | } |
623 | |
624 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
625 | impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockReadGuard<'_, T> { |
626 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
627 | (**self).fmt(f) |
628 | } |
629 | } |
630 | |
631 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
632 | impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockReadGuard<'_, T> { |
633 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
634 | (**self).fmt(f) |
635 | } |
636 | } |
637 | |
638 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
639 | impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockWriteGuard<'_, T> { |
640 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
641 | (**self).fmt(f) |
642 | } |
643 | } |
644 | |
645 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
646 | impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockWriteGuard<'_, T> { |
647 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
648 | (**self).fmt(f) |
649 | } |
650 | } |
651 | |
652 | #[stable (feature = "rust1" , since = "1.0.0" )] |
653 | impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> { |
654 | type Target = T; |
655 | |
656 | fn deref(&self) -> &T { |
657 | // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created. |
658 | unsafe { self.data.as_ref() } |
659 | } |
660 | } |
661 | |
662 | #[stable (feature = "rust1" , since = "1.0.0" )] |
663 | impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> { |
664 | type Target = T; |
665 | |
666 | fn deref(&self) -> &T { |
667 | // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created. |
668 | unsafe { &*self.lock.data.get() } |
669 | } |
670 | } |
671 | |
672 | #[stable (feature = "rust1" , since = "1.0.0" )] |
673 | impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> { |
674 | fn deref_mut(&mut self) -> &mut T { |
675 | // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created. |
676 | unsafe { &mut *self.lock.data.get() } |
677 | } |
678 | } |
679 | |
680 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
681 | impl<T: ?Sized> Deref for MappedRwLockReadGuard<'_, T> { |
682 | type Target = T; |
683 | |
684 | fn deref(&self) -> &T { |
685 | // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard |
686 | // was created, and have been upheld throughout `map` and/or `try_map`. |
687 | unsafe { self.data.as_ref() } |
688 | } |
689 | } |
690 | |
691 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
692 | impl<T: ?Sized> Deref for MappedRwLockWriteGuard<'_, T> { |
693 | type Target = T; |
694 | |
695 | fn deref(&self) -> &T { |
696 | // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard |
697 | // was created, and have been upheld throughout `map` and/or `try_map`. |
698 | unsafe { self.data.as_ref() } |
699 | } |
700 | } |
701 | |
702 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
703 | impl<T: ?Sized> DerefMut for MappedRwLockWriteGuard<'_, T> { |
704 | fn deref_mut(&mut self) -> &mut T { |
705 | // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard |
706 | // was created, and have been upheld throughout `map` and/or `try_map`. |
707 | unsafe { self.data.as_mut() } |
708 | } |
709 | } |
710 | |
711 | #[stable (feature = "rust1" , since = "1.0.0" )] |
712 | impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> { |
713 | fn drop(&mut self) { |
714 | // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created. |
715 | unsafe { |
716 | self.inner_lock.read_unlock(); |
717 | } |
718 | } |
719 | } |
720 | |
721 | #[stable (feature = "rust1" , since = "1.0.0" )] |
722 | impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> { |
723 | fn drop(&mut self) { |
724 | self.lock.poison.done(&self.poison); |
725 | // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created. |
726 | unsafe { |
727 | self.lock.inner.write_unlock(); |
728 | } |
729 | } |
730 | } |
731 | |
732 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
733 | impl<T: ?Sized> Drop for MappedRwLockReadGuard<'_, T> { |
734 | fn drop(&mut self) { |
735 | // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard |
736 | // was created, and have been upheld throughout `map` and/or `try_map`. |
737 | unsafe { |
738 | self.inner_lock.read_unlock(); |
739 | } |
740 | } |
741 | } |
742 | |
743 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
744 | impl<T: ?Sized> Drop for MappedRwLockWriteGuard<'_, T> { |
745 | fn drop(&mut self) { |
746 | self.poison_flag.done(&self.poison); |
747 | // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard |
748 | // was created, and have been upheld throughout `map` and/or `try_map`. |
749 | unsafe { |
750 | self.inner_lock.write_unlock(); |
751 | } |
752 | } |
753 | } |
754 | |
755 | impl<'a, T: ?Sized> RwLockReadGuard<'a, T> { |
756 | /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data, e.g. |
757 | /// an enum variant. |
758 | /// |
759 | /// The `RwLock` is already locked for reading, so this cannot fail. |
760 | /// |
761 | /// This is an associated function that needs to be used as |
762 | /// `RwLockReadGuard::map(...)`. A method would interfere with methods of |
763 | /// the same name on the contents of the `RwLockReadGuard` used through |
764 | /// `Deref`. |
765 | /// |
766 | /// # Panics |
767 | /// |
768 | /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will not be poisoned. |
769 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
770 | pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'a, U> |
771 | where |
772 | F: FnOnce(&T) -> &U, |
773 | U: ?Sized, |
774 | { |
775 | // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard |
776 | // was created, and have been upheld throughout `map` and/or `try_map`. |
777 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
778 | // passed to it. If the closure panics, the guard will be dropped. |
779 | let data = NonNull::from(f(unsafe { orig.data.as_ref() })); |
780 | let orig = ManuallyDrop::new(orig); |
781 | MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock } |
782 | } |
783 | |
784 | /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. The |
785 | /// original guard is returned as an `Err(...)` if the closure returns |
786 | /// `None`. |
787 | /// |
788 | /// The `RwLock` is already locked for reading, so this cannot fail. |
789 | /// |
790 | /// This is an associated function that needs to be used as |
791 | /// `RwLockReadGuard::try_map(...)`. A method would interfere with methods |
792 | /// of the same name on the contents of the `RwLockReadGuard` used through |
793 | /// `Deref`. |
794 | /// |
795 | /// # Panics |
796 | /// |
797 | /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will not be poisoned. |
798 | #[doc (alias = "filter_map" )] |
799 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
800 | pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'a, U>, Self> |
801 | where |
802 | F: FnOnce(&T) -> Option<&U>, |
803 | U: ?Sized, |
804 | { |
805 | // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard |
806 | // was created, and have been upheld throughout `map` and/or `try_map`. |
807 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
808 | // passed to it. If the closure panics, the guard will be dropped. |
809 | match f(unsafe { orig.data.as_ref() }) { |
810 | Some(data) => { |
811 | let data = NonNull::from(data); |
812 | let orig = ManuallyDrop::new(orig); |
813 | Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }) |
814 | } |
815 | None => Err(orig), |
816 | } |
817 | } |
818 | } |
819 | |
820 | impl<'a, T: ?Sized> MappedRwLockReadGuard<'a, T> { |
821 | /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data, |
822 | /// e.g. an enum variant. |
823 | /// |
824 | /// The `RwLock` is already locked for reading, so this cannot fail. |
825 | /// |
826 | /// This is an associated function that needs to be used as |
827 | /// `MappedRwLockReadGuard::map(...)`. A method would interfere with |
828 | /// methods of the same name on the contents of the `MappedRwLockReadGuard` |
829 | /// used through `Deref`. |
830 | /// |
831 | /// # Panics |
832 | /// |
833 | /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will not be poisoned. |
834 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
835 | pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'a, U> |
836 | where |
837 | F: FnOnce(&T) -> &U, |
838 | U: ?Sized, |
839 | { |
840 | // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard |
841 | // was created, and have been upheld throughout `map` and/or `try_map`. |
842 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
843 | // passed to it. If the closure panics, the guard will be dropped. |
844 | let data = NonNull::from(f(unsafe { orig.data.as_ref() })); |
845 | let orig = ManuallyDrop::new(orig); |
846 | MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock } |
847 | } |
848 | |
849 | /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. |
850 | /// The original guard is returned as an `Err(...)` if the closure returns |
851 | /// `None`. |
852 | /// |
853 | /// The `RwLock` is already locked for reading, so this cannot fail. |
854 | /// |
855 | /// This is an associated function that needs to be used as |
856 | /// `MappedRwLockReadGuard::try_map(...)`. A method would interfere with |
857 | /// methods of the same name on the contents of the `MappedRwLockReadGuard` |
858 | /// used through `Deref`. |
859 | /// |
860 | /// # Panics |
861 | /// |
862 | /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will not be poisoned. |
863 | #[doc (alias = "filter_map" )] |
864 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
865 | pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'a, U>, Self> |
866 | where |
867 | F: FnOnce(&T) -> Option<&U>, |
868 | U: ?Sized, |
869 | { |
870 | // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard |
871 | // was created, and have been upheld throughout `map` and/or `try_map`. |
872 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
873 | // passed to it. If the closure panics, the guard will be dropped. |
874 | match f(unsafe { orig.data.as_ref() }) { |
875 | Some(data) => { |
876 | let data = NonNull::from(data); |
877 | let orig = ManuallyDrop::new(orig); |
878 | Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }) |
879 | } |
880 | None => Err(orig), |
881 | } |
882 | } |
883 | } |
884 | |
885 | impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> { |
886 | /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data, e.g. |
887 | /// an enum variant. |
888 | /// |
889 | /// The `RwLock` is already locked for writing, so this cannot fail. |
890 | /// |
891 | /// This is an associated function that needs to be used as |
892 | /// `RwLockWriteGuard::map(...)`. A method would interfere with methods of |
893 | /// the same name on the contents of the `RwLockWriteGuard` used through |
894 | /// `Deref`. |
895 | /// |
896 | /// # Panics |
897 | /// |
898 | /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will be poisoned. |
899 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
900 | pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'a, U> |
901 | where |
902 | F: FnOnce(&mut T) -> &mut U, |
903 | U: ?Sized, |
904 | { |
905 | // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard |
906 | // was created, and have been upheld throughout `map` and/or `try_map`. |
907 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
908 | // passed to it. If the closure panics, the guard will be dropped. |
909 | let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() })); |
910 | let orig = ManuallyDrop::new(orig); |
911 | MappedRwLockWriteGuard { |
912 | data, |
913 | inner_lock: &orig.lock.inner, |
914 | poison_flag: &orig.lock.poison, |
915 | poison: orig.poison.clone(), |
916 | _variance: PhantomData, |
917 | } |
918 | } |
919 | |
920 | /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data. The |
921 | /// original guard is returned as an `Err(...)` if the closure returns |
922 | /// `None`. |
923 | /// |
924 | /// The `RwLock` is already locked for writing, so this cannot fail. |
925 | /// |
926 | /// This is an associated function that needs to be used as |
927 | /// `RwLockWriteGuard::try_map(...)`. A method would interfere with methods |
928 | /// of the same name on the contents of the `RwLockWriteGuard` used through |
929 | /// `Deref`. |
930 | /// |
931 | /// # Panics |
932 | /// |
933 | /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will be poisoned. |
934 | #[doc (alias = "filter_map" )] |
935 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
936 | pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, U>, Self> |
937 | where |
938 | F: FnOnce(&mut T) -> Option<&mut U>, |
939 | U: ?Sized, |
940 | { |
941 | // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard |
942 | // was created, and have been upheld throughout `map` and/or `try_map`. |
943 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
944 | // passed to it. If the closure panics, the guard will be dropped. |
945 | match f(unsafe { &mut *orig.lock.data.get() }) { |
946 | Some(data) => { |
947 | let data = NonNull::from(data); |
948 | let orig = ManuallyDrop::new(orig); |
949 | Ok(MappedRwLockWriteGuard { |
950 | data, |
951 | inner_lock: &orig.lock.inner, |
952 | poison_flag: &orig.lock.poison, |
953 | poison: orig.poison.clone(), |
954 | _variance: PhantomData, |
955 | }) |
956 | } |
957 | None => Err(orig), |
958 | } |
959 | } |
960 | } |
961 | |
962 | impl<'a, T: ?Sized> MappedRwLockWriteGuard<'a, T> { |
963 | /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data, |
964 | /// e.g. an enum variant. |
965 | /// |
966 | /// The `RwLock` is already locked for writing, so this cannot fail. |
967 | /// |
968 | /// This is an associated function that needs to be used as |
969 | /// `MappedRwLockWriteGuard::map(...)`. A method would interfere with |
970 | /// methods of the same name on the contents of the `MappedRwLockWriteGuard` |
971 | /// used through `Deref`. |
972 | /// |
973 | /// # Panics |
974 | /// |
975 | /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will be poisoned. |
976 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
977 | pub fn map<U, F>(mut orig: Self, f: F) -> MappedRwLockWriteGuard<'a, U> |
978 | where |
979 | F: FnOnce(&mut T) -> &mut U, |
980 | U: ?Sized, |
981 | { |
982 | // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard |
983 | // was created, and have been upheld throughout `map` and/or `try_map`. |
984 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
985 | // passed to it. If the closure panics, the guard will be dropped. |
986 | let data = NonNull::from(f(unsafe { orig.data.as_mut() })); |
987 | let orig = ManuallyDrop::new(orig); |
988 | MappedRwLockWriteGuard { |
989 | data, |
990 | inner_lock: orig.inner_lock, |
991 | poison_flag: orig.poison_flag, |
992 | poison: orig.poison.clone(), |
993 | _variance: PhantomData, |
994 | } |
995 | } |
996 | |
997 | /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data. |
998 | /// The original guard is returned as an `Err(...)` if the closure returns |
999 | /// `None`. |
1000 | /// |
1001 | /// The `RwLock` is already locked for writing, so this cannot fail. |
1002 | /// |
1003 | /// This is an associated function that needs to be used as |
1004 | /// `MappedRwLockWriteGuard::try_map(...)`. A method would interfere with |
1005 | /// methods of the same name on the contents of the `MappedRwLockWriteGuard` |
1006 | /// used through `Deref`. |
1007 | /// |
1008 | /// # Panics |
1009 | /// |
1010 | /// If the closure panics, the guard will be dropped (unlocked) and the RwLock will be poisoned. |
1011 | #[doc (alias = "filter_map" )] |
1012 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
1013 | pub fn try_map<U, F>(mut orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, U>, Self> |
1014 | where |
1015 | F: FnOnce(&mut T) -> Option<&mut U>, |
1016 | U: ?Sized, |
1017 | { |
1018 | // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard |
1019 | // was created, and have been upheld throughout `map` and/or `try_map`. |
1020 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
1021 | // passed to it. If the closure panics, the guard will be dropped. |
1022 | match f(unsafe { orig.data.as_mut() }) { |
1023 | Some(data) => { |
1024 | let data = NonNull::from(data); |
1025 | let orig = ManuallyDrop::new(orig); |
1026 | Ok(MappedRwLockWriteGuard { |
1027 | data, |
1028 | inner_lock: orig.inner_lock, |
1029 | poison_flag: orig.poison_flag, |
1030 | poison: orig.poison.clone(), |
1031 | _variance: PhantomData, |
1032 | }) |
1033 | } |
1034 | None => Err(orig), |
1035 | } |
1036 | } |
1037 | } |
1038 | |