Epse
Epse

Reputation: 67

Rust use of moved value

When using below function:

fn factors(number: &BigInt) -> Vec<BigInt> {
    let mut n = number.clone();
    let mut i: BigInt = ToBigInt::to_bigint(&2).unwrap();
    let mut factors = Vec::<BigInt>::new();

    while i * i <= n {
        if (n % i) == ToBigInt::to_bigint(&1).unwrap() {
            i = i + ToBigInt::to_bigint(&1).unwrap();
        }
        else {
            n = n/i as BigInt;
            factors.push(i);
        }
        i = i + ToBigInt::to_bigint(&1).unwrap();
    }
    if n > i {
        factors.push(n);
    }
    factors
}

I get moved value errors for literally every time i or n is used, starting from the line with while, also in the if. I have read about borrowing, which I understand decently, but this thing I don't understand. I am not "copying" the value at all, so I don't see anywhere were I could lose ownership of the variables.

Upvotes: 6

Views: 6760

Answers (2)

malbarbo
malbarbo

Reputation: 11187

Mul (and the other arithmetic operators) take the parameters by value, so i * i move the value i (this is not a problem for primitive numbers because they implement Copy - BigInt does not).

As Mul is implemented for (two) &BigInt, you can do the multiplication (and the other arithmetic operations) with &:

use num::*;

fn factors(number: &BigInt) -> Vec<BigInt> {
    let mut n = number.clone();
    let mut i = BigInt::from(2);
    let mut factors = Vec::new();

    while &i * &i <= n {
        if (&n % &i) == BigInt::one() {
            i = i + BigInt::one();

        } else {
            n = n / &i;
            factors.push(i.clone());
        }
        i = i + BigInt::one();
    }
    if n > i {
        factors.push(n);
    }
    factors
}

Note that I also made some simplifications, like omitting the type on Vec::new and using BigInt::from (cannot fail).

Upvotes: 9

JDemler
JDemler

Reputation: 1316

Remember that operators in Rust are just syntactic sugar for function calls.

a + b translates to a.add(b).

Primitive types such as i32 implement the trait Copy. Thus, they can be copied into such an add function and do not need to be moved.

I assume the BigInt type you are working with does not implement this trait. Therefore, in every binary operation you are moving the values.

Upvotes: 4

Related Questions