//! Workarounds for adding trait bounds to `yoke` objects. //! //! # Trait bounds in Yoke //! //! [Compiler bug #89196](https://github.com/rust-lang/rust/issues/89196) makes it tricky to add //! trait bounds involving `yoke` types. //! //! For example, you may want to write: //! //! `where for<'a> <Y as Yokeable<'a>>::Output: MyTrait` //! //! The above trait bound will compile, but at call sites, you get errors such as: //! //! > the trait `for<'de> MyTrait` is not implemented for `<Y as Yokeable<'de>>::Output` //! //! There are two known workarounds: //! //! 1. If the trait is well-defined on references, like `Debug`, bind the trait to a reference: //! `where for<'a> &'a <Y as Yokeable<'a>>::Output: MyTrait` //! 2. If the trait involves `Self`, like `Clone`, use [`YokeTraitHack`]: //! `where for<'a> YokeTraitHack<<Y as Yokeable<'a>>::Output>: MyTrait` //! //! # Examples //! //! Code that does not compile ([playground](https://play.rust-lang.org/?version=beta&mode=debug&edition=2018&gist=ebbda5b15a398d648bdff9e439b27dc0)): //! //! ```compile_fail //! # this compiles in 1.78+, so this text will make it fail //! use yoke::*; //! //! trait MiniDataMarker { //! type Yokeable: for<'a> Yokeable<'a>; //! } //! //! struct MiniDataPayload<M> //! where //! M: MiniDataMarker //! { //! pub yoke: Yoke<M::Yokeable, ()>, //! } //! //! impl<M> Clone for MiniDataPayload<M> //! where //! M: MiniDataMarker, //! for<'a> <M::Yokeable as Yokeable<'a>>::Output: Clone, //! { //! fn clone(&self) -> Self { //! unimplemented!() //! } //! } //! //! trait MiniDataProvider<M> //! where //! M: MiniDataMarker //! { //! fn mini_load_data(&self) -> MiniDataPayload<M>; //! } //! //! struct MiniStructProvider<M> //! where //! M: MiniDataMarker, //! { //! pub payload: MiniDataPayload<M>, //! } //! //! impl<M> MiniDataProvider<M> for MiniStructProvider<M> //! where //! M: MiniDataMarker, //! for<'a> <M::Yokeable as Yokeable<'a>>::Output: Clone, //! { //! fn mini_load_data(&self) -> MiniDataPayload<M> { //! self.payload.clone() //! } //! } //! //! #[derive(Clone)] //! struct SimpleStruct(pub u32); //! //! unsafe impl<'a> Yokeable<'a> for SimpleStruct { //! // (not shown; see `Yokeable` for examples) //! # type Output = SimpleStruct; //! # fn transform(&'a self) -> &'a Self::Output { //! # self //! # } //! # fn transform_owned(self) -> Self::Output { //! # self //! # } //! # unsafe fn make(from: Self::Output) -> Self { //! # std::mem::transmute(from) //! # } //! # fn transform_mut<F>(&'a mut self, f: F) //! # where //! # F: 'static + for<'b> FnOnce(&'b mut Self::Output), //! # { //! # unsafe { //! # f(std::mem::transmute::<&'a mut Self, &'a mut Self::Output>( //! # self, //! # )) //! # } //! # } //! } //! //! impl MiniDataMarker for SimpleStruct { //! type Yokeable = SimpleStruct; //! } //! //! let provider = MiniStructProvider { //! payload: MiniDataPayload { //! yoke: Yoke::new_always_owned(SimpleStruct(42)) //! } //! }; //! //! // Broken: //! // "method cannot be called on `MiniStructProvider<_>` due to unsatisfied trait bounds" //! let payload: MiniDataPayload<SimpleStruct> = provider.mini_load_data(); //! //! // Working: //! let payload = MiniDataProvider::<SimpleStruct>::mini_load_data(&provider); //! //! assert_eq!(payload.yoke.get().0, 42); //! ``` //! //! Example for binding the trait to a reference: //! //! ``` //! use yoke::Yoke; //! use yoke::Yokeable; //! //! // Example trait and struct for illustration purposes: //! trait MyTrait { //! fn demo(&self) -> u32; //! } //! struct MyStruct(u32); //! impl MyTrait for MyStruct { //! fn demo(&self) -> u32 { //! self.0 //! } //! } //! unsafe impl<'a> Yokeable<'a> for MyStruct { //! // (not shown; see `Yokeable` for examples) //! # type Output = MyStruct; //! # fn transform(&'a self) -> &'a Self::Output { //! # self //! # } //! # fn transform_owned(self) -> Self::Output { //! # self //! # } //! # unsafe fn make(from: Self::Output) -> Self { //! # std::mem::transmute(from) //! # } //! # fn transform_mut<F>(&'a mut self, f: F) //! # where //! # F: 'static + for<'b> FnOnce(&'b mut Self::Output), //! # { //! # unsafe { //! # f(std::mem::transmute::<&'a mut Self, &'a mut Self::Output>( //! # self, //! # )) //! # } //! # } //! } //! //! // The trait needs to be defined on references: //! impl<'a, T> MyTrait for &'a T //! where //! T: MyTrait, //! { //! fn demo(&self) -> u32 { //! self.demo() //! } //! } //! //! impl<Y, C> MyTrait for Yoke<Y, C> //! where //! Y: for<'a> Yokeable<'a>, //! for<'a> &'a <Y as Yokeable<'a>>::Output: MyTrait, //! { //! fn demo(&self) -> u32 { //! self.get().demo() //! } //! } //! //! fn example() { //! let y = Yoke::<MyStruct, ()>::new_always_owned(MyStruct(42)); //! let _: &dyn MyTrait = &y; //! } //! ``` //! //! Example for using [`YokeTraitHack`]: //! //! ``` //! use std::rc::Rc; //! use yoke::trait_hack::YokeTraitHack; //! use yoke::Yoke; //! use yoke::Yokeable; //! //! // Example trait and struct for illustration purposes: //! trait MyTrait { //! fn demo(data: u32) -> Self; //! } //! struct MyStruct(u32); //! impl MyTrait for MyStruct { //! fn demo(data: u32) -> Self { //! Self(data) //! } //! } //! unsafe impl<'a> Yokeable<'a> for MyStruct { //! // (not shown; see `Yokeable` for examples) //! # type Output = MyStruct; //! # fn transform(&'a self) -> &'a Self::Output { //! # self //! # } //! # fn transform_owned(self) -> Self::Output { //! # self //! # } //! # unsafe fn make(from: Self::Output) -> Self { //! # std::mem::transmute(from) //! # } //! # fn transform_mut<F>(&'a mut self, f: F) //! # where //! # F: 'static + for<'b> FnOnce(&'b mut Self::Output), //! # { //! # unsafe { //! # f(std::mem::transmute::<&'a mut Self, &'a mut Self::Output>( //! # self, //! # )) //! # } //! # } //! } //! //! // The trait needs to be defined on YokeTraitHack: //! impl<'a, T> MyTrait for YokeTraitHack<T> //! where //! T: MyTrait, //! { //! fn demo(data: u32) -> Self { //! YokeTraitHack(T::demo(data)) //! } //! } //! //! impl<Y> MyTrait for Yoke<Y, Rc<u32>> //! where //! Y: for<'a> Yokeable<'a>, //! for<'a> YokeTraitHack<<Y as Yokeable<'a>>::Output>: MyTrait, //! { //! fn demo(data: u32) -> Self { //! let rc_u32: Rc<u32> = Rc::new(data); //! Yoke::attach_to_cart(rc_u32, |u| { //! YokeTraitHack::<<Y as Yokeable>::Output>::demo(*u).0 //! }) //! } //! } //! //! fn example() { //! let _ = Yoke::<MyStruct, Rc<u32>>::demo(42); //! } //! ```
use core::mem;
/// A wrapper around a type `T`, forwarding trait calls down to the inner type. /// /// `YokeTraitHack` supports [`Clone`], [`PartialEq`], [`Eq`], and [`serde::Deserialize`] out of /// the box. Other traits can be implemented by the caller. /// /// For more information, see the module-level documentation. /// /// # Example /// /// Using `YokeTraitHack` as a type bound in a function comparing two `Yoke`s: /// /// ``` /// use yoke::trait_hack::YokeTraitHack; /// use yoke::*; /// /// fn compare_yokes<Y, C1, C2>(y1: Yoke<Y, C1>, y2: Yoke<Y, C2>) -> bool /// where /// Y: for<'a> Yokeable<'a>, /// for<'a> YokeTraitHack<<Y as Yokeable<'a>>::Output>: PartialEq, /// { /// YokeTraitHack(y1.get()).into_ref() == YokeTraitHack(y2.get()).into_ref() /// } /// ``` #[repr(transparent)] #[derive(Clone, PartialEq, Eq, Debug)] #[allow(clippy::exhaustive_structs)] // newtype pubstruct YokeTraitHack<T>(pub T);
impl<'a, T> YokeTraitHack<&'a T> { /// Converts from `YokeTraitHack<&T>` to `&YokeTraitHack<T>`. /// /// This is safe because `YokeTraitHack` is `repr(transparent)`. /// /// This method is required to implement `Clone` on `Yoke`. pubfn into_ref(self) -> &'a YokeTraitHack<T> { // YokeTraitHack is repr(transparent) so it's always safe // to transmute YTH<&T> to &YTH<T> unsafe { mem::transmute::<YokeTraitHack<&T>, &YokeTraitHack<T>>(self) }
}
}
// This is implemented manually to avoid the serde derive dependency. #[cfg(feature = "serde")] impl<'de, T> serde::de::Deserialize<'de> for YokeTraitHack<T> where
T: serde::de::Deserialize<'de>,
{ #[inline] fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where
D: serde::de::Deserializer<'de>,
{
T::deserialize(deserializer).map(YokeTraitHack)
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.