繁体   English   中英

使用 Any trait 获取对包含引用的结构的引用时的生命周期问题

[英]Lifetime issue when using the Any trait to get references to structs containing references

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

出于这个原因,我需要Any trait 才能将 trait 转换为结构体,所以在我的GameObj trait 中,我添加了一个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);
            }
        }
    }
}

操场

当我尝试构建代码时,它会导致以下错误消息。 如果我注释掉/删除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();
   |                       ^^^^^^

我如何在不使用'static情况下完成这项工作,或者为什么这是不可能的?

Any声明为trait Any: 'static并且只能存储'static types 因此,为了使dyn Any + 'a成为格式良好的类型,您的as_any方法被赋予了一个隐式的'a: 'static绑定,从而导致您显示的生命周期错误。

如果没有这个限制,您将能够通过将'a类型放入Any并取出'static类型来破坏安全性,因为TypeId无法区分 - 生命周期在编译期间被擦除。 有关更多信息,请参阅有关 RFC 1849讨论

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

如果你真的想使用Any ,那么你需要找到一种方法来使你的类型成为'static Rc (或Arc ,如果涉及线程)通常有助于此目的; 例如,您可以使用object存储Rc<String> (或更好的Rc<str> )而不是&'a String

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM