Perhaps two different types of references would be most useful:
-
&out T is a write-only reference to a !drop type
-
&uninit T is a write-once, then readable reference to any type
&out T borrowing rules would be that you could have any number of &out T references simultaneously, but, no concurrent &mut T or &T references only have a single &out T reference in effect, the same as &mut T. &uninit T would have the same borrowing rules as &mut T and you could not have an &uninit T concurrent with an &mut T.
Once fully initialized you could coerce an &uninit T to an &mut T or an &T. A !drop &uninit T could be coerced at any time to an &out T. A drop &uninit T could not be coerced to a &out T. You could never coerce an &mut T to an &uninit T.
So, we would then have 4 reference types:
-
&T - that we all know and love (read-only, multiple-concurrent)
-
&mut T - that we all know and love (read/write, exclusive)
-
&out T - (write-only, multiple-concurrent, !drop only types)
-
&uninit T - (write-once, then read, exclusive, drop|!drop types)
Valid coercions would be:
-
&T (none)
-
&mut T -> &T or &out T
-
&out T -> &T or &mut T (no, this would be unsafe)
-
&uninit T -> &T or &mut T once fully initialized (until then, may not be coerced) or -> &out T if it is a !drop type (at any time)
Caveat: Allowing coercions from/to &mut T and &T for &out T kind of defeats the real benefit of &out T (being write-only memory). So, it would be nice to NOT allow that so the coercions (safe coercions that is) would be:
-
&T (none)
-
&mut T -> &T or &out T
-
&out T (none, once an out always an out)
-
&uninit T -> &T or &mut T once fully initialized (until then, may not be coerced) OR to &out T if it is a !drop type (at any time)
It seems like having both a new &out T and a new &uninit T would be useful for different orthogonal purposes. &out T would be especially useful for things like write-only video buffers or other type of specially mapped pages. &uninit T would be useful for in-place initialization without copy/move.