Why does foo return an error "bar is dropped while still borrowed"? Is there a way to do that? Is this something missing from the compiler?
I'm trying to get rid of the first Arc::clone here but can't succeed. It won't let me reference self twice for the self.green.children and parent parts.
You can't take ownership of Arc's contents, because it's a shared type and others can be still using it.
So Arc doesn't have its own into_iter(). You get a fallback to slice's iterator, which borrows from the slice.
When you loan Arc to a function, it guarantees that the Arc lives longer and so does its content.
If you move Arc into a function, and don't keep it anywhere, it will be destroyed at the end of its scope. If that was the last Arc, the content will be destroyed too.
The problem is that the standard library doesn’t have an IntoIterator impl for Arc<[T]>, though it could provide one using indexing (like @cuviper's solution). You could write your own iterator type, though this is quite a bit more code:
Thanks! Is there a proposal to add that to the standard library? Isn't the issue with my children function that I'm doing self.green.children.iter(), where the compiler fails to move self to the iterator?
It probably doesn't exist in std as it requires cloning each slice member. I could see an iter_cloned on Arc<[T]> where T: Clone method or such though.
The issue with getting rid of the lifetime (going from self: &Arc<_> to self: Arc<_>) is that you would be trying to return an iterator that borrows from a local variable. The compiler can't spontaneously decide to move things into the borrowing iterator (slice::Iter<'_, GreenItem>), any more that it can decide to spontaneously add new fields to your own structs due to far away code.[1]
On top of that, even it was possible, it would be self-referencial and unsound.
where iter is borrowing data -- it holds pointers or references to data. When you move the MagicIter struct, the location of the [T; 10] and all the contained Ts move, and the pointers in data are now dangling.
Things don't always dangle when indirection (e.g. storing on the heap) is involved, but that's not part of the type system so it's nothing the compiler can solve on its own. The language would have to evolve significantly in order for such a self-referencial iterator to be possible without unsafe.
So you can't use .iter(), you need some non-borrowing iterator if you want to change the signature.
Maybe, maybe not. Nothing jumps out at me,[1] but there's more to borrow checking than dangling pointers -- and honestly I didn't spend much time thinking about it.
I didn't spend much time because: It's not worth it. Just go with the non-unsafe version that's available to you.
well, that transmute is unnecessary if you convert references/pointers instead ↩︎