struct Sieve {
iter: Box<dyn Iterator<Item=u32>>,
}
impl Iterator for Sieve {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
let num = self.iter.next().unwrap();
self.iter = Box::new(self.iter.filter(move |n| n % prime != 0)); // Error
Some(prime)
}
}
The problem with this is: cannot move out of `self.iter` which is behind a mutable reference, because .filter takes ownership of self.iter.
I saw someone else use iter: Option<...>, but that seems unnecessary when I'm replacing it immediately after, as it requires users of the struct to unpack it, while it's guaranteed to be Some. I tried mem::take, but there's no Default for Iterator, and creating a garbage Iterator is really unnecessary.
Can I somehow take ownership of the attribute if I promise to fill it immediately after? The compiler should be able to see that nothing I do in between can access self.iter.
If this is not possible, is a feature with which this is possible something that could be useful for the language?
This is a well-known problem. Many people, myself included, wanted this at one point, but it is very difficult to write safely. See the discussion of RFC 1736 for more info. There are these two crates you can try, but make sure to read their documentation:
In what sense is it unnecessary? It is absolutely necessary if you want to ensure memory safety. It doesn't cost anything, because Empty is zero-sized, so the box doesn't allocate, and optimizations will likely remove it completely anyway. Pulling in a dependency for something that already exists in std seem like an overkill.
(Not to mention that these crates aren't magic: they either also require a default value, or invoke the panic handling mechanism and hard-abort. That's probably strictly worse in most circumstances than just creating an effectively empty box.)
I find it unnecessary and unintuitive to make an empty iterator when I just want to replace it with something new. It might be much better, but for me, it's harder to read and understand "swap out the value with an empty iterator, then replace it with a new one" than just "replace it with a new one".
But the point is: "just replace it with a new one" is not possible. You have to understand this anyway if you ever plan to use the two aforementioned crates correctly. At that point, you don't gain much from a 3rd-party dependency.
Safe Rust with mem::replace will require putting a temporary dummy value in self.iter. This is because there must be a safe-to-destroy value in self.iter at all times, in case some code panics and runs the destructor. The crates like take_mut make it safe by turning any panics into aborts while the value of self.iter is moved.
If you don't want a wasteful allocation, you can have a wasteful branch, and use iter: Option<Box<…>> with Option::take.
It isn't possible, and it could be useful, but it will never make into the language. If you read RFC 1736 you will see there are just too many pitfalls, some very hard to reason about, for allowing this for arbitrary types T. For a language designer its just an untenable position.
However, as a user, you don't really care about every possible T, every possible use case, just the things you actually want to replace. Just use take_mut::take or replace_with_or_abort as suggested above. Your code panics only if Box fails to allocate anyways (not sure your program can do anything but abort if you are OOM).