我该如何解决这个问题:“期望一个实现了`Fn`特质的闭包,但是这个闭包只实现了`FnOnce`”?

3

我试图使用Governor crate让Warp中的速率限制工作。然而,当我尝试在闭包的Arc部分内使用rate_limiter实例时,我一直收到“预期闭包实现了Fn trait,但这个闭包仅实现了FnOnce”的错误信息。

我已经尝试在闭包内外克隆rate_limiter实例,但仍然报错。有人能帮我解决这个问题吗?

use crate::rejections::RateLimitFailure;
use dashmap::DashMap;
use governor::{
    clock::{QuantaClock, QuantaInstant},
    middleware::NoOpMiddleware,
    state::InMemoryState,
    Quota, RateLimiter,
};
use nonzero_ext::nonzero;
use std::collections::hash_map::RandomState;
use std::sync::Arc;
use warp::{Filter, Rejection};

const LIMIT: u32 = 50;

#[derive(Debug, Clone)]
pub struct FridayRateLimiter<'a> {
    pub lim: Arc<
        RateLimiter<
            &'a str,
            DashMap<&'a str, InMemoryState, RandomState>,
            QuantaClock,
            NoOpMiddleware<QuantaInstant>,
        >,
    >,
}

impl<'a> FridayRateLimiter<'a> {
    pub fn new() -> Self {
        let lim = Arc::new(RateLimiter::keyed(Quota::per_second(nonzero!(LIMIT))));
        FridayRateLimiter { lim }
    }
}

pub fn with_rate_limiter(
    rate_limiter: FridayRateLimiter,
) -> impl Filter<Extract = (bool,), Error = Rejection> + Clone {
    let addr = warp::header::<String>("HTTP_X_FORWARDED_FOR");
    let rate_limiter = rate_limiter.clone();

    addr.and_then(|ip: String| async move {
        let rate_limiter = rate_limiter.clone();

        if rate_limiter.lim.check_key(&ip.as_str()).is_err() {
            return Err(warp::reject::custom(RateLimitFailure));
        }

        Ok(true)
    })
}

请问您能否发布编译器输出结果? - Konstantin Tikhonov
--> src/rate_limiter.rs:41:19 | 41 | addr.and_then(|ip: String| async move { | -------- ^^^^^^^^^^^^ 此闭包实现了 FnOnce,而不是 Fn | | | 实现 Fn 的要求源自此处 42 | let rate_limiter = rate_limiter.clone(); | ------------ 闭包是 FnOnce,因为它将变量 rate_limiter 移出其环境 | = 注意:需要 [closure@src/rate_limiter.rs:41:19: 41:31] 实现 warp::generic::Func<(std::string::String,)> - Bhargav
1个回答

2

从这里开始:闭包何时实现Fn、FnMut和FnOnce?

首先,在闭包内部克隆速率限制器似乎是错误的。

接下来,我不明白为什么需要拥有所有权,所以我会放弃move。您只需要对速率限制器进行不可变借用调用check_key,不是吗?

这就是实现Fn的条件:因为它仅需要对其进行&访问,所以不会破坏其环境。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接