无法分配给`self.x`,因为它是借用的

时间:2017-11-06 09:29:48

标签: rust ownership borrow-checker

我有两个功能:

// A simple struct
struct S {
    w: u8,
    h: u8,
    x: Vec<u8>,
    y: Vec<u8>,
}

// Implementation of the struct S
impl S {
    // Seems to work
    fn new(_w: u8, _h: u8, _x: &Vec<u8>, _y: &Vec<u8>) -> S {
        S {
            w: _w,
            h: _h,
            x: _x.clone(),
            y: _y.clone(),
        }
    }

    fn calc(&mut self) {
        let mut min_x = self.x.iter().min().unwrap();
        let mut max_x = self.x.iter().max().unwrap();
        let mut min_y = self.y.iter().min().unwrap();
        let mut max_y = self.y.iter().max().unwrap();

        // Here's the line that gives the error
        self.x = self.x
            .iter()
            .map(|v| norm_value(*v, *min_x, *max_x, 0, self.w))
            .collect();
    }
}

fn norm_value<A, B, C, D, E>(_: A, _: B, _: C, _: D, _: E) -> ! { panic!() }
  1. new创建一个新的S对象。这似乎有效,但如果我做了一些可怕的错误并且碰巧正常工作,请纠正我。

  2. calc尝试修改成员xy

  3. 编译器报告此错误:

    error[E0506]: cannot assign to `self.x` because it is borrowed
      --> src/main.rs:28:9
       |
    22 |           let mut min_x = self.x.iter().min().unwrap();
       |                           ------ borrow of `self.x` occurs here
    ...
    28 | /         self.x = self.x
    29 | |             .iter()
    30 | |             .map(|v| norm_value(*v, *min_x, *max_x, 0, self.w))
    31 | |             .collect();
       | |______________________^ assignment to borrowed `self.x` occurs here
    

    我在哪里借self.x?我是Rust的新手,但这样的事情毫无意义。

1 个答案:

答案 0 :(得分:2)

calc开头的所有变量绑定都会将共享引用(&u8)返回到self.xself.y,这意味着您无法再变异它们。< / p>

为了不在最后一次分配时受到这些借用的约束,您可以clone()引用以获得常规u8

let mut min_x = self.x.iter().min().unwrap().clone();
let mut max_x = self.x.iter().max().unwrap().clone();
let mut min_y = self.y.iter().min().unwrap().clone();
let mut max_y = self.y.iter().max().unwrap().clone();

我不确定这是否能解决您的所有问题,因为您没有提供norm_value的签名。

对于new方法,您可能希望更改签名以按值而不是通过引用获取它们:

fn new(w: u8, h: u8, x: Vec<u8>, y: Vec<u8>) -> S {
    S { w: w, h: h, x: x, y: y }
}

let s = S::new(10, 10, vec![1, 2, 3, 4], vec![52, 10, 23, 56]);

请注意,我删除了下划线 - 您不需要在它们前面添加函数参数,如果删除它们,编译器仍然会清楚它们。使用下划线添加变量标识符通常用于使#[warn(unused_variables)]警告静音。