任何特征的终身问题

时间:2019-02-03 12:58:54

标签: rust lifetime any

我在玩小游戏时遇到了一生的问题。以下代码表示更新循环的简化版本。 我需要容器可变引用来获取对其他游戏对象的引用,或者创建新的对象或触发功能。

由于这个原因,我需要 v = choice[I](n); 特性才能将其转换为结构,因此在我的Any特性中,我添加了一个GameObj方法,但这导致一生的问题。

as_any

playground

当我尝试构建代码时,它导致以下错误消息。 如果我在use std::any::Any; trait GameObj<'a> { fn as_any<'b>(&'b self) -> &'b (dyn Any + 'a); fn update(&mut self, cont: &mut container); } struct object<'a> { content: &'a String, } impl<'a> GameObj<'a> for object<'a> { fn as_any<'b>(&'b self) -> &'b (dyn Any + 'a) { return self; } fn update(&mut self, cont: &mut container) { let val = cont.get_obj().unwrap(); let any = val.as_any(); } } struct container<'a> { data: Vec<Box<dyn GameObj<'a> + 'a>>, } impl<'a> container<'a> { fn get_obj<'b>(&'b self) -> Option<&'b Box<dyn GameObj<'a> + 'a>> { return Some(&self.data[0]); } } pub fn main() { let a = String::from("hallo"); let b = String::from("asdf"); { let abc = object { content: &a }; let def = object { content: &b }; let mut cont = container { data: Vec::new() }; cont.data.push(Box::new(abc)); cont.data.push(Box::new(def)); loop { for i in 0..cont.data.len() { let mut obj = cont.data.remove(0); obj.update(&mut cont); cont.data.insert(i, obj); } } } } 函数中注释/删除了let any = val.as_any();,则可以正常编译。

update

在不使用error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements --> src/main.rs:18:24 | 18 | let val = cont.get_obj().unwrap(); | ^^^^^^^ | note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the method body at 17:5... --> src/main.rs:17:5 | 17 | / fn update(&mut self, cont: &mut container) { 18 | | let val = cont.get_obj().unwrap(); 19 | | let any = val.as_any(); 20 | | } | |_____^ = note: ...so that the types are compatible: expected &container<'_> found &container<'_> = note: but, the lifetime must be valid for the static lifetime... note: ...so that the declared lifetime parameter bounds are satisfied --> src/main.rs:19:23 | 19 | let any = val.as_any(); | ^^^^^^ 的情况下如何进行这项工作,或者为什么这不可能呢?

1 个答案:

答案 0 :(得分:1)

Anydeclared trait Any: 'static,可以only store 'static types。因此,为了使dyn Any + 'a成为格式正确的类型,您的as_any方法被赋予了隐式的'a: 'static边界,从而导致了所显示的生命周期错误。

如果没有此限制,则可以通过将'a类型放入Any并排除'static类型来破坏安全性,因为TypeId无法分辨差异-编译期间会删除生命。有关更多信息,请参见discussion on RFC 1849

您应该更仔细地考虑为什么要使用Any。这几乎从来不是您真正想要的。也许像您想存储的所有不同对象类型的enum类型那样简单,就可以更好地满足您的用例?

如果您确实要使用Any,则需要找到一种使您的类型为'static的方法。 Rc(如果涉及线程,则为Arc)通常有助于实现此目的;例如,您可以将object的商店Rc<String>(或更好的Rc<str>)而不是&'a String