1/*!
2This create provides weak pointers for [`Pin`]`<`[`Rc<T>`]`>` and [`Pin`]`<`[`Arc<T>`]`>`
3
4## Motivation
5
6[`Pin`]`<`[`Rc<T>`]`>` and [`Pin`]`<`[`Arc<T>`]`>` cannot be converted safely to
7their `Weak<T>` equivalent if `T` does not implement [`Unpin`].
8That's because it would otherwise be possible to do something like this:
9
10```no_run
11# use std::{pin::Pin, marker::PhantomPinned, rc::{Rc, Weak}};
12struct SomeStruct(PhantomPinned);
13let pinned = Rc::pin(SomeStruct(PhantomPinned));
14
15// This is unsound !!!
16let weak = unsafe {
17 Rc::downgrade(&Pin::into_inner_unchecked(pinned.clone()))
18};
19
20// ... because otherwise it would be possible to move the content of pinned:
21let mut unpinned_rc = weak.upgrade().unwrap();
22std::mem::drop((pinned, weak));
23// unpinned_rc is now the only reference so this will work:
24let x = std::mem::replace(
25 Rc::get_mut(&mut unpinned_rc).unwrap(),
26 SomeStruct(PhantomPinned),
27);
28```
29
30In that example, `x` is the original `SomeStruct` which we moved in memory,
31**that is undefined behavior**, do not do that at home.
32
33## `PinWeak`
34
35This crate simply provide a [`rc::PinWeak`] and [`sync::PinWeak`] which allow to
36get weak pointer from `Pin<std::rc::Rc>` and `Pin<std::sync::Arc>`.
37
38This is safe because you can one can only get back a `Pin` out of it when
39trying to upgrade the weak pointer.
40
41`PinWeak` can be created using the `PinWeak` downgrade function.
42
43## Example
44
45```
46use pin_weak::rc::*;
47# use std::marker::PhantomPinned;
48struct SomeStruct(PhantomPinned, usize);
49let pinned = Rc::pin(SomeStruct(PhantomPinned, 42));
50let weak = PinWeak::downgrade(pinned.clone());
51assert_eq!(weak.upgrade().unwrap().1, 42);
52std::mem::drop(pinned);
53assert!(weak.upgrade().is_none());
54```
55
56*/
57
58#![no_std]
59extern crate alloc;
60
61#[cfg(doc)]
62use alloc::{rc::Rc, sync::Arc};
63#[cfg(doc)]
64use core::pin::Pin;
65
66/// The implementation is in a macro because it is repeated for Arc and Rc
67macro_rules! implementation {
68 ($Rc:ident, $Weak:ident, $rc_lit:literal) => {
69 #[doc(no_inline)]
70 /// re-exported for convenience
71 pub use core::pin::Pin;
72 /// This is a safe wrapper around something that could be compared to [`Pin`]`<`[`Weak<T>`]`>`
73 ///
74 /// The typical way to obtain a `PinWeak` is to call [`PinWeak::downgrade`]
75 #[derive(Debug)]
76 pub struct PinWeak<T: ?Sized>(Weak<T>);
77 impl<T> Default for PinWeak<T> {
78 fn default() -> Self {
79 Self(Weak::default())
80 }
81 }
82 impl<T: ?Sized> Clone for PinWeak<T> {
83 fn clone(&self) -> Self {
84 Self(self.0.clone())
85 }
86 }
87 impl<T: ?Sized> PinWeak<T> {
88 #[doc = concat!("Equivalent function to [`", $rc_lit, "::downgrade`], but taking a `Pin<", $rc_lit, "<T>>` instead.")]
89 pub fn downgrade(rc: Pin<$Rc<T>>) -> Self {
90 // Safety: we will never return anything else than a Pin<Rc>
91 unsafe { Self($Rc::downgrade(&Pin::into_inner_unchecked(rc))) }
92 }
93 #[doc = concat!("Equivalent function to [`Weak::upgrade`], but taking a `Pin<", $rc_lit, "<T>>` instead.")]
94 pub fn upgrade(&self) -> Option<Pin<$Rc<T>>> {
95 // Safety: the weak was constructed from a Pin<Rc<T>>
96 self.0.upgrade().map(|rc| unsafe { Pin::new_unchecked(rc) })
97 }
98
99 /// Equivalent to [`Weak::strong_count`]
100 pub fn strong_count(&self) -> usize {
101 self.0.strong_count()
102 }
103
104 /// Equivalent to [`Weak::weak_count`]
105 pub fn weak_count(&self) -> usize {
106 self.0.weak_count()
107 }
108
109 /// Equivalent to [`Weak::ptr_eq`]
110 pub fn ptr_eq(&self, other: &Self) -> bool {
111 self.0.ptr_eq(&other.0)
112 }
113 }
114
115 #[test]
116 fn test() {
117 struct Foo {
118 _p: core::marker::PhantomPinned,
119 u: u32,
120 }
121 impl Foo {
122 fn new(u: u32) -> Self {
123 Self { _p: core::marker::PhantomPinned, u }
124 }
125 }
126 let c = $Rc::pin(Foo::new(44));
127 let weak1 = PinWeak::downgrade(c.clone());
128 assert_eq!(weak1.upgrade().unwrap().u, 44);
129 assert_eq!(weak1.clone().upgrade().unwrap().u, 44);
130 assert_eq!(weak1.strong_count(), 1);
131 assert_eq!(weak1.weak_count(), 1);
132 let weak2 = PinWeak::downgrade(c.clone());
133 assert_eq!(weak2.upgrade().unwrap().u, 44);
134 assert_eq!(weak1.upgrade().unwrap().u, 44);
135 assert_eq!(weak2.strong_count(), 1);
136 assert_eq!(weak2.weak_count(), 2);
137 assert!(weak1.ptr_eq(&weak2));
138 assert!(!weak1.ptr_eq(&Default::default()));
139 // note that this moves c and therefore it will be dropped
140 let weak3 = PinWeak::downgrade(c);
141 assert!(weak3.upgrade().is_none());
142 assert!(weak2.upgrade().is_none());
143 assert!(weak1.upgrade().is_none());
144 assert!(weak1.clone().upgrade().is_none());
145 assert_eq!(weak2.strong_count(), 0);
146 assert_eq!(weak2.weak_count(), 0);
147
148 let def = PinWeak::<alloc::boxed::Box<&'static mut ()>>::default();
149 assert!(def.upgrade().is_none());
150 assert!(def.clone().upgrade().is_none());
151 }
152 };
153}
154
155pub mod rc {
156 #[doc(no_inline)]
157 /// re-exported for convenience
158 pub use alloc::rc::{Rc, Weak};
159 implementation! {Rc, Weak, "Rc"}
160}
161
162#[cfg(feature = "sync")]
163pub mod sync {
164 #[doc(no_inline)]
165 /// re-exported for convenience
166 pub use alloc::sync::{Arc, Weak};
167 implementation! {Arc, Weak, "Arc"}
168}
169