Incremental Sieve of Eratosthenes using iterators
Your code is totally fine and idiomatic, but I would change some minor points:

use std::collections::HashMap;

struct Sieve {
    composites: HashMap&lt;u64, Vec&lt;u64&gt;&gt;,
    current: u64,
}

impl Default for Sieve {
    fn default() -&gt; Self {
        Sieve {
            composites: HashMap::new(),
            current: 2,
        }
    }
}

impl Sieve {
    pub fn new() -&gt; Sieve {
        Default::default()
    }
}

impl Iterator for Sieve {
    type Item = u64;

    fn next(&amp;mut self) -&gt; Option&lt;u64&gt; {
        fn next_prime(composites: &amp;mut HashMap&lt;u64, Vec&lt;u64&gt;&gt;, x: u64) -&gt; u64 {
            match composites.get(&amp;x) {
                Some(numbers) =&gt; {
                    for num in numbers.to_owned() {
                        composites
                            .entry(x + num)
                            .and_modify(|v| v.push(num))
                            .or_insert_with(|| vec![num]);
                    }
                    composites.remove(&amp;x);
                    next_prime(composites, x + 1)
                }
                None =&gt; {
                    composites.insert(x * x, vec![x]);
                    x
                }
            }
        }

        let prime = next_prime(&amp;mut self.composites, self.current);
        self.current = prime + 1; // This number will be the next to be tested

        Some(prime)
    }
}

fn main() {
    let mut sieve = Sieve::new();

    assert_eq!(sieve.next(), Some(2));
    assert_eq!(sieve.next(), Some(3));
    assert_eq!(sieve.next(), Some(5));
    assert_eq!(sieve.next(), Some(7));
}



It is good to implement Default when you can build your data structure without parameters (related answer).
This is a good practice to put assertions instead of prints. That's easier to change to code and verify that it is still ok.
The naming of the variables is important; but I do not pretend that mine is perfect, though. By the way, _num should not be prefixed with an underscore because it is used.
You can run clippy to catch some common error. Clippy warns you that you create a vec![_num] at each iteration. You should give to or_insert_with a closure that will build the correct vector.
The more important refactoring that I did is to make the algorithm more "functional". I think that yours is difficult to reason about because it calls recursively the Iterator::next method and rely on internal state.