18

I am writing a very simple recursive program for finding all prime numbers between two numbers:

use std::cmp::PartialOrd; use std::ops::{Add, Div, Rem, Sub}; fn _is_prime<T>(n: T, dividend: T, one: T) -> bool where T: Copy + Rem<Output = T> + Sub<Output = T> + PartialOrd, { if dividend == one { true } else { if n % dividend < one { false } else { _is_prime(n, dividend - one, one) } } } fn _primes_between<'a, T>(a: T, b: T, one: T, v: &'a mut Vec<T>) -> &'a mut Vec<T> where T: Copy + Rem<Output = T> + Add<Output = T> + Sub<Output = T> + PartialOrd, { if a <= b { if _is_prime(a, a - one, one) { v.push(a); } _primes_between(a + one, b, one, v) } else { v } } fn primes_between<T>(a: T, b: T) -> Vec<T> where T: Copy + Div<Output = T> + Rem<Output = T> + Add<Output = T> + Sub<Output = T> + PartialOrd, { let one = a / a; let mut v: Vec<T> = Vec::new(); *_primes_between(a, b, one, &mut v) } fn main() { primes_between(3, 13).iter().for_each(|i| println!("{}", i)); } 

The problem is:

error[E0507]: cannot move out of a mutable reference --> src/main.rs:42:5 | 42 | *_primes_between(a, b, one, &mut v) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `std::vec::Vec<T>`, which does not implement the `Copy` trait 

How do I solve that error?

1
  • 8
    Not related to your question, but in Rust the _ prefix is not necessary for privacy because there is the pub keyword, and so it has acquired the meaning of "unused". A seasoned Rustacean wouldn't name functions things like _primes_between and _is_prime. Besides using pub, another thing you can do to limit visibility is declare functions inside other functions, if they are not used elsewhere. Commented Oct 17, 2020 at 1:38

1 Answer 1

9

I'm not 100% sure, but I think the problem is that _primes_between() returns a reference that the code on line 31 is trying to make a copy of. (by taking ownership with the * operator) You could fix the problem by calling .clone() on the result, but I think in this case you don't need _primes_between() to return a value - you can just add the appropriate entries to the v parameter instead. Something like

fn _primes_between<T>(a: T, b: T, one: T, v: &mut Vec<T>) where T: Copy + Rem<Output = T> + Add<Output = T> + Sub<Output = T> + PartialOrd, { if a <= b { if _is_prime(a, a - one, one) { v.push(a); } _primes_between(a + one, b, one, v); } } fn primes_between<T>(a: T, b: T) -> Vec<T> where T: Copy + Div<Output = T> + Rem<Output = T> + Add<Output = T> + Sub<Output = T> + PartialOrd, { let one = a / a; let mut v: Vec<T> = Vec::new(); _primes_between(a, b, one, &mut v); v } 
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you! So, if the return is a Vec<T>, it is always be a "clone" (deep copy)?
There is no clone or deep copy here. _primes_between grows v in place and it is moved out of the function when primes_between returns.
To be clear, Rust generally doesn't deep copy things automatically. To do that, you have to call clone() on a struct that implements the Clone trait.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.