在结构

时间:2017-08-03 11:31:24

标签: rust

我正在尝试将闭包存储在Vec中,这是结构的一部分。闭包是一个工厂函数,它接收2个引用作为参数,并产生一个trait对象,它存储闭包作为参数接收的引用。

因此,生成的特征对象的生命周期不得超过引用的生命周期。此外,component_registrations将从多个线程访问,因此包含在Arc<Mutex>

我尝试实现它,但编译器说F函数的泛型参数register_component不满足component_registrations中使用的特征绑定。

这是代码的相关部分:

use std::sync::Mutex;
use std::sync::Arc;

pub mod gl {
    pub struct Gl();
}

pub struct ComponentRegistry<'a> {
    gl: &'a gl::Gl
}

pub trait Component<'a> {
}

pub struct Application {
    component_registrations: Arc<Mutex<Vec<Box<for<'b> Fn(&'b ComponentRegistry<'b>, &'b gl::Gl) -> Box<Component<'b>> + Send + 'static>>>>
}

impl Application {
    pub fn new() -> Application {
        Application {
            component_registrations: Arc::new(Mutex::new(vec![]))
        }
    }

    pub fn register_component<'a, F>(&mut self, register: F) where F: Fn(&'a ComponentRegistry<'a>, &'a gl::Gl) -> Box<Component<'a>> + Send + 'static {
        self.component_registrations.lock().unwrap().push(Box::new(register));
    }
}
error[E0277]: the trait bound `for<'b> F: std::ops::Fn<(&'b ComponentRegistry<'b>, &'b gl::Gl)>` is not satisfied
  --> src/main.rs:27:59
   |
27 |         self.component_registrations.lock().unwrap().push(Box::new(register));
   |                                                           ^^^^^^^^^^^^^^^^^^ the trait `for<'b> std::ops::Fn<(&'b ComponentRegistry<'b>, &'b gl::Gl)>` is not implemented for `F`
   |
   = help: consider adding a `where for<'b> F: std::ops::Fn<(&'b ComponentRegistry<'b>, &'b gl::Gl)>` bound
   = note: required for the cast to the object type `for<'b> std::ops::Fn(&'b ComponentRegistry<'b>, &'b gl::Gl) -> std::boxed::Box<Component<'b>> + std::marker::Send`

error[E0271]: type mismatch resolving `for<'b> <F as std::ops::FnOnce<(&'b ComponentRegistry<'b>, &'b gl::Gl)>>::Output == std::boxed::Box<Component<'b>>`
  --> src/main.rs:27:59
   |
27 |         self.component_registrations.lock().unwrap().push(Box::new(register));
   |                                                           ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'b, found concrete lifetime
   |
note: concrete lifetime that was found is the lifetime 'a as defined on the method body at 26:5
  --> src/main.rs:26:5
   |
26 | /     pub fn register_component<'a, F>(&mut self, register: F) where F: Fn(&'a ComponentRegistry<'a>, &'a gl::Gl) -> Box<Component<'a>> + Send + 'static {
27 | |         self.component_registrations.lock().unwrap().push(Box::new(register));
28 | |     }
   | |_____^
   = note: required for the cast to the object type `for<'b> std::ops::Fn(&'b ComponentRegistry<'b>, &'b gl::Gl) -> std::boxed::Box<Component<'b>> + std::marker::Send`

1 个答案:

答案 0 :(得分:2)

如果您在定义component_registrations结构字段时使用排名更高的生命周期,则您应该为F使用更高排名的生命周期。

另外,如果您说Box<Component<'b>>,它实际上意味着Box<Component<'b> + 'static>(因此特征对象只能包含拥有的数据)。你真正需要的是Box<Component<'b> + 'b>,这意味着它是一个实现Component<'b>的特征对象,它还可以包含至少与'b一样长的借来的数据。

相关部分是

pub struct Application {
    component_registrations: Vec<Box<for<'b> Fn(&'b ComponentRegistry<'b>, &'b gl::Gl) -> Box<Component<'b> + 'b> + Send + 'static>>
}

impl Application {
    pub fn register_component<F>(&mut self, register: F) where F: for<'b> Fn(&'b ComponentRegistry<'b>, &'b gl::Gl) -> Box<Component<'b> + 'b> + Send + 'static {
        self.component_registrations.push(Box::new(register));
    }
}

您可以看到full example。请注意,我从您的示例中删除了ArcMutex类型,因为它们不相关。