/rust/registry/src/index.crates.io-1949cf8c6b5b557f/yoke-0.8.0/src/yoke.rs
Line  | Count  | Source  | 
1  |  | // This file is part of ICU4X. For terms of use, please see the file  | 
2  |  | // called LICENSE at the top level of the ICU4X source tree  | 
3  |  | // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).  | 
4  |  |  | 
5  |  | use crate::cartable_ptr::{CartableOptionPointer, CartablePointerLike}; | 
6  |  | use crate::either::EitherCart;  | 
7  |  | #[cfg(feature = "alloc")]  | 
8  |  | use crate::erased::{ErasedArcCart, ErasedBoxCart, ErasedRcCart}; | 
9  |  | use crate::kinda_sorta_dangling::KindaSortaDangling;  | 
10  |  | use crate::Yokeable;  | 
11  |  | use core::marker::PhantomData;  | 
12  |  | use core::ops::Deref;  | 
13  |  | use stable_deref_trait::StableDeref;  | 
14  |  |  | 
15  |  | #[cfg(feature = "alloc")]  | 
16  |  | use alloc::boxed::Box;  | 
17  |  | #[cfg(feature = "alloc")]  | 
18  |  | use alloc::rc::Rc;  | 
19  |  | #[cfg(feature = "alloc")]  | 
20  |  | use alloc::sync::Arc;  | 
21  |  |  | 
22  |  | /// A Cow-like borrowed object "yoked" to its backing data.  | 
23  |  | ///  | 
24  |  | /// This allows things like zero copy deserialized data to carry around  | 
25  |  | /// shared references to their backing buffer, by "erasing" their static lifetime  | 
26  |  | /// and turning it into a dynamically managed one.  | 
27  |  | ///  | 
28  |  | /// `Y` (the [`Yokeable`]) is the object containing the references,  | 
29  |  | /// and will typically be of the form `Foo<'static>`. The `'static` is  | 
30  |  | /// not the actual lifetime of the data, rather it is a convenient way to mark the  | 
31  |  | /// erased lifetime and make it dynamic.  | 
32  |  | ///  | 
33  |  | /// `C` is the "cart", which `Y` may contain references to. After the yoke is constructed,  | 
34  |  | /// the cart serves little purpose except to guarantee that `Y`'s references remain valid  | 
35  |  | /// for as long as the yoke remains in memory (by calling the destructor at the appropriate moment).  | 
36  |  | ///  | 
37  |  | /// The primary constructor for [`Yoke`] is [`Yoke::attach_to_cart()`]. Several variants of that  | 
38  |  | /// constructor are provided to serve numerous types of call sites and `Yoke` signatures.  | 
39  |  | ///  | 
40  |  | /// The key behind this type is [`Yoke::get()`], where calling [`.get()`][Yoke::get] on a type like  | 
41  |  | /// `Yoke<Cow<'static, str>, _>` will get you a short-lived `&'a Cow<'a, str>`, restricted to the  | 
42  |  | /// lifetime of the borrow used during `.get()`. This is entirely safe since the `Cow` borrows from  | 
43  |  | /// the cart type `C`, which cannot be interfered with as long as the `Yoke` is borrowed by `.get  | 
44  |  | /// ()`. `.get()` protects access by essentially reifying the erased lifetime to a safe local one  | 
45  |  | /// when necessary.  | 
46  |  | ///  | 
47  |  | /// Furthermore, there are various [`.map_project()`][Yoke::map_project] methods that allow turning a `Yoke`  | 
48  |  | /// into another `Yoke` containing a different type that may contain elements of the original yoked  | 
49  |  | /// value. See the [`Yoke::map_project()`] docs for more details.  | 
50  |  | ///  | 
51  |  | /// In general, `C` is a concrete type, but it is also possible for it to be a trait object.  | 
52  |  | ///  | 
53  |  | /// # Example  | 
54  |  | ///  | 
55  |  | /// For example, we can use this to store zero-copy deserialized data in a cache:  | 
56  |  | ///  | 
57  |  | /// ```rust  | 
58  |  | /// # use yoke::Yoke;  | 
59  |  | /// # use std::rc::Rc;  | 
60  |  | /// # use std::borrow::Cow;  | 
61  |  | /// # fn load_from_cache(_filename: &str) -> Rc<[u8]> { | 
62  |  | /// #     // dummy implementation  | 
63  |  | /// #     Rc::new([0x5, 0, 0, 0, 0, 0, 0, 0, 0x68, 0x65, 0x6c, 0x6c, 0x6f])  | 
64  |  | /// # }  | 
65  |  | ///  | 
66  |  | /// fn load_object(filename: &str) -> Yoke<Cow<'static, str>, Rc<[u8]>> { | 
67  |  | ///     let rc: Rc<[u8]> = load_from_cache(filename);  | 
68  |  | ///     Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| { | 
69  |  | ///         // essentially forcing a #[serde(borrow)]  | 
70  |  | ///         Cow::Borrowed(bincode::deserialize(data).unwrap())  | 
71  |  | ///     })  | 
72  |  | /// }  | 
73  |  | ///  | 
74  |  | /// let yoke = load_object("filename.bincode"); | 
75  |  | /// assert_eq!(&**yoke.get(), "hello");  | 
76  |  | /// assert!(matches!(yoke.get(), &Cow::Borrowed(_)));  | 
77  |  | /// ```  | 
78  |  | pub struct Yoke<Y: for<'a> Yokeable<'a>, C> { | 
79  |  |     // must be the first field for drop order  | 
80  |  |     // this will have a 'static lifetime parameter, that parameter is a lie  | 
81  |  |     yokeable: KindaSortaDangling<Y>,  | 
82  |  |     // Safety invariant: this type can be anything, but `yokeable` may only contain references to  | 
83  |  |     // StableDeref parts of this cart, and the targets of those references must be valid for the  | 
84  |  |     // lifetime of this cart (it must own or borrow them). It's ok for this cart to contain stack  | 
85  |  |     // data as long as it is not referenced by `yokeable` during construction. `attach_to_cart`,  | 
86  |  |     // the typical constructor of this type, upholds this invariant, but other constructors like  | 
87  |  |     // `replace_cart` need to uphold it.  | 
88  |  |     // The implementation guarantees that there are no live `yokeable`s that reference data  | 
89  |  |     // in a `cart` when the `cart` is dropped; this is guaranteed in the drop glue through field  | 
90  |  |     // order.  | 
91  |  |     cart: C,  | 
92  |  | }  | 
93  |  |  | 
94  |  | // Manual `Debug` implementation, since the derived one would be unsound.  | 
95  |  | // See https://github.com/unicode-org/icu4x/issues/3685  | 
96  |  | impl<Y: for<'a> Yokeable<'a>, C: core::fmt::Debug> core::fmt::Debug for Yoke<Y, C>  | 
97  |  | where  | 
98  |  |     for<'a> <Y as Yokeable<'a>>::Output: core::fmt::Debug,  | 
99  |  | { | 
100  | 0  |     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | 
101  | 0  |         f.debug_struct("Yoke") | 
102  | 0  |             .field("yokeable", self.get()) | 
103  | 0  |             .field("cart", self.backing_cart()) | 
104  | 0  |             .finish()  | 
105  | 0  |     }  | 
106  |  | }  | 
107  |  |  | 
108  |  | #[test]  | 
109  |  | fn test_debug() { | 
110  |  |     let local_data = "foo".to_owned();  | 
111  |  |     let y1 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(  | 
112  |  |         Rc::new(local_data),  | 
113  |  |     );  | 
114  |  |     assert_eq!(  | 
115  |  |         format!("{y1:?}"), | 
116  |  |         r#"Yoke { yokeable: "foo", cart: "foo" }"#, | 
117  |  |     );  | 
118  |  | }  | 
119  |  |  | 
120  |  | impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C>  | 
121  |  | where  | 
122  |  |     <C as Deref>::Target: 'static,  | 
123  |  | { | 
124  |  |     /// Construct a [`Yoke`] by yokeing an object to a cart in a closure.  | 
125  |  |     ///  | 
126  |  |     /// The closure can read and write data outside of its scope, but data it returns  | 
127  |  |     /// may borrow only from the argument passed to the closure.  | 
128  |  |     ///  | 
129  |  |     /// See also [`Yoke::try_attach_to_cart()`] to return a `Result` from the closure.  | 
130  |  |     ///  | 
131  |  |     /// Call sites for this function may not compile pre-1.61; if this still happens, use  | 
132  |  |     /// [`Yoke::attach_to_cart_badly()`] and file a bug.  | 
133  |  |     ///  | 
134  |  |     /// # Examples  | 
135  |  |     ///  | 
136  |  |     /// ```  | 
137  |  |     /// # use yoke::Yoke;  | 
138  |  |     /// # use std::rc::Rc;  | 
139  |  |     /// # use std::borrow::Cow;  | 
140  |  |     /// # fn load_from_cache(_filename: &str) -> Rc<[u8]> { | 
141  |  |     /// #     // dummy implementation  | 
142  |  |     /// #     Rc::new([0x5, 0, 0, 0, 0, 0, 0, 0, 0x68, 0x65, 0x6c, 0x6c, 0x6f])  | 
143  |  |     /// # }  | 
144  |  |     ///  | 
145  |  |     /// fn load_object(filename: &str) -> Yoke<Cow<'static, str>, Rc<[u8]>> { | 
146  |  |     ///     let rc: Rc<[u8]> = load_from_cache(filename);  | 
147  |  |     ///     Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| { | 
148  |  |     ///         // essentially forcing a #[serde(borrow)]  | 
149  |  |     ///         Cow::Borrowed(bincode::deserialize(data).unwrap())  | 
150  |  |     ///     })  | 
151  |  |     /// }  | 
152  |  |     ///  | 
153  |  |     /// let yoke: Yoke<Cow<str>, _> = load_object("filename.bincode"); | 
154  |  |     /// assert_eq!(&**yoke.get(), "hello");  | 
155  |  |     /// assert!(matches!(yoke.get(), &Cow::Borrowed(_)));  | 
156  |  |     /// ```  | 
157  |  |     ///  | 
158  |  |     /// Write the number of consumed bytes to a local variable:  | 
159  |  |     ///  | 
160  |  |     /// ```  | 
161  |  |     /// # use yoke::Yoke;  | 
162  |  |     /// # use std::rc::Rc;  | 
163  |  |     /// # use std::borrow::Cow;  | 
164  |  |     /// # fn load_from_cache(_filename: &str) -> Rc<[u8]> { | 
165  |  |     /// #     // dummy implementation  | 
166  |  |     /// #     Rc::new([0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0, 0, 0])  | 
167  |  |     /// # }  | 
168  |  |     ///  | 
169  |  |     /// fn load_object(  | 
170  |  |     ///     filename: &str,  | 
171  |  |     /// ) -> (Yoke<Cow<'static, str>, Rc<[u8]>>, usize) { | 
172  |  |     ///     let rc: Rc<[u8]> = load_from_cache(filename);  | 
173  |  |     ///     let mut bytes_remaining = 0;  | 
174  |  |     ///     let bytes_remaining = &mut bytes_remaining;  | 
175  |  |     ///     let yoke = Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart(  | 
176  |  |     ///         rc,  | 
177  |  |     ///         |data: &[u8]| { | 
178  |  |     ///             let mut d = postcard::Deserializer::from_bytes(data);  | 
179  |  |     ///             let output = serde::Deserialize::deserialize(&mut d);  | 
180  |  |     ///             *bytes_remaining = d.finalize().unwrap().len();  | 
181  |  |     ///             Cow::Borrowed(output.unwrap())  | 
182  |  |     ///         },  | 
183  |  |     ///     );  | 
184  |  |     ///     (yoke, *bytes_remaining)  | 
185  |  |     /// }  | 
186  |  |     ///  | 
187  |  |     /// let (yoke, bytes_remaining) = load_object("filename.postcard"); | 
188  |  |     /// assert_eq!(&**yoke.get(), "hello");  | 
189  |  |     /// assert!(matches!(yoke.get(), &Cow::Borrowed(_)));  | 
190  |  |     /// assert_eq!(bytes_remaining, 3);  | 
191  |  |     /// ```  | 
192  | 0  |     pub fn attach_to_cart<F>(cart: C, f: F) -> Self  | 
193  | 0  |     where  | 
194  | 0  |         // safety note: This works by enforcing that the *only* place the return value of F  | 
195  | 0  |         // can borrow from is the cart, since `F` must be valid for all lifetimes `'de`  | 
196  | 0  |         //  | 
197  | 0  |         // The <C as Deref>::Target: 'static on the impl is crucial for safety as well  | 
198  | 0  |         //  | 
199  | 0  |         // See safety docs at the bottom of this file for more information  | 
200  | 0  |         F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,  | 
201  | 0  |         <C as Deref>::Target: 'static,  | 
202  |  |     { | 
203  | 0  |         let deserialized = f(cart.deref());  | 
204  | 0  |         Self { | 
205  | 0  |             yokeable: KindaSortaDangling::new(  | 
206  | 0  |                 // Safety: the resulting `yokeable` is dropped before the `cart` because  | 
207  | 0  |                 // of the Yoke invariant. See the safety docs at the bottom of this file  | 
208  | 0  |                 // for the justification of why yokeable could only borrow from the Cart.  | 
209  | 0  |                 unsafe { Y::make(deserialized) }, | 
210  | 0  |             ),  | 
211  | 0  |             cart,  | 
212  | 0  |         }  | 
213  | 0  |     }  | 
214  |  |  | 
215  |  |     /// Construct a [`Yoke`] by yokeing an object to a cart. If an error occurs in the  | 
216  |  |     /// deserializer function, the error is passed up to the caller.  | 
217  |  |     ///  | 
218  |  |     /// Call sites for this function may not compile pre-1.61; if this still happens, use  | 
219  |  |     /// [`Yoke::try_attach_to_cart_badly()`] and file a bug.  | 
220  | 0  |     pub fn try_attach_to_cart<E, F>(cart: C, f: F) -> Result<Self, E>  | 
221  | 0  |     where  | 
222  | 0  |         F: for<'de> FnOnce(&'de <C as Deref>::Target) -> Result<<Y as Yokeable<'de>>::Output, E>,  | 
223  | 0  |         <C as Deref>::Target: 'static,  | 
224  |  |     { | 
225  | 0  |         let deserialized = f(cart.deref())?;  | 
226  | 0  |         Ok(Self { | 
227  | 0  |             yokeable: KindaSortaDangling::new(  | 
228  | 0  |                 // Safety: the resulting `yokeable` is dropped before the `cart` because  | 
229  | 0  |                 // of the Yoke invariant. See the safety docs at the bottom of this file  | 
230  | 0  |                 // for the justification of why yokeable could only borrow from the Cart.  | 
231  | 0  |                 unsafe { Y::make(deserialized) }, | 
232  | 0  |             ),  | 
233  | 0  |             cart,  | 
234  | 0  |         })  | 
235  | 0  |     }  | 
236  |  |  | 
237  |  |     /// Use [`Yoke::attach_to_cart()`].  | 
238  |  |     ///  | 
239  |  |     /// This was needed because the pre-1.61 compiler couldn't always handle the FnOnce trait bound.  | 
240  |  |     #[deprecated]  | 
241  | 0  |     pub fn attach_to_cart_badly(  | 
242  | 0  |         cart: C,  | 
243  | 0  |         f: for<'de> fn(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,  | 
244  | 0  |     ) -> Self { | 
245  | 0  |         Self::attach_to_cart(cart, f)  | 
246  | 0  |     }  | 
247  |  |  | 
248  |  |     /// Use [`Yoke::try_attach_to_cart()`].  | 
249  |  |     ///  | 
250  |  |     /// This was needed because the pre-1.61 compiler couldn't always handle the FnOnce trait bound.  | 
251  |  |     #[deprecated]  | 
252  | 0  |     pub fn try_attach_to_cart_badly<E>(  | 
253  | 0  |         cart: C,  | 
254  | 0  |         f: for<'de> fn(&'de <C as Deref>::Target) -> Result<<Y as Yokeable<'de>>::Output, E>,  | 
255  | 0  |     ) -> Result<Self, E> { | 
256  | 0  |         Self::try_attach_to_cart(cart, f)  | 
257  | 0  |     }  | 
258  |  | }  | 
259  |  |  | 
260  |  | impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> { | 
261  |  |     /// Obtain a valid reference to the yokeable data  | 
262  |  |     ///  | 
263  |  |     /// This essentially transforms the lifetime of the internal yokeable data to  | 
264  |  |     /// be valid.  | 
265  |  |     /// For example, if you're working with a `Yoke<Cow<'static, T>, C>`, this  | 
266  |  |     /// will return an `&'a Cow<'a, T>`  | 
267  |  |     ///  | 
268  |  |     /// # Example  | 
269  |  |     ///  | 
270  |  |     /// ```rust  | 
271  |  |     /// # use yoke::Yoke;  | 
272  |  |     /// # use std::rc::Rc;  | 
273  |  |     /// # use std::borrow::Cow;  | 
274  |  |     /// # fn load_from_cache(_filename: &str) -> Rc<[u8]> { | 
275  |  |     /// #     // dummy implementation  | 
276  |  |     /// #     Rc::new([0x5, 0, 0, 0, 0, 0, 0, 0, 0x68, 0x65, 0x6c, 0x6c, 0x6f])  | 
277  |  |     /// # }  | 
278  |  |     /// #  | 
279  |  |     /// # fn load_object(filename: &str) -> Yoke<Cow<'static, str>, Rc<[u8]>> { | 
280  |  |     /// #     let rc: Rc<[u8]> = load_from_cache(filename);  | 
281  |  |     /// #     Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| { | 
282  |  |     /// #         Cow::Borrowed(bincode::deserialize(data).unwrap())  | 
283  |  |     /// #     })  | 
284  |  |     /// # }  | 
285  |  |     ///  | 
286  |  |     /// // load_object() defined in the example at the top of this page  | 
287  |  |     /// let yoke: Yoke<Cow<str>, _> = load_object("filename.bincode"); | 
288  |  |     /// assert_eq!(yoke.get(), "hello");  | 
289  |  |     /// ```  | 
290  |  |     #[inline]  | 
291  | 0  |     pub fn get<'a>(&'a self) -> &'a <Y as Yokeable<'a>>::Output { | 
292  | 0  |         self.yokeable.transform()  | 
293  | 0  |     } Unexecuted instantiation: <yoke::yoke::Yoke<icu_properties::provider::PropertyUnicodeSet, yoke::cartable_ptr::CartableOptionPointer<&()>>>::get Unexecuted instantiation: <yoke::yoke::Yoke<icu_properties::provider::PropertyCodePointSet, yoke::cartable_ptr::CartableOptionPointer<&()>>>::get Unexecuted instantiation: <yoke::yoke::Yoke<icu_normalizer::provider::DecompositionData, yoke::cartable_ptr::CartableOptionPointer<&()>>>::get Unexecuted instantiation: <yoke::yoke::Yoke<icu_normalizer::provider::DecompositionTables, yoke::cartable_ptr::CartableOptionPointer<&()>>>::get Unexecuted instantiation: <yoke::yoke::Yoke<icu_normalizer::provider::CanonicalCompositions, yoke::cartable_ptr::CartableOptionPointer<&()>>>::get Unexecuted instantiation: <yoke::yoke::Yoke<icu_normalizer::provider::NonRecursiveDecompositionSupplement, yoke::cartable_ptr::CartableOptionPointer<&()>>>::get Unexecuted instantiation: <yoke::yoke::Yoke<_, _>>::get  | 
294  |  |  | 
295  |  |     /// Get a reference to the backing cart.  | 
296  |  |     ///  | 
297  |  |     /// This can be useful when building caches, etc. However, if you plan to store the cart  | 
298  |  |     /// separately from the yoke, read the note of caution below in [`Yoke::into_backing_cart`].  | 
299  | 0  |     pub fn backing_cart(&self) -> &C { | 
300  | 0  |         &self.cart  | 
301  | 0  |     }  | 
302  |  |  | 
303  |  |     /// Get the backing cart by value, dropping the yokeable object.  | 
304  |  |     ///  | 
305  |  |     /// **Caution:** Calling this method could cause information saved in the yokeable object but  | 
306  |  |     /// not the cart to be lost. Use this method only if the yokeable object cannot contain its  | 
307  |  |     /// own information.  | 
308  |  |     ///  | 
309  |  |     /// # Example  | 
310  |  |     ///  | 
311  |  |     /// Good example: the yokeable object is only a reference, so no information can be lost.  | 
312  |  |     ///  | 
313  |  |     /// ```  | 
314  |  |     /// use yoke::Yoke;  | 
315  |  |     ///  | 
316  |  |     /// let local_data = "foo".to_owned();  | 
317  |  |     /// let yoke = Yoke::<&'static str, Box<String>>::attach_to_zero_copy_cart(  | 
318  |  |     ///     Box::new(local_data),  | 
319  |  |     /// );  | 
320  |  |     /// assert_eq!(*yoke.get(), "foo");  | 
321  |  |     ///  | 
322  |  |     /// // Get back the cart  | 
323  |  |     /// let cart = yoke.into_backing_cart();  | 
324  |  |     /// assert_eq!(&*cart, "foo");  | 
325  |  |     /// ```  | 
326  |  |     ///  | 
327  |  |     /// Bad example: information specified in `.with_mut()` is lost.  | 
328  |  |     ///  | 
329  |  |     /// ```  | 
330  |  |     /// use std::borrow::Cow;  | 
331  |  |     /// use yoke::Yoke;  | 
332  |  |     ///  | 
333  |  |     /// let local_data = "foo".to_owned();  | 
334  |  |     /// let mut yoke =  | 
335  |  |     ///     Yoke::<Cow<'static, str>, Box<String>>::attach_to_zero_copy_cart(  | 
336  |  |     ///         Box::new(local_data),  | 
337  |  |     ///     );  | 
338  |  |     /// assert_eq!(yoke.get(), "foo");  | 
339  |  |     ///  | 
340  |  |     /// // Override data in the cart  | 
341  |  |     /// yoke.with_mut(|cow| { | 
342  |  |     ///     let mut_str = cow.to_mut();  | 
343  |  |     ///     mut_str.clear();  | 
344  |  |     ///     mut_str.push_str("bar"); | 
345  |  |     /// });  | 
346  |  |     /// assert_eq!(yoke.get(), "bar");  | 
347  |  |     ///  | 
348  |  |     /// // Get back the cart  | 
349  |  |     /// let cart = yoke.into_backing_cart();  | 
350  |  |     /// assert_eq!(&*cart, "foo"); // WHOOPS!  | 
351  |  |     /// ```  | 
352  | 0  |     pub fn into_backing_cart(self) -> C { | 
353  | 0  |         self.cart  | 
354  | 0  |     }  | 
355  |  |  | 
356  |  |     /// Unsafe function for replacing the cart with another  | 
357  |  |     ///  | 
358  |  |     /// This can be used for type-erasing the cart, for example.  | 
359  |  |     ///  | 
360  |  |     /// # Safety  | 
361  |  |     ///  | 
362  |  |     /// - `f()` must not panic  | 
363  |  |     /// - References from the yokeable `Y` should still be valid for the lifetime of the  | 
364  |  |     ///   returned cart type `C`.  | 
365  |  |     ///  | 
366  |  |     ///   For the purpose of determining this, `Yoke` guarantees that references from the Yokeable  | 
367  |  |     ///   `Y` into the cart `C` will never be references into its stack data, only heap data protected  | 
368  |  |     ///   by `StableDeref`. This does not necessarily mean that `C` implements `StableDeref`, rather that  | 
369  |  |     ///   any data referenced by `Y` must be accessed through a `StableDeref` impl on something `C` owns.  | 
370  |  |     ///  | 
371  |  |     ///   Concretely, this means that if `C = Option<Rc<T>>`, `Y` may contain references to the `T` but not  | 
372  |  |     ///   anything else.  | 
373  |  |     /// - Lifetimes inside C must not be lengthened, even if they are themselves contravariant.  | 
374  |  |     ///   I.e., if C contains an `fn(&'a u8)`, it cannot be replaced with `fn(&'static u8),  | 
375  |  |     ///   even though that is typically safe.  | 
376  |  |     ///  | 
377  |  |     /// Typically, this means implementing `f` as something which _wraps_ the inner cart type `C`.  | 
378  |  |     /// `Yoke` only really cares about destructors for its carts so it's fine to erase other  | 
379  |  |     /// information about the cart, as long as the backing data will still be destroyed at the  | 
380  |  |     /// same time.  | 
381  |  |     #[inline]  | 
382  | 0  |     pub unsafe fn replace_cart<C2>(self, f: impl FnOnce(C) -> C2) -> Yoke<Y, C2> { | 
383  | 0  |         Yoke { | 
384  | 0  |             // Safety note: the safety invariant of this function guarantees that  | 
385  | 0  |             // the data that the yokeable references has its ownership (if any)  | 
386  | 0  |             // transferred to the new cart before self.cart is dropped.  | 
387  | 0  |             yokeable: self.yokeable,  | 
388  | 0  |             cart: f(self.cart),  | 
389  | 0  |         }  | 
390  | 0  |     } Unexecuted instantiation: <yoke::yoke::Yoke<&[u8], core::option::Option<icu_provider::response::Cart>>>::replace_cart::<core::option::Option<&()>, <icu_provider::response::Cart>::unwrap_cart<&[u8]>::{closure#0}>Unexecuted instantiation: <yoke::yoke::Yoke<_, _>>::replace_cart::<_, _>  | 
391  |  |  | 
392  |  |     /// Mutate the stored [`Yokeable`] data.  | 
393  |  |     ///  | 
394  |  |     /// See [`Yokeable::transform_mut()`] for why this operation is safe.  | 
395  |  |     ///  | 
396  |  |     /// # Example  | 
397  |  |     ///  | 
398  |  |     /// This can be used to partially mutate the stored data, provided  | 
399  |  |     /// no _new_ borrowed data is introduced.  | 
400  |  |     ///  | 
401  |  |     /// ```rust  | 
402  |  |     /// # use yoke::{Yoke, Yokeable}; | 
403  |  |     /// # use std::rc::Rc;  | 
404  |  |     /// # use std::borrow::Cow;  | 
405  |  |     /// # use std::mem;  | 
406  |  |     /// # fn load_from_cache(_filename: &str) -> Rc<[u8]> { | 
407  |  |     /// #     // dummy implementation  | 
408  |  |     /// #     Rc::new([0x5, 0, 0, 0, 0, 0, 0, 0, 0x68, 0x65, 0x6c, 0x6c, 0x6f])  | 
409  |  |     /// # }  | 
410  |  |     /// #  | 
411  |  |     /// # fn load_object(filename: &str) -> Yoke<Bar<'static>, Rc<[u8]>> { | 
412  |  |     /// #     let rc: Rc<[u8]> = load_from_cache(filename);  | 
413  |  |     /// #     Yoke::<Bar<'static>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| { | 
414  |  |     /// #         // A real implementation would properly deserialize `Bar` as a whole  | 
415  |  |     /// #         Bar { | 
416  |  |     /// #             numbers: Cow::Borrowed(bincode::deserialize(data).unwrap()),  | 
417  |  |     /// #             string: Cow::Borrowed(bincode::deserialize(data).unwrap()),  | 
418  |  |     /// #             owned: Vec::new(),  | 
419  |  |     /// #         }  | 
420  |  |     /// #     })  | 
421  |  |     /// # }  | 
422  |  |     ///  | 
423  |  |     /// // also implements Yokeable  | 
424  |  |     /// struct Bar<'a> { | 
425  |  |     ///     numbers: Cow<'a, [u8]>,  | 
426  |  |     ///     string: Cow<'a, str>,  | 
427  |  |     ///     owned: Vec<u8>,  | 
428  |  |     /// }  | 
429  |  |     ///  | 
430  |  |     /// // `load_object()` deserializes an object from a file  | 
431  |  |     /// let mut bar: Yoke<Bar, _> = load_object("filename.bincode"); | 
432  |  |     /// assert_eq!(bar.get().string, "hello");  | 
433  |  |     /// assert!(matches!(bar.get().string, Cow::Borrowed(_)));  | 
434  |  |     /// assert_eq!(&*bar.get().numbers, &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);  | 
435  |  |     /// assert!(matches!(bar.get().numbers, Cow::Borrowed(_)));  | 
436  |  |     /// assert_eq!(&*bar.get().owned, &[]);  | 
437  |  |     ///  | 
438  |  |     /// bar.with_mut(|bar| { | 
439  |  |     ///     bar.string.to_mut().push_str(" world"); | 
440  |  |     ///     bar.owned.extend_from_slice(&[1, 4, 1, 5, 9]);  | 
441  |  |     /// });  | 
442  |  |     ///  | 
443  |  |     /// assert_eq!(bar.get().string, "hello world");  | 
444  |  |     /// assert!(matches!(bar.get().string, Cow::Owned(_)));  | 
445  |  |     /// assert_eq!(&*bar.get().owned, &[1, 4, 1, 5, 9]);  | 
446  |  |     /// // Unchanged and still Cow::Borrowed  | 
447  |  |     /// assert_eq!(&*bar.get().numbers, &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);  | 
448  |  |     /// assert!(matches!(bar.get().numbers, Cow::Borrowed(_)));  | 
449  |  |     ///  | 
450  |  |     /// # unsafe impl<'a> Yokeable<'a> for Bar<'static> { | 
451  |  |     /// #     type Output = Bar<'a>;  | 
452  |  |     /// #     fn transform(&'a self) -> &'a Bar<'a> { | 
453  |  |     /// #         self  | 
454  |  |     /// #     }  | 
455  |  |     /// #  | 
456  |  |     /// #     fn transform_owned(self) -> Bar<'a> { | 
457  |  |     /// #         // covariant lifetime cast, can be done safely  | 
458  |  |     /// #         self  | 
459  |  |     /// #     }  | 
460  |  |     /// #  | 
461  |  |     /// #     unsafe fn make(from: Bar<'a>) -> Self { | 
462  |  |     /// #         let ret = mem::transmute_copy(&from);  | 
463  |  |     /// #         mem::forget(from);  | 
464  |  |     /// #         ret  | 
465  |  |     /// #     }  | 
466  |  |     /// #  | 
467  |  |     /// #     fn transform_mut<F>(&'a mut self, f: F)  | 
468  |  |     /// #     where  | 
469  |  |     /// #         F: 'static + FnOnce(&'a mut Self::Output),  | 
470  |  |     /// #     { | 
471  |  |     /// #         unsafe { f(mem::transmute(self)) } | 
472  |  |     /// #     }  | 
473  |  |     /// # }  | 
474  |  |     /// ```  | 
475  | 0  |     pub fn with_mut<'a, F>(&'a mut self, f: F)  | 
476  | 0  |     where  | 
477  | 0  |         F: 'static + for<'b> FnOnce(&'b mut <Y as Yokeable<'a>>::Output),  | 
478  |  |     { | 
479  | 0  |         self.yokeable.transform_mut(f)  | 
480  | 0  |     }  | 
481  |  |  | 
482  |  |     /// Helper function allowing one to wrap the cart type `C` in an `Option<T>`.  | 
483  |  |     #[inline]  | 
484  | 0  |     pub fn wrap_cart_in_option(self) -> Yoke<Y, Option<C>> { | 
485  |  |         // Safety: the cart is preserved (since it is just wrapped into a Some),  | 
486  |  |         // so any data it owns is too.  | 
487  | 0  |         unsafe { self.replace_cart(Some) } | 
488  | 0  |     }  | 
489  |  | }  | 
490  |  |  | 
491  |  | impl<Y: for<'a> Yokeable<'a>> Yoke<Y, ()> { | 
492  |  |     /// Construct a new [`Yoke`] from static data. There will be no  | 
493  |  |     /// references to `cart` here since [`Yokeable`]s are `'static`,  | 
494  |  |     /// this is good for e.g. constructing fully owned  | 
495  |  |     /// [`Yoke`]s with no internal borrowing.  | 
496  |  |     ///  | 
497  |  |     /// This is similar to [`Yoke::new_owned()`] but it does not allow you to  | 
498  |  |     /// mix the [`Yoke`] with borrowed data. This is primarily useful  | 
499  |  |     /// for using [`Yoke`] in generic scenarios.  | 
500  |  |     ///  | 
501  |  |     /// # Example  | 
502  |  |     ///  | 
503  |  |     /// ```rust  | 
504  |  |     /// # use yoke::Yoke;  | 
505  |  |     /// # use std::borrow::Cow;  | 
506  |  |     ///  | 
507  |  |     /// let owned: Cow<str> = "hello".to_owned().into();  | 
508  |  |     /// // this yoke can be intermingled with actually-borrowed Yokes  | 
509  |  |     /// let yoke: Yoke<Cow<str>, ()> = Yoke::new_always_owned(owned);  | 
510  |  |     ///  | 
511  |  |     /// assert_eq!(yoke.get(), "hello");  | 
512  |  |     /// ```  | 
513  | 0  |     pub fn new_always_owned(yokeable: Y) -> Self { | 
514  | 0  |         Self { | 
515  | 0  |             // Safety note: this `yokeable` certainly does not reference data owned by (), so we do  | 
516  | 0  |             // not have to worry about when the `yokeable` is dropped.  | 
517  | 0  |             yokeable: KindaSortaDangling::new(yokeable),  | 
518  | 0  |             cart: (),  | 
519  | 0  |         }  | 
520  | 0  |     }  | 
521  |  |  | 
522  |  |     /// Obtain the yokeable out of a `Yoke<Y, ()>`  | 
523  |  |     ///  | 
524  |  |     /// For most `Yoke` types this would be unsafe but it's  | 
525  |  |     /// fine for `Yoke<Y, ()>` since there are no actual internal  | 
526  |  |     /// references  | 
527  | 0  |     pub fn into_yokeable(self) -> Y { | 
528  |  |         // Safety note: since `yokeable` cannot reference data owned by `()`, this is certainly  | 
529  |  |         // safe.  | 
530  | 0  |         self.yokeable.into_inner()  | 
531  | 0  |     }  | 
532  |  | }  | 
533  |  |  | 
534  |  | // C does not need to be StableDeref here, if the yoke was constructed it's valid,  | 
535  |  | // and new_owned() doesn't construct a yokeable that uses references,  | 
536  |  | impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, Option<C>> { | 
537  |  |     /// Construct a new [`Yoke`] from static data. There will be no  | 
538  |  |     /// references to `cart` here since [`Yokeable`]s are `'static`,  | 
539  |  |     /// this is good for e.g. constructing fully owned  | 
540  |  |     /// [`Yoke`]s with no internal borrowing.  | 
541  |  |     ///  | 
542  |  |     /// This can be paired with [`Yoke:: wrap_cart_in_option()`] to mix owned  | 
543  |  |     /// and borrowed data.  | 
544  |  |     ///  | 
545  |  |     /// If you do not wish to pair this with borrowed data, [`Yoke::new_always_owned()`] can  | 
546  |  |     /// be used to get a [`Yoke`] API on always-owned data.  | 
547  |  |     ///  | 
548  |  |     /// # Example  | 
549  |  |     ///  | 
550  |  |     /// ```rust  | 
551  |  |     /// # use yoke::Yoke;  | 
552  |  |     /// # use std::borrow::Cow;  | 
553  |  |     /// # use std::rc::Rc;  | 
554  |  |     ///  | 
555  |  |     /// let owned: Cow<str> = "hello".to_owned().into();  | 
556  |  |     /// // this yoke can be intermingled with actually-borrowed Yokes  | 
557  |  |     /// let yoke: Yoke<Cow<str>, Option<Rc<[u8]>>> = Yoke::new_owned(owned);  | 
558  |  |     ///  | 
559  |  |     /// assert_eq!(yoke.get(), "hello");  | 
560  |  |     /// ```  | 
561  | 0  |     pub const fn new_owned(yokeable: Y) -> Self { | 
562  | 0  |         Self { | 
563  | 0  |             // Safety note: this `yokeable` is known not to borrow from the cart.  | 
564  | 0  |             yokeable: KindaSortaDangling::new(yokeable),  | 
565  | 0  |             cart: None,  | 
566  | 0  |         }  | 
567  | 0  |     } Unexecuted instantiation: <yoke::yoke::Yoke<icu_properties::provider::PropertyUnicodeSet, core::option::Option<&()>>>::new_owned Unexecuted instantiation: <yoke::yoke::Yoke<icu_properties::provider::PropertyCodePointSet, core::option::Option<&()>>>::new_owned Unexecuted instantiation: <yoke::yoke::Yoke<&[u8], core::option::Option<&()>>>::new_owned Unexecuted instantiation: <yoke::yoke::Yoke<_, core::option::Option<_>>>::new_owned  | 
568  |  |  | 
569  |  |     /// Obtain the yokeable out of a `Yoke<Y, Option<C>>` if possible.  | 
570  |  |     ///  | 
571  |  |     /// If the cart is `None`, this returns `Ok`, but if the cart is `Some`,  | 
572  |  |     /// this returns `self` as an error.  | 
573  | 0  |     pub fn try_into_yokeable(self) -> Result<Y, Self> { | 
574  |  |         // Safety: if the cart is None there is no way for the yokeable to  | 
575  |  |         // have references into it because of the cart invariant.  | 
576  | 0  |         match self.cart { | 
577  | 0  |             Some(_) => Err(self),  | 
578  | 0  |             None => Ok(self.yokeable.into_inner()),  | 
579  |  |         }  | 
580  | 0  |     }  | 
581  |  | }  | 
582  |  |  | 
583  |  | impl<Y: for<'a> Yokeable<'a>, C: CartablePointerLike> Yoke<Y, Option<C>> { | 
584  |  |     /// Converts a `Yoke<Y, Option<C>>` to `Yoke<Y, CartableOptionPointer<C>>`  | 
585  |  |     /// for better niche optimization when stored as a field.  | 
586  |  |     ///  | 
587  |  |     /// # Examples  | 
588  |  |     ///  | 
589  |  |     /// ```  | 
590  |  |     /// use std::borrow::Cow;  | 
591  |  |     /// use yoke::Yoke;  | 
592  |  |     ///  | 
593  |  |     /// let yoke: Yoke<Cow<[u8]>, Box<Vec<u8>>> =  | 
594  |  |     ///     Yoke::attach_to_cart(vec![10, 20, 30].into(), |c| c.into());  | 
595  |  |     ///  | 
596  |  |     /// let yoke_option = yoke.wrap_cart_in_option();  | 
597  |  |     /// let yoke_option_pointer = yoke_option.convert_cart_into_option_pointer();  | 
598  |  |     /// ```  | 
599  |  |     ///  | 
600  |  |     /// The niche improves stack sizes:  | 
601  |  |     ///  | 
602  |  |     /// ```  | 
603  |  |     /// use yoke::Yoke;  | 
604  |  |     /// use yoke::cartable_ptr::CartableOptionPointer;  | 
605  |  |     /// use std::mem::size_of;  | 
606  |  |     /// use std::rc::Rc;  | 
607  |  |     ///  | 
608  |  |     /// // The data struct is 6 words:  | 
609  |  |     /// # #[derive(yoke::Yokeable)]  | 
610  |  |     /// # struct MyDataStruct<'a> { | 
611  |  |     /// #     _s: (usize, usize, usize, usize),  | 
612  |  |     /// #     _p: &'a str,  | 
613  |  |     /// # }  | 
614  |  |     /// const W: usize = core::mem::size_of::<usize>();  | 
615  |  |     /// assert_eq!(W * 6, size_of::<MyDataStruct>());  | 
616  |  |     ///  | 
617  |  |     /// // An enum containing the data struct with an `Option<Rc>` cart is 8 words:  | 
618  |  |     /// enum StaticOrYoke1 { | 
619  |  |     ///     Static(&'static MyDataStruct<'static>),  | 
620  |  |     ///     Yoke(Yoke<MyDataStruct<'static>, Option<Rc<String>>>),  | 
621  |  |     /// }  | 
622  |  |     /// assert_eq!(W * 8, size_of::<StaticOrYoke1>());  | 
623  |  |     ///  | 
624  |  |     /// // When using `CartableOptionPointer``, we need only 7 words for the same behavior:  | 
625  |  |     /// enum StaticOrYoke2 { | 
626  |  |     ///     Static(&'static MyDataStruct<'static>),  | 
627  |  |     ///     Yoke(Yoke<MyDataStruct<'static>, CartableOptionPointer<Rc<String>>>),  | 
628  |  |     /// }  | 
629  |  |     /// assert_eq!(W * 7, size_of::<StaticOrYoke2>());  | 
630  |  |     /// ```  | 
631  |  |     #[inline]  | 
632  | 0  |     pub fn convert_cart_into_option_pointer(self) -> Yoke<Y, CartableOptionPointer<C>> { | 
633  | 0  |         match self.cart { | 
634  | 0  |             Some(cart) => Yoke { | 
635  | 0  |                 // Safety note: CartableOptionPointer::from_cartable only wraps the `cart`,  | 
636  | 0  |                 // so the data referenced by the yokeable is still live.  | 
637  | 0  |                 yokeable: self.yokeable,  | 
638  | 0  |                 cart: CartableOptionPointer::from_cartable(cart),  | 
639  | 0  |             },  | 
640  | 0  |             None => Yoke { | 
641  | 0  |                 // Safety note: this Yokeable cannot refer to any data since self.cart is None.  | 
642  | 0  |                 yokeable: self.yokeable,  | 
643  | 0  |                 cart: CartableOptionPointer::none(),  | 
644  | 0  |             },  | 
645  |  |         }  | 
646  | 0  |     } Unexecuted instantiation: <yoke::yoke::Yoke<icu_properties::provider::PropertyUnicodeSet, core::option::Option<&()>>>::convert_cart_into_option_pointer Unexecuted instantiation: <yoke::yoke::Yoke<icu_properties::provider::PropertyCodePointSet, core::option::Option<&()>>>::convert_cart_into_option_pointer Unexecuted instantiation: <yoke::yoke::Yoke<&[u8], core::option::Option<&()>>>::convert_cart_into_option_pointer Unexecuted instantiation: <yoke::yoke::Yoke<_, core::option::Option<_>>>::convert_cart_into_option_pointer  | 
647  |  | }  | 
648  |  |  | 
649  |  | impl<Y: for<'a> Yokeable<'a>, C: CartablePointerLike> Yoke<Y, CartableOptionPointer<C>> { | 
650  |  |     /// Obtain the yokeable out of a `Yoke<Y, CartableOptionPointer<C>>` if possible.  | 
651  |  |     ///  | 
652  |  |     /// If the cart is `None`, this returns `Ok`, but if the cart is `Some`,  | 
653  |  |     /// this returns `self` as an error.  | 
654  |  |     #[inline]  | 
655  | 0  |     pub fn try_into_yokeable(self) -> Result<Y, Self> { | 
656  | 0  |         if self.cart.is_none() { | 
657  | 0  |             Ok(self.yokeable.into_inner())  | 
658  |  |         } else { | 
659  | 0  |             Err(self)  | 
660  |  |         }  | 
661  | 0  |     }  | 
662  |  | }  | 
663  |  |  | 
664  |  | /// This trait marks cart types that do not change source on cloning  | 
665  |  | ///  | 
666  |  | /// This is conceptually similar to [`stable_deref_trait::CloneStableDeref`],  | 
667  |  | /// however [`stable_deref_trait::CloneStableDeref`] is not (and should not) be  | 
668  |  | /// implemented on [`Option`] (since it's not [`Deref`]). [`CloneableCart`] essentially is  | 
669  |  | /// "if there _is_ data to borrow from here, cloning the cart gives you an additional  | 
670  |  | /// handle to the same data".  | 
671  |  | ///  | 
672  |  | /// # Safety  | 
673  |  | /// This trait is safe to implement on `StableDeref` types which, once `Clone`d, point to the same underlying data and retain ownership.  | 
674  |  | ///  | 
675  |  | /// This trait can also be implemented on aggregates of such types like `Option<T: CloneableCart>` and `(T: CloneableCart, U: CloneableCart)`.  | 
676  |  | ///  | 
677  |  | /// Essentially, all data that could be referenced by a Yokeable (i.e. data that is referenced via a StableDeref) must retain the same  | 
678  |  | /// pointer and ownership semantics once cloned.  | 
679  |  | pub unsafe trait CloneableCart: Clone {} | 
680  |  |  | 
681  |  | #[cfg(feature = "alloc")]  | 
682  |  | // Safety: Rc<T> implements CloneStableDeref.  | 
683  |  | unsafe impl<T: ?Sized> CloneableCart for Rc<T> {} | 
684  |  | #[cfg(feature = "alloc")]  | 
685  |  | // Safety: Arc<T> implements CloneStableDeref.  | 
686  |  | unsafe impl<T: ?Sized> CloneableCart for Arc<T> {} | 
687  |  | // Safety: Option<T> cannot deref to anything that T doesn't already deref to.  | 
688  |  | unsafe impl<T: CloneableCart> CloneableCart for Option<T> {} | 
689  |  | // Safety: &'a T is indeed StableDeref, and cloning it refers to the same data.  | 
690  |  | // &'a T does not own in the first place, so ownership is preserved.  | 
691  |  | unsafe impl<'a, T: ?Sized> CloneableCart for &'a T {} | 
692  |  | // Safety: () cannot deref to anything.  | 
693  |  | unsafe impl CloneableCart for () {} | 
694  |  |  | 
695  |  | /// Clone requires that the cart type `C` derefs to the same address after it is cloned. This works for  | 
696  |  | /// Rc, Arc, and &'a T.  | 
697  |  | ///  | 
698  |  | /// For other cart types, clone `.backing_cart()` and re-use `.attach_to_cart()`; however, doing  | 
699  |  | /// so may lose mutations performed via `.with_mut()`.  | 
700  |  | ///  | 
701  |  | /// Cloning a `Yoke` is often a cheap operation requiring no heap allocations, in much the same  | 
702  |  | /// way that cloning an `Rc` is a cheap operation. However, if the `yokeable` contains owned data  | 
703  |  | /// (e.g., from `.with_mut()`), that data will need to be cloned.  | 
704  |  | impl<Y: for<'a> Yokeable<'a>, C: CloneableCart> Clone for Yoke<Y, C>  | 
705  |  | where  | 
706  |  |     for<'a> <Y as Yokeable<'a>>::Output: Clone,  | 
707  |  | { | 
708  | 0  |     fn clone(&self) -> Self { | 
709  |  |         // We have an &T not a T, and we can clone T  | 
710  | 0  |         let this = self.get().clone();  | 
711  | 0  |         Yoke { | 
712  | 0  |             yokeable: KindaSortaDangling::new(  | 
713  | 0  |                 // Safety: C being a CloneableCart guarantees that the data referenced by the  | 
714  | 0  |                 // `yokeable` is kept alive by the clone of the cart.  | 
715  | 0  |                 unsafe { Y::make(this) }, | 
716  | 0  |             ),  | 
717  | 0  |             cart: self.cart.clone(),  | 
718  | 0  |         }  | 
719  | 0  |     }  | 
720  |  | }  | 
721  |  |  | 
722  |  | #[test]  | 
723  |  | fn test_clone() { | 
724  |  |     let local_data = "foo".to_owned();  | 
725  |  |     let y1 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(  | 
726  |  |         Rc::new(local_data),  | 
727  |  |     );  | 
728  |  |  | 
729  |  |     // Test basic clone  | 
730  |  |     let y2 = y1.clone();  | 
731  |  |     assert_eq!(y1.get(), "foo");  | 
732  |  |     assert_eq!(y2.get(), "foo");  | 
733  |  |  | 
734  |  |     // Test clone with mutation on target  | 
735  |  |     let mut y3 = y1.clone();  | 
736  |  |     y3.with_mut(|y| { | 
737  |  |         y.to_mut().push_str("bar"); | 
738  |  |     });  | 
739  |  |     assert_eq!(y1.get(), "foo");  | 
740  |  |     assert_eq!(y2.get(), "foo");  | 
741  |  |     assert_eq!(y3.get(), "foobar");  | 
742  |  |  | 
743  |  |     // Test that mutations on source do not affect target  | 
744  |  |     let y4 = y3.clone();  | 
745  |  |     y3.with_mut(|y| { | 
746  |  |         y.to_mut().push_str("baz"); | 
747  |  |     });  | 
748  |  |     assert_eq!(y1.get(), "foo");  | 
749  |  |     assert_eq!(y2.get(), "foo");  | 
750  |  |     assert_eq!(y3.get(), "foobarbaz");  | 
751  |  |     assert_eq!(y4.get(), "foobar");  | 
752  |  | }  | 
753  |  |  | 
754  |  | impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> { | 
755  |  |     /// Allows one to "project" a yoke to perform a transformation on the data, potentially  | 
756  |  |     /// looking at a subfield, and producing a new yoke. This will move cart, and the provided  | 
757  |  |     /// transformation is only allowed to use data known to be borrowed from the cart.  | 
758  |  |     ///  | 
759  |  |     /// The callback takes an additional `PhantomData<&()>` parameter to anchor lifetimes  | 
760  |  |     /// (see [#86702](https://github.com/rust-lang/rust/issues/86702)) This parameter  | 
761  |  |     /// should just be ignored in the callback.  | 
762  |  |     ///  | 
763  |  |     /// This can be used, for example, to transform data from one format to another:  | 
764  |  |     ///  | 
765  |  |     /// ```  | 
766  |  |     /// # use std::rc::Rc;  | 
767  |  |     /// # use yoke::Yoke;  | 
768  |  |     /// #  | 
769  |  |     /// fn slice(y: Yoke<&'static str, Rc<[u8]>>) -> Yoke<&'static [u8], Rc<[u8]>> { | 
770  |  |     ///     y.map_project(move |yk, _| yk.as_bytes())  | 
771  |  |     /// }  | 
772  |  |     /// ```  | 
773  |  |     ///  | 
774  |  |     /// This can also be used to create a yoke for a subfield  | 
775  |  |     ///  | 
776  |  |     /// ```  | 
777  |  |     /// # use yoke::{Yoke, Yokeable}; | 
778  |  |     /// # use std::mem;  | 
779  |  |     /// # use std::rc::Rc;  | 
780  |  |     /// #  | 
781  |  |     /// // also safely implements Yokeable<'a>  | 
782  |  |     /// struct Bar<'a> { | 
783  |  |     ///     string_1: &'a str,  | 
784  |  |     ///     string_2: &'a str,  | 
785  |  |     /// }  | 
786  |  |     ///  | 
787  |  |     /// fn map_project_string_1(  | 
788  |  |     ///     bar: Yoke<Bar<'static>, Rc<[u8]>>,  | 
789  |  |     /// ) -> Yoke<&'static str, Rc<[u8]>> { | 
790  |  |     ///     bar.map_project(|bar, _| bar.string_1)  | 
791  |  |     /// }  | 
792  |  |     ///  | 
793  |  |     /// #  | 
794  |  |     /// # unsafe impl<'a> Yokeable<'a> for Bar<'static> { | 
795  |  |     /// #     type Output = Bar<'a>;  | 
796  |  |     /// #     fn transform(&'a self) -> &'a Bar<'a> { | 
797  |  |     /// #         self  | 
798  |  |     /// #     }  | 
799  |  |     /// #  | 
800  |  |     /// #     fn transform_owned(self) -> Bar<'a> { | 
801  |  |     /// #         // covariant lifetime cast, can be done safely  | 
802  |  |     /// #         self  | 
803  |  |     /// #     }  | 
804  |  |     /// #  | 
805  |  |     /// #     unsafe fn make(from: Bar<'a>) -> Self { | 
806  |  |     /// #         let ret = mem::transmute_copy(&from);  | 
807  |  |     /// #         mem::forget(from);  | 
808  |  |     /// #         ret  | 
809  |  |     /// #     }  | 
810  |  |     /// #  | 
811  |  |     /// #     fn transform_mut<F>(&'a mut self, f: F)  | 
812  |  |     /// #     where  | 
813  |  |     /// #         F: 'static + FnOnce(&'a mut Self::Output),  | 
814  |  |     /// #     { | 
815  |  |     /// #         unsafe { f(mem::transmute(self)) } | 
816  |  |     /// #     }  | 
817  |  |     /// # }  | 
818  |  |     /// ```  | 
819  |  |     //  | 
820  |  |     // Safety docs can be found at the end of the file.  | 
821  | 0  |     pub fn map_project<P, F>(self, f: F) -> Yoke<P, C>  | 
822  | 0  |     where  | 
823  | 0  |         P: for<'a> Yokeable<'a>,  | 
824  | 0  |         F: for<'a> FnOnce(  | 
825  | 0  |             <Y as Yokeable<'a>>::Output,  | 
826  | 0  |             PhantomData<&'a ()>,  | 
827  | 0  |         ) -> <P as Yokeable<'a>>::Output,  | 
828  |  |     { | 
829  | 0  |         let p = f(self.yokeable.into_inner().transform_owned(), PhantomData);  | 
830  | 0  |         Yoke { | 
831  | 0  |             yokeable: KindaSortaDangling::new(  | 
832  | 0  |                 // Safety: the resulting `yokeable` is dropped before the `cart` because  | 
833  | 0  |                 // of the Yoke invariant. See the safety docs below for the justification of why  | 
834  | 0  |                 // yokeable could only borrow from the Cart.  | 
835  | 0  |                 unsafe { P::make(p) }, | 
836  | 0  |             ),  | 
837  | 0  |             cart: self.cart,  | 
838  | 0  |         }  | 
839  | 0  |     }  | 
840  |  |  | 
841  |  |     /// This is similar to [`Yoke::map_project`], however it does not move  | 
842  |  |     /// [`Self`] and instead clones the cart (only if the cart is a [`CloneableCart`])  | 
843  |  |     ///  | 
844  |  |     /// This is a bit more efficient than cloning the [`Yoke`] and then calling [`Yoke::map_project`]  | 
845  |  |     /// because then it will not clone fields that are going to be discarded.  | 
846  | 0  |     pub fn map_project_cloned<'this, P, F>(&'this self, f: F) -> Yoke<P, C>  | 
847  | 0  |     where  | 
848  | 0  |         P: for<'a> Yokeable<'a>,  | 
849  | 0  |         C: CloneableCart,  | 
850  | 0  |         F: for<'a> FnOnce(  | 
851  | 0  |             &'this <Y as Yokeable<'a>>::Output,  | 
852  | 0  |             PhantomData<&'a ()>,  | 
853  | 0  |         ) -> <P as Yokeable<'a>>::Output,  | 
854  |  |     { | 
855  | 0  |         let p = f(self.get(), PhantomData);  | 
856  | 0  |         Yoke { | 
857  | 0  |             yokeable: KindaSortaDangling::new(  | 
858  | 0  |                 // Safety: the resulting `yokeable` is dropped before the `cart` because  | 
859  | 0  |                 // of the Yoke invariant. See the safety docs below for the justification of why  | 
860  | 0  |                 // yokeable could only borrow from the Cart.  | 
861  | 0  |                 unsafe { P::make(p) }, | 
862  | 0  |             ),  | 
863  | 0  |             cart: self.cart.clone(),  | 
864  | 0  |         }  | 
865  | 0  |     }  | 
866  |  |  | 
867  |  |     /// This is similar to [`Yoke::map_project`], however it can also bubble up an error  | 
868  |  |     /// from the callback.  | 
869  |  |     ///  | 
870  |  |     /// ```  | 
871  |  |     /// # use std::rc::Rc;  | 
872  |  |     /// # use yoke::Yoke;  | 
873  |  |     /// # use std::str::{self, Utf8Error}; | 
874  |  |     /// #  | 
875  |  |     /// fn slice(  | 
876  |  |     ///     y: Yoke<&'static [u8], Rc<[u8]>>,  | 
877  |  |     /// ) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> { | 
878  |  |     ///     y.try_map_project(move |bytes, _| str::from_utf8(bytes))  | 
879  |  |     /// }  | 
880  |  |     /// ```  | 
881  |  |     ///  | 
882  |  |     /// This can also be used to create a yoke for a subfield  | 
883  |  |     ///  | 
884  |  |     /// ```  | 
885  |  |     /// # use yoke::{Yoke, Yokeable}; | 
886  |  |     /// # use std::mem;  | 
887  |  |     /// # use std::rc::Rc;  | 
888  |  |     /// # use std::str::{self, Utf8Error}; | 
889  |  |     /// #  | 
890  |  |     /// // also safely implements Yokeable<'a>  | 
891  |  |     /// struct Bar<'a> { | 
892  |  |     ///     bytes_1: &'a [u8],  | 
893  |  |     ///     string_2: &'a str,  | 
894  |  |     /// }  | 
895  |  |     ///  | 
896  |  |     /// fn map_project_string_1(  | 
897  |  |     ///     bar: Yoke<Bar<'static>, Rc<[u8]>>,  | 
898  |  |     /// ) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> { | 
899  |  |     ///     bar.try_map_project(|bar, _| str::from_utf8(bar.bytes_1))  | 
900  |  |     /// }  | 
901  |  |     ///  | 
902  |  |     /// #  | 
903  |  |     /// # unsafe impl<'a> Yokeable<'a> for Bar<'static> { | 
904  |  |     /// #     type Output = Bar<'a>;  | 
905  |  |     /// #     fn transform(&'a self) -> &'a Bar<'a> { | 
906  |  |     /// #         self  | 
907  |  |     /// #     }  | 
908  |  |     /// #  | 
909  |  |     /// #     fn transform_owned(self) -> Bar<'a> { | 
910  |  |     /// #         // covariant lifetime cast, can be done safely  | 
911  |  |     /// #         self  | 
912  |  |     /// #     }  | 
913  |  |     /// #  | 
914  |  |     /// #     unsafe fn make(from: Bar<'a>) -> Self { | 
915  |  |     /// #         let ret = mem::transmute_copy(&from);  | 
916  |  |     /// #         mem::forget(from);  | 
917  |  |     /// #         ret  | 
918  |  |     /// #     }  | 
919  |  |     /// #  | 
920  |  |     /// #     fn transform_mut<F>(&'a mut self, f: F)  | 
921  |  |     /// #     where  | 
922  |  |     /// #         F: 'static + FnOnce(&'a mut Self::Output),  | 
923  |  |     /// #     { | 
924  |  |     /// #         unsafe { f(mem::transmute(self)) } | 
925  |  |     /// #     }  | 
926  |  |     /// # }  | 
927  |  |     /// ```  | 
928  | 0  |     pub fn try_map_project<P, F, E>(self, f: F) -> Result<Yoke<P, C>, E>  | 
929  | 0  |     where  | 
930  | 0  |         P: for<'a> Yokeable<'a>,  | 
931  | 0  |         F: for<'a> FnOnce(  | 
932  | 0  |             <Y as Yokeable<'a>>::Output,  | 
933  | 0  |             PhantomData<&'a ()>,  | 
934  | 0  |         ) -> Result<<P as Yokeable<'a>>::Output, E>,  | 
935  |  |     { | 
936  | 0  |         let p = f(self.yokeable.into_inner().transform_owned(), PhantomData)?;  | 
937  | 0  |         Ok(Yoke { | 
938  | 0  |             yokeable: KindaSortaDangling::new(  | 
939  | 0  |                 // Safety: the resulting `yokeable` is dropped before the `cart` because  | 
940  | 0  |                 // of the Yoke invariant. See the safety docs below for the justification of why  | 
941  | 0  |                 // yokeable could only borrow from the Cart.  | 
942  | 0  |                 unsafe { P::make(p) }, | 
943  | 0  |             ),  | 
944  | 0  |             cart: self.cart,  | 
945  | 0  |         })  | 
946  | 0  |     }  | 
947  |  |  | 
948  |  |     /// This is similar to [`Yoke::try_map_project`], however it does not move  | 
949  |  |     /// [`Self`] and instead clones the cart (only if the cart is a [`CloneableCart`])  | 
950  |  |     ///  | 
951  |  |     /// This is a bit more efficient than cloning the [`Yoke`] and then calling [`Yoke::map_project`]  | 
952  |  |     /// because then it will not clone fields that are going to be discarded.  | 
953  | 0  |     pub fn try_map_project_cloned<'this, P, F, E>(&'this self, f: F) -> Result<Yoke<P, C>, E>  | 
954  | 0  |     where  | 
955  | 0  |         P: for<'a> Yokeable<'a>,  | 
956  | 0  |         C: CloneableCart,  | 
957  | 0  |         F: for<'a> FnOnce(  | 
958  | 0  |             &'this <Y as Yokeable<'a>>::Output,  | 
959  | 0  |             PhantomData<&'a ()>,  | 
960  | 0  |         ) -> Result<<P as Yokeable<'a>>::Output, E>,  | 
961  |  |     { | 
962  | 0  |         let p = f(self.get(), PhantomData)?;  | 
963  | 0  |         Ok(Yoke { | 
964  | 0  |             yokeable: KindaSortaDangling::new(  | 
965  | 0  |                 // Safety: the resulting `yokeable` is dropped before the `cart` because  | 
966  | 0  |                 // of the Yoke invariant. See the safety docs below for the justification of why  | 
967  | 0  |                 // yokeable could only borrow from the Cart.  | 
968  | 0  |                 unsafe { P::make(p) }, | 
969  | 0  |             ),  | 
970  | 0  |             cart: self.cart.clone(),  | 
971  | 0  |         })  | 
972  | 0  |     }  | 
973  |  |     /// This is similar to [`Yoke::map_project`], but it works around older versions  | 
974  |  |     /// of Rust not being able to use `FnOnce` by using an explicit capture input.  | 
975  |  |     /// See [#1061](https://github.com/unicode-org/icu4x/issues/1061).  | 
976  |  |     ///  | 
977  |  |     /// See the docs of [`Yoke::map_project`] for how this works.  | 
978  | 0  |     pub fn map_project_with_explicit_capture<P, T>(  | 
979  | 0  |         self,  | 
980  | 0  |         capture: T,  | 
981  | 0  |         f: for<'a> fn(  | 
982  | 0  |             <Y as Yokeable<'a>>::Output,  | 
983  | 0  |             capture: T,  | 
984  | 0  |             PhantomData<&'a ()>,  | 
985  | 0  |         ) -> <P as Yokeable<'a>>::Output,  | 
986  | 0  |     ) -> Yoke<P, C>  | 
987  | 0  |     where  | 
988  | 0  |         P: for<'a> Yokeable<'a>,  | 
989  |  |     { | 
990  | 0  |         let p = f(  | 
991  | 0  |             self.yokeable.into_inner().transform_owned(),  | 
992  | 0  |             capture,  | 
993  | 0  |             PhantomData,  | 
994  | 0  |         );  | 
995  | 0  |         Yoke { | 
996  | 0  |             yokeable: KindaSortaDangling::new(  | 
997  | 0  |                 // Safety: the resulting `yokeable` is dropped before the `cart` because  | 
998  | 0  |                 // of the Yoke invariant. See the safety docs below for the justification of why  | 
999  | 0  |                 // yokeable could only borrow from the Cart.  | 
1000  | 0  |                 unsafe { P::make(p) }, | 
1001  | 0  |             ),  | 
1002  | 0  |             cart: self.cart,  | 
1003  | 0  |         }  | 
1004  | 0  |     }  | 
1005  |  |  | 
1006  |  |     /// This is similar to [`Yoke::map_project_cloned`], but it works around older versions  | 
1007  |  |     /// of Rust not being able to use `FnOnce` by using an explicit capture input.  | 
1008  |  |     /// See [#1061](https://github.com/unicode-org/icu4x/issues/1061).  | 
1009  |  |     ///  | 
1010  |  |     /// See the docs of [`Yoke::map_project_cloned`] for how this works.  | 
1011  | 0  |     pub fn map_project_cloned_with_explicit_capture<'this, P, T>(  | 
1012  | 0  |         &'this self,  | 
1013  | 0  |         capture: T,  | 
1014  | 0  |         f: for<'a> fn(  | 
1015  | 0  |             &'this <Y as Yokeable<'a>>::Output,  | 
1016  | 0  |             capture: T,  | 
1017  | 0  |             PhantomData<&'a ()>,  | 
1018  | 0  |         ) -> <P as Yokeable<'a>>::Output,  | 
1019  | 0  |     ) -> Yoke<P, C>  | 
1020  | 0  |     where  | 
1021  | 0  |         P: for<'a> Yokeable<'a>,  | 
1022  | 0  |         C: CloneableCart,  | 
1023  |  |     { | 
1024  | 0  |         let p = f(self.get(), capture, PhantomData);  | 
1025  | 0  |         Yoke { | 
1026  | 0  |             yokeable: KindaSortaDangling::new(  | 
1027  | 0  |                 // Safety: the resulting `yokeable` is dropped before the `cart` because  | 
1028  | 0  |                 // of the Yoke invariant. See the safety docs below for the justification of why  | 
1029  | 0  |                 // yokeable could only borrow from the Cart.  | 
1030  | 0  |                 unsafe { P::make(p) }, | 
1031  | 0  |             ),  | 
1032  | 0  |             cart: self.cart.clone(),  | 
1033  | 0  |         }  | 
1034  | 0  |     }  | 
1035  |  |  | 
1036  |  |     /// This is similar to [`Yoke::try_map_project`], but it works around older versions  | 
1037  |  |     /// of Rust not being able to use `FnOnce` by using an explicit capture input.  | 
1038  |  |     /// See [#1061](https://github.com/unicode-org/icu4x/issues/1061).  | 
1039  |  |     ///  | 
1040  |  |     /// See the docs of [`Yoke::try_map_project`] for how this works.  | 
1041  |  |     #[allow(clippy::type_complexity)]  | 
1042  | 0  |     pub fn try_map_project_with_explicit_capture<P, T, E>(  | 
1043  | 0  |         self,  | 
1044  | 0  |         capture: T,  | 
1045  | 0  |         f: for<'a> fn(  | 
1046  | 0  |             <Y as Yokeable<'a>>::Output,  | 
1047  | 0  |             capture: T,  | 
1048  | 0  |             PhantomData<&'a ()>,  | 
1049  | 0  |         ) -> Result<<P as Yokeable<'a>>::Output, E>,  | 
1050  | 0  |     ) -> Result<Yoke<P, C>, E>  | 
1051  | 0  |     where  | 
1052  | 0  |         P: for<'a> Yokeable<'a>,  | 
1053  |  |     { | 
1054  | 0  |         let p = f(  | 
1055  | 0  |             self.yokeable.into_inner().transform_owned(),  | 
1056  | 0  |             capture,  | 
1057  | 0  |             PhantomData,  | 
1058  | 0  |         )?;  | 
1059  | 0  |         Ok(Yoke { | 
1060  | 0  |             yokeable: KindaSortaDangling::new(  | 
1061  | 0  |                 // Safety: the resulting `yokeable` is dropped before the `cart` because  | 
1062  | 0  |                 // of the Yoke invariant. See the safety docs below for the justification of why  | 
1063  | 0  |                 // yokeable could only borrow from the Cart.  | 
1064  | 0  |                 unsafe { P::make(p) }, | 
1065  | 0  |             ),  | 
1066  | 0  |             cart: self.cart,  | 
1067  | 0  |         })  | 
1068  | 0  |     }  | 
1069  |  |  | 
1070  |  |     /// This is similar to [`Yoke::try_map_project_cloned`], but it works around older versions  | 
1071  |  |     /// of Rust not being able to use `FnOnce` by using an explicit capture input.  | 
1072  |  |     /// See [#1061](https://github.com/unicode-org/icu4x/issues/1061).  | 
1073  |  |     ///  | 
1074  |  |     /// See the docs of [`Yoke::try_map_project_cloned`] for how this works.  | 
1075  |  |     #[allow(clippy::type_complexity)]  | 
1076  | 0  |     pub fn try_map_project_cloned_with_explicit_capture<'this, P, T, E>(  | 
1077  | 0  |         &'this self,  | 
1078  | 0  |         capture: T,  | 
1079  | 0  |         f: for<'a> fn(  | 
1080  | 0  |             &'this <Y as Yokeable<'a>>::Output,  | 
1081  | 0  |             capture: T,  | 
1082  | 0  |             PhantomData<&'a ()>,  | 
1083  | 0  |         ) -> Result<<P as Yokeable<'a>>::Output, E>,  | 
1084  | 0  |     ) -> Result<Yoke<P, C>, E>  | 
1085  | 0  |     where  | 
1086  | 0  |         P: for<'a> Yokeable<'a>,  | 
1087  | 0  |         C: CloneableCart,  | 
1088  |  |     { | 
1089  | 0  |         let p = f(self.get(), capture, PhantomData)?;  | 
1090  | 0  |         Ok(Yoke { | 
1091  | 0  |             yokeable: KindaSortaDangling::new(  | 
1092  | 0  |                 // Safety: the resulting `yokeable` is dropped before the `cart` because  | 
1093  | 0  |                 // of the Yoke invariant. See the safety docs below for the justification of why  | 
1094  | 0  |                 // yokeable could only borrow from the Cart.  | 
1095  | 0  |                 unsafe { P::make(p) }, | 
1096  | 0  |             ),  | 
1097  | 0  |             cart: self.cart.clone(),  | 
1098  | 0  |         })  | 
1099  | 0  |     }  | 
1100  |  | }  | 
1101  |  |  | 
1102  |  | #[cfg(feature = "alloc")]  | 
1103  |  | impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized> Yoke<Y, Rc<C>> { | 
1104  |  |     /// Allows type-erasing the cart in a `Yoke<Y, Rc<C>>`.  | 
1105  |  |     ///  | 
1106  |  |     /// The yoke only carries around a cart type `C` for its destructor,  | 
1107  |  |     /// since it needs to be able to guarantee that its internal references  | 
1108  |  |     /// are valid for the lifetime of the Yoke. As such, the actual type of the  | 
1109  |  |     /// Cart is not very useful unless you wish to extract data out of it  | 
1110  |  |     /// via [`Yoke::backing_cart()`]. Erasing the cart allows for one to mix  | 
1111  |  |     /// [`Yoke`]s obtained from different sources.  | 
1112  |  |     ///  | 
1113  |  |     /// In case the cart type `C` is not already an `Rc<T>`, you can use  | 
1114  |  |     /// [`Yoke::wrap_cart_in_rc()`] to wrap it.  | 
1115  |  |     ///  | 
1116  |  |     /// ✨ *Enabled with the `alloc` Cargo feature.*  | 
1117  |  |     ///  | 
1118  |  |     /// # Example  | 
1119  |  |     ///  | 
1120  |  |     /// ```rust  | 
1121  |  |     /// use std::rc::Rc;  | 
1122  |  |     /// use yoke::erased::ErasedRcCart;  | 
1123  |  |     /// use yoke::Yoke;  | 
1124  |  |     ///  | 
1125  |  |     /// let buffer1: Rc<String> = Rc::new("   foo bar baz  ".into()); | 
1126  |  |     /// let buffer2: Box<String> = Box::new("  baz quux  ".into()); | 
1127  |  |     ///  | 
1128  |  |     /// let yoke1 =  | 
1129  |  |     ///     Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());  | 
1130  |  |     /// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());  | 
1131  |  |     ///  | 
1132  |  |     /// let erased1: Yoke<_, ErasedRcCart> = yoke1.erase_rc_cart();  | 
1133  |  |     /// // Wrap the Box in an Rc to make it compatible  | 
1134  |  |     /// let erased2: Yoke<_, ErasedRcCart> =  | 
1135  |  |     ///     yoke2.wrap_cart_in_rc().erase_rc_cart();  | 
1136  |  |     ///  | 
1137  |  |     /// // Now erased1 and erased2 have the same type!  | 
1138  |  |     /// ```  | 
1139  | 0  |     pub fn erase_rc_cart(self) -> Yoke<Y, ErasedRcCart> { | 
1140  |  |         // Safety: safe because the cart is preserved, as it is just type-erased  | 
1141  | 0  |         unsafe { self.replace_cart(|c| c as ErasedRcCart) } | 
1142  | 0  |     }  | 
1143  |  | }  | 
1144  |  |  | 
1145  |  | #[cfg(feature = "alloc")]  | 
1146  |  | impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized + Send + Sync> Yoke<Y, Arc<C>> { | 
1147  |  |     /// Allows type-erasing the cart in a `Yoke<Y, Arc<C>>`.  | 
1148  |  |     ///  | 
1149  |  |     /// The yoke only carries around a cart type `C` for its destructor,  | 
1150  |  |     /// since it needs to be able to guarantee that its internal references  | 
1151  |  |     /// are valid for the lifetime of the Yoke. As such, the actual type of the  | 
1152  |  |     /// Cart is not very useful unless you wish to extract data out of it  | 
1153  |  |     /// via [`Yoke::backing_cart()`]. Erasing the cart allows for one to mix  | 
1154  |  |     /// [`Yoke`]s obtained from different sources.  | 
1155  |  |     ///  | 
1156  |  |     /// In case the cart type `C` is not already an `Arc<T>`, you can use  | 
1157  |  |     /// [`Yoke::wrap_cart_in_arc()`] to wrap it.  | 
1158  |  |     ///  | 
1159  |  |     /// ✨ *Enabled with the `alloc` Cargo feature.*  | 
1160  |  |     ///  | 
1161  |  |     /// # Example  | 
1162  |  |     ///  | 
1163  |  |     /// ```rust  | 
1164  |  |     /// use std::sync::Arc;  | 
1165  |  |     /// use yoke::erased::ErasedArcCart;  | 
1166  |  |     /// use yoke::Yoke;  | 
1167  |  |     ///  | 
1168  |  |     /// let buffer1: Arc<String> = Arc::new("   foo bar baz  ".into()); | 
1169  |  |     /// let buffer2: Box<String> = Box::new("  baz quux  ".into()); | 
1170  |  |     ///  | 
1171  |  |     /// let yoke1 =  | 
1172  |  |     ///     Yoke::<&'static str, _>::attach_to_cart(buffer1, |arc| arc.trim());  | 
1173  |  |     /// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());  | 
1174  |  |     ///  | 
1175  |  |     /// let erased1: Yoke<_, ErasedArcCart> = yoke1.erase_arc_cart();  | 
1176  |  |     /// // Wrap the Box in an Rc to make it compatible  | 
1177  |  |     /// let erased2: Yoke<_, ErasedArcCart> =  | 
1178  |  |     ///     yoke2.wrap_cart_in_arc().erase_arc_cart();  | 
1179  |  |     ///  | 
1180  |  |     /// // Now erased1 and erased2 have the same type!  | 
1181  |  |     /// ```  | 
1182  | 0  |     pub fn erase_arc_cart(self) -> Yoke<Y, ErasedArcCart> { | 
1183  |  |         // Safety: safe because the cart is preserved, as it is just type-erased  | 
1184  | 0  |         unsafe { self.replace_cart(|c| c as ErasedArcCart) } | 
1185  | 0  |     }  | 
1186  |  | }  | 
1187  |  |  | 
1188  |  | #[cfg(feature = "alloc")]  | 
1189  |  | impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized> Yoke<Y, Box<C>> { | 
1190  |  |     /// Allows type-erasing the cart in a `Yoke<Y, Box<C>>`.  | 
1191  |  |     ///  | 
1192  |  |     /// The yoke only carries around a cart type `C` for its destructor,  | 
1193  |  |     /// since it needs to be able to guarantee that its internal references  | 
1194  |  |     /// are valid for the lifetime of the Yoke. As such, the actual type of the  | 
1195  |  |     /// Cart is not very useful unless you wish to extract data out of it  | 
1196  |  |     /// via [`Yoke::backing_cart()`]. Erasing the cart allows for one to mix  | 
1197  |  |     /// [`Yoke`]s obtained from different sources.  | 
1198  |  |     ///  | 
1199  |  |     /// In case the cart type `C` is not already `Box<T>`, you can use  | 
1200  |  |     /// [`Yoke::wrap_cart_in_box()`] to wrap it.  | 
1201  |  |     ///  | 
1202  |  |     /// ✨ *Enabled with the `alloc` Cargo feature.*  | 
1203  |  |     ///  | 
1204  |  |     /// # Example  | 
1205  |  |     ///  | 
1206  |  |     /// ```rust  | 
1207  |  |     /// use std::rc::Rc;  | 
1208  |  |     /// use yoke::erased::ErasedBoxCart;  | 
1209  |  |     /// use yoke::Yoke;  | 
1210  |  |     ///  | 
1211  |  |     /// let buffer1: Rc<String> = Rc::new("   foo bar baz  ".into()); | 
1212  |  |     /// let buffer2: Box<String> = Box::new("  baz quux  ".into()); | 
1213  |  |     ///  | 
1214  |  |     /// let yoke1 =  | 
1215  |  |     ///     Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());  | 
1216  |  |     /// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());  | 
1217  |  |     ///  | 
1218  |  |     /// // Wrap the Rc in an Box to make it compatible  | 
1219  |  |     /// let erased1: Yoke<_, ErasedBoxCart> =  | 
1220  |  |     ///     yoke1.wrap_cart_in_box().erase_box_cart();  | 
1221  |  |     /// let erased2: Yoke<_, ErasedBoxCart> = yoke2.erase_box_cart();  | 
1222  |  |     ///  | 
1223  |  |     /// // Now erased1 and erased2 have the same type!  | 
1224  |  |     /// ```  | 
1225  | 0  |     pub fn erase_box_cart(self) -> Yoke<Y, ErasedBoxCart> { | 
1226  |  |         // Safety: safe because the cart is preserved, as it is just type-erased  | 
1227  | 0  |         unsafe { self.replace_cart(|c| c as ErasedBoxCart) } | 
1228  | 0  |     }  | 
1229  |  | }  | 
1230  |  |  | 
1231  |  | #[cfg(feature = "alloc")]  | 
1232  |  | impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> { | 
1233  |  |     /// Helper function allowing one to wrap the cart type `C` in a `Box<T>`.  | 
1234  |  |     /// Can be paired with [`Yoke::erase_box_cart()`]  | 
1235  |  |     ///  | 
1236  |  |     /// ✨ *Enabled with the `alloc` Cargo feature.*  | 
1237  |  |     #[inline]  | 
1238  | 0  |     pub fn wrap_cart_in_box(self) -> Yoke<Y, Box<C>> { | 
1239  |  |         // Safety: safe because the cart is preserved, as it is just wrapped.  | 
1240  | 0  |         unsafe { self.replace_cart(Box::new) } | 
1241  | 0  |     }  | 
1242  |  |     /// Helper function allowing one to wrap the cart type `C` in an `Rc<T>`.  | 
1243  |  |     /// Can be paired with [`Yoke::erase_rc_cart()`], or generally used  | 
1244  |  |     /// to make the [`Yoke`] cloneable.  | 
1245  |  |     ///  | 
1246  |  |     /// ✨ *Enabled with the `alloc` Cargo feature.*  | 
1247  |  |     #[inline]  | 
1248  | 0  |     pub fn wrap_cart_in_rc(self) -> Yoke<Y, Rc<C>> { | 
1249  |  |         // Safety: safe because the cart is preserved, as it is just wrapped  | 
1250  | 0  |         unsafe { self.replace_cart(Rc::new) } | 
1251  | 0  |     }  | 
1252  |  |     /// Helper function allowing one to wrap the cart type `C` in an `Rc<T>`.  | 
1253  |  |     /// Can be paired with [`Yoke::erase_arc_cart()`], or generally used  | 
1254  |  |     /// to make the [`Yoke`] cloneable.  | 
1255  |  |     ///  | 
1256  |  |     /// ✨ *Enabled with the `alloc` Cargo feature.*  | 
1257  |  |     #[inline]  | 
1258  | 0  |     pub fn wrap_cart_in_arc(self) -> Yoke<Y, Arc<C>> { | 
1259  |  |         // Safety: safe because the cart is preserved, as it is just wrapped  | 
1260  | 0  |         unsafe { self.replace_cart(Arc::new) } | 
1261  | 0  |     }  | 
1262  |  | }  | 
1263  |  |  | 
1264  |  | impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> { | 
1265  |  |     /// Helper function allowing one to wrap the cart type `C` in an [`EitherCart`].  | 
1266  |  |     ///  | 
1267  |  |     /// This function wraps the cart into the `A` variant. To wrap it into the  | 
1268  |  |     /// `B` variant, use [`Self::wrap_cart_in_either_b()`].  | 
1269  |  |     ///  | 
1270  |  |     /// For an example, see [`EitherCart`].  | 
1271  |  |     #[inline]  | 
1272  | 0  |     pub fn wrap_cart_in_either_a<B>(self) -> Yoke<Y, EitherCart<C, B>> { | 
1273  |  |         // Safety: safe because the cart is preserved, as it is just wrapped.  | 
1274  | 0  |         unsafe { self.replace_cart(EitherCart::A) } | 
1275  | 0  |     }  | 
1276  |  |     /// Helper function allowing one to wrap the cart type `C` in an [`EitherCart`].  | 
1277  |  |     ///  | 
1278  |  |     /// This function wraps the cart into the `B` variant. To wrap it into the  | 
1279  |  |     /// `A` variant, use [`Self::wrap_cart_in_either_a()`].  | 
1280  |  |     ///  | 
1281  |  |     /// For an example, see [`EitherCart`].  | 
1282  |  |     #[inline]  | 
1283  | 0  |     pub fn wrap_cart_in_either_b<A>(self) -> Yoke<Y, EitherCart<A, C>> { | 
1284  |  |         // Safety: safe because the cart is preserved, as it is just wrapped.  | 
1285  | 0  |         unsafe { self.replace_cart(EitherCart::B) } | 
1286  | 0  |     }  | 
1287  |  | }  | 
1288  |  |  | 
1289  |  | /// # Safety docs for project()  | 
1290  |  | ///  | 
1291  |  | /// (Docs are on a private const to allow the use of compile_fail doctests)  | 
1292  |  | ///  | 
1293  |  | /// This is safe to perform because of the choice of lifetimes on `f`, that is,  | 
1294  |  | /// `for<a> fn(<Y as Yokeable<'a>>::Output, &'a ()) -> <P as Yokeable<'a>>::Output`.  | 
1295  |  | ///  | 
1296  |  | /// Note that correctness arguments are similar if you replace `fn` with `FnOnce`.  | 
1297  |  | ///  | 
1298  |  | /// What we want this function to do is take a Yokeable (`Y`) that is borrowing from the cart, and  | 
1299  |  | /// produce another Yokeable (`P`) that also borrows from the same cart. There are a couple potential  | 
1300  |  | /// hazards here:  | 
1301  |  | ///  | 
1302  |  | /// - `P` ends up borrowing data from `Y` (or elsewhere) that did _not_ come from the cart,  | 
1303  |  | ///   for example `P` could borrow owned data from a `Cow`. This would make the `Yoke<P>` dependent  | 
1304  |  | ///   on data owned only by the `Yoke<Y>`.  | 
1305  |  | /// - Borrowed data from `Y` escapes with the wrong lifetime  | 
1306  |  | ///  | 
1307  |  | /// Let's walk through these and see how they're prevented.  | 
1308  |  | ///  | 
1309  |  | /// ```rust, compile_fail  | 
1310  |  | /// # use std::rc::Rc;  | 
1311  |  | /// # use yoke::Yoke;  | 
1312  |  | /// # use std::borrow::Cow;  | 
1313  |  | /// fn borrow_potentially_owned(y: &Yoke<Cow<'static, str>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> { | 
1314  |  | ///    y.map_project_cloned(|cow, _| &*cow)     | 
1315  |  | /// }  | 
1316  |  | /// ```  | 
1317  |  | ///  | 
1318  |  | /// In this case, the lifetime of `&*cow` is `&'this str`, however the function needs to be able to return  | 
1319  |  | /// `&'a str` _for all `'a`_, which isn't possible.  | 
1320  |  | ///  | 
1321  |  | ///  | 
1322  |  | /// ```rust, compile_fail  | 
1323  |  | /// # use std::rc::Rc;  | 
1324  |  | /// # use yoke::Yoke;  | 
1325  |  | /// # use std::borrow::Cow;  | 
1326  |  | /// fn borrow_potentially_owned(y: Yoke<Cow<'static, str>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> { | 
1327  |  | ///    y.map_project(|cow, _| &*cow)     | 
1328  |  | /// }  | 
1329  |  | /// ```  | 
1330  |  | ///  | 
1331  |  | /// This has the same issue, `&*cow` is borrowing for a local lifetime.  | 
1332  |  | ///  | 
1333  |  | /// Similarly, trying to project an owned field of a struct will produce similar errors:  | 
1334  |  | ///  | 
1335  |  | /// ```rust,compile_fail  | 
1336  |  | /// # use std::borrow::Cow;  | 
1337  |  | /// # use yoke::{Yoke, Yokeable}; | 
1338  |  | /// # use std::mem;  | 
1339  |  | /// # use std::rc::Rc;  | 
1340  |  | /// #  | 
1341  |  | /// // also safely implements Yokeable<'a>  | 
1342  |  | /// struct Bar<'a> { | 
1343  |  | ///     owned: String,  | 
1344  |  | ///     string_2: &'a str,  | 
1345  |  | /// }  | 
1346  |  | ///  | 
1347  |  | /// fn map_project_owned(bar: &Yoke<Bar<'static>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> { | 
1348  |  | ///     // ERROR (but works if you replace owned with string_2)  | 
1349  |  | ///     bar.map_project_cloned(|bar, _| &*bar.owned)     | 
1350  |  | /// }  | 
1351  |  | ///  | 
1352  |  | /// #  | 
1353  |  | /// # unsafe impl<'a> Yokeable<'a> for Bar<'static> { | 
1354  |  | /// #     type Output = Bar<'a>;  | 
1355  |  | /// #     fn transform(&'a self) -> &'a Bar<'a> { | 
1356  |  | /// #         self  | 
1357  |  | /// #     }  | 
1358  |  | /// #  | 
1359  |  | /// #     fn transform_owned(self) -> Bar<'a> { | 
1360  |  | /// #         // covariant lifetime cast, can be done safely  | 
1361  |  | /// #         self  | 
1362  |  | /// #     }  | 
1363  |  | /// #  | 
1364  |  | /// #     unsafe fn make(from: Bar<'a>) -> Self { | 
1365  |  | /// #         let ret = mem::transmute_copy(&from);  | 
1366  |  | /// #         mem::forget(from);  | 
1367  |  | /// #         ret  | 
1368  |  | /// #     }  | 
1369  |  | /// #  | 
1370  |  | /// #     fn transform_mut<F>(&'a mut self, f: F)  | 
1371  |  | /// #     where  | 
1372  |  | /// #         F: 'static + FnOnce(&'a mut Self::Output),  | 
1373  |  | /// #     { | 
1374  |  | /// #         unsafe { f(mem::transmute(self)) } | 
1375  |  | /// #     }  | 
1376  |  | /// # }  | 
1377  |  | /// ```  | 
1378  |  | ///  | 
1379  |  | /// Borrowed data from `Y` similarly cannot escape with the wrong lifetime because of the `for<'a>`, since  | 
1380  |  | /// it will never be valid for the borrowed data to escape for all lifetimes of 'a. Internally, `.project()`  | 
1381  |  | /// uses `.get()`, however the signature forces the callers to be able to handle every lifetime.  | 
1382  |  | ///  | 
1383  |  | ///  `'a` is the only lifetime that matters here; `Yokeable`s must be `'static` and since  | 
1384  |  | /// `Output` is an associated type it can only have one lifetime, `'a` (there's nowhere for it to get another from).  | 
1385  |  | /// `Yoke`s can get additional lifetimes via the cart, and indeed, `project()` can operate on `Yoke<_, &'b [u8]>`,  | 
1386  |  | /// however this lifetime is inaccessible to the closure, and even if it were accessible the `for<'a>` would force  | 
1387  |  | /// it out of the output. All external lifetimes (from other found outside the yoke/closures  | 
1388  |  | /// are similarly constrained here.  | 
1389  |  | ///  | 
1390  |  | /// Essentially, safety is achieved by using `for<'a> fn(...)` with `'a` used in both `Yokeable`s to ensure that  | 
1391  |  | /// the output yokeable can _only_ have borrowed data flow in to it from the input. All paths of unsoundness require the  | 
1392  |  | /// unification of an existential and universal lifetime, which isn't possible.  | 
1393  |  | const _: () = ();  | 
1394  |  |  | 
1395  |  | /// # Safety docs for attach_to_cart()'s signature  | 
1396  |  | ///  | 
1397  |  | /// The `attach_to_cart()` family of methods get by by using the following bound:  | 
1398  |  | ///  | 
1399  |  | /// ```rust,ignore  | 
1400  |  | /// F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,  | 
1401  |  | /// C::Target: 'static  | 
1402  |  | /// ```  | 
1403  |  | ///  | 
1404  |  | /// to enforce that the yoking closure produces a yokeable that is *only* allowed to borrow from the cart.  | 
1405  |  | /// A way to be sure of this is as follows: imagine if `F` *did* borrow data of lifetime `'a` and stuff it in  | 
1406  |  | /// its output. Then that lifetime `'a` would have to live at least as long as `'de` *for all `'de`*.  | 
1407  |  | /// The only lifetime that satisfies that is `'static` (since at least one of the potential `'de`s is `'static`),  | 
1408  |  | /// and we're fine with that.  | 
1409  |  | ///  | 
1410  |  | /// ## Implied bounds and variance  | 
1411  |  | ///  | 
1412  |  | /// The `C::Target: 'static` bound is tricky, however. Let's imagine a situation where we *didn't* have that bound.  | 
1413  |  | ///  | 
1414  |  | /// One thing to remember is that we are okay with the cart itself borrowing from places,  | 
1415  |  | /// e.g. `&[u8]` is a valid cart, as is `Box<&[u8]>`. `C` is not `'static`.  | 
1416  |  | ///  | 
1417  |  | /// (I'm going to use `CT` in prose to refer to `C::Target` here, since almost everything here has to do  | 
1418  |  | /// with C::Target and not C itself.)  | 
1419  |  | ///  | 
1420  |  | /// Unfortunately, there's a sneaky additional bound inside `F`. The signature of `F` is *actually*  | 
1421  |  | ///  | 
1422  |  | /// ```rust,ignore  | 
1423  |  | /// F: for<'de> where<C::Target: 'de> FnOnce(&'de C::Target) -> <Y as Yokeable<'de>>::Output  | 
1424  |  | /// ```  | 
1425  |  | ///  | 
1426  |  | /// using made-up "where clause inside HRTB" syntax to represent a type that can be represented inside the compiler  | 
1427  |  | /// and type system but not in Rust code. The `CT: 'de` bond comes from the `&'de C::Target`: any time you  | 
1428  |  | /// write `&'a T`, an implied bound of `T: 'a` materializes and is stored alongside it, since references cannot refer  | 
1429  |  | /// to data that itself refers to data of shorter lifetimes. If a reference is valid, its referent must be valid for  | 
1430  |  | /// the duration of the reference's lifetime, so every reference *inside* its referent must also be valid, giving us `T: 'a`.  | 
1431  |  | /// This kind of constraint is often called a "well formedness" constraint: `&'a T` is not "well formed" without that  | 
1432  |  | /// bound, and rustc is being helpful by giving it to us for free.  | 
1433  |  | ///  | 
1434  |  | /// Unfortunately, this messes with our universal quantification. The `for<'de>` is no longer "For all lifetimes `'de`",  | 
1435  |  | /// it is "for all lifetimes `'de` *where `CT: 'de`*". And if `CT` borrows from somewhere (with lifetime `'ct`), then we get a  | 
1436  |  | /// `'ct: 'de` bound, and `'de` candidates that live longer than `'ct` won't actually be considered.  | 
1437  |  | /// The neat little logic at the beginning stops working.  | 
1438  |  | ///  | 
1439  |  | /// `attach_to_cart()` will instead enforce that the produced yokeable *either* borrows from the cart (fine), or from  | 
1440  |  | /// data that has a lifetime that is at least `'ct`. Which means that `attach_to_cart()` will allow us to borrow locals  | 
1441  |  | /// provided they live at least as long as `'ct`.  | 
1442  |  | ///  | 
1443  |  | /// Is this a problem?  | 
1444  |  | ///  | 
1445  |  | /// This is totally fine if CT's lifetime is covariant: if C is something like `Box<&'ct [u8]>`, even if our  | 
1446  |  | /// yoked object borrows from locals outliving `'ct`, our Yoke can't outlive that  | 
1447  |  | /// lifetime `'ct` anyway (since it's a part of the cart type), so we're fine.  | 
1448  |  | ///  | 
1449  |  | /// However it's completely broken for contravariant carts (e.g. `Box<fn(&'ct u8)>`). In that case  | 
1450  |  | /// we still get `'ct: 'de`, and we still end up being able to  | 
1451  |  | /// borrow from locals that outlive `'ct`. However, our Yoke _can_ outlive  | 
1452  |  | /// that lifetime, because Yoke shares its variance over `'ct`  | 
1453  |  | /// with the cart type, and the cart type is contravariant over `'ct`.  | 
1454  |  | /// So the Yoke can be upcast to having a longer lifetime than `'ct`, and *that* Yoke  | 
1455  |  | /// can outlive `'ct`.  | 
1456  |  | ///  | 
1457  |  | /// We fix this by forcing `C::Target: 'static` in `attach_to_cart()`, which would make it work  | 
1458  |  | /// for fewer types, but would also allow Yoke to continue to be covariant over cart lifetimes if necessary.  | 
1459  |  | ///  | 
1460  |  | /// An alternate fix would be to not allowing yoke to ever be upcast over lifetimes contained in the cart  | 
1461  |  | /// by forcing them to be invariant. This is a bit more restrictive and affects *all* `Yoke` users, not just  | 
1462  |  | /// those using `attach_to_cart()`.  | 
1463  |  | ///  | 
1464  |  | /// See https://github.com/unicode-org/icu4x/issues/2926  | 
1465  |  | /// See also https://github.com/rust-lang/rust/issues/106431 for potentially fixing this upstream by  | 
1466  |  | /// changing how the bound works.  | 
1467  |  | ///  | 
1468  |  | /// # Tests  | 
1469  |  | ///  | 
1470  |  | /// Here's a broken `attach_to_cart()` that attempts to borrow from a local:  | 
1471  |  | ///  | 
1472  |  | /// ```rust,compile_fail  | 
1473  |  | /// use yoke::Yoke;  | 
1474  |  | ///  | 
1475  |  | /// let cart = vec![1, 2, 3, 4].into_boxed_slice();  | 
1476  |  | /// let local = vec![4, 5, 6, 7];  | 
1477  |  | /// let yoke: Yoke<&[u8], Box<[u8]>> = Yoke::attach_to_cart(cart, |_| &*local);  | 
1478  |  | /// ```  | 
1479  |  | ///  | 
1480  |  | /// Fails as expected.  | 
1481  |  | ///  | 
1482  |  | /// And here's a working one with a local borrowed cart that does not do any sneaky borrows whilst attaching.  | 
1483  |  | ///  | 
1484  |  | /// ```rust  | 
1485  |  | /// use yoke::Yoke;  | 
1486  |  | ///  | 
1487  |  | /// let cart = vec![1, 2, 3, 4].into_boxed_slice();  | 
1488  |  | /// let local = vec![4, 5, 6, 7];  | 
1489  |  | /// let yoke: Yoke<&[u8], &[u8]> = Yoke::attach_to_cart(&cart, |c| &*c);  | 
1490  |  | /// ```  | 
1491  |  | ///  | 
1492  |  | /// Here's an `attach_to_cart()` that attempts to borrow from a longer-lived local due to  | 
1493  |  | /// the cart being covariant. It fails, but would not if the alternate fix of forcing Yoke to be invariant  | 
1494  |  | /// were implemented. It is technically a safe operation:  | 
1495  |  | ///  | 
1496  |  | /// ```rust,compile_fail  | 
1497  |  | /// use yoke::Yoke;  | 
1498  |  | /// // longer lived  | 
1499  |  | /// let local = vec![4, 5, 6, 7];  | 
1500  |  | ///  | 
1501  |  | /// let backing = vec![1, 2, 3, 4];  | 
1502  |  | /// let cart = Box::new(&*backing);  | 
1503  |  | ///  | 
1504  |  | /// let yoke: Yoke<&[u8], Box<&[u8]>> = Yoke::attach_to_cart(cart, |_| &*local);  | 
1505  |  | /// println!("{:?}", yoke.get()); | 
1506  |  | /// ```  | 
1507  |  | ///  | 
1508  |  | /// Finally, here's an `attach_to_cart()` that attempts to borrow from a longer lived local  | 
1509  |  | /// in the case of a contravariant lifetime. It does not compile, but in and of itself is not dangerous:  | 
1510  |  | ///  | 
1511  |  | /// ```rust,compile_fail  | 
1512  |  | /// use yoke::Yoke;  | 
1513  |  | ///  | 
1514  |  | /// type Contra<'a> = fn(&'a ());  | 
1515  |  | ///  | 
1516  |  | /// let local = String::from("Hello World!"); | 
1517  |  | /// let yoke: Yoke<&'static str, Box<Contra<'_>>> = Yoke::attach_to_cart(Box::new((|_| {}) as _), |_| &local[..]); | 
1518  |  | /// println!("{:?}", yoke.get()); | 
1519  |  | /// ```  | 
1520  |  | ///  | 
1521  |  | /// It is dangerous if allowed to transform (testcase from #2926)  | 
1522  |  | ///  | 
1523  |  | /// ```rust,compile_fail  | 
1524  |  | /// use yoke::Yoke;  | 
1525  |  | ///  | 
1526  |  | /// type Contra<'a> = fn(&'a ());  | 
1527  |  | ///  | 
1528  |  | ///  | 
1529  |  | /// let local = String::from("Hello World!"); | 
1530  |  | /// let yoke: Yoke<&'static str, Box<Contra<'_>>> = Yoke::attach_to_cart(Box::new((|_| {}) as _), |_| &local[..]); | 
1531  |  | /// println!("{:?}", yoke.get()); | 
1532  |  | /// let yoke_longer: Yoke<&'static str, Box<Contra<'static>>> = yoke;  | 
1533  |  | /// let leaked: &'static Yoke<&'static str, Box<Contra<'static>>> = Box::leak(Box::new(yoke_longer));  | 
1534  |  | /// let reference: &'static str = leaked.get();  | 
1535  |  | ///  | 
1536  |  | /// println!("pre-drop: {reference}"); | 
1537  |  | /// drop(local);  | 
1538  |  | /// println!("post-drop: {reference}"); | 
1539  |  | /// ```  | 
1540  |  | const _: () = ();  |