[英]Why does implementing a trait change the behaviour of lifetimes?
This is the smallest thing I could get that reproduces my problem:这是我能得到的最小的东西,它重现了我的问题:
pub trait IoEventHandling {
fn add_key_callback(&mut self, callback : Box<dyn FnMut(&[KeyActionState])>);
}
pub struct KeyActionState;
type KeyEvent<'io> = Box<dyn FnMut(&[KeyActionState]) + 'io>;
struct Window<'io> {
key_callbacks: Vec<KeyEvent<'io>>,
}
// impl<'io> Window<'io> {
impl<'io> IoEventHandling for Window<'io> {
fn add_key_callback(&mut self, callback: KeyEvent<'io>) {
self.key_callbacks.push(callback);
}
}
struct PeripheralBureau<'io> {
window: Window<'io>,
}
impl<'io> PeripheralBureau<'io> {
fn window(&mut self) -> &mut Window<'io> {
&mut self.window
}
}
struct ECStorage;
impl ECStorage {
fn component_query<T>(&mut self) -> impl Iterator<Item = ()> {
std::iter::empty()
}
}
struct KeyBoardMotion;
fn move_user_controlled_entities<'io>(
ecs: &'io mut ECStorage,
io_context: &mut PeripheralBureau<'io>,
) {
io_context
.window()
.add_key_callback(Box::new(move |states| {
for motion in ecs.component_query::<KeyBoardMotion>() {}
}))
}
If you comment out impl<'io> IoEventHandling for Window<'io> {
and uncomment the line above it it will work.如果您注释掉impl<'io> IoEventHandling for Window<'io> {
并取消注释上面的行,它将起作用。
Why is implementing the trait breaking the code?为什么实现特征会破坏代码?
Your trait has a more strict requirement than the implementation.你的 trait 比实现有更严格的要求。 Namely, it requires callback
to be Box<dyn FnMut(&[KeyActionState])>
, which is (implicitly) Box<dyn FnMut(&[KeyActionState]) + 'static>
;即,它需要callback
为Box<dyn FnMut(&[KeyActionState])>
,即(隐式) Box<dyn FnMut(&[KeyActionState]) + 'static>
; and therefore, when you call the trait method, you're required to satisfy this 'static
bound - in other words, you're required to provide callback which can be held alive by the implementor indefinitely long.因此,当您调用 trait 方法时,您需要满足这个'static
界限”——换句话说,您需要提供可以由实现者无限期保持活动状态的回调。
When implementing add_key_callback
as an inherent method, however, you're lifting this restriction be making it dependent on the struct's lifetime - therefore, callback must simply outlive the struct.但是,当将add_key_callback
实现为固有方法时,您将解除此限制,使其依赖于结构的生命周期 - 因此,回调必须简单地超过结构。
To make this work with the trait, you have to make the trait itself generic, so that each Window<'io>
for different lifetime gets essentially its own impl<'io> IoEventHandling<'io>
, and these implementations will require different lifetimes on the argument, therefore avoiding constraining it too hard.为了使这个特性与特性一起工作,你必须使特性本身通用,以便不同生命周期的每个Window<'io>
基本上都有自己的impl<'io> IoEventHandling<'io>
,这些实现将需要不同的生命周期论点,因此避免过分约束它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.