@@ -191,9 +191,34 @@ fn derive_known_layout_inner(ast: &DeriveInput) -> proc_macro2::TokenStream {
191
191
} ;
192
192
193
193
// SAFETY:
194
- // - The recursive call to `raw_from_ptr_len` preserves both address and provenance.
195
- // - The `as` cast preserves both address and provenance.
196
- // - `NonNull::new_unchecked` preserves both address and provenance.
194
+ // - The returned pointer has the same address and provenance as
195
+ // `bytes`:
196
+ // - The recursive call to `raw_from_ptr_len` preserves both
197
+ // address and provenance.
198
+ // - The `as` cast preserves both address and provenance.
199
+ // - `NonNull::new_unchecked` preserves both address and
200
+ // provenance.
201
+ // - If `Self` is a slice DST, the returned pointer encodes
202
+ // `elems` elements in the trailing slice:
203
+ // - This is true of the recursive call to `raw_from_ptr_len`.
204
+ // - `trailing.as_ptr() as *mut Self` preserves trailing slice
205
+ // element count [1].
206
+ // - `NonNull::new_unchecked` preserves trailing slice element
207
+ // count.
208
+ //
209
+ // [1] Per https://doc.rust-lang.org/reference/expressions/operator-expr.html#pointer-to-pointer-cast:
210
+ //
211
+ // `*const T`` / `*mut T` can be cast to `*const U` / `*mut U`
212
+ // with the following behavior:
213
+ // ...
214
+ // - If `T` and `U` are both unsized, the pointer is also
215
+ // returned unchanged. In particular, the metadata is
216
+ // preserved exactly.
217
+ //
218
+ // For instance, a cast from `*const [T]` to `*const [U]`
219
+ // preserves the number of elements. ... The same holds
220
+ // for str and any compound type whose unsized tail is a
221
+ // slice type, such as struct `Foo(i32, [u8])` or `(u64, Foo)`.
197
222
#[ inline( always) ]
198
223
fn raw_from_ptr_len(
199
224
bytes: :: zerocopy:: macro_util:: core_reexport:: ptr:: NonNull <u8 >,
0 commit comments