@@ -51,15 +51,28 @@ Note that there are other ways to trigger this UB without explicitely using
51
51
```
52
52
53
53
- this is exactly equivalent to calling `mem :: uninitialized :: <T >()`,
54
+ which breaks the _validity_ invariant of `T ` and thus causes
55
+ " instant UB" .
56
+
57
+ There currently only two exceptions / _valid_ use cases:
58
+
59
+ - either [`type T = [MaybeUninit <U >; N ]`][`uninit_array `],
60
+
61
+ - or `T ` is an inhabited ZST (this may , however , break safety
62
+ invariants associated with the properties of the type , causing UB
63
+ once such broken invariant is witnessed ).
54
64
55
65
- yes , using [`MaybeUninit `] is more subtle than just changing a function
56
66
call .
57
67
58
68
- ```rust
59
69
let mut vec : Vec <u8 > = Vec :: with_capacity (100 ); // Fine
60
70
unsafe {
61
- vec . set_len (100 ); // UB: we have an uninitialized [u8; 100] in the heap
71
+ vec . set_len (100 ); // we have an uninitialized [u8; 100] in the heap
72
+ // This has broken the _safety_ invariant of `Vec`, but is not yet UB
73
+ // since no code has witnessed the broken state
62
74
}
75
+ let heap_bytes : & [u8 ] = & * vec ; // Witness the broken safety invariant: UB!
63
76
```
64
77
65
78
## Instead , (you can ) use [`MaybeUninit `]
@@ -98,6 +111,7 @@ It is all about the _**delayed** initialization pattern_:
98
111
let mut x = MaybeUninit :: <i32 >:: uninit ();
99
112
100
113
x = MaybeUninit :: new (42 );
114
+ assert_eq! (42 , unsafe { x . assume_init () });
101
115
```
102
116
103
117
- or through a raw `* mut T ` pointer (contrary to Rust references ,
@@ -110,9 +124,24 @@ It is all about the _**delayed** initialization pattern_:
110
124
111
125
unsafe {
112
126
x . as_mut_ptr (). write (42 );
127
+ assert_eq! (x . assume_init (), 42 );
113
128
}
114
129
```
115
130
131
+ - or , if you use the tools of this crate , by upgrading the
132
+ `& mut MaybeUninit <T >` into a "`& out T `" type called
133
+ [`Out <T >`][`crate :: prelude :: Out `]:
134
+
135
+ ```rust
136
+ #! [forbid(unsafe_code)] // no unsafe!
137
+ use :: core :: mem :: MaybeUninit ;
138
+ use :: uninit :: prelude :: * ;
139
+
140
+ let mut x = MaybeUninit :: uninit ();
141
+ let at_init_x : & i32 = x . as_out (). write (42 );
142
+ assert_eq! (at_init_x , & 42 );
143
+ ```
144
+
116
145
3 . * * Type - level upgrade **
117
146
118
147
Once we know , for sure , that the memory has been initialized , we can
@@ -151,9 +180,9 @@ pub trait Read {
151
180
}
152
181
```
153
182
154
- that is, there is no way to ` .read() ` into an unitialized buffer (it would
183
+ that is, there is no way to ` .read() ` into an uninitialized buffer (it would
155
184
require an api taking either a ` (*mut u8, usize) ` pair, or, equivalently and
156
- by the way more ergonomically, a ` &mut [MaybeUninit<u8>] ` ).
185
+ by the way more ergonomically, a [ ` &out [u8] ` ] [ `crate::prelude::Out` ] ).
157
186
158
187
# Enter ` ::uninit `
159
188
@@ -163,7 +192,7 @@ So, the objective of this crate is double:
163
192
164
193
For instance:
165
194
166
- - [`uninit_byte_array !`]
195
+ - [`uninit_array !`]
167
196
168
197
- [`Vec::reserve_uninit`]
169
198
@@ -174,19 +203,14 @@ So, the objective of this crate is double:
174
203
175
204
- [ ` ReadIntoUninit ` ]
176
205
177
- - [ ` .init_with_copy_from_slice() ` ]
178
-
179
- ## Status
180
-
181
- This is currently at an realy stage, so it "only" includes
182
- utilities to work with ** uninitialized bytes** or integers.
206
+ - [ Initialize an uninitialized buffer with ` .copy_from_slice() ` ]
183
207
184
208
[ `Read` ] : https://doc.rust-lang.org/1.36.0/std/io/trait.Read.html
185
209
[ `mem::uninitialized` ] : https://doc.rust-lang.org/core/mem/fn.uninitialized.html
186
210
[ `MaybeUninit` ] : https://doc.rust-lang.org/core/mem/union.MaybeUninit.html
187
- [ `.assume_init_by_ref()` ] : https://docs.rs/uninit/0.1 .0/uninit/trait.MaybeUninitExt.html#method .assume_init_by_ref
188
- [ `.assume_init_by_mut()` ] : https://docs.rs/uninit/0.1 .0/uninit/trait.MaybeUninitExt.html#method .assume_init_by_mut
189
- [ `uninit_byte_array !` ] : https://docs.rs/uninit/0.1 .0/uninit/macro.uninit_byte_array.html
190
- [ `Vec::reserve_uninit` ] : https://docs.rs/uninit/0.1 .0/uninit/trait.VecReserveUninit .html#tymethod.reserve_uninit
191
- [ `.init_with_copy_from_slice ()`] : https://docs.rs/uninit/0.1 .0/uninit/trait.InitWithCopyFromSlice .html#tymethod.init_with_copy_from_slice
192
- [ `ReadIntoUninit` ] : https://docs.rs/uninit/0.1 .0/uninit/trait.ReadIntoUninit.html
211
+ [ `.assume_init_by_ref()` ] : https://docs.rs/uninit/0.2 .0/uninit/extension_traits/ trait.MaybeUninitExt.html#tymethod .assume_init_by_ref
212
+ [ `.assume_init_by_mut()` ] : https://docs.rs/uninit/0.2 .0/uninit/extension_traits/ trait.MaybeUninitExt.html#tymethod .assume_init_by_mut
213
+ [ `uninit_array !` ] : https://docs.rs/uninit/0.2 .0/uninit/macro.uninit_byte_array.html
214
+ [ `Vec::reserve_uninit` ] : https://docs.rs/uninit/0.2 .0/uninit/extension_traits/ trait.VecCapacity .html#tymethod.reserve_uninit
215
+ [ Initialize an uninitialized buffer with `.copy_from_slice ()`] : https://docs.rs/uninit/0.2 .0/uninit/out_ref/struct.Out .html#method.copy_from_slice
216
+ [ `ReadIntoUninit` ] : https://docs.rs/uninit/0.2 .0/uninit/read /trait.ReadIntoUninit.html
0 commit comments