簡體   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