Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimentation with trait objects in Yoke #743

Closed
wants to merge 7 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Checkpoint
sffc committed May 28, 2021

Unverified

This user has not yet uploaded their public signing key.
commit bad1266cdb152cef24b3c3cf4dfe3ff28db917c7
112 changes: 98 additions & 14 deletions utils/yoke/src/dyn_impls.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,112 @@
use crate::Yoke;
use crate::Yokeable;
use crate::yokeable::Foo;
use crate::yokeable::FooWrap;
use stable_deref_trait::StableDeref;
use std::borrow::Cow;
use std::mem;
use std::ops::Deref;

pub trait Foo<'a> {
fn foo(&self) -> char;
}

/// Example implementation of trait Foo
impl<'s> Foo<'s> for Cow<'s, str> {
fn foo(&self) -> char {
self.chars().next().unwrap_or('?')
}
}

pub struct FooWrap<'a> {
pub inner: &'a dyn Foo<'a>,
}

unsafe impl<'a> Yokeable<'a> for FooWrap<'static> {
type Output = FooWrap<'a>;

fn transform(&'a self) -> &'a Self::Output {
// needs unsafe because the compiler has trouble with covariant trait object lifetimes
unsafe { mem::transmute(self) }
}

unsafe fn make(from: Self::Output) -> Self {
mem::transmute(from)
}

fn with_mut<F>(&'a mut self, f: F)
where
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
{
// Cast away the lifetime of Self
unsafe { f(mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) }
}
}

trait DynHelper {
type Yokeable: for<'a> Yokeable<'a>;
type Cart: StableDeref;

fn attach<'de>(
data: &'de <Self::Cart as Deref>::Target,
) -> <Self::Yokeable as Yokeable<'de>>::Output;

fn make_cart(input: Box<Self>) -> Self::Cart;
}

impl<'a> DynHelper for dyn Foo<'a> + 'a {
type Yokeable = FooWrap<'static>;
type Cart = Box<dyn Foo<'static>>;

fn attach<'de>(data: &'de dyn Foo<'static>) -> FooWrap<'de> {
let inner: &'de dyn Foo<'de> = unsafe { mem::transmute(data) };
FooWrap { inner }
}

fn make_cart(input: Box<dyn Foo<'a> + 'a>) -> Box<dyn Foo<'static>> {
unsafe { mem::transmute(input) }
}
}

// unsafe impl<T> DynHelper for T where T: Sized {
// type Yokeable = ();
// type Cart = ();
// }

impl<'b, Y, C> Foo<'b> for Yoke<Y, C>
where
Y: for<'a> Yokeable<'a>,
<Y as Yokeable<'b>>::Output: Foo<'b> + 'b
<Y as Yokeable<'b>>::Output: Foo<'b> + 'b,
{
}

fn foo_make<'de>(input: &'de dyn Foo<'static>) -> <FooWrap<'static> as Yokeable<'de>>::Output {
let inner: &'de dyn Foo<'de> = unsafe { std::mem::transmute(input) };
FooWrap {
inner,
fn foo(&self) -> char {
'y'
}
}

fn make_dyn<'b, 'q, Y, C>(input: Yoke<Y, C>) -> Yoke<FooWrap<'static>, Box<dyn Foo<'static>>>
fn yoke_from_box<'b, Y, C>(
input: Box<<Y as Yokeable<'b>>::Output>,
) -> Yoke<
<<Y as Yokeable<'b>>::Output as DynHelper>::Yokeable,
<<Y as Yokeable<'b>>::Output as DynHelper>::Cart,
>
where
Y: for<'a> Yokeable<'a>,
<Y as Yokeable<'b>>::Output: Foo<'b> + 'b
<Y as Yokeable<'b>>::Output: DynHelper,
{
let boxed: Box<dyn Foo<'b>> = Box::new(input);
let cart: Box<dyn Foo<'static>> = unsafe { std::mem::transmute(boxed) };
Yoke::<FooWrap<'static>, Box<dyn Foo<'static>>>::attach_to_cart_badly(cart, foo_make)
let cart: <<Y as Yokeable<'b>>::Output as DynHelper>::Cart =
<<Y as Yokeable<'b>>::Output as DynHelper>::make_cart(input);
Yoke::<
<<Y as Yokeable<'b>>::Output as DynHelper>::Yokeable,
<<Y as Yokeable<'b>>::Output as DynHelper>::Cart,
>::attach_to_cart_badly(cart, <<Y as Yokeable<'b>>::Output as DynHelper>::attach)
}

#[test]
fn test_dyn() {
let source_data = "zyx".to_string();

let string_yoke: Yoke<Cow<'static, str>, &str> =
Yoke::<Cow<'static, str>, &str>::attach_to_cart_badly(&source_data, |s| Cow::Borrowed(s));

let boxed: Box<dyn Foo<'_>> = Box::new(string_yoke);

let dyn_yoke: Yoke<FooWrap<'static>, Box<dyn Foo<'static>>> = yoke_from_box(boxed);
}
69 changes: 0 additions & 69 deletions utils/yoke/src/yokeable.rs
Original file line number Diff line number Diff line change
@@ -250,72 +250,3 @@ unsafe impl<'a, T: 'static + ?Sized> Yokeable<'a> for &'static T {
unsafe { f(mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) }
}
}

pub trait Foo<'a> {}

// unsafe impl<'a> Yokeable<'a> for &'static dyn Foo<'static> {
// type Output = &'a dyn Foo<'a>;

// fn transform(&'a self) -> &'a &'a dyn Foo<'a> {
// // Doesn't need unsafe: `'a` is covariant so this lifetime cast is always safe
// self
// }

// unsafe fn make(from: &'a dyn Foo<'a>) -> Self {
// mem::transmute(from)
// }

// fn with_mut<F>(&'a mut self, f: F)
// where
// F: 'static + for<'b> FnOnce(&'b mut Self::Output),
// {
// // Cast away the lifetime of Self
// unsafe { f(mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) }
// }
// }

unsafe impl<'a> Yokeable<'a> for Box<dyn Foo<'static> + 'static> {
type Output = Box<dyn Foo<'a> + 'a>;

fn transform(&'a self) -> &'a Self::Output {
// needs unsafe because the compiler has trouble with covariant trait object lifetimes
unsafe { mem::transmute(self) }
}

unsafe fn make(from: Self::Output) -> Self {
mem::transmute(from)
}

fn with_mut<F>(&'a mut self, f: F)
where
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
{
// Cast away the lifetime of Self
unsafe { f(mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) }
}
}

pub struct FooWrap<'a> {
pub inner: &'a dyn Foo<'a>,
}

unsafe impl<'a> Yokeable<'a> for FooWrap<'static> {
type Output = FooWrap<'a>;

fn transform(&'a self) -> &'a Self::Output {
// needs unsafe because the compiler has trouble with covariant trait object lifetimes
unsafe { mem::transmute(self) }
}

unsafe fn make(from: Self::Output) -> Self {
mem::transmute(from)
}

fn with_mut<F>(&'a mut self, f: F)
where
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
{
// Cast away the lifetime of Self
unsafe { f(mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) }
}
}