Я запустил очень маленькую программу для работы с комбинаторами синтаксического анализа в 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, ()>
, как я и думал.