提问人:Cherry 提问时间:3/16/2023 最后编辑:Cherry 更新时间:3/16/2023 访问量:51
由于在通用类型锈蚀中的生存期,无法从闭合中返回闭合
Unable to return closure from closure due to lifetimes in generic type rust
问:
我是 rust 的新手,我正在尝试将库从 kotlin 重写为 rust。它是回调事件库。当尝试从另一个闭包返回闭包时,它会破坏注册表回调的函数,并且还会破坏由于调用程序泛型中的生存期而获取调用程序函数的调用程序函数。我在许多论坛上问这个问题,但无法获得帮助。on_event
法典
lib.rs
mod event;
#[cfg(test)]
mod tests {
use crate::event::*;
fn test(mut x: i32,y: i32, entries: &[&dyn Fn(i32)]) -> i32 {
for entry in entries {
x *= 3;
(entry)(x);
}
x * y
}
fn invoker<'a>(entries: &'a [&'a dyn Fn(i32)]) -> impl Fn(i32) -> i32 + 'a {
move |y|test(1,y,&entries)
}
#[test]
fn it_works() {
let mut event_test = EventKey::new(invoker);
let test = &|x: i32| {
println!("Hello {}", x);
};
event_test.on_event(test);
event_test.on_event(test);
event_test.on_event(test);
let result = event_test.invoke()(10);
assert_eq!(result, 270);
}
}
event.rs
/// Event file
/// I - invoker type
/// R - additional return type
/// C - Callback arguments
/// Please know that this applies to everything in this file
pub struct EventKey<I, C> {
invoker: I,
callbacks: Vec<C>
}
impl<I,C,R> EventKey<I,C>
where I: Fn (&[C]) -> R
{
pub fn new(invoker: I) -> EventKey<I, C> {
EventKey {
invoker,
callbacks: Vec::new()
}
}
pub fn on_event(&mut self, callback: C) {
self.callbacks.push(callback);
}
pub fn invoke(&self) -> R {
(self.invoker)(&self.callbacks)
}
}
错误
- 没有寿命
error[E0700]: hidden type for `impl Fn(i32) -> i32` captures lifetime that does not appear in bounds
--> src/lib.rs:14:9
|
13 | fn invoker(entries: &[&dyn Fn(i32)]) -> impl Fn(i32) -> i32 {
| --------------- hidden type `[closure@src/lib.rs:14:9: 14:17]` captures the anonymous lifetime defined here
14 | move |y|test(1,y,&entries)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: to declare that `impl Fn(i32) -> i32` captures `'_`, you can introduce a named lifetime parameter `'a`
|
13 | fn invoker<'a>(entries: &'a [&'a dyn Fn(i32)]) -> impl Fn(i32) -> i32 + 'a {
| ++++ ++ ++ ++++
- 有寿命
error[E0599]: the method `on_event` exists for struct `EventKey<for<'a> fn(&'a [&'a (dyn Fn(i32) + 'a)]) -> impl Fn(i32) -> i32 + 'a {invoker}, &dyn Fn(i32)>`, but its trait bounds were not satisfied
--> src/lib.rs:22:20
|
22 | event_test.on_event(test);
| ^^^^^^^^ method cannot be called due to unsatisfied trait bounds
|
::: src/event.rs:7:1
|
7 | pub struct EventKey<I, C> {
| ------------------------- method `on_event` not found for this struct
|
note: the following trait bounds were not satisfied:
`<for<'a> fn(&'a [&'a (dyn Fn(i32) + 'a)]) -> impl Fn(i32) -> i32 + 'a {invoker} as FnOnce<(&[&dyn Fn(i32)],)>>::Output = _`
`for<'a> fn(&'a [&'a (dyn Fn(i32) + 'a)]) -> impl Fn(i32) -> i32 + 'a {invoker}: Fn<(&[&dyn Fn(i32)],)>`
--> src/event.rs:13:10
|
12 | impl<I,C,R> EventKey<I,C>
| -------------
13 | where I: Fn (&[C]) -> R
| ^^^^^^^^^^^^^^
| | |
| | unsatisfied trait bound introduced here
| unsatisfied trait bound introduced here
= note: the following trait bounds were not satisfied:
`for<'a> fn(&'a [&'a (dyn Fn(i32) + 'a)]) -> impl Fn(i32) -> i32 + 'a {invoker}: FnMut<(&[&dyn Fn(i32)],)>`
which is required by `for<'a> fn(&'a [&'a (dyn Fn(i32) + 'a)]) -> impl Fn(i32) -> i32 + 'a {invoker}: Fn<(&[&dyn Fn(i32)],)>`
`for<'a> fn(&'a [&'a (dyn Fn(i32) + 'a)]) -> impl Fn(i32) -> i32 + 'a {invoker}: FnOnce<(&[&dyn Fn(i32)],)>`
which is required by `for<'a> fn(&'a [&'a (dyn Fn(i32) + 'a)]) -> impl Fn(i32) -> i32 + 'a {invoker}: Fn<(&[&dyn Fn(i32)],)>`
答:
0赞
cafce25
3/16/2023
#1
如果确保 in 的类型正确:test
it_works
let test: &dyn Fn(i32) = &|x| {
println!("Hello {}", x);
};
您必须在实现中注释生存期,以匹配您的使用情况:
impl<I, C> EventKey<I, C> {
pub fn new(invoker: I) -> EventKey<I, C> {
EventKey {
invoker,
callbacks: Vec::new(),
}
}
pub fn on_event(&mut self, callback: C) {
self.callbacks.push(callback);
}
pub fn invoke<'a, R>(&'a self) -> R
where
I: Fn(&'a [C]) -> R + 'a,
R: 'a,
C: 'a,
{
(self.invoker)(&self.callbacks)
}
}
注意:在正确注释生存期后,编译器会抱怨它不受约束,这是理所当然的,为了修复它,我移动了 bounds 和 type 参数以仅应用于该方法。R
invoke
评论
test
entries
test