使用Any特质获取包含引用的结构的引用时的生命周期问题 [英] Lifetime issue when using the Any trait to get references to structs containing references
问题描述
我在玩小游戏时遇到了一生的问题.下面的代码表示更新循环的简化版本.我需要容器可变引用来获取对其他游戏对象的引用,或者创建新的对象或触发功能.
I ran into a lifetime problem with a little game. The below code represents a very boiled down version of the update loop. I need the container mutable reference to get references to other game objects or to create new ones or trigger a functionality.
由于这个原因,我需要 Any
特性才能将其转换为结构,因此在我的 GameObj
特性中添加了 as_any
方法,但这会导致生命周期问题.
For that reason, I need the Any
trait to be able to cast the trait to a struct, so in my GameObj
trait I added an as_any
method, but this resulted in a lifetime issue.
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);
}
}
}
}
当我尝试构建代码时,它导致以下错误消息.如果我在 update
函数中注释/删除 let any = val.as_any();
,则可以正常编译.
When I try to build the code, it results in the following error message.
If I comment out/delete let any = val.as_any();
in the update
function it compiles fine.
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();
| ^^^^^^
如何在不使用'static
的情况下实现此目的,或者为什么这不可能呢?
How I can make this work without using 'static
, or why is this impossible?
推荐答案
任何
是,并且可以仅存储 'static
类型.因此,为了使 dyn Any +'a
成为格式正确的类型,您的 as_any
方法被赋予了隐式的'a:'static
绑定,导致您显示的生命周期错误.
Any
is declared trait Any: 'static
and can only store 'static
types. So in order to make dyn Any + 'a
a well-formed type, your as_any
method was given an implicit 'a: 'static
bound, leading to the lifetime error you showed.
如果没有此限制,则可以通过将'a
类型放入 Any
类型并获取'static
类型,因为 TypeId
不能说出区别-编译期间会删除生命.有关更多信息,请参见关于RFC 1849的讨论.
If not for this restriction, you would be able to break safety by putting in an 'a
type into an Any
and getting out a 'static
type, because TypeId
can’t tell the difference—lifetimes are erased during compilation. See the discussion on RFC 1849 for more information.
您应该更仔细地考虑为什么要使用 Any
.这几乎从来不是您真正想要的.也许和 枚举
一样简单a>您可能要存储的所有不同对象类型的类型将更好地满足您的用例?
You should think more carefully about why you want to use Any
. It’s almost never what you actually want. Perhaps something as simple as an enum
type of all the different object types you might want to store would satisfy your use case better?
如果您真的想使用 Any
,那么您将需要一种使类型变为'static
的方法. Rc
(或 Arc 代码> (如果涉及线程)通常对此很有帮助;例如,您可以让
object
存储 Rc< String>
(或者更好的是 Rc< str>
),而不是&'一个字符串
.
If you really want to use Any
, then you’ll need to find a way to make your types 'static
. Rc
(or Arc
, if threads are involved) is often helpful for this purpose; for example, you could have your object
store Rc<String>
(or better, Rc<str>
) instead of &'a String
.
这篇关于使用Any特质获取包含引用的结构的引用时的生命周期问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!