Module yoke::trait_hack [−][src]
Expand description
Workarounds for adding trait bounds to yoke
objects.
Trait bounds in Yoke
Compiler bug #85636 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:
- 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
- If the trait involves
Self
, likeClone
, useYokeTraitHack
:where for<'a> YokeTraitHack<<Y as Yokeable<'a>>::Output>: MyTrait
Examples
Code that does not compile:
ⓘ
use yoke::Yoke; use yoke::Yokeable; // Example trait and struct for illustration purposes: trait MyTrait {} struct MyStruct {} impl MyTrait for MyStruct {} unsafe impl<'a> Yokeable<'a> for MyStruct { // (not shown; see `Yokeable` for examples) } impl<Y, C> MyTrait for Yoke<Y, C> where Y: for<'a> Yokeable<'a>, for<'a> <Y as Yokeable<'a>>::Output: MyTrait, {} fn example() { let y = Yoke::<MyStruct, ()>::new_always_owned(MyStruct {}); // error[E0277]: the trait bound `for<'a> <MyStruct as Yokeable<'a>>::Output: MyTrait` is not satisfied let _: &dyn MyTrait = &y; }
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) } // 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 yoke::Yoke; use yoke::Yokeable; use yoke::trait_hack::YokeTraitHack; use std::rc::Rc; // 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) } // 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_badly(rc_u32, |u| { YokeTraitHack::<<Y as Yokeable>::Output>::demo(*u).0 }) } } fn example() { let _ = Yoke::<MyStruct, Rc<u32>>::demo(42); }
Structs
A wrapper around a type T
, forwarding trait calls down to the inner type.