Thanks, that's good to know, I wasn't aware of this!
So this is "safe", it may or may not be as "efficient", but it's definitely not "convenient" enough for me to recommend it to users of my API.
I would still like to have an easier way, e.g. by calling a single function/method.
OK, thanks, so I think this would change my little example to:
let init_slice = uninit_slice.as_out().copy_from_slice(init_slice);
This is still too complicated for my taste.
I think I understand the problem now, thanks to the linked example, but I don't think it applies in my case. And I don't think I actually need something like the
You are talking about what happens when I get a
&mut [T] from somewhere out of my control and
transmute() it willy-nilly to a
However, I never get a
&mut [T] and I completely control all my internal storage.
When I return a
&mut [MaybeUninit<T>] from my API, I know that it's not referencing memory where a "living" object is stored. It may or may be initialized, but if it's initialized, it just contains garbage values where nobody else has a reference to. Therefore, users are free to assign
MaybeUninit::uninit() as much as they want. They will only ever cause their previously written objects to leak, but I think they will not be able to cause the above-mentioned problem.
In the meantime I've come up with a possible solution in my concrete case:
This will allow users to write:
uninit_slice is the
&mut [MaybeUninit<T>] they got from my API and
other_slice is a "normal"
&[T] from wherever they want.
Without further steps this would still leak their objects, and they indeed have to call a separate
unsafe function (provided by my API) that will mark their initialized items as "initialized", which will lead to them being dropped properly at a later time.
While writing this comment I've already found a problem with my initial implementation and I have removed the return value.
I think that's the problem with my original question: I was asking for returning a
&mut [T] after copying, but I now think that's bad! I only actually need the copying to happen, I don't really need the return value. I was just asking for it "for completeness", because it looked like a nicely symmetric thing to do. It looked harmless, but now I think it isn't!
I don't think it's officially unsound (but I'm of course not sure), but it could lead to leaks.
I think this also applies to any function that may be added to the standard library: It should not return a
When writing to
&mut [MaybeUninit<T>], the contract is that the written objects may or may not be dropped at some point. Further guarantees might be given by the library implementer, but not by the language itself.
However, when assigning to a
&mut [T], the contract is clearly that the previous inhabitant will be dropped immediately and the new object is guaranteed to be dropped at some later point. AFAIK, that's guaranteed by safe Rust.
The suggested function
write_frome_slice() cannot guarantee that, therefore it shouldn't return a
The copying should still be fine, AFAICT, and it would still be a very useful function!
Thanks, I've seen that. I think that's indeed a very similar situation, but as you say, it's
u8-only and I would like to be able to use a more generic