在调用一个&'一个mut self方法之后,不能一次多次将变量借用变量

时间:2018-04-19 19:29:19

标签: rust

我的Graph对象的生命周期/借用存在问题。

fn main() {
    let mut g = Graph {
        nodePointer: &mut 0,
        edgePointer: &mut 0,
        nodes: &mut Vec::new(),
        edges: &mut Vec::new(),
    };
    let node1 = g.add_node((1, 1));
    let node2 = g.get_node(0);
}

pub struct Graph<'a> {
    pub nodePointer: &'a mut usize,
    pub edgePointer: &'a mut usize,
    pub nodes: &'a mut Vec<Node>,
    pub edges: &'a mut Vec<Edge>,
}

impl<'a> Graph<'a> {
    pub fn add_node(&'a mut self, data: (u64, u64)) -> usize {
        let id: usize = *self.nodePointer;
        self.nodes.push(Node {
            id: id,
            datum: data,
        });
        *self.nodePointer += 1;
        return id;
    }

    pub fn get_node(&'a mut self, id: usize) -> &'a Node {
        return &self.nodes[id];
    }

    pub fn add_edge(&'a mut self, source: u64, target: u64, weight: u16) -> usize {
        let id: usize = *self.nodePointer;
        self.edges.push(Edge {
            id: id,
            source,
            target,
            weight,
        });
        *self.edgePointer = *self.edgePointer + 1;
        return id;
    }
}

pub struct Node {
    pub id: usize,
    pub datum: (u64, u64),
}

pub struct Edge {
    pub id: usize,
    pub source: u64,
    pub target: u64,
    pub weight: u16,
}
error[E0499]: cannot borrow `g` as mutable more than once at a time
  --> src/main.rs:9:17
   |
8  |     let node1 = g.add_node((1, 1));
   |                 - first mutable borrow occurs here
9  |     let node2 = g.get_node(0);
   |                 ^ second mutable borrow occurs here
10 | }
   | - first borrow ends here

2 个答案:

答案 0 :(得分:2)

您的问题源于对生命的滥用,特别是在您add_node的签名中:

pub fn add_node(&'a mut self, data: (u64, u64)) -> usize

在此签名中,您声明add_node&'a mut self上占用Graph<'a>;换句话说,你告诉Rust这个方法需要在图表的生命周期'a结束之前不能删除图表。但由于它的图形本身持有对图形的引用,因此删除引用的唯一时间是图形本身被删除。

由于add_node并不要求您返回对结构中任何对象的引用,因此保持该借用是无关紧要的。如果您更改add_node方法以删除显式生存期:

pub fn add_node(&mut self, data: (u64, u64)) -> usize

然后您的示例不再引发错误,因为add_node现在只是借用self,直到它完成了该功能。 (在幕后,这有效地创建了第二个生命周期'b并使签名成为&'b mut self

请参阅the playground以获取证明。

答案 1 :(得分:0)

考虑一下:

struct Foo<'a> {
    x: &'a i32,
}

正如book所述:

  

那么为什么我们需要一辈子呢?我们需要确保对Foo的任何引用都不能超过它包含的i32的引用。

如果您写的内容如下:

impl<'a> Graph<'a> {
    pub fn add_node(&'a mut self, data: (u64, u64)) -> usize {
        ...

生命周期声明&'a mut self不是为了将Graph实例的生命周期与包含的引用相关联, 但是为了声明可变self引用保持为'a字段引用声明的相同生命周期Graph

fn main() {    
    let mut g = Graph {                          // <------------
        nodePointer: &mut 0,                     //             |            
        edgePointer: &mut 0,                     // lifetime    |
        nodes: &mut Vec::new(),                  // of Graph    | 'a
        edges: &mut Vec::new(),                  // references  |
    };                                           //             |
    let node1 = Graph::add_node(&mut g, (1, 1)); //             |   
    let node2 = Graph::get_node(&mut g, 0);      //             |
}                                                //<-------------

g.get_node(0)被重写为Graph::get_node(&mut g, 0),仅仅是为了明确公开&mut引用

查看'a的生命周期很明显,引用&mut g可以多次借用,这会导致错误。