rust 获取错误:参数要求“1”必须比“a”寿命长

gblwokeq  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(116)

我有以下内容:

use std::collections::HashMap;
use std::*;

fn main() {
    let mut struct_a: struct_A = struct_A::new();
    loop {
        let _res = struct_a.process();
    }
}

pub struct struct_A<'a> {
    pub entities: struct_B<'a>,
}

impl<'a> struct_A<'a> {
    pub fn new() -> struct_A<'a> {
        let mut struct_A: struct_A = struct_A {
            entities: struct_B::new(),
        };

        struct_A
    }

    pub fn process(&mut self) -> Result<(), String> {
        self.entities.get_connection(832);
        Ok(())
    }
}

pub struct struct_B<'a> {
    chain: Chain<u32, struct_c<'a>>,
}

pub struct struct_c<'a> {
    // other fields here
    u: &'a u32,
}

impl<'a> struct_B<'a> {
    pub fn new() -> Self {
        let cache = HashMap::new();
        struct_B {
            chain: Chain::<u32, struct_c>::new(cache),
        }
    }

    pub fn get_connection(&self, mac: u32) -> Option<&'a mut Node<struct_c>> {
        self.chain.find(mac)
    }
}

pub struct Chain<K, V> {
    pub cache: HashMap<K, *mut Node<V>>,
}

#[derive(Default)]
pub struct Node<T> {
    pub data: T,
}

impl<K, V> Chain<K, V>
where
    K: std::cmp::Eq + std::hash::Hash,
{
    pub fn new(pool: HashMap<K, *mut Node<V>>) -> Self {
        Chain { cache: pool }
    }

    pub fn find(&self, key: K) -> Option<&mut Node<V>> {
        if let Some(node) = self.cache.get(&key) {
            unsafe {
                return Some(node.as_mut().unwrap());
            }
        }
        None
    }
}

编译,我得到:

error[E0499]: cannot borrow `struct_a` as mutable more than once at a time
 --> src/main.rs:7:20
  |

当我编译时,我得到:

--> src/main.rs:25:9
   |
15 | impl<'a> struct_A<'a> {
   |      -- lifetime `'a` defined here
...
24 |     pub fn process(&mut self) -> Result<(), String> {
   |                    - let's call the lifetime of this reference `'1`
25 |         self.entities.get_connection(832);
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`

如果我给process()加上生命周期,就像这样:

pub fn process<'b>(&'b mut self) -> Result<(), String>
    where
        'b: 'a,
    {
        self.entities.get_connection(832);
        Ok(())
    }

编译,我得到:

error[E0499]: cannot borrow `struct_a` as mutable more than once at a time
 --> src/main.rs:7:20
  |
7 |         let _res = struct_a.process();
  |                    ^^^^^^^^^^^^^^^^^^
  |                    |
  |                    `struct_a` was mutably borrowed here in the previous iteration of the loop
  |                    first borrow used here, in later iteration of loop

我真的很难理解为什么我得到了原来的编译错误,开始,我认为这与variance有关,但我不确定到底是什么。

tvmytwxo

tvmytwxo1#

您的get_connection返回列表中为'a生存的节点的可变引用,在本例中,这基本上是列表的整个生存期。这也强制get_connection&self引用至少要借用'a
现在在process中,您引用self.entities并调用get_connection。由于上述原因,必须借用此引用至少'a。因此,process中的整个&mut self引用必须至少存在'a。这是你得到的第一个错误,因为它不能保证。
添加&'b mut self where 'b: 'a约束“解决”了这个问题,因为process现在可以借用足够长的时间。但这仍然是不正确的。
在main中,struct_a至少与循环一样长。所以这里的'a参数对应于代码中的实际生存期:

fn main() {
    let mut struct_a: struct_A = struct_A::new(); // 'a starts here
    loop {
        let _res = struct_a.process();            // 'a continues, struct_a has to live here
    }
                                                  // struct_a no longer used, lifetime ends

}

因此struct_A::new创建了一个struct_B示例,该示例的生存期必须至少与包含struct_a的示例的生存期一样长,将'a设置为struct_a的生存期。然后,每个对process的调用必须借用 * 至少 * 'a,可变的。因此,循环的每次迭代都必须在其整个生命周期内可变地借用struct_a,这是不可能的,因为一次只能存在一个可变引用。
根据您提供的代码,process没有理由接受可变引用,因为它不会改变任何东西。如果你把这个引用改为&'b self where 'b: 'a,一切都能正常工作并编译。在整个循环期间,引用仍然被采用,但由于它们是不可变的,因此它们可以共存。
请参见in playground

相关问题