使用 Any 特性获取对包含引用的结构的引用时的生命周期问题
Lifetime issue when using the Any trait to get references to structs containing references
我运行用一个小游戏解决了一辈子的问题。下面的代码代表了更新循环的一个非常简化的版本。
我需要容器可变引用来获取对其他游戏对象的引用或创建新对象或触发功能。
出于这个原因,我需要 Any
特征才能将特征转换为结构,所以在我的 GameObj
特征中我添加了一个 as_any
方法,但是这个导致终身问题。
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
函数中注释 out/delete let any = val.as_any();
它编译正常。
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
的情况下完成这项工作,或者为什么这是不可能的?
Any
是 declared trait Any: 'static
and can only store 'static
types。因此,为了使 dyn Any + 'a
成为格式正确的类型,您的 as_any
方法被赋予隐式 'a: 'static
绑定,导致您显示的生命周期错误。
如果没有这个限制,你可以通过将 'a
类型放入 Any
并输出 'static
类型来破坏安全性,因为 TypeId
无法区分——生命周期在编译过程中被删除。有关详细信息,请参阅 discussion on RFC 1849。
你应该更仔细地考虑一下为什么要使用Any
。这几乎从来都不是你真正想要的。也许像您可能想要存储的所有不同对象类型的 enum
类型这样简单的东西会更好地满足您的用例?
如果你真的想使用 Any
,那么你需要想办法让你的类型 'static
。 Rc
(or Arc
,如果涉及线程)通常有助于此目的;例如,您可以让 object
存储 Rc<String>
(或更好,Rc<str>
)而不是 &'a String
.
我运行用一个小游戏解决了一辈子的问题。下面的代码代表了更新循环的一个非常简化的版本。 我需要容器可变引用来获取对其他游戏对象的引用或创建新对象或触发功能。
出于这个原因,我需要 Any
特征才能将特征转换为结构,所以在我的 GameObj
特征中我添加了一个 as_any
方法,但是这个导致终身问题。
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
函数中注释 out/delete let any = val.as_any();
它编译正常。
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
的情况下完成这项工作,或者为什么这是不可能的?
Any
是 declared trait Any: 'static
and can only store 'static
types。因此,为了使 dyn Any + 'a
成为格式正确的类型,您的 as_any
方法被赋予隐式 'a: 'static
绑定,导致您显示的生命周期错误。
如果没有这个限制,你可以通过将 'a
类型放入 Any
并输出 'static
类型来破坏安全性,因为 TypeId
无法区分——生命周期在编译过程中被删除。有关详细信息,请参阅 discussion on RFC 1849。
你应该更仔细地考虑一下为什么要使用Any
。这几乎从来都不是你真正想要的。也许像您可能想要存储的所有不同对象类型的 enum
类型这样简单的东西会更好地满足您的用例?
如果你真的想使用 Any
,那么你需要想办法让你的类型 'static
。 Rc
(or Arc
,如果涉及线程)通常有助于此目的;例如,您可以让 object
存储 Rc<String>
(或更好,Rc<str>
)而不是 &'a String
.