ref_portals/
sync.rs

1//! Theadsafe anchors and portals.  
2//! These (but not their guards) are various degrees of `Send` and `Sync` depending on their type parameter.
3
4use {
5    crate::{ANCHOR_DROPPED, ANCHOR_POISONED, ANCHOR_STILL_IN_USE},
6    std::{
7        borrow::Borrow,
8        fmt::Debug,
9        marker::PhantomData,
10        mem::ManuallyDrop,
11        ops::{Deref, DerefMut},
12        panic::{RefUnwindSafe, UnwindSafe},
13        ptr::NonNull,
14        sync::{Arc, Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard, Weak},
15    },
16    wyz::pipe::*,
17};
18
19/// An externally synchronised `NonNull<T>`.
20/// SS stands for Send Sync.
21#[derive(Debug, Clone, Copy)]
22#[repr(transparent)]
23struct SSNonNull<T: ?Sized>(NonNull<T>);
24unsafe impl<T: ?Sized + Send> Send for SSNonNull<T> {
25    //SAFETY: Externally synchronised in this crate.
26}
27unsafe impl<T: ?Sized + Sync> Sync for SSNonNull<T> {
28    //SAFETY: Externally synchronised in this crate.
29}
30impl<T: ?Sized> From<&T> for SSNonNull<T> {
31    #[inline]
32    fn from(value: &T) -> Self {
33        Self(value.into())
34    }
35}
36impl<T: ?Sized> From<&mut T> for SSNonNull<T> {
37    #[inline]
38    fn from(value: &mut T) -> Self {
39        Self(value.into())
40    }
41}
42impl<T: ?Sized> Deref for SSNonNull<T> {
43    type Target = NonNull<T>;
44    #[inline]
45    fn deref(&self) -> &Self::Target {
46        &self.0
47    }
48}
49impl<T: ?Sized> DerefMut for SSNonNull<T> {
50    #[inline]
51    fn deref_mut(&mut self) -> &mut Self::Target {
52        &mut self.0
53    }
54}
55
56/// A threadsafe immutable anchor with concurrent read access.  
57/// Use this to capture immutable references in a threaded environment.
58///
59/// # Panics
60///
61/// On drop, if any associated `Portal`s exist:
62///
63/// ```rust
64/// # use assert_panic::assert_panic;
65/// use ref_portals::sync::Anchor;
66///
67/// let x = "Scoped".to_owned();
68/// let anchor = Anchor::new(&x);
69/// Box::leak(Box::new(anchor.portal()));
70///
71/// assert_panic!(
72///     drop(anchor),
73///     &str,
74///     "Anchor still in use (at least one portal exists)",
75/// );
76/// ```
77#[derive(Debug)]
78#[repr(transparent)]
79pub struct Anchor<'a, T: ?Sized> {
80    /// Internal pointer to the target of the captured reference.
81    reference: ManuallyDrop<Arc<SSNonNull<T>>>,
82
83    /// Act as sharing borrower.
84    _phantom: PhantomData<&'a T>,
85}
86
87/// A threadsafe mutable anchor with concurrent read access.  
88/// Use this to capture mutable references to `Sync` types in a threaded environment.
89///
90/// # Panics
91///
92/// On drop, if any associated `RwPortal`s exist:
93///
94/// ```rust
95/// # use assert_panic::assert_panic;
96/// use ref_portals::sync::RwAnchor;
97///
98/// let mut x = "Scoped".to_owned();
99/// let anchor = RwAnchor::new(&mut x);
100/// Box::leak(Box::new(anchor.portal()));
101///
102/// assert_panic!(
103///     drop(anchor),
104///     &str,
105///     "Anchor still in use (at least one portal exists)",
106/// );
107/// ```
108///
109/// Otherwise, on drop, iff the anchor has been poisoned:
110///
111/// ```rust
112/// # use assert_panic::assert_panic;
113/// use ref_portals::sync::RwAnchor;
114///
115/// let mut x = "Scoped".to_owned();
116/// let anchor = RwAnchor::new(&mut x);
117/// {
118///     let portal = anchor.portal();
119///     assert_panic!({
120///         let guard = portal.write();
121///         panic!()
122///     });
123/// }
124///
125/// assert_panic!(
126///     drop(anchor),
127///     String,
128///     starts with "Anchor poisoned:",
129/// );
130/// ```
131#[derive(Debug)]
132#[repr(transparent)]
133pub struct RwAnchor<'a, T: ?Sized> {
134    /// Internal pointer to the target of the captured reference.
135    reference: ManuallyDrop<Arc<RwLock<SSNonNull<T>>>>,
136
137    /// Act as exclusive borrower.
138    _phantom: PhantomData<&'a mut T>,
139}
140
141/// A threadsafe mutable anchor with concurrent read access.  
142/// Use this to capture mutable references to `!Sync` types in a threaded environment.
143///
144/// # Panics
145///
146/// On drop, if any associated `WPortal`s exist:
147///
148/// ```rust
149/// # use assert_panic::assert_panic;
150/// use ref_portals::sync::WAnchor;
151///
152/// let mut x = "Scoped".to_owned();
153/// let anchor = WAnchor::new(&mut x);
154/// Box::leak(Box::new(anchor.portal()));
155///
156/// assert_panic!(
157///     drop(anchor),
158///     &str,
159///     "Anchor still in use (at least one portal exists)",
160/// );
161/// ```
162///
163/// Otherwise, on drop, iff the anchor has been poisoned:
164///
165/// ```rust
166/// # use assert_panic::assert_panic;
167/// use ref_portals::sync::WAnchor;
168///
169/// let mut x = "Scoped".to_owned();
170/// let anchor = WAnchor::new(&mut x);
171/// {
172///     let portal = anchor.portal();
173///     assert_panic!({
174///         let guard = portal.lock();
175///         panic!()
176///     });
177/// }
178///
179/// assert_panic!(
180///     drop(anchor),
181///     String,
182///     starts with "Anchor poisoned:",
183/// );
184/// ```
185#[derive(Debug)]
186#[repr(transparent)]
187pub struct WAnchor<'a, T: ?Sized> {
188    /// Internal pointer to the target of the captured reference.
189    reference: ManuallyDrop<Arc<Mutex<SSNonNull<T>>>>,
190
191    /// Act as exclusive borrower.
192    _phantom: PhantomData<&'a mut T>,
193}
194
195impl<'a, T: ?Sized> Anchor<'a, T> {
196    #[inline]
197    pub fn new(reference: &'a T) -> Self {
198        Self {
199            reference: ManuallyDrop::new(Arc::new(reference.into())),
200            _phantom: PhantomData,
201        }
202    }
203
204    #[inline]
205    pub fn portal(&self) -> Portal<T> {
206        self.reference.pipe_deref(Arc::clone).pipe(Portal)
207    }
208
209    #[inline]
210    pub fn weak_portal(&self) -> WeakPortal<T> {
211        Portal::downgrade(&self.portal())
212    }
213}
214
215impl<'a, T: ?Sized> RwAnchor<'a, T> {
216    #[inline]
217    pub fn new(reference: &'a mut T) -> Self {
218        Self {
219            reference: ManuallyDrop::new(Arc::new(RwLock::new(reference.into()))),
220            _phantom: PhantomData,
221        }
222    }
223
224    #[inline]
225    pub fn portal(&self) -> RwPortal<T> {
226        self.reference.pipe_deref(Arc::clone).pipe(RwPortal)
227    }
228
229    #[inline]
230    pub fn weak_portal(&self) -> WeakRwPortal<T> {
231        self.portal().downgrade()
232    }
233}
234
235impl<'a, T: ?Sized> WAnchor<'a, T> {
236    #[inline]
237    pub fn new(reference: &'a mut T) -> Self {
238        Self {
239            reference: ManuallyDrop::new(Arc::new(Mutex::new(reference.into()))),
240            _phantom: PhantomData,
241        }
242    }
243
244    #[inline]
245    pub fn portal(&self) -> WPortal<T> {
246        self.reference.pipe_deref(Arc::clone).pipe(WPortal)
247    }
248
249    #[inline]
250    pub fn weak_portal(&self) -> WeakWPortal<T> {
251        self.portal().downgrade()
252    }
253}
254
255impl<'a, T: ?Sized> Drop for Anchor<'a, T> {
256    /// Executes the destructor for this type. [Read more](https://doc.rust-lang.org/nightly/core/ops/drop/trait.Drop.html#tymethod.drop)
257    ///
258    /// # Panics
259    ///
260    /// If any associated `Portal`s exist:
261    ///
262    /// ```rust
263    /// # use assert_panic::assert_panic;
264    /// use ref_portals::sync::Anchor;
265    ///
266    /// let x = "Scoped".to_owned();
267    /// let anchor = Anchor::new(&x);
268    /// let portal = anchor.portal();
269    ///
270    /// assert_panic!(
271    ///     drop(anchor),
272    ///     &str,
273    ///     "Anchor still in use (at least one portal exists)",
274    /// );
275    /// ```
276    fn drop(&mut self) {
277        unsafe {
278            //SAFETY: Dropping.
279            ManuallyDrop::take(&mut self.reference)
280        }
281        .pipe(Arc::try_unwrap)
282        .unwrap_or_else(|_| panic!(ANCHOR_STILL_IN_USE));
283    }
284}
285
286impl<'a, T: ?Sized> Drop for RwAnchor<'a, T> {
287    /// Executes the destructor for this type. [Read more](https://doc.rust-lang.org/nightly/core/ops/drop/trait.Drop.html#tymethod.drop)
288    ///
289    /// # Panics
290    ///
291    /// If any associated `RwPortal`s exist or, otherwise, iff the anchor has been poisoned:
292    ///
293    /// ```rust
294    /// # use assert_panic::assert_panic;
295    /// use ref_portals::sync::RwAnchor;
296    ///
297    /// let mut x = "Scoped".to_owned();
298    /// let anchor = RwAnchor::new(&mut x);
299    /// let portal = anchor.portal();
300    /// assert_panic!({
301    ///     // Poison anchor.
302    ///     let _guard = portal.write();
303    ///     panic!()
304    /// });
305    ///
306    /// assert_panic!(
307    ///     drop(anchor),
308    ///     &str,
309    ///     "Anchor still in use (at least one portal exists)",
310    /// );
311    /// ```
312    fn drop(&mut self) {
313        unsafe {
314            //SAFETY: Dropping.
315            ManuallyDrop::take(&mut self.reference)
316        }
317        .pipe(Arc::try_unwrap)
318        .unwrap_or_else(|reference| {
319            // Poison RwLock.
320            let _guard = reference.write();
321            panic!(ANCHOR_STILL_IN_USE);
322        })
323        .into_inner()
324        .unwrap_or_else(|error| Err(error).expect(ANCHOR_POISONED));
325    }
326}
327
328impl<'a, T: ?Sized> Drop for WAnchor<'a, T> {
329    /// Executes the destructor for this type. [Read more](https://doc.rust-lang.org/nightly/core/ops/drop/trait.Drop.html#tymethod.drop)
330    ///
331    /// # Panics
332    ///
333    /// If any associated `WPortal`s exist or, otherwise, iff the anchor has been poisoned:
334    ///
335    /// ```rust
336    /// # use assert_panic::assert_panic;
337    /// use ref_portals::sync::WAnchor;
338    ///
339    /// let mut x = "Scoped".to_owned();
340    /// let anchor = WAnchor::new(&mut x);
341    /// let portal = anchor.portal();
342    /// assert_panic!({
343    ///     // Poison anchor.
344    ///     let _guard = portal.lock();
345    ///     panic!()
346    /// });
347    ///
348    /// assert_panic!(
349    ///     drop(anchor),
350    ///     &str,
351    ///     "Anchor still in use (at least one portal exists)",
352    /// );
353    /// ```
354    fn drop(&mut self) {
355        unsafe {
356            //SAFETY: Dropping.
357            ManuallyDrop::take(&mut self.reference)
358        }
359        .pipe(Arc::try_unwrap)
360        .unwrap_or_else(|reference| {
361            // Poison Mutex.
362            let _guard = reference.lock();
363            panic!(ANCHOR_STILL_IN_USE);
364        })
365        .into_inner()
366        .unwrap_or_else(|error| Err(error).expect(ANCHOR_POISONED));
367    }
368}
369
370/// # Safety:
371///
372/// ```rust
373/// # use assert_panic::assert_panic;
374/// use ref_portals::sync::RwAnchor;
375///
376/// let mut x = "Scoped".to_owned();
377/// let anchor = RwAnchor::new(&mut x);
378/// let portal = anchor.portal();
379///
380/// assert_panic!(
381///     drop(anchor),
382///     &str,
383///     "Anchor still in use (at least one portal exists)",
384/// );
385/// assert_panic!(
386///     { portal.read(); },
387///     String,
388///     starts with "Anchor poisoned:",
389/// );
390/// ```
391impl<'a, T: ?Sized> UnwindSafe for RwAnchor<'a, T> where T: RefUnwindSafe {}
392
393/// # Safety:
394///
395/// ```rust
396/// # use assert_panic::assert_panic;
397/// use ref_portals::sync::WAnchor;
398///
399/// let mut x = "Scoped".to_owned();
400/// let anchor = WAnchor::new(&mut x);
401/// let portal = anchor.portal();
402///
403/// assert_panic!(
404///     drop(anchor),
405///     &str,
406///     "Anchor still in use (at least one portal exists)",
407/// );
408/// assert_panic!(
409///     { portal.lock(); },
410///     String,
411///     starts with "Anchor poisoned:",
412/// );
413/// ```
414impl<'a, T: ?Sized> UnwindSafe for WAnchor<'a, T> where T: RefUnwindSafe {}
415
416/// A threadsafe immutable portal.  
417/// Dereference it directly with `*` or `.deref()`.
418#[derive(Debug)]
419#[must_use]
420#[repr(transparent)]
421pub struct Portal<T: ?Sized>(Arc<SSNonNull<T>>);
422
423/// A threadsafe mutable portal supporting concurred reads.  
424/// Acquire a guard by calling `.read()` or `.write()`.
425#[derive(Debug)]
426#[must_use]
427#[repr(transparent)]
428pub struct RwPortal<T: ?Sized>(Arc<RwLock<SSNonNull<T>>>);
429
430/// A threadsafe mutable portal with only exclusive access.  
431/// Acquire a guard by calling `.lock()`.
432#[derive(Debug)]
433#[must_use]
434#[repr(transparent)]
435pub struct WPortal<T: ?Sized>(Arc<Mutex<SSNonNull<T>>>);
436
437impl<T: ?Sized> Portal<T> {
438    /// Creates a weak portal associated with the same anchor as `portal`.  
439    /// Dropping an anchor doesn't panic if only weak portals exist.
440    #[inline]
441    pub fn downgrade(portal: &Self) -> WeakPortal<T> {
442        Arc::downgrade(&portal.0).pipe(WeakPortal)
443    }
444}
445
446impl<T: ?Sized> Deref for Portal<T> {
447    type Target = T;
448    #[inline]
449    fn deref(&self) -> &Self::Target {
450        let pointer = self.0.deref();
451        unsafe {
452            //SAFETY: Valid as long as self.0 is.
453            pointer.as_ref()
454        }
455    }
456}
457
458impl<T: ?Sized> Borrow<T> for Portal<T> {
459    #[inline]
460    fn borrow(&self) -> &T {
461        &*self
462    }
463}
464
465impl<T: ?Sized> RwPortal<T> {
466    /// Creates a weak portal associated with the same anchor as this one.  
467    /// Dropping an anchor doesn't panic if only weak portals exist.
468    #[inline]
469    pub fn downgrade(&self) -> WeakRwPortal<T> {
470        Arc::downgrade(&self.0).pipe(WeakRwPortal)
471    }
472
473    #[inline]
474    pub fn read<'a>(&'a self) -> impl Deref<Target = T> + 'a {
475        self.0.read().expect(ANCHOR_POISONED).pipe(PortalReadGuard)
476    }
477
478    #[inline]
479    pub fn write<'a>(&'a self) -> impl DerefMut<Target = T> + 'a {
480        self.0
481            .write()
482            .expect(ANCHOR_POISONED)
483            .pipe(PortalWriteGuard)
484    }
485}
486
487impl<T: ?Sized> WPortal<T> {
488    /// Creates a weak portal associated with the same anchor as this one.  
489    /// Dropping an anchor doesn't panic if only weak portals exist.
490    #[inline]
491    pub fn downgrade(&self) -> WeakWPortal<T> {
492        Arc::downgrade(&self.0).pipe(WeakWPortal)
493    }
494
495    #[inline]
496    pub fn lock<'a>(&'a self) -> impl DerefMut<Target = T> + 'a {
497        self.0.lock().expect(ANCHOR_POISONED).pipe(PortalMutexGuard)
498    }
499}
500
501impl<T: ?Sized> Clone for Portal<T> {
502    #[inline]
503    fn clone(&self) -> Self {
504        self.0.pipe_ref(Arc::clone).pipe(Self)
505    }
506}
507
508impl<T: ?Sized> Clone for RwPortal<T> {
509    #[inline]
510    fn clone(&self) -> Self {
511        self.0.pipe_ref(Arc::clone).pipe(Self)
512    }
513}
514
515impl<T: ?Sized> Clone for WPortal<T> {
516    #[inline]
517    fn clone(&self) -> Self {
518        self.0.pipe_ref(Arc::clone).pipe(Self)
519    }
520}
521
522#[derive(Debug)]
523#[must_use]
524#[repr(transparent)]
525pub struct WeakPortal<T: ?Sized>(Weak<SSNonNull<T>>);
526
527#[derive(Debug)]
528#[must_use]
529#[repr(transparent)]
530pub struct WeakRwPortal<T: ?Sized>(Weak<RwLock<SSNonNull<T>>>);
531
532#[derive(Debug)]
533#[must_use]
534#[repr(transparent)]
535pub struct WeakWPortal<T: ?Sized>(Weak<Mutex<SSNonNull<T>>>);
536
537impl<T: ?Sized> WeakPortal<T> {
538    #[inline]
539    pub fn try_upgrade(&self) -> Option<Portal<T>> {
540        self.0.upgrade().map(Portal)
541    }
542
543    #[inline]
544    pub fn upgrade(&self) -> Portal<T> {
545        self.try_upgrade().expect(ANCHOR_DROPPED)
546    }
547}
548
549impl<T: ?Sized> WeakRwPortal<T> {
550    #[inline]
551    pub fn try_upgrade(&self) -> Option<RwPortal<T>> {
552        self.0.upgrade().map(RwPortal)
553    }
554
555    #[inline]
556    pub fn upgrade(&self) -> RwPortal<T> {
557        self.try_upgrade().expect(ANCHOR_DROPPED)
558    }
559}
560
561impl<T: ?Sized> WeakWPortal<T> {
562    #[inline]
563    pub fn try_upgrade(&self) -> Option<WPortal<T>> {
564        self.0.upgrade().map(WPortal)
565    }
566
567    #[inline]
568    pub fn upgrade(&self) -> WPortal<T> {
569        self.try_upgrade().expect(ANCHOR_DROPPED)
570    }
571}
572
573impl<T: ?Sized> Clone for WeakPortal<T> {
574    #[inline]
575    fn clone(&self) -> Self {
576        self.0.pipe_ref(Weak::clone).pipe(Self)
577    }
578}
579
580impl<T: ?Sized> Clone for WeakRwPortal<T> {
581    #[inline]
582    fn clone(&self) -> Self {
583        self.0.pipe_ref(Weak::clone).pipe(Self)
584    }
585}
586
587impl<T: ?Sized> Clone for WeakWPortal<T> {
588    #[inline]
589    fn clone(&self) -> Self {
590        self.0.pipe_ref(Weak::clone).pipe(Self)
591    }
592}
593
594#[repr(transparent)]
595struct PortalReadGuard<'a, T: 'a + ?Sized>(RwLockReadGuard<'a, SSNonNull<T>>);
596
597#[repr(transparent)]
598struct PortalWriteGuard<'a, T: 'a + ?Sized>(RwLockWriteGuard<'a, SSNonNull<T>>);
599
600#[repr(transparent)]
601struct PortalMutexGuard<'a, T: 'a + ?Sized>(MutexGuard<'a, SSNonNull<T>>);
602
603impl<'a, T: ?Sized> Deref for PortalReadGuard<'a, T> {
604    type Target = T;
605    #[inline]
606    fn deref(&self) -> &T {
607        let pointer = self.0.deref();
608        unsafe {
609            //SAFETY: Valid as long as self.0 is.
610            pointer.as_ref()
611        }
612    }
613}
614
615impl<'a, T: ?Sized> Deref for PortalWriteGuard<'a, T> {
616    type Target = T;
617    #[inline]
618    fn deref(&self) -> &T {
619        let pointer = self.0.deref();
620        unsafe {
621            //SAFETY: Valid as long as self.0 is.
622            pointer.as_ref()
623        }
624    }
625}
626
627impl<'a, T: ?Sized> Deref for PortalMutexGuard<'a, T> {
628    type Target = T;
629    #[inline]
630    fn deref(&self) -> &T {
631        let pointer = self.0.deref();
632        unsafe {
633            //SAFETY: Valid as long as self.0 is.
634            pointer.as_ref()
635        }
636    }
637}
638
639impl<'a, T: ?Sized> DerefMut for PortalWriteGuard<'a, T> {
640    #[inline]
641    fn deref_mut(&mut self) -> &mut T {
642        let pointer = self.0.deref_mut();
643        unsafe {
644            //SAFETY: Valid as long as self.0 is. Can't be created from a read-only anchor.
645            pointer.as_mut()
646        }
647    }
648}
649
650impl<'a, T: ?Sized> DerefMut for PortalMutexGuard<'a, T> {
651    #[inline]
652    fn deref_mut(&mut self) -> &mut T {
653        let pointer = self.0.deref_mut();
654        unsafe {
655            //SAFETY: Valid as long as self.0 is. Can't be created from a read-only anchor.
656            pointer.as_mut()
657        }
658    }
659}
660
661#[cfg(test)]
662mod tests {
663    use super::*;
664
665    fn _auto_trait_assertions() {
666        // Anything that necessitates changes in this method is a breaking change.
667        use {assert_impl::assert_impl, core::any::Any};
668
669        trait S: Send {}
670        trait SS: Send + Sync {}
671
672        assert_impl!(!Send: WAnchor<'_, dyn Any>, WPortal<dyn Any>);
673        assert_impl!(Send: WAnchor<'_, dyn S>, WPortal<dyn S>);
674        assert_impl!(
675            !Send: Anchor<'_, dyn S>,
676            RwAnchor<'_, dyn S>,
677            Portal<dyn S>,
678            RwPortal<dyn S>,
679        );
680        assert_impl!(
681            Send: Anchor<'_, dyn SS>,
682            RwAnchor<'_, dyn SS>,
683            Portal<dyn SS>,
684            RwPortal<dyn SS>,
685        );
686        assert_impl!(
687            !Send: PortalReadGuard<'_, ()>,
688            PortalWriteGuard<'_, ()>,
689            PortalMutexGuard<'_, ()>,
690        );
691
692        assert_impl!(!Sync: WPortal<dyn Any>);
693        assert_impl!(Sync: WPortal<dyn S>);
694        assert_impl!(
695            !Sync: Anchor<'_, dyn S>,
696            RwAnchor<'_, dyn S>,
697            WAnchor<'_, dyn S>,
698            Portal<dyn S>,
699            RwPortal<dyn S>,
700            PortalReadGuard<'_, dyn S>,
701            PortalWriteGuard<'_, dyn S>,
702            PortalMutexGuard<'_, dyn S>,
703        );
704        assert_impl!(
705            Sync: Anchor<'_, dyn SS>,
706            RwAnchor<'_, dyn SS>,
707            WAnchor<'_, dyn SS>,
708            Portal<dyn SS>,
709            RwPortal<dyn SS>,
710            PortalReadGuard<'_, dyn SS>,
711            PortalWriteGuard<'_, dyn SS>,
712            PortalMutexGuard<'_, dyn SS>,
713        );
714
715        assert_impl!(
716            UnwindSafe: PortalReadGuard<'_, dyn Any>,
717            PortalWriteGuard<'_, dyn Any>,
718            PortalMutexGuard<'_, dyn Any>,
719        );
720        assert_impl!(
721            !UnwindSafe: Anchor<'_, dyn UnwindSafe>,
722            Portal<dyn UnwindSafe>,
723        );
724        assert_impl!(
725            UnwindSafe: Anchor<'_, dyn RefUnwindSafe>,
726            RwAnchor<'_, dyn RefUnwindSafe>,
727            WAnchor<'_, dyn RefUnwindSafe>,
728            Portal<dyn RefUnwindSafe>,
729        );
730
731        assert_impl!(
732            RefUnwindSafe: RwPortal<dyn Any>,
733            WPortal<dyn Any>,
734            PortalReadGuard<'_, dyn Any>,
735            PortalWriteGuard<'_, dyn Any>,
736            PortalMutexGuard<'_, dyn Any>,
737        );
738        assert_impl!(
739            !RefUnwindSafe: Anchor<'_, dyn UnwindSafe>,
740            RwAnchor<'_, dyn UnwindSafe>,
741            WAnchor<'_, dyn UnwindSafe>,
742            Portal<dyn UnwindSafe>,
743        );
744        assert_impl!(
745            RefUnwindSafe: Anchor<'_, dyn RefUnwindSafe>,
746            RwAnchor<'_, dyn RefUnwindSafe>,
747            WAnchor<'_, dyn RefUnwindSafe>,
748            Portal<dyn RefUnwindSafe>,
749        );
750
751        assert_impl!(
752            Unpin: Anchor<'_, dyn Any>,
753            RwAnchor<'_, dyn Any>,
754            WAnchor<'_, dyn Any>,
755            Portal<dyn Any>,
756            RwPortal<dyn Any>,
757            WPortal<dyn Any>,
758            PortalReadGuard<'_, dyn Any>,
759            PortalWriteGuard<'_, dyn Any>,
760            PortalMutexGuard<'_, dyn Any>,
761        )
762    }
763
764    fn _impl_trait_assertions() {
765        use {assert_impl::assert_impl, core::any::Any};
766
767        assert_impl!(
768            Clone: Portal<dyn Any>,
769            RwPortal<dyn Any>,
770            WeakPortal<dyn Any>,
771            WeakRwPortal<dyn Any>,
772        );
773
774        assert_impl!(Deref<Target = dyn Any>: Portal<dyn Any>);
775        assert_impl!(Borrow<dyn Any>: Portal<dyn Any>);
776    }
777    //TODO
778}