Borrowing and use after move issue

Hi,

I have two functions that I am trying to combine to one function. I am struggling with borrow/movement concept. Can I combine calc_prc and calc_prc2? The calling function is calling calc_prc and calc_prc2 with the same df_rows vector.

pub fn build_df(res:&mut Vec<crate::dbhandling::Res1>)
{
    let mut df_rows = Vec::new();
    let mut prices = Vec::new();

    copy_data_df(res, &mut df_rows, &mut prices);
    calc_prc(&mut df_rows, &mut prices);
    calc_prc2(&mut df_rows);
}

fn calc_prc(df_rows: &mut Vec<Dfrow>, prices: &mut Vec<f64>)
{
    let mut i = 0;
    for d in df_rows
    {
        if i == 0
        {
            i += 1;
            continue;
        }
        d.back_prc[0] = prc(prices[i], prices[i-1]);

        i += 1;
    }
}

fn calc_prc2(df_rows2: &mut Vec<Dfrow>)
{
    let num_entries = df_rows2.len();

    for t in 1..100
    {
        for i in t..num_entries
        {
            df_rows2[i].back_prc[t] = df_rows2[i-1].back_prc[t-1];
        }
    }
}

fn prc(newdata:f64, old:f64) -> f64
{
    return 100000.0 * (newdata - old) / old;
}

Thanks,
Mor

What is the error?

if I try to combine i get this:

fn calc_prc(df_rows: &mut Vec<Dfrow>, prices: &mut Vec<f64>)
{
    let mut i = 0;
    for d in df_rows
    {
        if i == 0
        {
            i += 1;
            continue;
        }
        d.back_prc[0] = prc(prices[i], prices[i-1]);

        i += 1;
    }
// }

// fn calc_prc2(df_rows2: &mut Vec<Dfrow>)
// {
    let num_entries = df_rows.len();

    for t in 1..100
    {
        for i in t..num_entries
        {
            df_rows[i].back_prc[t] = df_rows[i-1].back_prc[t-1];
        }
    }
}

48 | fn calc_prc(df_rows: &mut Vec, prices: &mut Vec)
| ------- move occurs because df_rows has type &mut Vec<Dfrow>, which does not implement the Copy trait
...
51 | for d in df_rows
| -------
| |
| df_rows moved due to this implicit call to .into_iter()
| help: consider borrowing to avoid moving into the for loop: &df_rows
...
66 | let num_entries = df_rows.len();
| ^^^^^^^ value borrowed here after move
|
note: this function consumes the receiver self by taking ownership of it, which moves df_rows
--> C:\Users\mgrut.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\iter\traits\collect.rs:232:18
|
232 | fn into_iter(self) -> Self::IntoIter;
| ^^^^

error: aborting due to previous error

Replace for d in df_rows with for d in &mut *df_rows

When I do that, I get:

error[E0277]: Vec<Dfrow> is not an iterator
--> src\myapp.rs:51:14
|
51 | for d in &mut df_rows
| ^^^^^^^^^^^^ Vec<Dfrow> is not an iterator
|
= help: the trait std::iter::Iterator is not implemented for Vec<Dfrow>
= note: required because of the requirements on the impl of std::iter::Iterator for &mut Vec<Dfrow>
= note: required because of the requirements on the impl of std::iter::Iterator for &mut &mut Vec<Dfrow>
= note: required because of the requirements on the impl of IntoIterator for &mut &mut Vec<Dfrow>
= note: required by into_iter

error: aborting due to previous error

for d in &mut *df_rows - note the asterisk.

Works! Thanks.

Can anyone add a small explanation? Or link to the right page in the document?

Thanks again.

A mutable reference does not implement the Copy trait because mutable references are guaranteed to be unique. Thus, since the for loop consumes the object given to it, the mutable reference is not accessible later.

The &mut *df_rows syntax creates a new mutable sub-reference to the same vector. The for loop then consumes the sub-mutable reference, leaving the original mutable reference intact and usable later. Creating a sub-reference like this is called reborrowing.

The compiler can automatically reborrow mutable references in some cases, but this is not one of them.

You can also write this as for d in df_rows.iter_mut().

ok, Thanks all for your help

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.