Playground(Stable Rust 1.45.0,2018 版)例如不需要外部板条箱。
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)
}
}
Run Code Online (Sandbox Code Playgroud)
我在get_valuefor的实现上遇到编译器错误RawBytes:
error[E0195]: lifetime parameters or bounds on method `get_value` do not match the trait declaration
Run Code Online (Sandbox Code Playgroud)
我不明白问题是什么。两个定义之间的生命周期规范似乎相同。我如何编写get_valuefor 的实现RawBytes以使其有效?
我会认为从那时u8: Sized起<u8 as AsSized<'a>>::AsSized = u8,<[u8] as AsSized<'a>>::AsSized = &'a [u8]但似乎情况并非如此?
Format采用基于 arena 的分配器,并将字节片与复杂类型相互转换。我计划为各种 Serde 格式编写一个适配器。RawBytes是一个简单的实现,Format用于只返回原始切片的字节切片。
的两种方法Format都允许返回从输入值借用的值。格式本身可以在线程之间共享,因此 self 的生命周期与返回值无关。
的目的AsSized是允许像str和那样[u8]直接使用动态大小的类型,但是由于不能直接返回动态大小的类型,因此AsSized为任何类型提供了大小的等效项;动态大小的类型返回对 DST 的引用(从 arena 借来)。像u8这样可以直接返回的大小类型有一个AsSizedself 类型
fn get_value<'a>(&self, bytes: &'a [u8], arena: &'a Arena) -> Result<'a [u8]>
Run Code Online (Sandbox Code Playgroud)
我尝试简化 implget_value以直接命名切片;rust 然后说 impl forget_value完全丢失了。
fn get_value<'a>(&self, bytes: &'a [u8], arena: &'a Arena) -> Result<&'a [<u8 as AsSized<'a>>::AsSized]>
Run Code Online (Sandbox Code Playgroud)
这给出了相同的“生命周期参数......不匹配”错误。
部分答案(我也被困住了:)
\n我不断删除代码,直到达到重现错误的最小示例:
\npub trait AsSized<\'a> {\n type AsSized: Sized + \'a;\n}\n\npub trait Format<T>\nwhere\n T: ?Sized,\n{\n fn get_value<\'a>(&self, bytes: &\'a [u8])\n where\n T: AsSized<\'a>;\n}\n\nimpl Format<[u8]> for () {\n fn get_value<\'a>(&self, bytes: &\'a [u8]) {\n todo!()\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n现在很明显,在特征定义中,对生命周期有进一步的限制\'a:我们要求T: AsSized<\'a>,这就是导致错误的原因。该块上没有这样的子句impl,因此编译器不接受等效的生命周期。
(我不确定它们是否实际上不兼容或者这是否是编译器的限制)
\n所以我决定也添加where [u8]: AsSized<\'a>这个功能。impl为了让它编译,我还:
Arena(类型泄漏问题)where [u8]: for<\'a> AsSized<\'a, AsSized=&\'a [u8]>impl这个 where 子句对我来说没有意义 \xe2\x80\x93 似乎没有意义,因为它不涉及泛型?我可能是错的。无论如何,它导致了一个奇怪的错误)todo!()所以编译如下:
\nfn main() {}\n\ntype Error = Box<dyn std::error::Error>;\ntype Result<R = ()> = std::result::Result<R, Error>;\n\npub struct Arena;\n\npub trait AsSized<\'a> {\n type AsSized: Sized + \'a;\n}\nimpl<\'a, T: Sized + \'a> AsSized<\'a> for T {\n type AsSized = Self;\n}\nimpl<\'a, T: AsSized<\'a>> AsSized<\'a> for [T] {\n type AsSized = &\'a [T::AsSized];\n}\n\npub trait Format<T>: Send + Sync\nwhere\n T: ?Sized,\n{\n fn get_bytes<\'a>(&self, value: &\'a T, arena: &\'a Arena) -> Result<&\'a [u8]>;\n fn get_value<\'a>(&self, bytes: &\'a [u8], arena: &\'a Arena) -> Result<T::AsSized>\n where\n T: AsSized<\'a>;\n}\n\nstruct RawBytes;\n\nimpl Format<[u8]> for RawBytes {\n fn get_bytes<\'a>(&self, value: &\'a [u8], _arena: &\'a Arena) -> Result<&\'a [u8]> {\n Ok(value)\n }\n fn get_value<\'a>(\n &self,\n bytes: &\'a [u8],\n arena: &\'a Arena,\n ) -> Result<<[u8] as AsSized<\'a>>::AsSized>\n where\n [u8]: AsSized<\'a>,\n {\n todo!()\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n不幸的是,当我把后背换成todo!()你的后Ok(bytes),它又坏了。编译器显然不知道它<[u8] as AsSized<\'a>>::AsSized与&\'a [u8]. 那好吧。
error[E0308]: mismatched types\n --> src/main.rs:42:12\n |\n42 | Ok(bytes)\n | -- ^^^^^ expected associated type, found `&[u8]`\n | |\n | arguments to this enum variant are incorrect\n |\n = note: expected associated type `<[u8] as AsSized<\'a>>::AsSized`\n found reference `&\'a [u8]`\n = help: consider constraining the associated type `<[u8] as AsSized<\'a>>::AsSized` to `&\'a [u8]` or calling a method that returns `<[u8] as AsSized<\'a>>::AsSized`\n = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html\nRun Code Online (Sandbox Code Playgroud)\n