warning [E0502]:不能将`c`借作不可变的,因为它也被借为可变的

时间:2019-08-20 23:06:34

标签: rust

此代码使用Pascal三角形的mod计算组合。

MUsize是一种在操作中自动模量的结构。

当我使用特质存储结构来实现运算符重载时,我遇到了错误。

当我使用usize而不是MUsize时,不会发生此警告。

我应该在哪里修改?

我认为与ize相比,某些应该推导到MUsize的特征不能被推导。

// pascal's triangle
/*
from AtCoder abc 132
https://www.youtube.com/watch?v=mso8tE1yMl8
*/
/*
    1
   1 1
  1 2 1
 1 3 3 1

aCb -> row: a, column: b
*/

static MOD: usize = 1_000_000_000 + 7;
use std::ops::{AddAssign, SubAssign, MulAssign};
use std::ops::{Add, Sub, Mul};
#[derive(Copy, Clone, Debug)]
struct MUsize {x: usize}
impl MUsize {
    fn new(x: usize) -> MUsize {
        MUsize{x: x%MOD}
    }
}
impl AddAssign for MUsize {
    fn add_assign(&mut self, other: MUsize) {
        let tmp = self.x + other.x;
        *self = MUsize {
            x: if tmp >= MOD {tmp - MOD} else {tmp}
        };
    }
}
impl<'a> AddAssign<&'a MUsize> for MUsize {
    fn add_assign(&mut self, other: &MUsize) {
        let tmp = self.x + other.x;
        *self = MUsize {
            x: if tmp >= MOD {tmp - MOD} else {tmp}
        };
    }
}
impl SubAssign for MUsize {
    fn sub_assign(&mut self, other: MUsize) {
        let tmp = self.x + MOD - other.x;
        *self = MUsize {
            x: if tmp >= MOD {tmp - MOD} else {tmp}
        };
    }
}
impl MulAssign for MUsize {
    fn mul_assign(&mut self, other: MUsize) {
        *self = MUsize {
            x: self.x * other.x % MOD
        };
    }
}
impl Add for MUsize {
    type Output = MUsize;
    fn add(self, other: MUsize) -> MUsize {
        let mut res = MUsize::new(self.x);
        res += other.clone();
        res
    }
}
impl Sub for MUsize {
    type Output = MUsize;
    fn sub(self, other: MUsize) -> MUsize {
        let mut res = MUsize::new(self.x);
        res -= other;
        res
    }
}
impl Mul for MUsize {
    type Output = MUsize;
    fn mul(self, other: MUsize) -> MUsize {
        let mut res = MUsize::new(self.x);
        res *= other;
        res
    }
}

struct C {
    c: Vec<Vec<MUsize>>
}
impl C {
    fn new(max: usize) -> C {
        let mut c = vec![vec![MUsize::new(0); max+2]; max+2];
        c[0][0] = MUsize::new(1);
        for i in 0..max+1 {
            for j in 0..i+1 {
                c[i+1][j] += c[i][j];
                c[i+1][j+1] += c[i][j];
            }
        }
        C {c}
    }
    fn c(&self, n: usize, k: usize) -> usize {
        self.c[n][k].x
    }
}

fn main() {
    let c = C::new(40);
    println!("{}", c.c(5, 2));
}
   warning[E0502]: cannot borrow `c` as immutable because it is also borrowed as mutable
      --> src/main.rs:83:30
       |
    83 |                 c[i+1][j] += c[i][j];
       |                 -------------^------
       |                 |            |
       |                 |            immutable borrow occurs here
       |                 mutable borrow occurs here
       |                 mutable borrow later used here
       |
       = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
       = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future

    warning[E0502]: cannot borrow `c` as immutable because it is also borrowed as mutable
      --> src/main.rs:84:32
       |
    84 |                 c[i+1][j+1] += c[i][j];
       |                 ---------------^------
       |                 |              |
       |                 |              immutable borrow occurs here
       |                 mutable borrow occurs here
       |                 mutable borrow later used here
       |
       = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
       = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future

        Finished dev [unoptimized + debuginfo] target(s) in 0.47s

1 个答案:

答案 0 :(得分:0)

- c[i+1][j] += c[i][j];
- c[i+1][j+1] += c[i][j];

+ let tmp = c[i][j];
+ c[i+1][j] += tmp;
+ c[i+1][j+1] += tmp;

这可以在没有警告的情况下工作,但是这种方式并不酷。