繁体   English   中英

如何键入注释捕获 function 参数的闭包

[英]How to type annotate a closure that captures a function parameter

我有这段代码:

use std::iter::TakeWhile;

pub trait Until<T, P>: Iterator<Item = T>
where
    P: FnMut(&T) -> bool,
    Self: Sized,
{
    fn until<'a>(self, f: P) -> TakeWhile<Self, fn(&'a T) -> bool> {
        self.take_while((move |item| !f(item)) as fn(&'a T) -> bool)
    }
}

impl<T, P, I> Until<T, P> for I
where
    P: FnMut(&T) -> bool,
    I: Iterator<Item = T>,
{
}

哪个不会出现此错误:

   Compiling until v0.1.0 (/home/rne/until)
error[E0605]: non-primitive cast: `[closure@src/lib.rs:9:26: 9:37]` as `fn(&'a T) -> bool`
 --> src/lib.rs:9:25
  |
9 |         self.take_while((move |item| !f(item)) as fn(&'a T) -> bool)
  |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast

For more information about this error, try `rustc --explain E0605`.
error: could not compile `until` due to previous error

如果我省略显式演员表:

use std::iter::TakeWhile;

pub trait Until<T, P>: Iterator<Item = T>
where
    P: FnMut(&T) -> bool,
    Self: Sized,
{
    fn until<'a>(self, f: P) -> TakeWhile<Self, fn(&'a T) -> bool> {
        self.take_while(move |item| !f(item))
    }
}

impl<T, P, I> Until<T, P> for I
where
    P: FnMut(&T) -> bool,
    I: Iterator<Item = T>,
{
}

我得到:

error[E0308]: mismatched types
    --> src/lib.rs:9:25
     |
9    |         self.take_while(move |item| !f(item))
     |              ---------- ^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure
     |              |
     |              arguments to this function are incorrect
     |
     = note: expected fn pointer `fn(&T) -> bool`
                   found closure `[closure@src/lib.rs:9:25: 9:36]`
note: closures can only be coerced to `fn` types if they do not capture any variables
    --> src/lib.rs:9:38
     |
9    |         self.take_while(move |item| !f(item))
     |                                      ^ `f` captured here
note: associated function defined here
    --> /usr/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:1204:8
     |
1204 |     fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
     |        ^^^^^^^^^^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `until` due to previous error

如何在TakeWhile返回类型中正确指定返回的 function 的类型? 注意:我不想使用带有动态dyn <Trait>内容的Box ,而是使用纯 generics。

您只能在夜间使用return_position_impl_trait_in_trait功能执行此操作:

#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]

pub trait Until<T, P>: Iterator<Item = T>
where
    P: FnMut(&T) -> bool,
    Self: Sized,
{
    fn until<'a>(self, mut f: P) -> TakeWhile<Self, impl FnMut(&'a T) -> bool> {
        self.take_while(move |item| !f(item))
    }
}

当且仅当回调 ( P ) 的大小为零,即不捕获任何内容时,您可以使用unsafe代码在稳定版上创建它的假实例:

fn until(self, _f: P) -> TakeWhile<Self, fn(&T) -> bool> {
    assert_eq!(std::mem::size_of::<P>(), 0, "`P` must be a ZST");
    self.take_while(move |item| {
        // SAFETY: `P` is zero-sized, so all-zeroes bit pattern is valid for it.
        let mut f = unsafe { std::mem::zeroed::<P>() };
        !f(item)
    })
}

但在这一点上,我会创建一个自定义迭代器适配器而不是使用take_while()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM