Blanket impl,HRTB和“ Impl”抽象返回类型:“期望的绑定生存期参数”

时间:2019-03-25 15:08:17

标签: rust polymorphism closures lifetime

我在Rust中启动了一个很小的程序来与解析器组合器一起玩,很快遇到一个错误,发现奇怪:

trait Parser<T, E> {
    fn parse<'a>(&self, input: &'a [u8]) -> Result<(&'a [u8], T), E>;
}

impl<F, T, E> Parser<T, E> for F
where
    F: for<'a> Fn(&'a [u8]) -> Result<(&'a [u8], T), E>,
{
    fn parse<'a>(&self, input: &'a [u8]) -> Result<(&'a [u8], T), E> {
        (*self)(input)
    }
}

// why can't I write:
// fn byte(b: u8) -> impl Parser<u8, ()> {

// this works, and the blanket Parser impl picks it up correctly
fn byte(b: u8) -> impl for<'a> Fn(&'a [u8]) -> Result<(&'a [u8], u8), ()> {
    move |input: &[u8]| match input.first() {
        Some(x) if *x == b => Ok((&input[1..], *x)),
        _ => Err(()),
    }
}

fn main() {
    println!("{:?}", byte(b'c').parse(b"c123"));
}

byte的注释掉的签名(返回impl Parser<u8, ()>)无法编译为:

error[E0271]: type mismatch resolving `for<'a> <[closure@parser.rs:14:5: 19:6 b:_] as std::ops::FnOnce<(&'a [u8],)>>::Output == std::result::Result<(&'a [u8], u8), ()>`
  --> parser.rs:12:19
   |
12 | fn byte(b: u8) -> impl Parser<u8, ()> {
   |                   ^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime
   |
   = note: required because of the requirements on the impl of `Parser<u8, ()>` for `[closure@parser.rs:14:5: 19:6 b:_]`
   = note: the return type of a function must have a statically known size

我既不理解为什么期望绑定寿命参数,也没有找到具体的寿命。

我的看法是,返回的闭包具有某种无法定义的类型。此类型实现for <'a> Fn(&'a [u8]) -> Result<(&'a [u8], u8), ()>(并且编译器可以识别)。结果,它也应该由隐式实现Parser<u8, ()>来实现,或者我以为如此。

1 个答案:

答案 0 :(得分:0)

  

我的看法是,返回的闭包具有某种无法定义的类型。这种类型实现了<'a> Fn(&'a [u8])-> Result <(&'a [u8],u8),()>(并且编译器可以识别出来)。

只有在您指定它的情况下。

考虑没有生命周期信息的功能签名:

fn byte(b: u8) -> impl Fn(&[u8]) -> Result<(&[u8], u8), ()>

如果您写下被淘汰的寿命,则给出

fn byte<'a>(b: u8) -> impl Fn(&'a [u8]) -> Result<(&'a [u8], u8), ()>

这不会实现高阶for<'a> Fn ...-它仅对某个固定的Fn实现'a特性,该特性由调用者确定为byte

这是编译器所抱怨的具体生存期-期望找到for<...>约束的生存期,而是找到已经描述的生存期。