66// This file may not be copied, modified, or distributed except according to
77// those terms.
88
9- use core:: { marker:: PhantomData , mem , ops:: Range , ptr:: NonNull } ;
9+ use core:: { marker:: PhantomData , ops:: Range , ptr:: NonNull } ;
1010
1111pub use _def:: PtrInner ;
1212
1313#[ allow( unused_imports) ]
1414use crate :: util:: polyfills:: NumExt as _;
1515use crate :: {
1616 layout:: { CastType , MetadataCastError } ,
17+ pointer:: cast,
1718 util:: AsAddress ,
1819 AlignmentError , CastError , HasField , KnownLayout , MetadataOf , SizeError , SplitAt ,
1920} ;
@@ -170,31 +171,7 @@ impl<'a, T: ?Sized> PtrInner<'a, T> {
170171 where
171172 T : Sized ,
172173 {
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) }
174+ self . cast ( cast:: CastSized )
198175 }
199176
200177 /// Projects a field.
@@ -204,7 +181,46 @@ impl<'a, T: ?Sized> PtrInner<'a, T> {
204181 where
205182 T : HasField < F , VARIANT_ID , FIELD_ID > ,
206183 {
207- <T as HasField < F , VARIANT_ID , FIELD_ID > >:: project ( self )
184+ let cast = unsafe {
185+ crate :: pointer:: cast:: FnCast :: new ( <T as HasField < F , VARIANT_ID , FIELD_ID > >:: project)
186+ } ;
187+ self . cast ( cast)
188+ }
189+
190+ #[ must_use]
191+ #[ inline( always) ]
192+ pub fn cast < U : ?Sized , C : cast:: Cast < T , U > > ( self , cast : C ) -> PtrInner < ' a , U > {
193+ let non_null = self . as_non_null ( ) ;
194+ let raw = non_null. as_ptr ( ) ;
195+
196+ // SAFETY: By invariant on `self`, `raw`'s referent is zero-sized or
197+ // lives in a single allocation.
198+ let projected_raw = unsafe { cast. cast ( raw) } ;
199+
200+ // SAFETY: `self`'s referent lives at a `NonNull` address, and is either
201+ // zero-sized or lives in an allocation. In either case, it does not
202+ // wrap around the address space [1], and so none of the addresses
203+ // contained in it or one-past-the-end of it are null.
204+ //
205+ // By invariant on `C: Cast`, `C::cast` is a provenance-preserving cast
206+ // which preserves or shrinks the set of referent bytes, so
207+ // `projected_raw` references a subset of `self`'s referent, and so it
208+ // cannot be null.
209+ //
210+ // [1] https://doc.rust-lang.org/1.92.0/std/ptr/index.html#allocation
211+ let projected_non_null = unsafe { NonNull :: new_unchecked ( projected_raw) } ;
212+
213+ // SAFETY: As described in the preceding safety comment, `projected_raw`,
214+ // and thus `projected_non_null`, addresses a subset of `self`'s
215+ // referent. Thus, `projected_non_null` either:
216+ // - Addresses zero bytes or,
217+ // - Addresses a subset of the referent of `self`. In this case, `self`
218+ // has provenance for its referent, which lives in an allocation.
219+ // Since `projected_non_null` was constructed using a sequence of
220+ // provenance-preserving operations, it also has provenance for its
221+ // referent and that referent lives in an allocation. By invariant on
222+ // `self`, that allocation lives for `'a`.
223+ unsafe { PtrInner :: new ( projected_non_null) }
208224 }
209225}
210226
@@ -262,37 +278,6 @@ where
262278 // zero sized, then `A` is guaranteed to live for at least `'a`.
263279 unsafe { PtrInner :: new ( raw) }
264280 }
265-
266- pub ( crate ) fn as_bytes ( self ) -> PtrInner < ' a , [ u8 ] > {
267- let ptr = self . as_non_null ( ) ;
268- let bytes = match T :: size_of_val_raw ( ptr) {
269- Some ( bytes) => bytes,
270- // SAFETY: `KnownLayout::size_of_val_raw` promises to always
271- // return `Some` so long as the resulting size fits in a
272- // `usize`. By invariant on `PtrInner`, `self` refers to a range
273- // of bytes whose size fits in an `isize`, which implies that it
274- // also fits in a `usize`.
275- None => unsafe { core:: hint:: unreachable_unchecked ( ) } ,
276- } ;
277-
278- let ptr = core:: ptr:: slice_from_raw_parts_mut ( ptr. cast :: < u8 > ( ) . as_ptr ( ) , bytes) ;
279-
280- // SAFETY: `ptr` has the same address as `ptr = self.as_non_null()`,
281- // which is non-null by construction.
282- let ptr = unsafe { NonNull :: new_unchecked ( ptr) } ;
283-
284- // SAFETY: `ptr` points to `bytes` `u8`s starting at the same address as
285- // `self`'s referent. Since `bytes` is the length of `self`'s referent,
286- // `ptr` addresses the same byte range as `self`. Thus, by invariant on
287- // `self` (as a `PtrInner`):
288- //
289- // 0. If `ptr`'s referent is not zero sized, then `ptr` has valid
290- // provenance for its referent, which is entirely contained in some
291- // Rust allocation, `A`.
292- // 1. If `ptr`'s referent is not zero sized, `A` is guaranteed to live
293- // for at least `'a`.
294- unsafe { PtrInner :: new ( ptr) }
295- }
296281}
297282
298283#[ allow( clippy:: needless_lifetimes) ]
0 commit comments