@@ -170,31 +170,7 @@ impl<'a, T: ?Sized> PtrInner<'a, T> {
170170 where
171171 T : Sized ,
172172 {
173- static_assert ! ( T , U => mem:: size_of:: <T >( ) >= mem:: size_of:: <U >( ) ) ;
174- // SAFETY: By the preceding assert, `U` is no larger than `T`, which is
175- // the size of `self`'s referent.
176- unsafe { self . cast ( ) }
177- }
178-
179- /// # Safety
180- ///
181- /// `U` must not be larger than the size of `self`'s referent.
182- #[ must_use]
183- #[ inline( always) ]
184- pub unsafe fn cast < U > ( self ) -> PtrInner < ' a , U > {
185- let ptr = self . as_non_null ( ) . cast :: < U > ( ) ;
186-
187- // SAFETY: The caller promises that `U` is no larger than `self`'s
188- // referent. Thus, `ptr` addresses a subset of the bytes addressed by
189- // `self`.
190- //
191- // 0. By invariant on `self`, if `self`'s referent is not zero sized,
192- // then `self` has valid provenance for its referent, which is
193- // entirely contained in some Rust allocation, `A`. Thus, the same
194- // holds of `ptr`.
195- // 1. By invariant on `self`, if `self`'s referent is not zero sized,
196- // then `A` is guaranteed to live for at least `'a`.
197- unsafe { PtrInner :: new ( ptr) }
173+ self . cast ( CastSized :: new ( ) )
198174 }
199175
200176 /// Projects a field.
@@ -206,6 +182,123 @@ impl<'a, T: ?Sized> PtrInner<'a, T> {
206182 {
207183 <T as HasField < F , VARIANT_ID , FIELD_ID > >:: project ( self )
208184 }
185+
186+ pub fn cast < C : Cast < T > > ( self , cast : C ) -> PtrInner < ' a , C :: Dst > {
187+ let non_null = self . as_non_null ( ) ;
188+ let raw = non_null. as_ptr ( ) ;
189+
190+ // SAFETY: By invariant on `self`, `raw`'s referent is zero-sized or
191+ // lives in a single allocation.
192+ let projected_raw = unsafe { cast. cast ( raw) } ;
193+
194+ // SAFETY: `self`'s referent lives at a `NonNull` address, and is either
195+ // zero-sized or lives in an allocation. In either case, it does not
196+ // wrap around the address space [1], and so none of the addresses
197+ // contained in it or one-past-the-end of it are null.
198+ //
199+ // By invariant on `C: Cast`, `C::cast` is a provenance-preserving cast
200+ // which preserves or shrinks the set of referent bytes, so
201+ // `projected_raw` references a subset of `self`'s referent, and so it
202+ // cannot be null.
203+ //
204+ // [1] https://doc.rust-lang.org/1.92.0/std/ptr/index.html#allocation
205+ let projected_non_null = unsafe { NonNull :: new_unchecked ( projected_raw) } ;
206+
207+ // SAFETY: As described in the preceding safety comment, `projected_raw`,
208+ // and thus `projected_non_null`, addresses a subset of `self`'s
209+ // referent. Thus, `projected_non_null` either:
210+ // - Addresses zero bytes or,
211+ // - Addresses a subset of the referent of `self`. In this case, `self`
212+ // has provenance for its referent, which lives in an allocation.
213+ // Since `projected_non_null` was constructed using a sequence of
214+ // provenance-preserving operations, it also has provenance for its
215+ // referent and that referent lives in an allocation. By invariant on
216+ // `self`, that allocation lives for `'a`.
217+ unsafe { PtrInner :: new ( projected_non_null) }
218+ }
219+ }
220+
221+ // TODO: Migrate other casts to this:
222+ // - `Ptr`'s various cast methods
223+ // - `SizeEq`
224+
225+ /// # Safety
226+ ///
227+ /// `cast` must be a provenance-preserving cast which preserves or shrinks the
228+ /// set of referent bytes.
229+ pub unsafe trait Cast < Src : ?Sized > {
230+ type Dst : ?Sized ;
231+
232+ /// # Safety
233+ ///
234+ /// `src` must have provenance for its entire referent, which must be
235+ /// zero-sized or live in a single allocation.
236+ unsafe fn cast ( self , src : * mut Src ) -> * mut Self :: Dst ;
237+ }
238+
239+ #[ allow( missing_debug_implementations) ]
240+ pub struct FnCast < F > ( F ) ;
241+
242+ impl < F > FnCast < F > {
243+ pub const unsafe fn new ( f : F ) -> Self {
244+ Self ( f)
245+ }
246+ }
247+
248+ unsafe impl < F , Src : ?Sized , Dst : ?Sized > Cast < Src > for FnCast < F >
249+ where
250+ F : Fn ( * mut Src ) -> * mut Dst ,
251+ {
252+ type Dst = Dst ;
253+
254+ unsafe fn cast ( self , src : * mut Src ) -> * mut Self :: Dst {
255+ ( self . 0 ) ( src)
256+ }
257+ }
258+ struct CastSized < Dst > ( PhantomData < Dst > ) ;
259+
260+ impl < Dst > Default for CastSized < Dst > {
261+ fn default ( ) -> Self {
262+ Self ( PhantomData )
263+ }
264+ }
265+
266+ impl < Dst > CastSized < Dst > {
267+ const fn new ( ) -> Self {
268+ Self ( PhantomData )
269+ }
270+ }
271+
272+ // SAFETY: By the `static_assert!`, `Dst` is no larger than `Src`,
273+ // and `<*mut Src>::cast` is a provenance-preserving cast.
274+ unsafe impl < Src , Dst > Cast < Src > for CastSized < Dst > {
275+ type Dst = Dst ;
276+
277+ unsafe fn cast ( self , src : * mut Src ) -> * mut Self :: Dst {
278+ static_assert ! ( Src , Dst => mem:: size_of:: <Src >( ) >= mem:: size_of:: <Dst >( ) ) ;
279+ src. cast :: < Dst > ( )
280+ }
281+ }
282+
283+ /// Constructs a [`Cast`] which projects from a type to one of its fields.
284+ #[ macro_export]
285+ #[ doc( hidden) ]
286+ macro_rules! project_cast {
287+ ( $src: ty => $field_name: tt) => {
288+ $crate:: pointer:: __project_cast:: <$src, _, _>( |src| {
289+ $crate:: util:: macro_util:: core_reexport:: ptr:: addr_of_mut!( ( * src) . $field_name)
290+ } )
291+ } ;
292+ }
293+
294+ #[ doc( hidden) ]
295+ pub const unsafe fn __project_cast < Src : ?Sized , Dst : ?Sized , F > (
296+ cast : F ,
297+ ) -> impl Cast < Src , Dst = Dst >
298+ where
299+ F : Fn ( * mut Src ) -> * mut Dst ,
300+ {
301+ unsafe { FnCast :: new ( cast) }
209302}
210303
211304#[ allow( clippy:: needless_lifetimes) ]
0 commit comments