Code
Playground (Stable Rust 1.45.0, 2018 edition) No external crates needed for example.
type Error = Box<dyn std::error::Error>;
type Result<R=()> = std::result::Result<R, Error>;
struct Arena;
pub trait AsSized<'a> {
type AsSized: Sized + 'a;
}
impl<'a, T: Sized + 'a> AsSized<'a> for T {
type AsSized = Self;
}
impl<'a, T: AsSized<'a>> AsSized<'a> for [T] {
type AsSized = &'a [T::AsSized];
}
pub trait Format<T>: Send + Sync
where T: ?Sized
{
fn get_bytes<'a>(&self, value: &'a T, arena: &'a Arena) -> Result<&'a [u8]>;
fn get_value<'a>(&self, bytes: &'a [u8], arena: &'a Arena) -> Result<T::AsSized>
where T: AsSized<'a>;
}
struct RawBytes;
impl Format<[u8]> for RawBytes
where [u8]: for<'a> AsSized<'a, AsSized=&'a [u8]>
{
fn get_bytes<'a>(&self, value: &'a [u8], _arena: &'a Arena) -> Result<&'a [u8]> {
Ok(value)
}
fn get_value<'a>(&self, bytes: &'a [u8], arena: &'a Arena) -> Result<<[u8] as AsSized<'a>>::AsSized> {
Ok(bytes)
}
}
Issue
I'm getting a compiler error on the impl of get_value for RawBytes:
error[E0195]: lifetime parameters or bounds on method `get_value` do not match the trait declaration
I don't understand what the problem is. It seems like the lifetime specification is the same between both definitions. How do I write the impl of get_value for RawBytes so that it works?
I would think that since u8: Sized then <u8 as AsSized<'a>>::AsSized = u8 and then <[u8] as AsSized<'a>>::AsSized = &'a [u8] but it seems like that isn't the case?
Background
Format takes an arena based allocator and converts a slice of bytes to and from a complex type. I plan to write an adapter for various Serde formats. RawBytes is a trivial implementaiton of Format for a slice of bytes that just returns the original slice.
Both methods of Format are allowed to return a value that borrows from the input value. The format itself may be shared between threads, so the lifetime of self is unrelated to the returned value.
The purpose of AsSized is to allow dynamically sized types like str and [u8] to be used directly, but since dynamically sized types can't be returned directly, AsSized provides a sized equivalent for any type; dynamically sized types return a reference to the DST instead (borrowed from the arena). Sized types like u8 that can be returned directly have an AsSized type of self
Also tried
fn get_value<'a>(&self, bytes: &'a [u8], arena: &'a Arena) -> Result<'a [u8]>
I tried simplifying the impl's get_value to just name the slice directly; rust then says that the impl for get_value is missing entirely.
fn get_value<'a>(&self, bytes: &'a [u8], arena: &'a Arena) -> Result<&'a [<u8 as AsSized<'a>>::AsSized]>
This give the same "lifetime parameters... do not match" error.