Skip to main content

yoke/
yoke.rs

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
5use crate::cartable_ptr::{CartableOptionPointer, CartablePointerLike};
6use crate::either::EitherCart;
7#[cfg(feature = "alloc")]
8use crate::erased::{ErasedArcCart, ErasedBoxCart, ErasedRcCart};
9use crate::kinda_sorta_dangling::KindaSortaDangling;
10use crate::utils;
11use crate::Yokeable;
12use core::marker::PhantomData;
13use core::mem::ManuallyDrop;
14use core::ops::Deref;
15use stable_deref_trait::StableDeref;
16
17#[cfg(feature = "alloc")]
18use alloc::boxed::Box;
19#[cfg(feature = "alloc")]
20use alloc::rc::Rc;
21#[cfg(feature = "alloc")]
22use alloc::sync::Arc;
23
24/// A Cow-like borrowed object "yoked" to its backing data.
25///
26/// This allows things like zero copy deserialized data to carry around
27/// shared references to their backing buffer, by "erasing" their static lifetime
28/// and turning it into a dynamically managed one.
29///
30/// `Y` (the [`Yokeable`]) is the object containing the references,
31/// and will typically be of the form `Foo<'static>`. The `'static` is
32/// not the actual lifetime of the data, rather it is a convenient way to mark the
33/// erased lifetime and make it dynamic.
34///
35/// `C` is the "cart", which `Y` may contain references to. After the yoke is constructed,
36/// the cart serves little purpose except to guarantee that `Y`'s references remain valid
37/// for as long as the yoke remains in memory (by calling the destructor at the appropriate moment).
38///
39/// The primary constructor for [`Yoke`] is [`Yoke::attach_to_cart()`]. Several variants of that
40/// constructor are provided to serve numerous types of call sites and `Yoke` signatures.
41///
42/// The key behind this type is [`Yoke::get()`], where calling [`.get()`][Yoke::get] on a type like
43/// `Yoke<Cow<'static, str>, _>` will get you a short-lived `&'a Cow<'a, str>`, restricted to the
44/// lifetime of the borrow used during `.get()`. This is entirely safe since the `Cow` borrows from
45/// the cart type `C`, which cannot be interfered with as long as the `Yoke` is borrowed by `.get
46/// ()`. `.get()` protects access by essentially reifying the erased lifetime to a safe local one
47/// when necessary.
48///
49/// Furthermore, there are various [`.map_project()`][Yoke::map_project] methods that allow turning a `Yoke`
50/// into another `Yoke` containing a different type that may contain elements of the original yoked
51/// value. See the [`Yoke::map_project()`] docs for more details.
52///
53/// In general, `C` is a concrete type, but it is also possible for it to be a trait object.
54///
55/// # Example
56///
57/// For example, we can use this to store zero-copy deserialized data in a cache:
58///
59/// ```rust
60/// # use yoke::Yoke;
61/// # use std::rc::Rc;
62/// # use std::borrow::Cow;
63/// # fn load_from_cache(_filename: &str) -> Rc<[u8]> {
64/// #     // dummy implementation
65/// #     Rc::new([0x5, 0, 0, 0, 0, 0, 0, 0, 0x68, 0x65, 0x6c, 0x6c, 0x6f])
66/// # }
67///
68/// fn load_object(filename: &str) -> Yoke<Cow<'static, str>, Rc<[u8]>> {
69///     let rc: Rc<[u8]> = load_from_cache(filename);
70///     Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| {
71///         // essentially forcing a #[serde(borrow)]
72///         Cow::Borrowed(bincode::deserialize(data).unwrap())
73///     })
74/// }
75///
76/// let yoke = load_object("filename.bincode");
77/// assert_eq!(&**yoke.get(), "hello");
78/// assert!(matches!(yoke.get(), &Cow::Borrowed(_)));
79/// ```
80pub struct Yoke<Y: for<'a> Yokeable<'a>, C> {
81    // must be the first field for drop order
82    // this will have a 'static lifetime parameter, that parameter is a lie
83    yokeable: KindaSortaDangling<Y>,
84    // Safety invariant: this type can be anything, but `yokeable` may only contain references to
85    // StableDeref parts of this cart, and the targets of those references must be valid for the
86    // lifetime of this cart (it must own or borrow them). It's ok for this cart to contain stack
87    // data as long as it is not referenced by `yokeable` during construction. `attach_to_cart`,
88    // the typical constructor of this type, upholds this invariant, but other constructors like
89    // `replace_cart` need to uphold it.
90    // The implementation guarantees that there are no live `yokeable`s that reference data
91    // in a `cart` when the `cart` is dropped; this is guaranteed in the drop glue through field
92    // order.
93    cart: C,
94}
95
96// Manual `Debug` implementation, since the derived one would be unsound.
97// See https://github.com/unicode-org/icu4x/issues/3685
98impl<Y: for<'a> Yokeable<'a>, C: core::fmt::Debug> core::fmt::Debug for Yoke<Y, C>
99where
100    for<'a> <Y as Yokeable<'a>>::Output: core::fmt::Debug,
101{
102    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
103        f.debug_struct("Yoke")
104            .field("yokeable", self.get())
105            .field("cart", self.backing_cart())
106            .finish()
107    }
108}
109
110impl<Y, C> core::fmt::Display for Yoke<Y, C>
111where
112    Y: for<'a> Yokeable<'a>,
113    for<'a> <Y as Yokeable<'a>>::Output: core::fmt::Display,
114{
115    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
116        core::fmt::Display::fmt(self.get(), f)
117    }
118}
119
120impl<Y, C> PartialEq for Yoke<Y, C>
121where
122    Y: for<'a> Yokeable<'a>,
123    for<'a> <Y as Yokeable<'a>>::Output: PartialEq,
124{
125    fn eq(&self, other: &Self) -> bool {
126        self.get() == other.get()
127    }
128}
129
130impl<Y, C> Eq for Yoke<Y, C>
131where
132    Y: for<'a> Yokeable<'a>,
133    for<'a> <Y as Yokeable<'a>>::Output: Eq,
134{
135}
136
137impl<Y, C> PartialOrd for Yoke<Y, C>
138where
139    Y: for<'a> Yokeable<'a>,
140    for<'a> <Y as Yokeable<'a>>::Output: PartialOrd,
141{
142    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
143        self.get().partial_cmp(other.get())
144    }
145}
146
147impl<Y, C> Ord for Yoke<Y, C>
148where
149    Y: for<'a> Yokeable<'a>,
150    for<'a> <Y as Yokeable<'a>>::Output: Ord,
151{
152    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
153        self.get().cmp(other.get())
154    }
155}
156
157impl<T: ?Sized, Y, C> AsRef<T> for Yoke<Y, C>
158where
159    Y: for<'a> Yokeable<'a>,
160    for<'a> <Y as Yokeable<'a>>::Output: AsRef<T>,
161{
162    fn as_ref(&self) -> &T {
163        self.get().as_ref()
164    }
165}
166
167#[test]
168fn test_debug() {
169    let local_data = "foo".to_owned();
170    let y1 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(
171        Rc::new(local_data),
172    );
173    assert_eq!(
174        format!("{y1:?}"),
175        r#"Yoke { yokeable: "foo", cart: "foo" }"#,
176    );
177}
178
179#[test]
180fn test_display() {
181    let local_data = "hello".to_owned();
182    let y = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(
183        Rc::new(local_data),
184    );
185    assert_eq!(format!("{}", y), "hello");
186}
187
188#[test]
189fn test_partialeq() {
190    let a = Rc::new("same".to_string());
191    let b = Rc::new("same".to_string());
192
193    let y1 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(a);
194    let y2 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(b);
195
196    assert_eq!(y1, y2);
197}
198
199#[test]
200fn test_eq_trait() {
201    let x = Rc::new("equal".to_string());
202    let y = Rc::new("equal".to_string());
203
204    let y1 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(x);
205    let y2 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(y);
206
207    assert!(y1 == y2);
208
209    let vec = [y1];
210    assert!(vec.contains(&y2));
211}
212
213#[test]
214fn test_partialord_ord() {
215    let a = Rc::new("a".to_string());
216    let b = Rc::new("b".to_string());
217
218    let y1 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(a);
219    let y2 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(b);
220
221    assert!(y1 < y2);
222    assert_eq!(y1.partial_cmp(&y2), Some(core::cmp::Ordering::Less));
223}
224
225#[test]
226fn test_as_ref() {
227    let a = Rc::new("hello".to_string());
228
229    let y1 = Yoke::<&str, Rc<String>>::attach_to_zero_copy_cart(Rc::clone(&a));
230    let y2 = Yoke::<alloc::borrow::Cow<'_, str>, Rc<String>>::attach_to_zero_copy_cart(a);
231    let y3 = Yoke::<Vec<u8>, ()>::new_always_owned(vec![1, 2, 3]);
232
233    assert_eq!(AsRef::<str>::as_ref(&y1), "hello");
234    assert_eq!(AsRef::<str>::as_ref(&y2), "hello");
235    assert_eq!(AsRef::<[u8]>::as_ref(&y3), [1, 2, 3]);
236}
237
238impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C>
239where
240    <C as Deref>::Target: 'static,
241{
242    /// Construct a [`Yoke`] by yokeing an object to a cart in a closure.
243    ///
244    /// The closure can read and write data outside of its scope, but data it returns
245    /// may borrow only from the argument passed to the closure.
246    ///
247    /// See also [`Yoke::try_attach_to_cart()`] to return a `Result` from the closure.
248    ///
249    /// Call sites for this function may not compile pre-1.61; if this still happens, use
250    /// [`Yoke::attach_to_cart_badly()`] and file a bug.
251    ///
252    /// # Examples
253    ///
254    /// ```
255    /// # use yoke::Yoke;
256    /// # use std::rc::Rc;
257    /// # use std::borrow::Cow;
258    /// # fn load_from_cache(_filename: &str) -> Rc<[u8]> {
259    /// #     // dummy implementation
260    /// #     Rc::new([0x5, 0, 0, 0, 0, 0, 0, 0, 0x68, 0x65, 0x6c, 0x6c, 0x6f])
261    /// # }
262    ///
263    /// fn load_object(filename: &str) -> Yoke<Cow<'static, str>, Rc<[u8]>> {
264    ///     let rc: Rc<[u8]> = load_from_cache(filename);
265    ///     Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| {
266    ///         // essentially forcing a #[serde(borrow)]
267    ///         Cow::Borrowed(bincode::deserialize(data).unwrap())
268    ///     })
269    /// }
270    ///
271    /// let yoke: Yoke<Cow<str>, _> = load_object("filename.bincode");
272    /// assert_eq!(&**yoke.get(), "hello");
273    /// assert!(matches!(yoke.get(), &Cow::Borrowed(_)));
274    /// ```
275    ///
276    /// Write the number of consumed bytes to a local variable:
277    ///
278    /// ```
279    /// # use yoke::Yoke;
280    /// # use std::rc::Rc;
281    /// # use std::borrow::Cow;
282    /// # fn load_from_cache(_filename: &str) -> Rc<[u8]> {
283    /// #     // dummy implementation
284    /// #     Rc::new([0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0, 0, 0])
285    /// # }
286    ///
287    /// fn load_object(
288    ///     filename: &str,
289    /// ) -> (Yoke<Cow<'static, str>, Rc<[u8]>>, usize) {
290    ///     let rc: Rc<[u8]> = load_from_cache(filename);
291    ///     let mut bytes_remaining = 0;
292    ///     let bytes_remaining = &mut bytes_remaining;
293    ///     let yoke = Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart(
294    ///         rc,
295    ///         |data: &[u8]| {
296    ///             let mut d = postcard::Deserializer::from_bytes(data);
297    ///             let output = serde::Deserialize::deserialize(&mut d);
298    ///             *bytes_remaining = d.finalize().unwrap().len();
299    ///             Cow::Borrowed(output.unwrap())
300    ///         },
301    ///     );
302    ///     (yoke, *bytes_remaining)
303    /// }
304    ///
305    /// let (yoke, bytes_remaining) = load_object("filename.postcard");
306    /// assert_eq!(&**yoke.get(), "hello");
307    /// assert!(matches!(yoke.get(), &Cow::Borrowed(_)));
308    /// assert_eq!(bytes_remaining, 3);
309    /// ```
310    pub fn attach_to_cart<F>(cart: C, f: F) -> Self
311    where
312        // safety note: This works by enforcing that the *only* place the return value of F
313        // can borrow from is the cart, since `F` must be valid for all lifetimes `'de`
314        //
315        // The <C as Deref>::Target: 'static on the impl is crucial for safety as well
316        //
317        // See safety docs at the bottom of this file for more information
318        F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,
319        <C as Deref>::Target: 'static,
320    {
321        let deserialized = f(cart.deref());
322        Self {
323            yokeable: KindaSortaDangling::new(
324                // Safety: the resulting `yokeable` is dropped before the `cart` because
325                // of the Yoke invariant. See the safety docs at the bottom of this file
326                // for the justification of why yokeable could only borrow from the Cart.
327                unsafe { Y::make(deserialized) },
328            ),
329            cart,
330        }
331    }
332
333    /// Construct a [`Yoke`] by yokeing an object to a cart. If an error occurs in the
334    /// deserializer function, the error is passed up to the caller.
335    ///
336    /// Call sites for this function may not compile pre-1.61; if this still happens, use
337    /// [`Yoke::try_attach_to_cart_badly()`] and file a bug.
338    pub fn try_attach_to_cart<E, F>(cart: C, f: F) -> Result<Self, E>
339    where
340        F: for<'de> FnOnce(&'de <C as Deref>::Target) -> Result<<Y as Yokeable<'de>>::Output, E>,
341        <C as Deref>::Target: 'static,
342    {
343        let deserialized = f(cart.deref())?;
344        Ok(Self {
345            yokeable: KindaSortaDangling::new(
346                // Safety: the resulting `yokeable` is dropped before the `cart` because
347                // of the Yoke invariant. See the safety docs at the bottom of this file
348                // for the justification of why yokeable could only borrow from the Cart.
349                unsafe { Y::make(deserialized) },
350            ),
351            cart,
352        })
353    }
354
355    /// Use [`Yoke::attach_to_cart()`].
356    ///
357    /// This was needed because the pre-1.61 compiler couldn't always handle the [`FnOnce`] trait bound.
358    #[deprecated]
359    pub fn attach_to_cart_badly(
360        cart: C,
361        f: for<'de> fn(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,
362    ) -> Self {
363        Self::attach_to_cart(cart, f)
364    }
365
366    /// Use [`Yoke::try_attach_to_cart()`].
367    ///
368    /// This was needed because the pre-1.61 compiler couldn't always handle the [`FnOnce`] trait bound.
369    #[deprecated]
370    pub fn try_attach_to_cart_badly<E>(
371        cart: C,
372        f: for<'de> fn(&'de <C as Deref>::Target) -> Result<<Y as Yokeable<'de>>::Output, E>,
373    ) -> Result<Self, E> {
374        Self::try_attach_to_cart(cart, f)
375    }
376}
377
378impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
379    /// Obtain a valid reference to the yokeable data
380    ///
381    /// This essentially transforms the lifetime of the internal yokeable data to
382    /// be valid.
383    /// For example, if you're working with a `Yoke<Cow<'static, T>, C>`, this
384    /// will return an `&'a Cow<'a, T>`
385    ///
386    /// # Example
387    ///
388    /// ```rust
389    /// # use yoke::Yoke;
390    /// # use std::rc::Rc;
391    /// # use std::borrow::Cow;
392    /// # fn load_from_cache(_filename: &str) -> Rc<[u8]> {
393    /// #     // dummy implementation
394    /// #     Rc::new([0x5, 0, 0, 0, 0, 0, 0, 0, 0x68, 0x65, 0x6c, 0x6c, 0x6f])
395    /// # }
396    /// #
397    /// # fn load_object(filename: &str) -> Yoke<Cow<'static, str>, Rc<[u8]>> {
398    /// #     let rc: Rc<[u8]> = load_from_cache(filename);
399    /// #     Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| {
400    /// #         Cow::Borrowed(bincode::deserialize(data).unwrap())
401    /// #     })
402    /// # }
403    ///
404    /// // load_object() defined in the example at the top of this page
405    /// let yoke: Yoke<Cow<str>, _> = load_object("filename.bincode");
406    /// assert_eq!(yoke.get(), "hello");
407    /// ```
408    #[inline]
409    pub fn get<'a>(&'a self) -> &'a <Y as Yokeable<'a>>::Output {
410        self.yokeable.transform()
411    }
412
413    /// Get a reference to the backing cart.
414    ///
415    /// This can be useful when building caches, etc. However, if you plan to store the cart
416    /// separately from the yoke, read the note of caution below in [`Yoke::into_backing_cart`].
417    pub fn backing_cart(&self) -> &C {
418        &self.cart
419    }
420
421    /// Get the backing cart by value, dropping the yokeable object.
422    ///
423    /// **Caution:** Calling this method could cause information saved in the yokeable object but
424    /// not the cart to be lost. Use this method only if the yokeable object cannot contain its
425    /// own information.
426    ///
427    /// # Example
428    ///
429    /// Good example: the yokeable object is only a reference, so no information can be lost.
430    ///
431    /// ```
432    /// use yoke::Yoke;
433    ///
434    /// let local_data = "foo".to_owned();
435    /// let yoke = Yoke::<&'static str, Box<String>>::attach_to_zero_copy_cart(
436    ///     Box::new(local_data),
437    /// );
438    /// assert_eq!(*yoke.get(), "foo");
439    ///
440    /// // Get back the cart
441    /// let cart = yoke.into_backing_cart();
442    /// assert_eq!(&*cart, "foo");
443    /// ```
444    ///
445    /// Bad example: information specified in `.with_mut()` is lost.
446    ///
447    /// ```
448    /// use std::borrow::Cow;
449    /// use yoke::Yoke;
450    ///
451    /// let local_data = "foo".to_owned();
452    /// let mut yoke =
453    ///     Yoke::<Cow<'static, str>, Box<String>>::attach_to_zero_copy_cart(
454    ///         Box::new(local_data),
455    ///     );
456    /// assert_eq!(yoke.get(), "foo");
457    ///
458    /// // Override data in the cart
459    /// yoke.with_mut(|cow| {
460    ///     let mut_str = cow.to_mut();
461    ///     mut_str.clear();
462    ///     mut_str.push_str("bar");
463    /// });
464    /// assert_eq!(yoke.get(), "bar");
465    ///
466    /// // Get back the cart
467    /// let cart = yoke.into_backing_cart();
468    /// assert_eq!(&*cart, "foo"); // WHOOPS!
469    /// ```
470    pub fn into_backing_cart(self) -> C {
471        self.cart
472    }
473
474    /// Unsafe function for replacing the cart with another
475    ///
476    /// This can be used for type-erasing the cart, for example.
477    ///
478    /// # Safety
479    ///
480    /// - References from the yokeable `Y` should still be valid for the lifetime of the
481    ///   returned cart type `C`.
482    ///
483    ///   For the purpose of determining this, `Yoke` guarantees that references from the Yokeable
484    ///   `Y` into the cart `C` will never be references into its stack data, only heap data protected
485    ///   by `StableDeref`. This does not necessarily mean that `C` implements `StableDeref`, rather that
486    ///   any data referenced by `Y` must be accessed through a `StableDeref` impl on something `C` owns.
487    ///
488    ///   Concretely, this means that if `C = Option<Rc<T>>`, `Y` may contain references to the `T` but not
489    ///   anything else.
490    /// - Lifetimes inside C must not be lengthened, even if they are themselves contravariant.
491    ///   I.e., if C contains an `fn(&'a u8)`, it cannot be replaced with `fn(&'static u8)`,
492    ///   even though that is typically safe.
493    ///
494    /// Note: `f` *is* allowed to panic.
495    ///
496    /// Typically, this means implementing `f` as something which _wraps_ the inner cart type `C`.
497    /// `Yoke` only really cares about destructors for its carts so it's fine to erase other
498    /// information about the cart, as long as the backing data will still be destroyed at the
499    /// same time.
500    #[inline]
501    pub unsafe fn replace_cart<C2>(self, f: impl FnOnce(C) -> C2) -> Yoke<Y, C2> {
502        let yokeable = ManuallyDrop::new(self.yokeable);
503        let cart = f(self.cart);
504        Yoke {
505            // Safety note: the safety invariant of this function guarantees that
506            // the data that the yokeable references has its ownership (if any)
507            // transferred to the new cart before self.cart is dropped, unless
508            // `f` panics, in which case the above `ManuallyDrop` ensures that
509            // the yokeable is leaked (preventing any UB from dropping the
510            // yokeable after its cart).
511            yokeable: ManuallyDrop::into_inner(yokeable),
512            cart,
513        }
514    }
515
516    /// Mutate the stored [`Yokeable`] data.
517    ///
518    /// If the callback needs to return `'static` data, then [`Yoke::with_mut_return`] can be
519    /// used until the next breaking release of `yoke`, at which time the callback to this
520    /// function will be able to return any `'static` data.
521    ///
522    /// See [`Yokeable::transform_mut()`] for why this operation is safe.
523    ///
524    /// # Example
525    ///
526    /// This can be used to partially mutate the stored data, provided
527    /// no _new_ borrowed data is introduced.
528    ///
529    /// ```rust
530    /// # use yoke::{Yoke, Yokeable};
531    /// # use std::rc::Rc;
532    /// # use std::borrow::Cow;
533    /// # use std::mem;
534    /// # fn load_from_cache(_filename: &str) -> Rc<[u8]> {
535    /// #     // dummy implementation
536    /// #     Rc::new([0x5, 0, 0, 0, 0, 0, 0, 0, 0x68, 0x65, 0x6c, 0x6c, 0x6f])
537    /// # }
538    /// #
539    /// # fn load_object(filename: &str) -> Yoke<Bar<'static>, Rc<[u8]>> {
540    /// #     let rc: Rc<[u8]> = load_from_cache(filename);
541    /// #     Yoke::<Bar<'static>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| {
542    /// #         // A real implementation would properly deserialize `Bar` as a whole
543    /// #         Bar {
544    /// #             numbers: Cow::Borrowed(bincode::deserialize(data).unwrap()),
545    /// #             string: Cow::Borrowed(bincode::deserialize(data).unwrap()),
546    /// #             owned: Vec::new(),
547    /// #         }
548    /// #     })
549    /// # }
550    ///
551    /// #[derive(Yokeable)]
552    /// struct Bar<'a> {
553    ///     numbers: Cow<'a, [u8]>,
554    ///     string: Cow<'a, str>,
555    ///     owned: Vec<u8>,
556    /// }
557    ///
558    /// // `load_object()` deserializes an object from a file
559    /// let mut bar: Yoke<Bar, _> = load_object("filename.bincode");
560    /// assert_eq!(bar.get().string, "hello");
561    /// assert!(matches!(bar.get().string, Cow::Borrowed(_)));
562    /// assert_eq!(&*bar.get().numbers, &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);
563    /// assert!(matches!(bar.get().numbers, Cow::Borrowed(_)));
564    /// assert_eq!(&*bar.get().owned, &[]);
565    ///
566    /// bar.with_mut(|bar| {
567    ///     bar.string.to_mut().push_str(" world");
568    ///     bar.owned.extend_from_slice(&[1, 4, 1, 5, 9]);
569    /// });
570    ///
571    /// assert_eq!(bar.get().string, "hello world");
572    /// assert!(matches!(bar.get().string, Cow::Owned(_)));
573    /// assert_eq!(&*bar.get().owned, &[1, 4, 1, 5, 9]);
574    /// // Unchanged and still Cow::Borrowed
575    /// assert_eq!(&*bar.get().numbers, &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);
576    /// assert!(matches!(bar.get().numbers, Cow::Borrowed(_)));
577    /// ```
578    pub fn with_mut<'a, F>(&'a mut self, f: F)
579    where
580        F: 'static + for<'b> FnOnce(&'b mut <Y as Yokeable<'a>>::Output),
581    {
582        self.yokeable.transform_mut(f);
583    }
584
585    /// Mutate the stored [`Yokeable`] data, and return `'static` data (possibly just `()`).
586    ///
587    /// See [`Yokeable::transform_mut()`] for why this operation is safe, noting that no
588    /// `'static`.
589    ///
590    /// ### Will be removed
591    /// This method will be removed on the next breaking release of `yoke`, when the callback of
592    /// [`Yoke::with_mut`] will gain the ability to return any `R: 'static` and supersede this
593    /// method.
594    pub fn with_mut_return<'a, F, R>(&'a mut self, f: F) -> R
595    where
596        F: 'static + for<'b> FnOnce(&'b mut <Y as Yokeable<'a>>::Output) -> R,
597        R: 'static,
598    {
599        utils::transform_mut_yokeable(&mut *self.yokeable, f)
600    }
601
602    /// Helper function allowing one to wrap the cart type `C` in an `Option<T>`.
603    #[inline]
604    pub fn wrap_cart_in_option(self) -> Yoke<Y, Option<C>> {
605        // Safety: the cart is preserved (since it is just wrapped into a Some),
606        // so any data it owns is too.
607        unsafe { self.replace_cart(Some) }
608    }
609}
610
611impl<Y: for<'a> Yokeable<'a>> Yoke<Y, ()> {
612    /// Construct a new [`Yoke`] from static data. There will be no
613    /// references to `cart` here since [`Yokeable`]s are `'static`,
614    /// this is good for e.g. constructing fully owned
615    /// [`Yoke`]s with no internal borrowing.
616    ///
617    /// This is similar to [`Yoke::new_owned()`] but it does not allow you to
618    /// mix the [`Yoke`] with borrowed data. This is primarily useful
619    /// for using [`Yoke`] in generic scenarios.
620    ///
621    /// # Example
622    ///
623    /// ```rust
624    /// # use yoke::Yoke;
625    /// # use std::borrow::Cow;
626    ///
627    /// let owned: Cow<str> = "hello".to_owned().into();
628    /// // this yoke can be intermingled with actually-borrowed Yokes
629    /// let yoke: Yoke<Cow<str>, ()> = Yoke::new_always_owned(owned);
630    ///
631    /// assert_eq!(yoke.get(), "hello");
632    /// ```
633    pub fn new_always_owned(yokeable: Y) -> Self {
634        Self {
635            // Safety note: this `yokeable` certainly does not reference data owned by (), so we do
636            // not have to worry about when the `yokeable` is dropped.
637            yokeable: KindaSortaDangling::new(yokeable),
638            cart: (),
639        }
640    }
641
642    /// Obtain the yokeable out of a `Yoke<Y, ()>`
643    ///
644    /// For most `Yoke` types this would be unsafe but it's
645    /// fine for `Yoke<Y, ()>` since there are no actual internal
646    /// references
647    pub fn into_yokeable(self) -> Y {
648        // Safety note: since `yokeable` cannot reference data owned by `()`, this is certainly
649        // safe.
650        self.yokeable.into_inner()
651    }
652}
653
654// C does not need to be StableDeref here, if the yoke was constructed it's valid,
655// and new_owned() doesn't construct a yokeable that uses references,
656impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, Option<C>> {
657    /// Construct a new [`Yoke`] from static data. There will be no
658    /// references to `cart` here since [`Yokeable`]s are `'static`,
659    /// this is good for e.g. constructing fully owned
660    /// [`Yoke`]s with no internal borrowing.
661    ///
662    /// This can be paired with [`Yoke:: wrap_cart_in_option()`] to mix owned
663    /// and borrowed data.
664    ///
665    /// If you do not wish to pair this with borrowed data, [`Yoke::new_always_owned()`] can
666    /// be used to get a [`Yoke`] API on always-owned data.
667    ///
668    /// # Example
669    ///
670    /// ```rust
671    /// # use yoke::Yoke;
672    /// # use std::borrow::Cow;
673    /// # use std::rc::Rc;
674    ///
675    /// let owned: Cow<str> = "hello".to_owned().into();
676    /// // this yoke can be intermingled with actually-borrowed Yokes
677    /// let yoke: Yoke<Cow<str>, Option<Rc<[u8]>>> = Yoke::new_owned(owned);
678    ///
679    /// assert_eq!(yoke.get(), "hello");
680    /// ```
681    pub const fn new_owned(yokeable: Y) -> Self {
682        Self {
683            // Safety note: this `yokeable` is known not to borrow from the cart.
684            yokeable: KindaSortaDangling::new(yokeable),
685            cart: None,
686        }
687    }
688
689    /// Obtain the yokeable out of a `Yoke<Y, Option<C>>` if possible.
690    ///
691    /// If the cart is `None`, this returns `Ok`, but if the cart is `Some`,
692    /// this returns `self` as an error.
693    pub fn try_into_yokeable(self) -> Result<Y, Self> {
694        // Safety: if the cart is None there is no way for the yokeable to
695        // have references into it because of the cart invariant.
696        match self.cart {
697            Some(_) => Err(self),
698            None => Ok(self.yokeable.into_inner()),
699        }
700    }
701}
702
703impl<Y: for<'a> Yokeable<'a>, C: CartablePointerLike> Yoke<Y, Option<C>> {
704    /// Converts a `Yoke<Y, Option<C>>` to `Yoke<Y, CartableOptionPointer<C>>`
705    /// for better niche optimization when stored as a field.
706    ///
707    /// # Examples
708    ///
709    /// ```
710    /// use std::borrow::Cow;
711    /// use yoke::Yoke;
712    ///
713    /// let yoke: Yoke<Cow<[u8]>, Box<Vec<u8>>> =
714    ///     Yoke::attach_to_cart(vec![10, 20, 30].into(), |c| c.into());
715    ///
716    /// let yoke_option = yoke.wrap_cart_in_option();
717    /// let yoke_option_pointer = yoke_option.convert_cart_into_option_pointer();
718    /// ```
719    ///
720    /// The niche improves stack sizes:
721    ///
722    /// ```
723    /// use yoke::Yoke;
724    /// use yoke::cartable_ptr::CartableOptionPointer;
725    /// use std::rc::Rc;
726    ///
727    /// // The data struct is 6 words:
728    /// # #[derive(yoke::Yokeable)]
729    /// # struct MyDataStruct<'a> {
730    /// #     _s: (usize, usize, usize, usize),
731    /// #     _p: &'a str,
732    /// # }
733    /// const W: usize = size_of::<usize>();
734    /// assert_eq!(W * 6, size_of::<MyDataStruct>());
735    ///
736    /// // An enum containing the data struct with an `Option<Rc>` cart is 8 words:
737    /// enum StaticOrYoke1 {
738    ///     Static(&'static MyDataStruct<'static>),
739    ///     Yoke(Yoke<MyDataStruct<'static>, Option<Rc<String>>>),
740    /// }
741    /// assert_eq!(W * 8, size_of::<StaticOrYoke1>());
742    ///
743    /// // When using `CartableOptionPointer``, we need only 7 words for the same behavior:
744    /// enum StaticOrYoke2 {
745    ///     Static(&'static MyDataStruct<'static>),
746    ///     Yoke(Yoke<MyDataStruct<'static>, CartableOptionPointer<Rc<String>>>),
747    /// }
748    /// assert_eq!(W * 7, size_of::<StaticOrYoke2>());
749    /// ```
750    #[inline]
751    pub fn convert_cart_into_option_pointer(self) -> Yoke<Y, CartableOptionPointer<C>> {
752        match self.cart {
753            Some(cart) => Yoke {
754                // Safety note: CartableOptionPointer::from_cartable only wraps the `cart`,
755                // so the data referenced by the yokeable is still live.
756                yokeable: self.yokeable,
757                cart: CartableOptionPointer::from_cartable(cart),
758            },
759            None => Yoke {
760                // Safety note: this Yokeable cannot refer to any data since self.cart is None.
761                yokeable: self.yokeable,
762                cart: CartableOptionPointer::none(),
763            },
764        }
765    }
766}
767
768impl<Y: for<'a> Yokeable<'a>, C: CartablePointerLike> Yoke<Y, CartableOptionPointer<C>> {
769    /// Obtain the yokeable out of a `Yoke<Y, CartableOptionPointer<C>>` if possible.
770    ///
771    /// If the cart is `None`, this returns `Ok`, but if the cart is `Some`,
772    /// this returns `self` as an error.
773    #[inline]
774    pub fn try_into_yokeable(self) -> Result<Y, Self> {
775        if self.cart.is_none() {
776            Ok(self.yokeable.into_inner())
777        } else {
778            Err(self)
779        }
780    }
781}
782
783/// This trait marks cart types that do not change source on cloning
784///
785/// This is conceptually similar to [`stable_deref_trait::CloneStableDeref`],
786/// however [`stable_deref_trait::CloneStableDeref`] is not (and should not) be
787/// implemented on [`Option`] (since it's not [`Deref`]). [`CloneableCart`] essentially is
788/// "if there _is_ data to borrow from here, cloning the cart gives you an additional
789/// handle to the same data".
790///
791/// # Safety
792/// This trait is safe to implement on `StableDeref` types which, once `Clone`d, point to the same underlying data and retain ownership.
793///
794/// This trait can also be implemented on aggregates of such types like `Option<T: CloneableCart>` and `(T: CloneableCart, U: CloneableCart)`.
795///
796/// Essentially, all data that could be referenced by a Yokeable (i.e. data that is referenced via a [`StableDeref`]) must retain the same
797/// pointer and ownership semantics once cloned.
798pub unsafe trait CloneableCart: Clone {}
799
800#[cfg(feature = "alloc")]
801// Safety: Rc<T> implements CloneStableDeref.
802unsafe impl<T: ?Sized> CloneableCart for Rc<T> {}
803#[cfg(feature = "alloc")]
804// Safety: Arc<T> implements CloneStableDeref.
805unsafe impl<T: ?Sized> CloneableCart for Arc<T> {}
806// Safety: Option<T> cannot deref to anything that T doesn't already deref to.
807unsafe impl<T: CloneableCart> CloneableCart for Option<T> {}
808// Safety: &'a T is indeed StableDeref, and cloning it refers to the same data.
809// &'a T does not own in the first place, so ownership is preserved.
810unsafe impl<'a, T: ?Sized> CloneableCart for &'a T {}
811// Safety: () cannot deref to anything.
812unsafe impl CloneableCart for () {}
813
814/// Clone requires that the cart type `C` derefs to the same address after it is cloned. This works for
815/// Rc, Arc, and &'a T.
816///
817/// For other cart types, clone `.backing_cart()` and re-use `.attach_to_cart()`; however, doing
818/// so may lose mutations performed via `.with_mut()`.
819///
820/// Cloning a `Yoke` is often a cheap operation requiring no heap allocations, in much the same
821/// way that cloning an `Rc` is a cheap operation. However, if the `yokeable` contains owned data
822/// (e.g., from `.with_mut()`), that data will need to be cloned.
823impl<Y: for<'a> Yokeable<'a>, C: CloneableCart> Clone for Yoke<Y, C>
824where
825    for<'a> <Y as Yokeable<'a>>::Output: Clone,
826{
827    fn clone(&self) -> Self {
828        // We have an &T not a T, and we can clone T
829        let this = self.get().clone();
830        Yoke {
831            yokeable: KindaSortaDangling::new(
832                // Safety: C being a CloneableCart guarantees that the data referenced by the
833                // `yokeable` is kept alive by the clone of the cart.
834                unsafe { Y::make(this) },
835            ),
836            cart: self.cart.clone(),
837        }
838    }
839}
840
841#[test]
842fn test_clone() {
843    let local_data = "foo".to_owned();
844    let y1 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(
845        Rc::new(local_data),
846    );
847
848    // Test basic clone
849    let y2 = y1.clone();
850    assert_eq!(y1.get(), "foo");
851    assert_eq!(y2.get(), "foo");
852
853    // Test clone with mutation on target
854    let mut y3 = y1.clone();
855    y3.with_mut(|y| {
856        y.to_mut().push_str("bar");
857    });
858    assert_eq!(y1.get(), "foo");
859    assert_eq!(y2.get(), "foo");
860    assert_eq!(y3.get(), "foobar");
861
862    // Test that mutations on source do not affect target
863    let y4 = y3.clone();
864    y3.with_mut(|y| {
865        y.to_mut().push_str("baz");
866    });
867    assert_eq!(y1.get(), "foo");
868    assert_eq!(y2.get(), "foo");
869    assert_eq!(y3.get(), "foobarbaz");
870    assert_eq!(y4.get(), "foobar");
871}
872
873impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
874    /// Allows one to "project" a yoke to perform a transformation on the data, potentially
875    /// looking at a subfield, and producing a new yoke. This will move cart, and the provided
876    /// transformation is only allowed to use data known to be borrowed from the cart.
877    ///
878    /// If producing the new [`Yokeable`] `P` requires access to the cart in addition to the old
879    /// `Y`, then [`Yoke::map_with_cart`] can be used if the cart satisfies additional constraints.
880    ///
881    /// The callback takes an additional `PhantomData<&()>` parameter to anchor lifetimes
882    /// (see [#86702](https://github.com/rust-lang/rust/issues/86702)) This parameter
883    /// should just be ignored in the callback.
884    ///
885    /// This can be used, for example, to transform data from one format to another:
886    ///
887    /// ```
888    /// # use std::rc::Rc;
889    /// # use yoke::Yoke;
890    /// #
891    /// fn slice(y: Yoke<&'static str, Rc<[u8]>>) -> Yoke<&'static [u8], Rc<[u8]>> {
892    ///     y.map_project(move |yk, _| yk.as_bytes())
893    /// }
894    /// ```
895    ///
896    /// This can also be used to create a yoke for a subfield
897    ///
898    /// ```
899    /// # use yoke::{Yoke, Yokeable};
900    /// # use std::mem;
901    /// # use std::rc::Rc;
902    /// #
903    /// // also safely implements Yokeable<'a>
904    /// struct Bar<'a> {
905    ///     string_1: &'a str,
906    ///     string_2: &'a str,
907    /// }
908    ///
909    /// fn map_project_string_1(
910    ///     bar: Yoke<Bar<'static>, Rc<[u8]>>,
911    /// ) -> Yoke<&'static str, Rc<[u8]>> {
912    ///     bar.map_project(|bar, _| bar.string_1)
913    /// }
914    ///
915    /// #
916    /// # unsafe impl<'a> Yokeable<'a> for Bar<'static> {
917    /// #     type Output = Bar<'a>;
918    /// #     fn transform(&'a self) -> &'a Bar<'a> {
919    /// #         self
920    /// #     }
921    /// #
922    /// #     fn transform_owned(self) -> Bar<'a> {
923    /// #         // covariant lifetime cast, can be done safely
924    /// #         self
925    /// #     }
926    /// #
927    /// #     unsafe fn make(from: Bar<'a>) -> Self {
928    /// #         unsafe { mem::transmute::<Self::Output, Self>(from) }
929    /// #     }
930    /// #
931    /// #     fn transform_mut<F>(&'a mut self, f: F)
932    /// #     where
933    /// #         F: 'static + FnOnce(&'a mut Self::Output),
934    /// #     {
935    /// #         unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
936    /// #     }
937    /// # }
938    /// ```
939    //
940    // Safety docs can be found at the end of the file.
941    pub fn map_project<P, F>(self, f: F) -> Yoke<P, C>
942    where
943        P: for<'a> Yokeable<'a>,
944        F: for<'a> FnOnce(
945            <Y as Yokeable<'a>>::Output,
946            PhantomData<&'a ()>,
947        ) -> <P as Yokeable<'a>>::Output,
948    {
949        let p = f(self.yokeable.into_inner().transform_owned(), PhantomData);
950        Yoke {
951            yokeable: KindaSortaDangling::new(
952                // Safety: the resulting `yokeable` is dropped before the `cart` because
953                // of the Yoke invariant. See the safety docs below for the justification of why
954                // yokeable could only borrow from the Cart.
955                unsafe { P::make(p) },
956            ),
957            cart: self.cart,
958        }
959    }
960
961    /// This is similar to [`Yoke::map_project`], however it does not move
962    /// [`Self`] and instead clones the cart (only if the cart is a [`CloneableCart`])
963    ///
964    /// This is a bit more efficient than cloning the [`Yoke`] and then calling [`Yoke::map_project`]
965    /// because then it will not clone fields that are going to be discarded.
966    pub fn map_project_cloned<'this, P, F>(&'this self, f: F) -> Yoke<P, C>
967    where
968        P: for<'a> Yokeable<'a>,
969        C: CloneableCart,
970        F: for<'a> FnOnce(
971            &'this <Y as Yokeable<'a>>::Output,
972            PhantomData<&'a ()>,
973        ) -> <P as Yokeable<'a>>::Output,
974    {
975        let p = f(self.get(), PhantomData);
976        Yoke {
977            yokeable: KindaSortaDangling::new(
978                // Safety: the resulting `yokeable` is dropped before the `cart` because
979                // of the Yoke invariant. See the safety docs below for the justification of why
980                // yokeable could only borrow from the Cart.
981                unsafe { P::make(p) },
982            ),
983            cart: self.cart.clone(),
984        }
985    }
986
987    /// This is similar to [`Yoke::map_project`], however it can also bubble up an error
988    /// from the callback.
989    ///
990    /// ```
991    /// # use std::rc::Rc;
992    /// # use yoke::Yoke;
993    /// # use std::str::{self, Utf8Error};
994    /// #
995    /// fn slice(
996    ///     y: Yoke<&'static [u8], Rc<[u8]>>,
997    /// ) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> {
998    ///     y.try_map_project(move |bytes, _| str::from_utf8(bytes))
999    /// }
1000    /// ```
1001    ///
1002    /// This can also be used to create a yoke for a subfield
1003    ///
1004    /// ```
1005    /// # use yoke::{Yoke, Yokeable};
1006    /// # use std::mem;
1007    /// # use std::rc::Rc;
1008    /// # use std::str::{self, Utf8Error};
1009    /// #
1010    /// // also safely implements Yokeable<'a>
1011    /// struct Bar<'a> {
1012    ///     bytes_1: &'a [u8],
1013    ///     string_2: &'a str,
1014    /// }
1015    ///
1016    /// fn map_project_string_1(
1017    ///     bar: Yoke<Bar<'static>, Rc<[u8]>>,
1018    /// ) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> {
1019    ///     bar.try_map_project(|bar, _| str::from_utf8(bar.bytes_1))
1020    /// }
1021    ///
1022    /// #
1023    /// # unsafe impl<'a> Yokeable<'a> for Bar<'static> {
1024    /// #     type Output = Bar<'a>;
1025    /// #     fn transform(&'a self) -> &'a Bar<'a> {
1026    /// #         self
1027    /// #     }
1028    /// #
1029    /// #     fn transform_owned(self) -> Bar<'a> {
1030    /// #         // covariant lifetime cast, can be done safely
1031    /// #         self
1032    /// #     }
1033    /// #
1034    /// #     unsafe fn make(from: Bar<'a>) -> Self {
1035    /// #         unsafe { mem::transmute::<Self::Output, Self>(from) }
1036    /// #     }
1037    /// #
1038    /// #     fn transform_mut<F>(&'a mut self, f: F)
1039    /// #     where
1040    /// #         F: 'static + FnOnce(&'a mut Self::Output),
1041    /// #     {
1042    /// #         unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
1043    /// #     }
1044    /// # }
1045    /// ```
1046    pub fn try_map_project<P, F, E>(self, f: F) -> Result<Yoke<P, C>, E>
1047    where
1048        P: for<'a> Yokeable<'a>,
1049        F: for<'a> FnOnce(
1050            <Y as Yokeable<'a>>::Output,
1051            PhantomData<&'a ()>,
1052        ) -> Result<<P as Yokeable<'a>>::Output, E>,
1053    {
1054        let p = f(self.yokeable.into_inner().transform_owned(), PhantomData)?;
1055        Ok(Yoke {
1056            yokeable: KindaSortaDangling::new(
1057                // Safety: the resulting `yokeable` is dropped before the `cart` because
1058                // of the Yoke invariant. See the safety docs below for the justification of why
1059                // yokeable could only borrow from the Cart.
1060                unsafe { P::make(p) },
1061            ),
1062            cart: self.cart,
1063        })
1064    }
1065
1066    /// This is similar to [`Yoke::try_map_project`], however it does not move
1067    /// [`Self`] and instead clones the cart (only if the cart is a [`CloneableCart`])
1068    ///
1069    /// This is a bit more efficient than cloning the [`Yoke`] and then calling [`Yoke::map_project`]
1070    /// because then it will not clone fields that are going to be discarded.
1071    pub fn try_map_project_cloned<'this, P, F, E>(&'this self, f: F) -> Result<Yoke<P, C>, E>
1072    where
1073        P: for<'a> Yokeable<'a>,
1074        C: CloneableCart,
1075        F: for<'a> FnOnce(
1076            &'this <Y as Yokeable<'a>>::Output,
1077            PhantomData<&'a ()>,
1078        ) -> Result<<P as Yokeable<'a>>::Output, E>,
1079    {
1080        let p = f(self.get(), PhantomData)?;
1081        Ok(Yoke {
1082            yokeable: KindaSortaDangling::new(
1083                // Safety: the resulting `yokeable` is dropped before the `cart` because
1084                // of the Yoke invariant. See the safety docs below for the justification of why
1085                // yokeable could only borrow from the Cart.
1086                unsafe { P::make(p) },
1087            ),
1088            cart: self.cart.clone(),
1089        })
1090    }
1091    /// This is similar to [`Yoke::map_project`], but it works around older versions
1092    /// of Rust not being able to use `FnOnce` by using an explicit capture input.
1093    /// See [#1061](https://github.com/unicode-org/icu4x/issues/1061).
1094    ///
1095    /// See the docs of [`Yoke::map_project`] for how this works.
1096    pub fn map_project_with_explicit_capture<P, T>(
1097        self,
1098        capture: T,
1099        f: for<'a> fn(
1100            <Y as Yokeable<'a>>::Output,
1101            capture: T,
1102            PhantomData<&'a ()>,
1103        ) -> <P as Yokeable<'a>>::Output,
1104    ) -> Yoke<P, C>
1105    where
1106        P: for<'a> Yokeable<'a>,
1107    {
1108        let p = f(
1109            self.yokeable.into_inner().transform_owned(),
1110            capture,
1111            PhantomData,
1112        );
1113        Yoke {
1114            yokeable: KindaSortaDangling::new(
1115                // Safety: the resulting `yokeable` is dropped before the `cart` because
1116                // of the Yoke invariant. See the safety docs below for the justification of why
1117                // yokeable could only borrow from the Cart.
1118                unsafe { P::make(p) },
1119            ),
1120            cart: self.cart,
1121        }
1122    }
1123
1124    /// This is similar to [`Yoke::map_project_cloned`], but it works around older versions
1125    /// of Rust not being able to use `FnOnce` by using an explicit capture input.
1126    /// See [#1061](https://github.com/unicode-org/icu4x/issues/1061).
1127    ///
1128    /// See the docs of [`Yoke::map_project_cloned`] for how this works.
1129    pub fn map_project_cloned_with_explicit_capture<'this, P, T>(
1130        &'this self,
1131        capture: T,
1132        f: for<'a> fn(
1133            &'this <Y as Yokeable<'a>>::Output,
1134            capture: T,
1135            PhantomData<&'a ()>,
1136        ) -> <P as Yokeable<'a>>::Output,
1137    ) -> Yoke<P, C>
1138    where
1139        P: for<'a> Yokeable<'a>,
1140        C: CloneableCart,
1141    {
1142        let p = f(self.get(), capture, PhantomData);
1143        Yoke {
1144            yokeable: KindaSortaDangling::new(
1145                // Safety: the resulting `yokeable` is dropped before the `cart` because
1146                // of the Yoke invariant. See the safety docs below for the justification of why
1147                // yokeable could only borrow from the Cart.
1148                unsafe { P::make(p) },
1149            ),
1150            cart: self.cart.clone(),
1151        }
1152    }
1153
1154    /// This is similar to [`Yoke::try_map_project`], but it works around older versions
1155    /// of Rust not being able to use `FnOnce` by using an explicit capture input.
1156    /// See [#1061](https://github.com/unicode-org/icu4x/issues/1061).
1157    ///
1158    /// See the docs of [`Yoke::try_map_project`] for how this works.
1159    #[expect(clippy::type_complexity)]
1160    pub fn try_map_project_with_explicit_capture<P, T, E>(
1161        self,
1162        capture: T,
1163        f: for<'a> fn(
1164            <Y as Yokeable<'a>>::Output,
1165            capture: T,
1166            PhantomData<&'a ()>,
1167        ) -> Result<<P as Yokeable<'a>>::Output, E>,
1168    ) -> Result<Yoke<P, C>, E>
1169    where
1170        P: for<'a> Yokeable<'a>,
1171    {
1172        let p = f(
1173            self.yokeable.into_inner().transform_owned(),
1174            capture,
1175            PhantomData,
1176        )?;
1177        Ok(Yoke {
1178            yokeable: KindaSortaDangling::new(
1179                // Safety: the resulting `yokeable` is dropped before the `cart` because
1180                // of the Yoke invariant. See the safety docs below for the justification of why
1181                // yokeable could only borrow from the Cart.
1182                unsafe { P::make(p) },
1183            ),
1184            cart: self.cart,
1185        })
1186    }
1187
1188    /// This is similar to [`Yoke::try_map_project_cloned`], but it works around older versions
1189    /// of Rust not being able to use `FnOnce` by using an explicit capture input.
1190    /// See [#1061](https://github.com/unicode-org/icu4x/issues/1061).
1191    ///
1192    /// See the docs of [`Yoke::try_map_project_cloned`] for how this works.
1193    #[expect(clippy::type_complexity)]
1194    pub fn try_map_project_cloned_with_explicit_capture<'this, P, T, E>(
1195        &'this self,
1196        capture: T,
1197        f: for<'a> fn(
1198            &'this <Y as Yokeable<'a>>::Output,
1199            capture: T,
1200            PhantomData<&'a ()>,
1201        ) -> Result<<P as Yokeable<'a>>::Output, E>,
1202    ) -> Result<Yoke<P, C>, E>
1203    where
1204        P: for<'a> Yokeable<'a>,
1205        C: CloneableCart,
1206    {
1207        let p = f(self.get(), capture, PhantomData)?;
1208        Ok(Yoke {
1209            yokeable: KindaSortaDangling::new(
1210                // Safety: the resulting `yokeable` is dropped before the `cart` because
1211                // of the Yoke invariant. See the safety docs below for the justification of why
1212                // yokeable could only borrow from the Cart.
1213                unsafe { P::make(p) },
1214            ),
1215            cart: self.cart.clone(),
1216        })
1217    }
1218}
1219
1220impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C>
1221where
1222    <C as Deref>::Target: 'static,
1223{
1224    /// Allows one to produce a new yoke from both the cart and the old yoke. This will move the
1225    /// cart, and the provided transformation is only allowed to use data known to be borrowed from
1226    /// the cart.
1227    ///
1228    /// If access to the old [`Yokeable`] `Y` is sufficient to produce the new [`Yokeable`] `P`,
1229    /// then [`Yoke::map_project`] should be preferred, as `map_with_cart` places additional
1230    /// constraints on the cart.
1231    ///
1232    /// This can be used, for example, to transform data between two formats, one of which contains
1233    /// more data:
1234    ///
1235    /// ```
1236    /// # use yoke::{Yoke, Yokeable};
1237    /// # use std::mem;
1238    /// # use std::rc::Rc;
1239    /// #
1240    /// // Both structs have `first_line`, which won't need to be recomputed in `map_with_cart`.
1241    /// // They also safely implement `Yokeable<'a>`
1242    /// struct Foo<'a> {
1243    ///     first_line: Option<&'a str>,
1244    /// }
1245    /// struct Bar<'a> {
1246    ///     first_line: Option<&'a str>,
1247    ///     last_line: Option<&'a str>,
1248    /// }
1249    ///
1250    /// fn foo_to_bar(
1251    ///     foo: Yoke<Foo<'static>, Rc<str>>,
1252    /// ) -> Yoke<Bar<'static>, Rc<str>> {
1253    ///     foo.map_with_cart(|foo, cart| {
1254    ///         Bar {
1255    ///             first_line: foo.first_line,
1256    ///             last_line: cart.lines().next_back(),
1257    ///         }
1258    ///     })
1259    /// }
1260    ///
1261    /// fn bar_to_foo(
1262    ///     bar: Yoke<Bar<'static>, Rc<str>>,
1263    /// ) -> Yoke<Foo<'static>, Rc<str>> {
1264    ///     bar.map_project(|bar, _| {
1265    ///         Foo {
1266    ///             first_line: bar.first_line,
1267    ///         }
1268    ///     })
1269    /// }
1270    ///
1271    /// #
1272    /// # unsafe impl<'a> Yokeable<'a> for Foo<'static> {
1273    /// #     type Output = Foo<'a>;
1274    /// #     fn transform(&'a self) -> &'a Foo<'a> {
1275    /// #         self
1276    /// #     }
1277    /// #
1278    /// #     fn transform_owned(self) -> Foo<'a> {
1279    /// #         // covariant lifetime cast, can be done safely
1280    /// #         self
1281    /// #     }
1282    /// #
1283    /// #     unsafe fn make(from: Foo<'a>) -> Self {
1284    /// #         unsafe { mem::transmute::<Self::Output, Self>(from) }
1285    /// #     }
1286    /// #
1287    /// #     fn transform_mut<F>(&'a mut self, f: F)
1288    /// #     where
1289    /// #         F: 'static + FnOnce(&'a mut Self::Output),
1290    /// #     {
1291    /// #         unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
1292    /// #     }
1293    /// # }
1294    /// #
1295    /// # unsafe impl<'a> Yokeable<'a> for Bar<'static> {
1296    /// #     type Output = Bar<'a>;
1297    /// #     fn transform(&'a self) -> &'a Bar<'a> {
1298    /// #         self
1299    /// #     }
1300    /// #
1301    /// #     fn transform_owned(self) -> Bar<'a> {
1302    /// #         // covariant lifetime cast, can be done safely
1303    /// #         self
1304    /// #     }
1305    /// #
1306    /// #     unsafe fn make(from: Bar<'a>) -> Self {
1307    /// #         unsafe { mem::transmute::<Self::Output, Self>(from) }
1308    /// #     }
1309    /// #
1310    /// #     fn transform_mut<F>(&'a mut self, f: F)
1311    /// #     where
1312    /// #         F: 'static + FnOnce(&'a mut Self::Output),
1313    /// #     {
1314    /// #         unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
1315    /// #     }
1316    /// # }
1317    /// ```
1318    //
1319    // Safety docs can be found at the end of the file.
1320    pub fn map_with_cart<P, F>(self, f: F) -> Yoke<P, C>
1321    where
1322        P: for<'a> Yokeable<'a>,
1323        F: for<'a> FnOnce(
1324            <Y as Yokeable<'a>>::Output,
1325            &'a <C as Deref>::Target,
1326        ) -> <P as Yokeable<'a>>::Output,
1327        <C as Deref>::Target: 'static,
1328    {
1329        let p = f(
1330            self.yokeable.into_inner().transform_owned(),
1331            self.cart.deref(),
1332        );
1333        Yoke {
1334            yokeable: KindaSortaDangling::new(
1335                // Safety: the resulting `yokeable` is dropped before the `cart` because
1336                // of the Yoke invariant. See the safety docs below for the justification of why
1337                // yokeable could only borrow from the Cart.
1338                unsafe { P::make(p) },
1339            ),
1340            cart: self.cart,
1341        }
1342    }
1343
1344    /// This is similar to [`Yoke::map_with_cart`], but it does not move [`Self`] and instead
1345    /// clones the cart (only if the cart is a [`CloneableCart`]).
1346    ///
1347    /// This is a bit more efficient than cloning the [`Yoke`] and then calling
1348    /// [`Yoke::map_with_cart`] because it will not clone fields that are going to be discarded.
1349    ///
1350    /// If access to the old [`Yokeable`] `Y` is sufficient to produce the new [`Yokeable`] `P`,
1351    /// then [`Yoke::map_project_cloned`] should be preferred, as `map_with_cart_cloned` places
1352    /// additional constraints on the cart.
1353    pub fn map_with_cart_cloned<'this, P, F>(&'this self, f: F) -> Yoke<P, C>
1354    where
1355        P: for<'a> Yokeable<'a>,
1356        F: for<'a> FnOnce(
1357            &'this <Y as Yokeable<'a>>::Output,
1358            &'a <C as Deref>::Target,
1359        ) -> <P as Yokeable<'a>>::Output,
1360        C: CloneableCart,
1361        <C as Deref>::Target: 'static,
1362    {
1363        let p = f(self.get(), self.cart.deref());
1364        Yoke {
1365            yokeable: KindaSortaDangling::new(
1366                // Safety: the resulting `yokeable` is dropped before the `cart` because
1367                // of the Yoke invariant. See the safety docs below for the justification of why
1368                // yokeable could only borrow from the Cart.
1369                unsafe { P::make(p) },
1370            ),
1371            cart: self.cart.clone(),
1372        }
1373    }
1374
1375    /// This is similar to [`Yoke::map_with_cart`], but it can also bubble up an error
1376    /// from the callback.
1377    ///
1378    /// If access to the old [`Yokeable`] `Y` is sufficient to produce the new [`Yokeable`] `P`,
1379    /// then [`Yoke::try_map_project`] should be preferred, as `try_map_with_cart` places
1380    /// additional constraints on the cart.
1381    ///
1382    /// ```
1383    /// # use std::rc::Rc;
1384    /// # use yoke::Yoke;
1385    /// # use std::str::{self, Utf8Error};
1386    /// #
1387    /// // Implements `Yokeable`
1388    /// type P<'a> = (&'a str, Option<&'a u8>);
1389    ///
1390    /// fn slice(
1391    ///     y: Yoke<&'static [u8], Rc<[u8]>>,
1392    /// ) -> Result<Yoke<P<'static>, Rc<[u8]>>, Utf8Error> {
1393    ///     y.try_map_with_cart(move |bytes, cart| {
1394    ///         Ok((str::from_utf8(bytes)?, bytes.first()))
1395    ///     })
1396    /// }
1397    /// ```
1398    pub fn try_map_with_cart<P, F, E>(self, f: F) -> Result<Yoke<P, C>, E>
1399    where
1400        P: for<'a> Yokeable<'a>,
1401        F: for<'a> FnOnce(
1402            <Y as Yokeable<'a>>::Output,
1403            &'a <C as Deref>::Target,
1404        ) -> Result<<P as Yokeable<'a>>::Output, E>,
1405        <C as Deref>::Target: 'static,
1406    {
1407        let p = f(
1408            self.yokeable.into_inner().transform_owned(),
1409            self.cart.deref(),
1410        )?;
1411        Ok(Yoke {
1412            yokeable: KindaSortaDangling::new(
1413                // Safety: the resulting `yokeable` is dropped before the `cart` because
1414                // of the Yoke invariant. See the safety docs below for the justification of why
1415                // yokeable could only borrow from the Cart.
1416                unsafe { P::make(p) },
1417            ),
1418            cart: self.cart,
1419        })
1420    }
1421
1422    /// This is similar to [`Yoke::try_map_with_cart`], but it does not move [`Self`] and instead
1423    /// clones the cart (only if the cart is a [`CloneableCart`]).
1424    ///
1425    /// This is a bit more efficient than cloning the [`Yoke`] and then calling
1426    /// [`Yoke::try_map_with_cart`] because it will not clone fields that are going to be discarded.
1427    ///
1428    /// If access to the old [`Yokeable`] `Y` is sufficient to producethe new [`Yokeable`] `P`,
1429    /// then [`Yoke::try_map_project_cloned`] should be preferred, as `try_map_with_cart_cloned`
1430    /// places additional constraints on the cart.
1431    pub fn try_map_with_cart_cloned<'this, P, F, E>(&'this self, f: F) -> Result<Yoke<P, C>, E>
1432    where
1433        P: for<'a> Yokeable<'a>,
1434        C: CloneableCart,
1435        F: for<'a> FnOnce(
1436            &'this <Y as Yokeable<'a>>::Output,
1437            &'a <C as Deref>::Target,
1438        ) -> Result<<P as Yokeable<'a>>::Output, E>,
1439        <C as Deref>::Target: 'static,
1440    {
1441        let p = f(self.get(), self.cart.deref())?;
1442        Ok(Yoke {
1443            yokeable: KindaSortaDangling::new(
1444                // Safety: the resulting `yokeable` is dropped before the `cart` because
1445                // of the Yoke invariant. See the safety docs below for the justification of why
1446                // yokeable could only borrow from the Cart.
1447                unsafe { P::make(p) },
1448            ),
1449            cart: self.cart.clone(),
1450        })
1451    }
1452}
1453
1454#[cfg(feature = "alloc")]
1455impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized> Yoke<Y, Rc<C>> {
1456    /// Allows type-erasing the cart in a `Yoke<Y, Rc<C>>`.
1457    ///
1458    /// The yoke only carries around a cart type `C` for its destructor,
1459    /// since it needs to be able to guarantee that its internal references
1460    /// are valid for the lifetime of the Yoke. As such, the actual type of the
1461    /// Cart is not very useful unless you wish to extract data out of it
1462    /// via [`Yoke::backing_cart()`]. Erasing the cart allows for one to mix
1463    /// [`Yoke`]s obtained from different sources.
1464    ///
1465    /// In case the cart type `C` is not already an `Rc<T>`, you can use
1466    /// [`Yoke::wrap_cart_in_rc()`] to wrap it.
1467    ///
1468    /// ✨ *Enabled with the `alloc` Cargo feature.*
1469    ///
1470    /// # Example
1471    ///
1472    /// ```rust
1473    /// use std::rc::Rc;
1474    /// use yoke::erased::ErasedRcCart;
1475    /// use yoke::Yoke;
1476    ///
1477    /// let buffer1: Rc<String> = Rc::new("   foo bar baz  ".into());
1478    /// let buffer2: Box<String> = Box::new("  baz quux  ".into());
1479    ///
1480    /// let yoke1 =
1481    ///     Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());
1482    /// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());
1483    ///
1484    /// let erased1: Yoke<_, ErasedRcCart> = yoke1.erase_rc_cart();
1485    /// // Wrap the Box in an Rc to make it compatible
1486    /// let erased2: Yoke<_, ErasedRcCart> =
1487    ///     yoke2.wrap_cart_in_rc().erase_rc_cart();
1488    ///
1489    /// // Now erased1 and erased2 have the same type!
1490    /// ```
1491    pub fn erase_rc_cart(self) -> Yoke<Y, ErasedRcCart> {
1492        // Safety: safe because the cart is preserved, as it is just type-erased
1493        unsafe { self.replace_cart(|c| c as ErasedRcCart) }
1494    }
1495}
1496
1497#[cfg(feature = "alloc")]
1498impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized + Send + Sync> Yoke<Y, Arc<C>> {
1499    /// Allows type-erasing the cart in a `Yoke<Y, Arc<C>>`.
1500    ///
1501    /// The yoke only carries around a cart type `C` for its destructor,
1502    /// since it needs to be able to guarantee that its internal references
1503    /// are valid for the lifetime of the Yoke. As such, the actual type of the
1504    /// Cart is not very useful unless you wish to extract data out of it
1505    /// via [`Yoke::backing_cart()`]. Erasing the cart allows for one to mix
1506    /// [`Yoke`]s obtained from different sources.
1507    ///
1508    /// In case the cart type `C` is not already an `Arc<T>`, you can use
1509    /// [`Yoke::wrap_cart_in_arc()`] to wrap it.
1510    ///
1511    /// ✨ *Enabled with the `alloc` Cargo feature.*
1512    ///
1513    /// # Example
1514    ///
1515    /// ```rust
1516    /// use std::sync::Arc;
1517    /// use yoke::erased::ErasedArcCart;
1518    /// use yoke::Yoke;
1519    ///
1520    /// let buffer1: Arc<String> = Arc::new("   foo bar baz  ".into());
1521    /// let buffer2: Box<String> = Box::new("  baz quux  ".into());
1522    ///
1523    /// let yoke1 =
1524    ///     Yoke::<&'static str, _>::attach_to_cart(buffer1, |arc| arc.trim());
1525    /// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());
1526    ///
1527    /// let erased1: Yoke<_, ErasedArcCart> = yoke1.erase_arc_cart();
1528    /// // Wrap the Box in an Rc to make it compatible
1529    /// let erased2: Yoke<_, ErasedArcCart> =
1530    ///     yoke2.wrap_cart_in_arc().erase_arc_cart();
1531    ///
1532    /// // Now erased1 and erased2 have the same type!
1533    /// ```
1534    pub fn erase_arc_cart(self) -> Yoke<Y, ErasedArcCart> {
1535        // Safety: safe because the cart is preserved, as it is just type-erased
1536        unsafe { self.replace_cart(|c| c as ErasedArcCart) }
1537    }
1538}
1539
1540#[cfg(feature = "alloc")]
1541impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized> Yoke<Y, Box<C>> {
1542    /// Allows type-erasing the cart in a `Yoke<Y, Box<C>>`.
1543    ///
1544    /// The yoke only carries around a cart type `C` for its destructor,
1545    /// since it needs to be able to guarantee that its internal references
1546    /// are valid for the lifetime of the Yoke. As such, the actual type of the
1547    /// Cart is not very useful unless you wish to extract data out of it
1548    /// via [`Yoke::backing_cart()`]. Erasing the cart allows for one to mix
1549    /// [`Yoke`]s obtained from different sources.
1550    ///
1551    /// In case the cart type `C` is not already `Box<T>`, you can use
1552    /// [`Yoke::wrap_cart_in_box()`] to wrap it.
1553    ///
1554    /// ✨ *Enabled with the `alloc` Cargo feature.*
1555    ///
1556    /// # Example
1557    ///
1558    /// ```rust
1559    /// use std::rc::Rc;
1560    /// use yoke::erased::ErasedBoxCart;
1561    /// use yoke::Yoke;
1562    ///
1563    /// let buffer1: Rc<String> = Rc::new("   foo bar baz  ".into());
1564    /// let buffer2: Box<String> = Box::new("  baz quux  ".into());
1565    ///
1566    /// let yoke1 =
1567    ///     Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());
1568    /// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());
1569    ///
1570    /// // Wrap the Rc in an Box to make it compatible
1571    /// let erased1: Yoke<_, ErasedBoxCart> =
1572    ///     yoke1.wrap_cart_in_box().erase_box_cart();
1573    /// let erased2: Yoke<_, ErasedBoxCart> = yoke2.erase_box_cart();
1574    ///
1575    /// // Now erased1 and erased2 have the same type!
1576    /// ```
1577    pub fn erase_box_cart(self) -> Yoke<Y, ErasedBoxCart> {
1578        // Safety: safe because the cart is preserved, as it is just type-erased
1579        unsafe { self.replace_cart(|c| c as ErasedBoxCart) }
1580    }
1581}
1582
1583#[cfg(feature = "alloc")]
1584impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
1585    /// Helper function allowing one to wrap the cart type `C` in a `Box<T>`.
1586    /// Can be paired with [`Yoke::erase_box_cart()`]
1587    ///
1588    /// ✨ *Enabled with the `alloc` Cargo feature.*
1589    #[inline]
1590    pub fn wrap_cart_in_box(self) -> Yoke<Y, Box<C>> {
1591        // Safety: safe because the cart is preserved, as it is just wrapped.
1592        // `replace_cart()` explicitly allows panics.
1593        unsafe { self.replace_cart(Box::new) }
1594    }
1595    /// Helper function allowing one to wrap the cart type `C` in an `Rc<T>`.
1596    /// Can be paired with [`Yoke::erase_rc_cart()`], or generally used
1597    /// to make the [`Yoke`] cloneable.
1598    ///
1599    /// ✨ *Enabled with the `alloc` Cargo feature.*
1600    #[inline]
1601    pub fn wrap_cart_in_rc(self) -> Yoke<Y, Rc<C>> {
1602        // Safety: safe because the cart is preserved, as it is just wrapped.
1603        // `replace_cart()` explicitly allows panics.
1604        unsafe { self.replace_cart(Rc::new) }
1605    }
1606    /// Helper function allowing one to wrap the cart type `C` in an `Arc<T>`.
1607    /// Can be paired with [`Yoke::erase_arc_cart()`], or generally used
1608    /// to make the [`Yoke`] cloneable.
1609    ///
1610    /// ✨ *Enabled with the `alloc` Cargo feature.*
1611    #[inline]
1612    pub fn wrap_cart_in_arc(self) -> Yoke<Y, Arc<C>> {
1613        // Safety: safe because the cart is preserved, as it is just wrapped.
1614        // `replace_cart()` explicitly allows panics.
1615        unsafe { self.replace_cart(Arc::new) }
1616    }
1617}
1618
1619impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
1620    /// Helper function allowing one to wrap the cart type `C` in an [`EitherCart`].
1621    ///
1622    /// This function wraps the cart into the `A` variant. To wrap it into the
1623    /// `B` variant, use [`Self::wrap_cart_in_either_b()`].
1624    ///
1625    /// For an example, see [`EitherCart`].
1626    #[inline]
1627    pub fn wrap_cart_in_either_a<B>(self) -> Yoke<Y, EitherCart<C, B>> {
1628        // Safety: safe because the cart is preserved, as it is just wrapped.
1629        unsafe { self.replace_cart(EitherCart::A) }
1630    }
1631    /// Helper function allowing one to wrap the cart type `C` in an [`EitherCart`].
1632    ///
1633    /// This function wraps the cart into the `B` variant. To wrap it into the
1634    /// `A` variant, use [`Self::wrap_cart_in_either_a()`].
1635    ///
1636    /// For an example, see [`EitherCart`].
1637    #[inline]
1638    pub fn wrap_cart_in_either_b<A>(self) -> Yoke<Y, EitherCart<A, C>> {
1639        // Safety: safe because the cart is preserved, as it is just wrapped.
1640        unsafe { self.replace_cart(EitherCart::B) }
1641    }
1642}
1643
1644/// # Safety docs for `*map_project*()`
1645///
1646/// (Docs are on a private const to allow the use of `compile_fail` doctests)
1647///
1648/// This is safe to perform because of the choice of lifetimes on `f`, that is,
1649/// `for<a> fn(<Y as Yokeable<'a>>::Output, &'a ()) -> <P as Yokeable<'a>>::Output`.
1650///
1651/// Note that correctness arguments are similar if you replace `fn` with `FnOnce`.
1652///
1653/// What we want this function to do is take a Yokeable (`Y`) that is borrowing from the cart, and
1654/// produce another Yokeable (`P`) that also borrows from the same cart. There are a couple potential
1655/// hazards here:
1656///
1657/// - `P` ends up borrowing data from `Y` (or elsewhere) that did _not_ come from the cart,
1658///   for example `P` could borrow owned data from a `Cow`. This would make the `Yoke<P>` dependent
1659///   on data owned only by the `Yoke<Y>`.
1660/// - Borrowed data from `Y` escapes with the wrong lifetime
1661///
1662/// Let's walk through these and see how they're prevented.
1663///
1664/// ```rust,compile_fail,E0271
1665/// # use std::rc::Rc;
1666/// # use yoke::Yoke;
1667/// # use std::borrow::Cow;
1668/// fn borrow_potentially_owned(y: &Yoke<Cow<'static, str>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> {
1669///    y.map_project_cloned(|cow, _| &*cow)
1670/// }
1671/// ```
1672///
1673/// In this case, the lifetime of `&*cow` is `&'this str`, however the function needs to be able to return
1674/// `&'a str` _for all `'a`_, which isn't possible.
1675///
1676///
1677/// ```rust,compile_fail,E0515
1678/// # use std::rc::Rc;
1679/// # use yoke::Yoke;
1680/// # use std::borrow::Cow;
1681/// fn borrow_potentially_owned(y: Yoke<Cow<'static, str>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> {
1682///    y.map_project(|cow, _| &*cow)
1683/// }
1684/// ```
1685///
1686/// This has the same issue, `&*cow` is borrowing for a local lifetime.
1687///
1688/// Similarly, trying to project an owned field of a struct will produce similar errors:
1689///
1690/// ```rust,compile_fail
1691/// # use std::borrow::Cow;
1692/// # use yoke::{Yoke, Yokeable};
1693/// # use std::mem;
1694/// # use std::rc::Rc;
1695/// #
1696/// // also safely implements Yokeable<'a>
1697/// struct Bar<'a> {
1698///     owned: String,
1699///     string_2: &'a str,
1700/// }
1701///
1702/// fn map_project_owned(bar: &Yoke<Bar<'static>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> {
1703///     // ERROR (but works if you replace owned with string_2)
1704///     bar.map_project_cloned(|bar, _| &*bar.owned)
1705/// }
1706///
1707/// #
1708/// # unsafe impl<'a> Yokeable<'a> for Bar<'static> {
1709/// #     type Output = Bar<'a>;
1710/// #     fn transform(&'a self) -> &'a Bar<'a> {
1711/// #         self
1712/// #     }
1713/// #
1714/// #     fn transform_owned(self) -> Bar<'a> {
1715/// #         // covariant lifetime cast, can be done safely
1716/// #         self
1717/// #     }
1718/// #
1719/// #     unsafe fn make(from: Bar<'a>) -> Self {
1720/// #         let ret = mem::transmute_copy(&from);
1721/// #         mem::forget(from);
1722/// #         ret
1723/// #     }
1724/// #
1725/// #     fn transform_mut<F>(&'a mut self, f: F)
1726/// #     where
1727/// #         F: 'static + FnOnce(&'a mut Self::Output),
1728/// #     {
1729/// #         unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
1730/// #     }
1731/// # }
1732/// ```
1733///
1734/// Borrowed data from `Y` similarly cannot escape with the wrong lifetime because of the `for<'a>`, since
1735/// it will never be valid for the borrowed data to escape for all lifetimes of 'a. Internally, `.map_project()`
1736/// uses `.get()`, however the signature forces the callers to be able to handle every lifetime.
1737///
1738///  `'a` is the only lifetime that matters here; `Yokeable`s must be `'static` and since
1739/// `Output` is an associated type it can only have one lifetime, `'a` (there's nowhere for it to get another from).
1740/// `Yoke`s can get additional lifetimes via the cart, and indeed, `map_project()` can operate on `Yoke<_, &'b [u8]>`,
1741/// however this lifetime is inaccessible to the closure, and even if it were accessible the `for<'a>` would force
1742/// it out of the output. All external lifetimes (from other found outside the yoke/closures
1743/// are similarly constrained here.
1744///
1745/// Essentially, safety is achieved by using `for<'a> fn(...)` with `'a` used in both `Yokeable`s to ensure that
1746/// the output yokeable can _only_ have borrowed data flow in to it from the input. All paths of unsoundness require the
1747/// unification of an existential and universal lifetime, which isn't possible.
1748const _: () = ();
1749
1750/// # Safety docs for `attach_to_cart()`'s signature
1751///
1752/// The `attach_to_cart()` family of methods get by by using the following bound:
1753///
1754/// ```rust,ignore
1755/// F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,
1756/// C::Target: 'static
1757/// ```
1758///
1759/// to enforce that the yoking closure produces a yokeable that is *only* allowed to borrow from the cart.
1760/// A way to be sure of this is as follows: imagine if `F` *did* borrow data of lifetime `'a` and stuff it in
1761/// its output. Then that lifetime `'a` would have to live at least as long as `'de` *for all `'de`*.
1762/// The only lifetime that satisfies that is `'static` (since at least one of the potential `'de`s is `'static`),
1763/// and we're fine with that.
1764///
1765/// ## Implied bounds and variance
1766///
1767/// The `C::Target: 'static` bound is tricky, however. Let's imagine a situation where we *didn't* have that bound.
1768///
1769/// One thing to remember is that we are okay with the cart itself borrowing from places,
1770/// e.g. `&[u8]` is a valid cart, as is `Box<&[u8]>`. `C` is not `'static`.
1771///
1772/// (I'm going to use `CT` in prose to refer to `C::Target` here, since almost everything here has to do
1773/// with `C::Target` and not C itself.)
1774///
1775/// Unfortunately, there's a sneaky additional bound inside `F`. The signature of `F` is *actually*
1776///
1777/// ```rust,ignore
1778/// F: for<'de> where<C::Target: 'de> FnOnce(&'de C::Target) -> <Y as Yokeable<'de>>::Output
1779/// ```
1780///
1781/// using made-up "where clause inside HRTB" syntax to represent a type that can be represented inside the compiler
1782/// and type system but not in Rust code. The `CT: 'de` bond comes from the `&'de C::Target`: any time you
1783/// write `&'a T`, an implied bound of `T: 'a` materializes and is stored alongside it, since references cannot refer
1784/// to data that itself refers to data of shorter lifetimes. If a reference is valid, its referent must be valid for
1785/// the duration of the reference's lifetime, so every reference *inside* its referent must also be valid, giving us `T: 'a`.
1786/// This kind of constraint is often called a "well formedness" constraint: `&'a T` is not "well formed" without that
1787/// bound, and rustc is being helpful by giving it to us for free.
1788///
1789/// Unfortunately, this messes with our universal quantification. The `for<'de>` is no longer "For all lifetimes `'de`",
1790/// it is "for all lifetimes `'de` *where `CT: 'de`*". And if `CT` borrows from somewhere (with lifetime `'ct`), then we get a
1791/// `'ct: 'de` bound, and `'de` candidates that live longer than `'ct` won't actually be considered.
1792/// The neat little logic at the beginning stops working.
1793///
1794/// `attach_to_cart()` will instead enforce that the produced yokeable *either* borrows from the cart (fine), or from
1795/// data that has a lifetime that is at least `'ct`. Which means that `attach_to_cart()` will allow us to borrow locals
1796/// provided they live at least as long as `'ct`.
1797///
1798/// Is this a problem?
1799///
1800/// This is totally fine if CT's lifetime is covariant: if C is something like `Box<&'ct [u8]>`, even if our
1801/// yoked object borrows from locals outliving `'ct`, our Yoke can't outlive that
1802/// lifetime `'ct` anyway (since it's a part of the cart type), so we're fine.
1803///
1804/// However it's completely broken for contravariant carts (e.g. `Box<fn(&'ct u8)>`). In that case
1805/// we still get `'ct: 'de`, and we still end up being able to
1806/// borrow from locals that outlive `'ct`. However, our Yoke _can_ outlive
1807/// that lifetime, because Yoke shares its variance over `'ct`
1808/// with the cart type, and the cart type is contravariant over `'ct`.
1809/// So the Yoke can be upcast to having a longer lifetime than `'ct`, and *that* Yoke
1810/// can outlive `'ct`.
1811///
1812/// We fix this by forcing `C::Target: 'static` in `attach_to_cart()`, which would make it work
1813/// for fewer types, but would also allow Yoke to continue to be covariant over cart lifetimes if necessary.
1814///
1815/// An alternate fix would be to not allowing yoke to ever be upcast over lifetimes contained in the cart
1816/// by forcing them to be invariant. This is a bit more restrictive and affects *all* `Yoke` users, not just
1817/// those using `attach_to_cart()`.
1818///
1819/// See <https://github.com/unicode-org/icu4x/issues/2926>
1820/// See also <https://github.com/rust-lang/rust/issues/106431> for potentially fixing this upstream by
1821/// changing how the bound works.
1822///
1823/// # Tests
1824///
1825/// Here's a broken `attach_to_cart()` that attempts to borrow from a local:
1826///
1827/// ```rust,compile_fail,E0597
1828/// use yoke::Yoke;
1829///
1830/// let cart = vec![1, 2, 3, 4].into_boxed_slice();
1831/// let local = vec![4, 5, 6, 7];
1832/// let yoke: Yoke<&[u8], Box<[u8]>> = Yoke::attach_to_cart(cart, |_| &*local);
1833/// ```
1834///
1835/// Fails as expected.
1836///
1837/// And here's a working one with a local borrowed cart that does not do any sneaky borrows whilst attaching.
1838///
1839/// ```rust
1840/// use yoke::Yoke;
1841///
1842/// let cart = vec![1, 2, 3, 4].into_boxed_slice();
1843/// let yoke: Yoke<&[u8], &[u8]> = Yoke::attach_to_cart(&cart, |c| c);
1844/// ```
1845///
1846/// Here's an `attach_to_cart()` that attempts to borrow from a longer-lived local due to
1847/// the cart being covariant. It fails, but would not if the alternate fix of forcing Yoke to be invariant
1848/// were implemented. It is technically a safe operation:
1849///
1850/// ```rust,compile_fail,E0597
1851/// use yoke::Yoke;
1852/// // longer lived
1853/// let local = vec![4, 5, 6, 7];
1854///
1855/// let backing = vec![1, 2, 3, 4];
1856/// let cart = Box::new(&*backing);
1857///
1858/// let yoke: Yoke<&[u8], Box<&[u8]>> = Yoke::attach_to_cart(cart, |_| &*local);
1859/// println!("{:?}", yoke.get());
1860/// ```
1861///
1862/// Finally, here's an `attach_to_cart()` that attempts to borrow from a longer lived local
1863/// in the case of a contravariant lifetime. It does not compile, but in and of itself is not dangerous:
1864///
1865/// ```rust,compile_fail,E0597
1866/// use yoke::Yoke;
1867///
1868/// type Contra<'a> = fn(&'a ());
1869///
1870/// let local = String::from("Hello World!");
1871/// let yoke: Yoke<&'static str, Box<Contra<'_>>> = Yoke::attach_to_cart(Box::new((|_| {}) as _), |_| &local[..]);
1872/// println!("{:?}", yoke.get());
1873/// ```
1874///
1875/// It is dangerous if allowed to transform (testcase from #2926)
1876///
1877/// ```rust,compile_fail,E0597
1878/// use yoke::Yoke;
1879///
1880/// type Contra<'a> = fn(&'a ());
1881///
1882///
1883/// let local = String::from("Hello World!");
1884/// let yoke: Yoke<&'static str, Box<Contra<'_>>> = Yoke::attach_to_cart(Box::new((|_| {}) as _), |_| &local[..]);
1885/// println!("{:?}", yoke.get());
1886/// let yoke_longer: Yoke<&'static str, Box<Contra<'static>>> = yoke;
1887/// let leaked: &'static Yoke<&'static str, Box<Contra<'static>>> = Box::leak(Box::new(yoke_longer));
1888/// let reference: &'static str = leaked.get();
1889///
1890/// println!("pre-drop: {reference}");
1891/// drop(local);
1892/// println!("post-drop: {reference}");
1893/// ```
1894const _: () = ();
1895
1896/// # Safety docs for `*map_with_cart*()`
1897///
1898/// [`Yoke::map_with_cart`] has both the problems of [`Yoke::map_project`] (with a
1899/// potentially-pathological callback) and [`Yoke::attach_to_cart`] (with a potentially
1900/// pathological cart, capable of permitting a bad callback).
1901///
1902/// [`map_project`] forces the callback to be well-behaved with the bounds:
1903/// ```rust,ignore
1904/// F: for<'a> FnOnce(
1905///     <Y as Yokeable<'a>>::Output,
1906///     PhantomData<&'a ()>,
1907/// ) -> <P as Yokeable<'a>>::Output,
1908/// ```
1909///
1910/// The `for<'a>` constraint prevents `F` from inserting additional borrows that did not come
1911/// from the input; `<P as Yokeable<'a>>::Output` can be `'static` or only `'a`, but that
1912/// `'a` could potentially be `'static` as well. Therefore, `F` has to be capable of returning
1913/// `'static` data (under certain constraints), and cannot insert additional borrows. Nor can a
1914/// reference leak out, as for a sufficiently short `'a`, the data would not live long enough.
1915/// The `PhantomData<&'a ()>` is just to make sure that the lifetime `'a` is constrained
1916/// to fix <https://github.com/rust-lang/rust/issues/86702>.
1917///
1918/// Next, [`Yoke::attach_to_cart`] follows mostly the same approach, but needs to ensure that
1919/// the `for<'a>` bound remains a fully universal quantifier.
1920/// It uses the bounds:
1921/// ```rust,ignore
1922/// F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,
1923/// <C as Deref>::Target: 'static,
1924/// ```
1925///
1926/// The problem is that the `for<'de>` quantifier is bounded by whatever the lifetime of
1927/// `<C as Deref>::Target` is, so for it to cover all lifetimes, `<C as Deref>::Target` must
1928/// be `'static`.
1929///
1930///
1931/// [`Yoke::map_with_cart`] combines the relevant bounds into one:
1932/// ```rust,ignore
1933/// F: for<'a> FnOnce(
1934///     <Y as Yokeable<'a>>::Output,
1935///     &'a <C as Deref>::Target,
1936/// ) -> <P as Yokeable<'a>>::Output,
1937/// <C as Deref>::Target: 'static,
1938/// ```
1939///
1940/// The techniques ensure that, for any lifetime `'a`, the callback must be capable of taking in
1941/// data from the old `Yokeable` and from the cart which is known only to outlive `'a`, and return
1942/// data that outlives `'a`. `F` is incapable of inserting external data which is not `'static`,
1943/// and is otherwise constrained to using the data in the cart and old `Yokeable` to produce
1944/// a new `Yokeable`.
1945/// A `PhantomData` is not needed, since the lifetime `'a` is constrained by
1946/// `&'a <C as Deref>::Target`.
1947///
1948/// # Fail tests
1949///
1950/// We can confirm that problematic cases analogous to those in [`Yoke::map_project`] and
1951/// [`Yoke::attach_to_cart`] still fail here. They're copied and adapted slightly.
1952///
1953/// ### From `map_project`'s safety docs
1954///
1955/// ```rust,compile_fail
1956/// # use std::rc::Rc;
1957/// # use yoke::Yoke;
1958/// # use std::borrow::Cow;
1959/// fn borrow_potentially_owned(y: &Yoke<Cow<'static, str>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> {
1960///    y.map_with_cart_cloned(|cow, _cart| &**cow)
1961/// }
1962/// ```
1963///
1964/// ```rust,compile_fail,E0515
1965/// # use std::rc::Rc;
1966/// # use yoke::Yoke;
1967/// # use std::borrow::Cow;
1968/// fn borrow_potentially_owned(y: Yoke<Cow<'static, str>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> {
1969///    y.map_with_cart(|cow: Cow<'_, _>, _cart| &*cow)
1970/// }
1971/// ```
1972///
1973/// ```rust,compile_fail
1974/// # use std::borrow::Cow;
1975/// # use yoke::{Yoke, Yokeable};
1976/// # use std::mem;
1977/// # use std::rc::Rc;
1978/// #
1979/// // also safely implements Yokeable<'a>
1980/// struct Bar<'a> {
1981///     owned: String,
1982///     string_2: &'a str,
1983/// }
1984///
1985/// fn map_with_cart_owned(bar: &Yoke<Bar<'static>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> {
1986///     // ERROR (but works if you replace owned with string_2)
1987///     bar.map_with_cart_cloned(|bar, _cart| &*bar.owned)
1988/// }
1989///
1990/// #
1991/// # unsafe impl<'a> Yokeable<'a> for Bar<'static> {
1992/// #     type Output = Bar<'a>;
1993/// #     fn transform(&'a self) -> &'a Bar<'a> {
1994/// #         self
1995/// #     }
1996/// #
1997/// #     fn transform_owned(self) -> Bar<'a> {
1998/// #         // covariant lifetime cast, can be done safely
1999/// #         self
2000/// #     }
2001/// #
2002/// #     unsafe fn make(from: Bar<'a>) -> Self {
2003/// #         let ret = mem::transmute_copy(&from);
2004/// #         mem::forget(from);
2005/// #         ret
2006/// #     }
2007/// #
2008/// #     fn transform_mut<F>(&'a mut self, f: F)
2009/// #     where
2010/// #         F: 'static + FnOnce(&'a mut Self::Output),
2011/// #     {
2012/// #         unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
2013/// #     }
2014/// # }
2015/// ```
2016///
2017/// ### From `attach_to_cart`'s safety docs
2018///
2019/// Being slightly paranoid, confirm that the expected line is the one causing the error.
2020/// ```rust
2021/// use std::rc::Rc;
2022/// use yoke::Yoke;
2023///
2024/// let cart: Vec<u8> = vec![1, 2, 3, 4];
2025/// let cart: Rc<[u8]> = Rc::from(&*cart);
2026///
2027/// let local = vec![4, 5, 6, 7];
2028/// let local: Rc<[u8]> = Rc::from(&*local);
2029///
2030/// let yoke: Yoke<&[u8], Rc<[u8]>> = Yoke::attach_to_cart(cart, |cart| cart);
2031/// let yoke: Yoke<&[u8], Rc<[u8]>> = yoke.map_with_cart(|_, cart| cart);
2032/// ```
2033///
2034/// ```rust,compile_fail,E0597
2035/// use std::rc::Rc;
2036/// use yoke::Yoke;
2037///
2038/// let cart: Vec<u8> = vec![1, 2, 3, 4];
2039/// let cart: Rc<[u8]> = Rc::from(&*cart);
2040///
2041/// let local = vec![4, 5, 6, 7];
2042/// let local: Rc<[u8]> = Rc::from(&*local);
2043///
2044/// let yoke: Yoke<&[u8], Rc<[u8]>> = Yoke::attach_to_cart(cart, |cart| &*cart);
2045/// let yoke: Yoke<&[u8], Rc<[u8]>> = yoke.map_with_cart(|_, _| &*local);
2046/// ```
2047///
2048///
2049/// ```rust
2050/// use std::rc::Rc;
2051/// use yoke::Yoke;
2052///
2053/// // longer lived
2054/// let local = vec![4_u8, 5, 6, 7];
2055/// let local: Rc<[u8]> = Rc::from(&*local);
2056///
2057/// let backing = vec![1_u8, 2, 3, 4];
2058/// let cart: Rc<[u8]> = Rc::from(&*backing);
2059///
2060/// let yoke: Yoke<&[u8], Rc<[u8]>> = Yoke::attach_to_cart(cart, |cart| cart);
2061/// let yoke: Yoke<&[u8], Rc<[u8]>> = yoke.map_with_cart(|_, cart: &[u8]| cart);
2062/// println!("{:?}", yoke.get());
2063/// ```
2064///
2065/// ```rust,compile_fail,E0425
2066/// use std::rc::Rc;
2067/// use yoke::Yoke;
2068///
2069/// // longer lived
2070/// let local: Rc<[u8]> = Rc::from(&*local);
2071///
2072/// let backing = vec![1_u8, 2, 3, 4];
2073/// let cart: Rc<[u8]> = Rc::from(&*backing);
2074///
2075/// let yoke: Yoke<&[u8], Rc<[u8]>> = Yoke::attach_to_cart(cart, |cart| &*cart);
2076/// let yoke: Yoke<&[u8], Rc<[u8]>> = yoke.map_with_cart(|_, cart: &[u8]| &*local);
2077/// println!("{:?}", yoke.get());
2078/// ```
2079///
2080///
2081/// I don't see a way to closely adapt `attach_to_cart`'s last two test cases on contravariant
2082/// carts, since the problematic `Cart` type is stopped at the stage of construction. We can use
2083/// one of `Yoke`'s other constructors instead, and try mapping it.
2084///
2085/// ```rust
2086/// use std::rc::Rc;
2087/// use yoke::Yoke;
2088///
2089/// type Contra<'a> = fn(&'a ());
2090///
2091/// let local = String::from("Hello World!");
2092/// let yoke: Yoke<&'static str, Option<Rc<Contra<'_>>>> =
2093///     Yoke::new_owned("hi");
2094/// println!("{:?}", yoke.get());
2095/// ```
2096///
2097/// This case might actually be fine to allow, since `attach_to_cart` could not possibly succeed
2098/// with this cart type and thus the `Yokeable` must always be owned. But whether it's safe to
2099/// permit *any* contravariant cart in `map_with_cart` is not immediately clear to me. Therefore,
2100/// compile fail.
2101/// ```rust,compile_fail
2102/// use std::rc::Rc;
2103/// use yoke::Yoke;
2104///
2105/// type Contra<'a> = fn(&'a ());
2106///
2107/// #[allow(clippy::extra_unused_lifetimes)]
2108/// fn scope<'b>() {
2109///     let local = String::from("Hello World!");
2110///     let yoke: Yoke<&'static str, Option<Rc<Contra<'b>>>> = Yoke::new_owned("hi");
2111///     let yoke: Yoke<&'static str, Rc<Option<Rc<Contra<'b>>>>> = yoke.wrap_cart_in_rc);
2112///     let yoke: Yoke<&'static str, Rc<Option<Rc<Contra<'b>>>>> = yoke.map_with_cart(|yoke, _| yoke);
2113///     println!("{:?}", yoke.get());
2114/// }
2115/// ```
2116///
2117/// This version succeeds, though.
2118/// ```rust
2119/// use std::rc::Rc;
2120/// use yoke::Yoke;
2121///
2122/// type Contra<'a> = fn(&'a ());
2123///
2124/// #[allow(clippy::extra_unused_lifetimes)]
2125/// fn scope<'b>() {
2126///     let local = String::from("Hello World!");
2127///     let yoke: Yoke<&'static str, Option<Rc<Contra<'b>>>> =
2128///         Yoke::new_owned("hi");
2129///     let yoke: Yoke<&'static str, Rc<Option<Rc<Contra<'b>>>>> =
2130///         yoke.wrap_cart_in_rc();
2131///     let yoke: Yoke<&'static str, Rc<Option<Rc<Contra<'static>>>>> = yoke;
2132///     let yoke: Yoke<&'static str, Rc<Option<Rc<Contra<'static>>>>> =
2133///         yoke.map_with_cart(|yoke, _| yoke);
2134///     println!("{:?}", yoke.get());
2135/// }
2136/// ```
2137///
2138/// # Test running the function
2139///
2140/// The above verifies the method signature. We can also check that the implementation is correct,
2141/// by running Miri on the following test (analogous to [`Yoke::map_with_cart`]'s doctest):
2142/// ```
2143/// use std::rc::Rc;
2144/// use yoke::Yoke;
2145///
2146/// type Foo<'a> = Option<&'a str>;
2147/// type Bar<'a> = (Option<&'a str>, Option<&'a str>);
2148///
2149/// fn foo_to_bar(
2150///     foo: Yoke<Foo<'static>, Rc<str>>,
2151/// ) -> Yoke<Bar<'static>, Rc<str>> {
2152///     foo.map_with_cart(|foo, cart| (foo, cart.lines().next_back()))
2153/// }
2154///
2155/// fn foo_to_bar_cloned(
2156///     foo: &Yoke<Foo<'static>, Rc<str>>,
2157/// ) -> Yoke<Bar<'static>, Rc<str>> {
2158///     foo.map_with_cart_cloned(|foo, cart| (*foo, cart.lines().next_back()))
2159/// }
2160///
2161/// fn bar_to_foo(
2162///     bar: Yoke<Bar<'static>, Rc<str>>,
2163/// ) -> Yoke<Foo<'static>, Rc<str>> {
2164///     bar.map_project(|bar, _| (bar.0))
2165/// }
2166///
2167/// fn main() {
2168///     fn assert_hello_world(bar: &Yoke<Bar<'static>, Rc<str>>) {
2169///         assert_eq!(bar.get().0, Some("hello"));
2170///         assert_eq!(bar.get().1, Some("world"));
2171///     }
2172///
2173///     let foo = Yoke::<Foo<'static>, Rc<str>>::attach_to_cart(
2174///         Rc::from("hello\nworld"),
2175///         |cart| cart.lines().next(),
2176///     );
2177///
2178///     assert_eq!(*foo.get(), Some("hello"));
2179///
2180///     let bar = foo_to_bar(foo);
2181///     assert_hello_world(&bar);
2182///
2183///     let foo = bar_to_foo(bar);
2184///
2185///     let bar_one = foo_to_bar_cloned(&foo);
2186///     let bar_two = foo_to_bar_cloned(&foo);
2187///
2188///     assert_hello_world(&bar_one);
2189///     assert_hello_world(&bar_two);
2190/// }
2191/// ```
2192const _: () = ();