Modify fixed Array of a Struct by function

Viewed 165

I want to create a struct that have an array and that struct should have a function to modify that array by some parameters. Like I have a white paper and I want to draw a line in a specific direction over that paper, but after one call, I get the error: value used here after move.

I understand what the problem is, but I don't understand why this is a problem and how to solve that generally. I think I have not understood that principle behind that compiler error.

My second question is, is there a faster way to change a set of values by index in the fixed size array? In numpy I would write arr[x1,0:y] = newVal.

Here is the not-working example:

const N: usize = 4;

fn main() {
    println!("Hello, world!");
    let bebalken = [[false; N]; N];
    let stuetzen = [[true; N]; N];


    let mut f = Feld {
        abst: [[0; N]; N],
        bebalken: &bebalken,
        stuetzen: &stuetzen,
        balken: [[0; N]; N],

    };

    f.balken_einfugen(0, 0, 1, 4, 1);
    f.balken_einfugen(1, 0, 1, 4, 1);
}


struct Feld<'a> {
    abst: [[u8; N]; N],
    bebalken: &'a [[bool; N]; N],
    stuetzen: &'a [[bool; N]; N],
    balken: [[u8; N]; N], 
  
}

impl Feld<'_> {
    pub fn balken_einfugen<'a>(mut self, x: usize, y: usize, dir: u8, r: u8, connBar: u8) {
        let imax: usize = N;

        if dir == 1 {
            for i in 0..imax {
                self.balken[x + i][y] = connBar;
            }
        };
    }
}

And here the full compiler error:

error[E0382]: use of moved value: `f`
  --> src\main.rs:19:5
   |
10 |     let mut f = Feld {
   |         ----- move occurs because `f` has type `Feld<'_>`, which does not implement the `Copy` trait
...
18 |     f.balken_einfugen(0, 0, 1, 4, 1);
   |       ------------------------------ `f` moved due to this method call
19 |     f.balken_einfugen(1, 0, 1, 4, 1);
   |     ^ value used here after move
   |
note: this function consumes the receiver `self` by taking ownership of it, which moves `f`
  --> src\main.rs:35:36
   |
35 |     pub fn balken_einfugen<'a>(mut self, x: usize, y: usize, dir: u8, r: u8, connBar: u8)  {
   |                                    ^^^^
1 Answers

Methods which take self as an argument take ownership of the struct they're called on. This means you can only call the method once since it consumes the struct.

If you'd like maintain ownership of the struct, and call the method multiple times, you have to write the method so that it mutably borrows the struct instead of taking ownership, i.e. &mut self instead of mut self.

Once you make this change in your code it compiles:

const N: usize = 4;

fn main() {
    let bebalken = [[false; N]; N];
    let stuetzen = [[true; N]; N];

    let mut f = Feld {
        abst: [[0; N]; N],
        bebalken: &bebalken,
        stuetzen: &stuetzen,
        balken: [[0; N]; N],
    };

    f.balken_einfugen(0, 0, 1, 4, 1);
    f.balken_einfugen(1, 0, 1, 4, 1);
}

struct Feld<'a> {
    abst: [[u8; N]; N],
    bebalken: &'a [[bool; N]; N],
    stuetzen: &'a [[bool; N]; N],
    balken: [[u8; N]; N],
}

impl Feld<'_> {
    // `mut self` changed to `&mut self` here
    pub fn balken_einfugen<'a>(&mut self, x: usize, y: usize, dir: u8, r: u8, connBar: u8) {
        let imax: usize = N;

        if dir == 1 {
            for i in 0..imax {
                self.balken[x + i][y] = connBar;
            }
        };
    }
}

playground

Related