1use crate::*;
2use core::{
3 fmt::{Debug, Display},
4 hash::Hash,
5};
6
7#[must_use = "dropping a `Loaned` panics; use `loaned::drop!` instead"]
31#[repr(transparent)]
32pub struct Loaned<'t, T> {
33 pub(crate) inner: RawLoaned<T>,
36 pub(crate) _contravariant: PhantomData<fn(&'t ())>,
37}
38
39unsafe impl<'t, T: Sync> Send for Loaned<'t, T> {}
61
62impl<'t, T> Loaned<'t, T> {
63 #[inline]
66 pub fn loan(value: T) -> (&'t T::Target, Self)
67 where
68 T: Loanable<'t>,
69 {
70 let loaned = unsafe { Loaned::from_raw(RawLoaned::new(value)) };
71 (loaned.borrow(), loaned)
72 }
73
74 #[inline(always)]
77 pub fn new(value: T) -> Self {
78 unsafe { Loaned::from_raw(RawLoaned::new(value)) }
79 }
80
81 #[inline(always)]
84 pub fn place(self, place: &'t mut impl Place<'t, T>) {
85 Place::place(self.into(), place)
86 }
87
88 #[inline(always)]
90 pub fn borrow(&self) -> &'t T::Target
91 where
92 T: Loanable<'t>,
93 {
94 unsafe { &*(&**self.inner.as_ref() as *const _) }
95 }
96
97 #[inline(always)]
98 pub(crate) fn into_raw(self) -> RawLoaned<T> {
99 unsafe { ptr::read(&ManuallyDrop::new(self).inner) }
100 }
101
102 #[inline(always)]
103 pub(crate) unsafe fn from_raw(inner: RawLoaned<T>) -> Self {
104 Loaned {
105 inner,
106 _contravariant: PhantomData,
107 }
108 }
109}
110
111impl<'t, T> Deref for Loaned<'t, T> {
112 type Target = T;
113 #[inline(always)]
114 fn deref(&self) -> &T {
115 unsafe { self.inner.as_ref() }
116 }
117}
118
119impl<'t, T> Drop for Loaned<'t, T> {
120 #[cold]
121 fn drop(&mut self) {
122 #[cfg(feature = "std")]
123 if mem::needs_drop::<T>() && !std::thread::panicking() {
124 panic!(
125 "memory leak: cannot drop `{Self}`
126 if leaking is desired, use `ManuallyDrop<{Self}>` or `mem::forget`
127 otherwise, use `drop!(loaned)` to drop the inner value",
128 Self = core::any::type_name::<Self>()
129 )
130 }
131 }
132}
133
134impl<'t, T: Debug> Debug for Loaned<'t, T> {
135 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
136 f.debug_tuple("Loaned").field(&**self).finish()
137 }
138}
139
140impl<'t, T: Display> Display for Loaned<'t, T> {
141 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
142 (**self).fmt(f)
143 }
144}
145
146impl<'t, T: Clone> Clone for Loaned<'t, T> {
147 fn clone(&self) -> Self {
148 Loaned::new((**self).clone())
149 }
150}
151
152impl<'t, T: Default> Default for Loaned<'t, T> {
153 fn default() -> Self {
154 Loaned::new(Default::default())
155 }
156}
157
158impl<'t, 'u, T: PartialEq<U>, U> PartialEq<Loaned<'u, U>> for Loaned<'t, T> {
159 fn eq(&self, other: &Loaned<'u, U>) -> bool {
160 (&**self) == (&**other)
161 }
162}
163
164impl<'t, T: Eq> Eq for Loaned<'t, T> {}
165
166impl<'t, 'u, T: PartialOrd<U>, U> PartialOrd<Loaned<'u, U>> for Loaned<'t, T> {
167 fn partial_cmp(&self, other: &Loaned<'u, U>) -> Option<core::cmp::Ordering> {
168 (**self).partial_cmp(&**other)
169 }
170}
171
172impl<'t, T: Ord> Ord for Loaned<'t, T> {
173 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
174 (**self).cmp(&**other)
175 }
176}
177
178impl<'t, T: Hash> Hash for Loaned<'t, T> {
179 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
180 (**self).hash(state);
181 }
182}
183
184impl<'t, T> From<T> for Loaned<'t, T> {
185 fn from(value: T) -> Self {
186 Loaned::new(value)
187 }
188}
189
190impl<'t, T> Loaned<'t, T> {
191 pub fn merge(value: T, f: impl for<'i> FnOnce(&'i mut T, &'i Merge<'t, 'i>)) -> Self {
204 unsafe {
205 let mut inner = RawLoaned::new(value);
206 f(inner.as_mut(), &Merge(PhantomData));
207 Loaned::from_raw(inner)
208 }
209 }
210}
211
212#[doc(hidden)]
214pub struct Merge<'t, 'i>(PhantomData<(&'t mut &'t (), &'i mut &'i ())>);
215
216impl<'t, 'i> Merge<'t, 'i> {
217 pub fn place<T>(&'i self, loaned: Loaned<'t, T>, place: &'i mut impl Place<'i, T>) {
219 Place::place(unsafe { LoanedMut::from_raw(loaned.into_raw()) }, place)
220 }
221}
222
223impl<'t, T> Loaned<'t, T> {
224 pub fn loan_with<L>(
237 value: T,
238 f: impl for<'i> FnOnce(&'i mut T, &'i LoanWith<'t, 'i>) -> L,
239 ) -> (L, Self) {
240 unsafe {
241 let mut inner = RawLoaned::new(value);
242 let loans = f(inner.as_mut(), &LoanWith(PhantomData));
243 (loans, Loaned::from_raw(inner))
244 }
245 }
246}
247
248#[doc(hidden)]
250pub struct LoanWith<'t, 'i>(PhantomData<(&'t mut &'t (), &'i mut &'i ())>);
251
252impl<'t, 'i> LoanWith<'t, 'i> {
253 pub fn loan<T: Loanable<'i>>(&'i self, value: &'i T) -> &'t T::Target {
255 unsafe { &*(&**value as *const _) }
256 }
257}