首页 > 解决方案 > 将(迭代器)值传递给闭包(预期类型参数`I`,找到结构`std::slice::Iter`)有什么问题?

问题描述

我想了解以下错误:

error[E0308]: mismatched types
  --> src/tabs.rs:70:44
   |
43 | fn detab_go<'a, I, R, W>(
   |                 - this type parameter
...
70 |                         f_out, bytes_iter, buf_iter,
   |                                            ^^^^^^^^ expected type parameter `I`, found struct `std::slice::Iter`
   |
   = note: expected type parameter `I`
                      found struct `std::slice::Iter<'_, u8>`

导致错误的代码如下所示(从我一直在处理的宏扩展而来):

fn detab_go<'a, I, R, W>(
    f_out: &mut W,
    bytes_iter: BytesIter<R>,
    buf_iter: I,
    tab_pos_last: usize,
) -> Result<(), Error>
where
    I: Iterator<Item = &'a u8>,
    R: Read,
    W: Write,
{
    tailcall::trampoline::run_res(
        #[inline(always)]
        |(f_out, mut bytes_iter, mut buf_iter, tab_pos_last)| {
            Ok(tailcall::trampoline::Finish({
                match buf_iter.next() {
                    Some(byte) => {
                        if !is_tab_or_newline(*byte) {
                            write_u8(f_out, *byte)?;
                        }
                        return Ok(tailcall::trampoline::Recurse((
                            f_out, bytes_iter, buf_iter, 1,
                        )));
                    }
                    None => match bytes_iter.next() {
                        Some(buf_new) => {
                            let buf_test: Vec<u8> = buf_new?;
                            let buf_iter = buf_test.iter();
                            return Ok(tailcall::trampoline::Recurse((
                                f_out, bytes_iter, buf_iter, 1,
                            )));
                        }
                        None => Ok(()),
                    },
                }
            }))
        },
        (f_out, bytes_iter, buf_iter, tab_pos_last),
    )
}

非宏扩展代码不会导致编译错误。它应该与宏扩展代码具有相同的含义(尽管运行时特性略有不同),并且看起来像:

fn detab_go<'a, I, R, W>(
    f_out: &mut W,
    mut bytes_iter: BytesIter<R>,
    mut buf_iter: I,
    tab_pos_last: usize,
) -> Result<(), Error>
where
    I: Iterator<Item = &'a u8>,
    R: Read,
    W: Write,
{
    match buf_iter.next() {
        Some(byte) => {
            if !is_tab_or_newline(*byte) {
                write_u8(f_out, *byte)?;
            }
            detab_go(
                f_out, bytes_iter, buf_iter,
                /*&tab_pos_new*/ /*todo!() */ 1,
            )
        }
        None => {
            match bytes_iter.next() {
                Some(buf_new) => {
                    let buf_test: Vec<u8> = buf_new?;
                    let buf_iter = buf_test.iter(); //shadow
                    detab_go(
                        f_out, bytes_iter, buf_iter,
                        /*&tab_pos_new*/ /*todo!()*/ 1,
                    )
                }
                None => Ok(()), /* Finished */
            }
        }
    }
}

标签: rust

解决方案


我认为区别在于递归的类型:直接detab_go递归调用允许编译器看到detab_go接受任意的Iterator<Item=u8>,而trampoline版本似乎修复了I- 不允许不同类型作为输入。

也许它有助于detab_go接受 astd::slice::Iter<'_, u8>而不是泛型Iterator


推荐阅读