TryFrom<&[u8]> trait bound in trait

awd*_*drt 2 rust

I'm trying to implement common trait for a bunch of types created from binary data (read from a disk). Majority of trait methods could use default implementations and only conversions etc. would be needed to be implemented separately. I would like to use TryFrom<&[u8]> trait for conversions from binary data to my types but I don't know how to express (in the context of trait) that lifetime of &[u8] and lifetimes of values of my types created from it are not related. Here is minimal example of the problem.

use std::convert::TryFrom;

struct Foo;

// Value of Foo can be created from &[u8] but it doesn't borrow anything.
impl TryFrom<&[u8]> for Foo {
    type Error = ();

    fn try_from(v: &[u8]) -> Result<Self, ()> {
        Ok(Foo)
    }
}

trait Bar<'a>
where
    Self: TryFrom<&'a [u8], Error = ()>, // `&` without an explicit lifetime name cannot be used here
{
    fn baz() -> Self {
        let vec = Vec::new();
        Self::try_from(&vec).unwrap() // ERROR: vec does not live long enough (nothing is borrowed)
    }
}
Run Code Online (Sandbox Code Playgroud)

Alternative solution would be to make conversions as trait methods but it would be nicer to use common std traits. Is there a way to achieve this? (Or I could use const generics but I don't want to rely on nightly compiler.)

Luk*_*odt 7

你想要的是“更高等级的特质界限”(HRTB,或者简单的“热情的男孩”)。它们看起来像这样:for<'a> T: 'a。这个例子只是意味着:“对于每一个可能的生命周期'aT必须......”。在你的情况下:

trait Bar
where
    Self: for<'a> TryFrom<&'a [u8], Error = ()>,
Run Code Online (Sandbox Code Playgroud)

您还可以直接将该要求指定为超级特征绑定而不是where子句:

trait Bar: for<'a> TryFrom<&'a [u8], Error = ()> { ... }
Run Code Online (Sandbox Code Playgroud)

是的,现在它只是意味着所有实现者都Bar必须在所有TryFrom<&'a [u8], Error = ()>可能的生命周期内实现。那就是你想要的。

工作游乐场