/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerocopy-0.8.33/src/pointer/mod.rs
Line | Count | Source |
1 | | // Copyright 2023 The Fuchsia Authors |
2 | | // |
3 | | // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 |
4 | | // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT |
5 | | // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. |
6 | | // This file may not be copied, modified, or distributed except according to |
7 | | // those terms. |
8 | | |
9 | | //! Abstractions over raw pointers. |
10 | | |
11 | | mod inner; |
12 | | #[doc(hidden)] |
13 | | pub mod invariant; |
14 | | mod ptr; |
15 | | mod transmute; |
16 | | |
17 | | #[doc(hidden)] |
18 | | pub use {inner::PtrInner, transmute::*}; |
19 | | #[doc(hidden)] |
20 | | pub use { |
21 | | invariant::{BecauseExclusive, BecauseImmutable, Read}, |
22 | | ptr::Ptr, |
23 | | }; |
24 | | |
25 | | /// A shorthand for a maybe-valid, maybe-aligned reference. Used as the argument |
26 | | /// to [`TryFromBytes::is_bit_valid`]. |
27 | | /// |
28 | | /// [`TryFromBytes::is_bit_valid`]: crate::TryFromBytes::is_bit_valid |
29 | | pub type Maybe<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Unaligned> = |
30 | | Ptr<'a, T, (Aliasing, Alignment, invariant::Initialized)>; |
31 | | |
32 | | /// Checks if the referent is zeroed. |
33 | 0 | pub(crate) fn is_zeroed<T, I>(ptr: Ptr<'_, T, I>) -> bool |
34 | 0 | where |
35 | 0 | T: crate::Immutable + crate::KnownLayout, |
36 | 0 | I: invariant::Invariants<Validity = invariant::Initialized>, |
37 | 0 | I::Aliasing: invariant::Reference, |
38 | | { |
39 | 0 | ptr.as_bytes::<BecauseImmutable>().as_ref().iter().all(|&byte| byte == 0) |
40 | 0 | } |
41 | | |
42 | | #[doc(hidden)] |
43 | | pub mod cast { |
44 | | use core::{marker::PhantomData, mem}; |
45 | | |
46 | | use crate::{ |
47 | | layout::{SizeInfo, TrailingSliceLayout}, |
48 | | HasField, KnownLayout, PtrInner, |
49 | | }; |
50 | | |
51 | | /// A pointer cast or projection. |
52 | | /// |
53 | | /// # Safety |
54 | | /// |
55 | | /// The implementation of `project` must satisfy its safety post-condition. |
56 | | pub unsafe trait Project<Src: ?Sized, Dst: ?Sized> { |
57 | | /// Projects a pointer from `Src` to `Dst`. |
58 | | /// |
59 | | /// # Safety |
60 | | /// |
61 | | /// The returned pointer refers to a non-strict subset of the bytes of |
62 | | /// `src`'s referent, and has the same provenance as `src`. |
63 | | fn project(src: PtrInner<'_, Src>) -> *mut Dst; |
64 | | } |
65 | | |
66 | | /// A [`Project`] which preserves the address of the referent – a pointer |
67 | | /// cast. |
68 | | /// |
69 | | /// # Safety |
70 | | /// |
71 | | /// A `Cast` projection must preserve the address of the referent. It may |
72 | | /// shrink the set of referent bytes, and it may change the referent's type. |
73 | | pub unsafe trait Cast<Src: ?Sized, Dst: ?Sized>: Project<Src, Dst> {} |
74 | | |
75 | | /// A no-op pointer cast. |
76 | | #[derive(Default, Copy, Clone)] |
77 | | #[allow(missing_debug_implementations)] |
78 | | pub struct IdCast; |
79 | | |
80 | | // SAFETY: `project` returns its argument unchanged, and so it is a |
81 | | // provenance-preserving projection which preserves the set of referent |
82 | | // bytes. |
83 | | unsafe impl<T: ?Sized> Project<T, T> for IdCast { |
84 | | #[inline(always)] |
85 | 565k | fn project(src: PtrInner<'_, T>) -> *mut T { |
86 | 565k | src.as_ptr() |
87 | 565k | } <zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::D<[u16]>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::D<[u16]>>>::project Line | Count | Source | 85 | 141k | fn project(src: PtrInner<'_, T>) -> *mut T { | 86 | 141k | src.as_ptr() | 87 | 141k | } |
<zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>>>::project Line | Count | Source | 85 | 141k | fn project(src: PtrInner<'_, T>) -> *mut T { | 86 | 141k | src.as_ptr() | 87 | 141k | } |
<zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::D<[u16]>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::D<[u16]>>>::project Line | Count | Source | 85 | 141k | fn project(src: PtrInner<'_, T>) -> *mut T { | 86 | 141k | src.as_ptr() | 87 | 141k | } |
<zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>>>::project Line | Count | Source | 85 | 141k | fn project(src: PtrInner<'_, T>) -> *mut T { | 86 | 141k | src.as_ptr() | 87 | 141k | } |
Unexecuted instantiation: <zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::D<[u16]>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::D<[u16]>>>::project Unexecuted instantiation: <zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>>>::project Unexecuted instantiation: <zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::D<[u16]>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::D<[u16]>>>::project Unexecuted instantiation: <zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>>>::project Unexecuted instantiation: <zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::D<[u16]>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::D<[u16]>>>::project Unexecuted instantiation: <zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>>>::project Unexecuted instantiation: <zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<_, _>>::project Unexecuted instantiation: <zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::D<[u16]>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::D<[u16]>>>::project Unexecuted instantiation: <zerocopy::pointer::cast::IdCast as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>>>::project |
88 | | } |
89 | | |
90 | | // SAFETY: The `Project::project` impl preserves referent address. |
91 | | unsafe impl<T: ?Sized> Cast<T, T> for IdCast {} |
92 | | |
93 | | /// A pointer cast which preserves or shrinks the set of referent bytes of |
94 | | /// a statically-sized referent. |
95 | | /// |
96 | | /// # Safety |
97 | | /// |
98 | | /// The implementation of [`Project`] uses a compile-time assertion to |
99 | | /// guarantee that `Dst` is no larger than `Src`. Thus, `CastSized` has a |
100 | | /// sound implementation of [`Project`] for all `Src` and `Dst` – the caller |
101 | | /// may pass any `Src` and `Dst` without being responsible for soundness. |
102 | | #[allow(missing_debug_implementations, missing_copy_implementations)] |
103 | | pub enum CastSized {} |
104 | | |
105 | | // SAFETY: By the `static_assert!`, `Dst` is no larger than `Src`, |
106 | | // and so all casts preserve or shrink the set of referent bytes. All |
107 | | // operations preserve provenance. |
108 | | unsafe impl<Src, Dst> Project<Src, Dst> for CastSized { |
109 | | #[inline(always)] |
110 | 0 | fn project(src: PtrInner<'_, Src>) -> *mut Dst { |
111 | 0 | static_assert!(Src, Dst => mem::size_of::<Src>() >= mem::size_of::<Dst>()); |
112 | 0 | src.as_ptr().cast::<Dst>() |
113 | 0 | } |
114 | | } |
115 | | |
116 | | // SAFETY: The `Project::project` impl preserves referent address. |
117 | | unsafe impl<Src, Dst> Cast<Src, Dst> for CastSized {} |
118 | | |
119 | | /// A pointer cast which preserves or shrinks the set of referent bytes of |
120 | | /// a dynamically-sized referent. |
121 | | /// |
122 | | /// # Safety |
123 | | /// |
124 | | /// The implementation of [`Project`] uses a compile-time assertion to |
125 | | /// guarantee that the cast preserves the set of referent bytes. Thus, |
126 | | /// `CastUnsized` has a sound implementation of [`Project`] for all `Src` |
127 | | /// and `Dst` – the caller may pass any `Src` and `Dst` without being |
128 | | /// responsible for soundness. |
129 | | #[allow(missing_debug_implementations, missing_copy_implementations)] |
130 | | pub enum CastUnsized {} |
131 | | |
132 | | // SAFETY: The `static_assert!` ensures that `Src` and `Dst` have the same |
133 | | // `SizeInfo`. Thus, casting preserves the set of referent bytes. All |
134 | | // operations are provenance-preserving. |
135 | | unsafe impl<Src, Dst> Project<Src, Dst> for CastUnsized |
136 | | where |
137 | | Src: ?Sized + KnownLayout, |
138 | | Dst: ?Sized + KnownLayout<PointerMetadata = Src::PointerMetadata>, |
139 | | { |
140 | | #[inline(always)] |
141 | 0 | fn project(src: PtrInner<'_, Src>) -> *mut Dst { |
142 | | // FIXME: |
143 | | // - Is the alignment check necessary for soundness? It's not |
144 | | // necessary for the soundness of the `Project` impl, but what |
145 | | // about the soundness of particular use sites? |
146 | | // - Do we want this to support shrinking casts as well? |
147 | 0 | static_assert!(Src: ?Sized + KnownLayout, Dst: ?Sized + KnownLayout => { |
148 | | let t = <Src as KnownLayout>::LAYOUT; |
149 | | let u = <Dst as KnownLayout>::LAYOUT; |
150 | | t.align.get() >= u.align.get() && match (t.size_info, u.size_info) { |
151 | | (SizeInfo::Sized { size: t }, SizeInfo::Sized { size: u }) => t == u, |
152 | | ( |
153 | | SizeInfo::SliceDst(TrailingSliceLayout { offset: t_offset, elem_size: t_elem_size }), |
154 | | SizeInfo::SliceDst(TrailingSliceLayout { offset: u_offset, elem_size: u_elem_size }) |
155 | | ) => t_offset == u_offset && t_elem_size == u_elem_size, |
156 | | _ => false, |
157 | | } |
158 | | }); |
159 | | |
160 | 0 | let metadata = Src::pointer_to_metadata(src.as_ptr()); |
161 | 0 | Dst::raw_from_ptr_len(src.as_non_null().cast::<u8>(), metadata).as_ptr() |
162 | 0 | } |
163 | | } |
164 | | |
165 | | // SAFETY: The `Project::project` impl preserves referent address. |
166 | | unsafe impl<Src, Dst> Cast<Src, Dst> for CastUnsized |
167 | | where |
168 | | Src: ?Sized + KnownLayout, |
169 | | Dst: ?Sized + KnownLayout<PointerMetadata = Src::PointerMetadata>, |
170 | | { |
171 | | } |
172 | | |
173 | | /// A field projection |
174 | | /// |
175 | | /// A `Projection` is a [`Project`] which implements projection by |
176 | | /// delegating to an implementation of [`HasField::project`]. |
177 | | #[allow(missing_debug_implementations, missing_copy_implementations)] |
178 | | pub struct Projection<F: ?Sized, const VARIANT_ID: i128, const FIELD_ID: i128> { |
179 | | _never: core::convert::Infallible, |
180 | | _phantom: PhantomData<F>, |
181 | | } |
182 | | |
183 | | // SAFETY: `HasField::project` has the same safety post-conditions as |
184 | | // `Project::project`. |
185 | | unsafe impl<T: ?Sized, F, const VARIANT_ID: i128, const FIELD_ID: i128> Project<T, T::Type> |
186 | | for Projection<F, VARIANT_ID, FIELD_ID> |
187 | | where |
188 | | T: HasField<F, VARIANT_ID, FIELD_ID>, |
189 | | { |
190 | | #[inline(always)] |
191 | 0 | fn project(src: PtrInner<'_, T>) -> *mut T::Type { |
192 | 0 | T::project(src) |
193 | 0 | } |
194 | | } |
195 | | |
196 | | /// A transitive sequence of projections. |
197 | | /// |
198 | | /// Given `TU: Project` and `UV: Project`, `TransitiveProject<_, TU, UV>` is |
199 | | /// a [`Project`] which projects by applying `TU` followed by `UV`. |
200 | | /// |
201 | | /// If `TU: Cast` and `UV: Cast`, then `TransitiveProject<_, TU, UV>: Cast`. |
202 | | #[allow(missing_debug_implementations)] |
203 | | pub struct TransitiveProject<U: ?Sized, TU, UV> { |
204 | | _never: core::convert::Infallible, |
205 | | _projections: PhantomData<(TU, UV)>, |
206 | | // On our MSRV (1.56), the debuginfo for a tuple containing both an |
207 | | // uninhabited type and a DST causes an ICE. We split `U` from `TU` and |
208 | | // `UV` to avoid this situation. |
209 | | _u: PhantomData<U>, |
210 | | } |
211 | | |
212 | | // SAFETY: Since `TU::project` and `UV::project` are each |
213 | | // provenance-preserving operations which preserve or shrink the set of |
214 | | // referent bytes, so is their composition. |
215 | | unsafe impl<T, U, V, TU, UV> Project<T, V> for TransitiveProject<U, TU, UV> |
216 | | where |
217 | | T: ?Sized, |
218 | | U: ?Sized, |
219 | | V: ?Sized, |
220 | | TU: Project<T, U>, |
221 | | UV: Project<U, V>, |
222 | | { |
223 | | #[inline(always)] |
224 | 565k | fn project(t: PtrInner<'_, T>) -> *mut V { |
225 | 565k | t.project::<_, TU>().project::<_, UV>().as_ptr() |
226 | 565k | } Unexecuted instantiation: <zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>, [u16]>>::project Unexecuted instantiation: <zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>, [u16]>>::project Unexecuted instantiation: <zerocopy::pointer::cast::TransitiveProject<[u16], zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::DstCast> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::D<[u16]>>>::project Unexecuted instantiation: <zerocopy::pointer::cast::TransitiveProject<[u16], zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::DstCast> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::D<[u16]>>>::project <zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>, [u16]>>::project Line | Count | Source | 224 | 141k | fn project(t: PtrInner<'_, T>) -> *mut V { | 225 | 141k | t.project::<_, TU>().project::<_, UV>().as_ptr() | 226 | 141k | } |
Unexecuted instantiation: <zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>, [u16]>>::project <zerocopy::pointer::cast::TransitiveProject<[u16], zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::DstCast> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::D<[u16]>>>::project Line | Count | Source | 224 | 141k | fn project(t: PtrInner<'_, T>) -> *mut V { | 225 | 141k | t.project::<_, TU>().project::<_, UV>().as_ptr() | 226 | 141k | } |
Unexecuted instantiation: <zerocopy::pointer::cast::TransitiveProject<[u16], zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::DstCast> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::D<[u16]>>>::project <zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>, [u16]>>::project Line | Count | Source | 224 | 141k | fn project(t: PtrInner<'_, T>) -> *mut V { | 225 | 141k | t.project::<_, TU>().project::<_, UV>().as_ptr() | 226 | 141k | } |
<zerocopy::pointer::cast::TransitiveProject<[u16], zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::DstCast> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&mut _, &mut _> as zerocopy::util::macro_util::TransmuteMutDst>::transmute_mut::D<[u16]>>>::project Line | Count | Source | 224 | 141k | fn project(t: PtrInner<'_, T>) -> *mut V { | 225 | 141k | t.project::<_, TU>().project::<_, UV>().as_ptr() | 226 | 141k | } |
Unexecuted instantiation: <zerocopy::pointer::cast::TransitiveProject<_, _, _> as zerocopy::pointer::cast::Project<_, _>>::project Unexecuted instantiation: <zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>, [u16]>>::project Unexecuted instantiation: <zerocopy::pointer::cast::TransitiveProject<[u16], zerocopy::pointer::cast::TransitiveProject<[half::binary16::f16], <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::SrcCast, zerocopy::layout::cast_from::CastFrom<[u16]>>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::DstCast> as zerocopy::pointer::cast::Project<<zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::S<[half::binary16::f16]>, <zerocopy::util::macro_util::Wrap<&_, &_> as zerocopy::util::macro_util::TransmuteRefDst>::transmute_ref::D<[u16]>>>::project |
227 | | } |
228 | | |
229 | | // SAFETY: Since the `Project::project` impl delegates to `TU::project` and |
230 | | // `UV::project`, and since `TU` and `UV` are `Cast`, the `Project::project` |
231 | | // impl preserves the address of the referent. |
232 | | unsafe impl<T, U, V, TU, UV> Cast<T, V> for TransitiveProject<U, TU, UV> |
233 | | where |
234 | | T: ?Sized, |
235 | | U: ?Sized, |
236 | | V: ?Sized, |
237 | | TU: Cast<T, U>, |
238 | | UV: Cast<U, V>, |
239 | | { |
240 | | } |
241 | | |
242 | | /// A cast from `T` to `[u8]`. |
243 | | pub(crate) struct AsBytesCast; |
244 | | |
245 | | // SAFETY: `project` constructs a pointer with the same address as `src` |
246 | | // and with a referent of the same size as `*src`. It does this using |
247 | | // provenance-preserving operations. |
248 | | // |
249 | | // FIXME(https://github.com/rust-lang/unsafe-code-guidelines/issues/594): |
250 | | // Technically, this proof assumes that `*src` is contiguous (the same is |
251 | | // true of other proofs in this codebase). Is this guaranteed anywhere? |
252 | | unsafe impl<T: ?Sized + KnownLayout> Project<T, [u8]> for AsBytesCast { |
253 | | #[inline(always)] |
254 | 0 | fn project(src: PtrInner<'_, T>) -> *mut [u8] { |
255 | 0 | let bytes = match T::size_of_val_raw(src.as_non_null()) { |
256 | 0 | Some(bytes) => bytes, |
257 | | // SAFETY: `KnownLayout::size_of_val_raw` promises to always |
258 | | // return `Some` so long as the resulting size fits in a |
259 | | // `usize`. By invariant on `PtrInner`, `src` refers to a range |
260 | | // of bytes whose size fits in an `isize`, which implies that it |
261 | | // also fits in a `usize`. |
262 | 0 | None => unsafe { core::hint::unreachable_unchecked() }, |
263 | | }; |
264 | | |
265 | 0 | core::ptr::slice_from_raw_parts_mut(src.as_ptr().cast::<u8>(), bytes) |
266 | 0 | } |
267 | | } |
268 | | |
269 | | // SAFETY: The `Project::project` impl preserves referent address. |
270 | | unsafe impl<T: ?Sized + KnownLayout> Cast<T, [u8]> for AsBytesCast {} |
271 | | } |