@@ -139,6 +139,159 @@ impl<'a, T: ?Sized> PtrInner<'a, T> {
139
139
}
140
140
}
141
141
142
+ #[ allow( clippy:: needless_lifetimes) ]
143
+ impl < ' a , T > PtrInner < ' a , T >
144
+ where
145
+ T : ?Sized + KnownLayout ,
146
+ {
147
+ /// Produces the metadata of this `ptr`.
148
+ ///
149
+ /// # Safety
150
+ ///
151
+ /// Unsafe code my rely on `len` satisfying the above contract.
152
+ pub ( crate ) fn meta ( self ) -> T :: PointerMetadata {
153
+ T :: pointer_to_metadata ( self . as_non_null ( ) . as_ptr ( ) )
154
+ }
155
+
156
+ /// Produces a `PtrInner` with the same address and provenance as `self` but
157
+ /// the given `meta`.
158
+ ///
159
+ /// # Safety
160
+ ///
161
+ /// The caller promises that if `self`'s referent is not zero sized, then
162
+ /// a pointer constructed from its address with the given `meta` metadata
163
+ /// will address a subset of the allocation pointed to by `self`.
164
+ #[ inline]
165
+ pub ( crate ) unsafe fn with_meta ( self , meta : T :: PointerMetadata ) -> Self
166
+ where
167
+ T : KnownLayout ,
168
+ {
169
+ let raw = T :: raw_from_ptr_len ( self . as_non_null ( ) . cast ( ) , meta) ;
170
+
171
+ // SAFETY:
172
+ //
173
+ // Lemma 0: `raw` either addresses zero bytes, or addresses a subset of
174
+ // the allocation pointed to by `self` and has the same
175
+ // provenance as `self`. Proof: `raw` is constructed using
176
+ // provenance-preserving operations, and the caller has
177
+ // promised that, if `self`'s referent is not zero-sized, the
178
+ // resulting pointer addresses a subset of the allocation
179
+ // pointed to by `self`.
180
+ //
181
+ // 0. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
182
+ // zero sized, then `ptr` is derived from some valid Rust allocation,
183
+ // `A`.
184
+ // 1. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
185
+ // zero sized, then `ptr` has valid provenance for `A`.
186
+ // 2. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
187
+ // zero sized, then `ptr` addresses a byte range which is entirely
188
+ // contained in `A`.
189
+ // 3. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte
190
+ // range whose length fits in an `isize`.
191
+ // 4. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte
192
+ // range which does not wrap around the address space.
193
+ // 5. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
194
+ // zero sized, then `A` is guaranteed to live for at least `'a`.
195
+ unsafe { PtrInner :: new ( raw) }
196
+ }
197
+ }
198
+
199
+ #[ allow( clippy:: needless_lifetimes) ]
200
+ impl < ' a , T > PtrInner < ' a , T >
201
+ where
202
+ T : ?Sized + KnownLayout < PointerMetadata = usize > ,
203
+ {
204
+ /// The number of trailing slice elements in the object referenced by
205
+ /// `self`.
206
+ ///
207
+ /// # Safety
208
+ ///
209
+ /// Unsafe code my rely on `len` satisfying the above contract.
210
+ pub ( crate ) fn len ( & self ) -> usize {
211
+ self . meta ( )
212
+ }
213
+
214
+ /// Splits `T` into two.
215
+ ///
216
+ /// # Safety
217
+ ///
218
+ /// The caller promises that:
219
+ /// - `l_len <= self.len()`.
220
+ ///
221
+ /// Given `let (left, right) = ptr.split_at(l_len)`, it is guaranteed
222
+ /// that `left` and `right` are contiguous and non-overlapping if
223
+ /// `self.padding_needed_for_len(l_len) == Some(0)`. This is true for
224
+ /// all `[T]`.
225
+ ///
226
+ /// If `self.padding_needed_for_len(l_len) != Some(0)`, then the left
227
+ /// pointer will overlap the right pointer to satisfy `T`'s padding
228
+ /// requirements.
229
+ pub ( crate ) unsafe fn split_at_unchecked (
230
+ self ,
231
+ l_len : usize ,
232
+ ) -> ( Self , PtrInner < ' a , [ T :: TrailingElem ] > ) {
233
+ // SAFETY: The caller promises that `l_len <= self.len()`.
234
+ // Trivially, `0 <= l_len`.
235
+ let left = unsafe { self . with_meta ( l_len) } ;
236
+
237
+ let right = self . trailing_slice ( ) ;
238
+ // SAFETY: The caller promises that `l_len <= self.len() =
239
+ // slf.len()`. Trivially, `slf.len() <= slf.len()`.
240
+ let right = unsafe { right. slice_unchecked ( l_len..self . len ( ) ) } ;
241
+
242
+ // SAFETY: If `self.padding_needed_for_len(l_len) == Some(0)`, then
243
+ // `left` and `right` are non-overlapping. Proof: `left` is constructed
244
+ // `slf` with `l_len` as its (exclusive) upper bound. If
245
+ // `self.padding_needed_for_len(l_len) == Some(0)`, then `left` requires
246
+ // no trailing padding following its final element. Since `right` is
247
+ // constructed from `slf`'s trailing slice with `l_len` as its
248
+ // (inclusive) lower bound, no byte is referred to by both pointers.
249
+ //
250
+ // Conversely, `self.padding_needed_for_len(l_len) == Some(N)`, where `N
251
+ // > 0`, `left` requires `N` bytes of trailing padding following its
252
+ // final element. Since `right` is constructed from the trailing slice
253
+ // of `slf` with `l_len` as its (inclusive) lower bound, the first `N`
254
+ // bytes of `right` are aliased by `left`.
255
+ ( left, right)
256
+ }
257
+
258
+ /// Produces the number of padding bytes that must follow the trailing
259
+ /// element of `self` if its trailing slice has length `len`.
260
+ ///
261
+ /// # Safety
262
+ ///
263
+ /// Unsafe code my rely on `len` satisfying the above contract.
264
+ #[ allow( unused) ]
265
+ pub ( crate ) fn padding_needed_for_len ( & self , len : usize ) -> Option < usize > {
266
+ len. padding_needed_for ( T :: LAYOUT )
267
+ }
268
+
269
+ /// Produces the trailing slice of `self`.
270
+ ///
271
+ /// # Safety
272
+ ///
273
+ /// Unsafe code my rely on `len` satisfying the above contract.
274
+ pub ( crate ) fn trailing_slice ( self ) -> PtrInner < ' a , [ T :: TrailingElem ] > {
275
+ let offset = match T :: LAYOUT . size_info {
276
+ crate :: SizeInfo :: Sized { size } => size,
277
+ crate :: SizeInfo :: SliceDst ( crate :: TrailingSliceLayout { offset, .. } ) => offset,
278
+ } ;
279
+
280
+ let bytes = self . as_non_null ( ) . cast :: < u8 > ( ) . as_ptr ( ) ;
281
+
282
+ // SAFETY: TODO.
283
+ let bytes = unsafe { bytes. add ( offset) } ;
284
+
285
+ // SAFETY: TODO
286
+ let bytes = unsafe { NonNull :: new_unchecked ( bytes) } ;
287
+
288
+ let raw = KnownLayout :: raw_from_ptr_len ( bytes, self . len ( ) ) ;
289
+
290
+ // SAFETY: TODO
291
+ unsafe { PtrInner :: new ( raw) }
292
+ }
293
+ }
294
+
142
295
#[ allow( clippy:: needless_lifetimes) ]
143
296
impl < ' a , T > PtrInner < ' a , [ T ] > {
144
297
/// Creates a pointer which addresses the given `range` of self.
@@ -200,31 +353,6 @@ impl<'a, T> PtrInner<'a, [T]> {
200
353
unsafe { PtrInner :: new ( ptr) }
201
354
}
202
355
203
- /// Splits the slice in two.
204
- ///
205
- /// # Safety
206
- ///
207
- /// The caller promises that `l_len <= self.len()`.
208
- ///
209
- /// Given `let (left, right) = ptr.split_at(l_len)`, it is guaranteed
210
- /// that `left` and `right` are contiguous and non-overlapping.
211
- pub ( crate ) unsafe fn split_at ( self , l_len : usize ) -> ( Self , Self ) {
212
- // SAFETY: The caller promises that `l_len <= self.len()`.
213
- // Trivially, `0 <= l_len`.
214
- let left = unsafe { self . slice_unchecked ( 0 ..l_len) } ;
215
-
216
- // SAFETY: The caller promises that `l_len <= self.len() =
217
- // slf.len()`. Trivially, `slf.len() <= slf.len()`.
218
- let right = unsafe { self . slice_unchecked ( l_len..self . len ( ) ) } ;
219
-
220
- // SAFETY: `left` and `right` are non-overlapping. Proof: `left` is
221
- // constructed from `slf` with `l_len` as its (exclusive) upper
222
- // bound, while `right` is constructed from `slf` with `l_len` as
223
- // its (inclusive) lower bound. Thus, no index is a member of both
224
- // ranges.
225
- ( left, right)
226
- }
227
-
228
356
/// Iteratively projects the elements `PtrInner<T>` from `PtrInner<[T]>`.
229
357
pub ( crate ) fn iter ( & self ) -> impl Iterator < Item = PtrInner < ' a , T > > {
230
358
// TODO(#429): Once `NonNull::cast` documents that it preserves
@@ -297,32 +425,6 @@ impl<'a, T> PtrInner<'a, [T]> {
297
425
unsafe { PtrInner :: new ( elem) }
298
426
} )
299
427
}
300
-
301
- /// The number of slice elements in the object referenced by `self`.
302
- ///
303
- /// # Safety
304
- ///
305
- /// Unsafe code my rely on `len` satisfying the above contract.
306
- pub ( crate ) fn len ( & self ) -> usize {
307
- self . trailing_slice_len ( )
308
- }
309
- }
310
-
311
- #[ allow( clippy:: needless_lifetimes) ]
312
- impl < ' a , T > PtrInner < ' a , T >
313
- where
314
- T : ?Sized + KnownLayout < PointerMetadata = usize > ,
315
- {
316
- /// The number of trailing slice elements in the object referenced by
317
- /// `self`.
318
- ///
319
- /// # Safety
320
- ///
321
- /// Unsafe code my rely on `trailing_slice_len` satisfying the above
322
- /// contract.
323
- pub ( super ) fn trailing_slice_len ( & self ) -> usize {
324
- T :: pointer_to_metadata ( self . as_non_null ( ) . as_ptr ( ) )
325
- }
326
428
}
327
429
328
430
impl < ' a , T , const N : usize > PtrInner < ' a , [ T ; N ] > {
@@ -442,7 +544,11 @@ impl<'a> PtrInner<'a, [u8]> {
442
544
443
545
// SAFETY: `validate_cast_and_convert_metadata` promises to return
444
546
// `split_at <= self.len()`.
445
- let ( l_slice, r_slice) = unsafe { self . split_at ( split_at) } ;
547
+ //
548
+ // Lemma 0: `l_slice` and `r_slice` are non-overlapping. Proof: By
549
+ // contract on `PtrInner::split_at_unchecked`, the produced `PtrInner`s
550
+ // are always non-overlapping if `self` is a `[T]`; here it is a `[u8]`.
551
+ let ( l_slice, r_slice) = unsafe { self . split_at_unchecked ( split_at) } ;
446
552
447
553
let ( target, remainder) = match cast_type {
448
554
CastType :: Prefix => ( l_slice, r_slice) ,
@@ -500,7 +606,7 @@ mod tests {
500
606
for i in 0 ..=N {
501
607
assert_eq ! ( ptr. len( ) , N ) ;
502
608
// SAFETY: `i` is in bounds by construction.
503
- let ( l, r) = unsafe { ptr. split_at ( i) } ;
609
+ let ( l, r) = unsafe { ptr. split_at_unchecked ( i) } ;
504
610
// SAFETY: Points to a valid value by construction.
505
611
#[ allow( clippy:: undocumented_unsafe_blocks) ] // Clippy false positive
506
612
let l_sum: usize = l
0 commit comments