@@ -717,13 +717,25 @@ mod _transitions {
717
717
/// # Safety
718
718
///
719
719
/// The caller promises that `self` satisfies the invariants `H`.
720
- pub ( super ) unsafe fn assume_invariants < H : Invariants > ( self ) -> Ptr < ' a , T , H > {
720
+ unsafe fn assume_invariants < H : Invariants > ( self ) -> Ptr < ' a , T , H > {
721
721
// SAFETY: The caller has promised to satisfy all parameterized
722
722
// invariants of `Ptr`. `Ptr`'s other invariants are satisfied
723
723
// by-contract by the source `Ptr`.
724
724
unsafe { Ptr :: new ( self . as_non_null ( ) ) }
725
725
}
726
726
727
+ /// Helps the type system unify two distinct invariant types which are
728
+ /// actually the same.
729
+ pub ( super ) fn unify_invariants <
730
+ H : Invariants < Aliasing = I :: Aliasing , Alignment = I :: Alignment , Validity = I :: Validity > ,
731
+ > (
732
+ self ,
733
+ ) -> Ptr < ' a , T , H > {
734
+ // SAFETY: The associated type bounds on `H` ensure that the
735
+ // invariants are unchanged.
736
+ unsafe { self . assume_invariants :: < H > ( ) }
737
+ }
738
+
727
739
/// Assumes that `self` satisfies the aliasing requirement of `A`.
728
740
///
729
741
/// # Safety
@@ -1288,22 +1300,76 @@ mod _casts {
1288
1300
} else {
1289
1301
// Undo the cast so we can return the original bytes.
1290
1302
let slf = slf. as_bytes ( ) ;
1291
- // Restore the initial invariants of `self`.
1303
+ // Restore the initial alignment invariant of `self`.
1292
1304
//
1293
1305
// SAFETY: The referent type of `slf` is now equal to
1294
- // that of `self`, but the invariants nominally differ.
1295
- // Since `slf` and `self` refer to the same memory and
1296
- // no actions have been taken that would violate the
1297
- // original invariants on `self`, it is sound to apply
1298
- // the invariants of `self` onto `slf`.
1299
- let slf = unsafe { slf. assume_invariants ( ) } ;
1306
+ // that of `self`, but the alignment invariants
1307
+ // nominally differ. Since `slf` and `self` refer to the
1308
+ // same memory and no actions have been taken that would
1309
+ // violate the original invariants on `self`, it is
1310
+ // sound to apply the alignment invariant of `self` onto
1311
+ // `slf`.
1312
+ let slf = unsafe { slf. assume_alignment :: < I :: Alignment > ( ) } ;
1313
+ let slf = slf. unify_invariants ( ) ;
1300
1314
Err ( CastError :: Size ( SizeError :: < _ , U > :: new ( slf) ) )
1301
1315
}
1302
1316
}
1303
1317
Err ( err) => Err ( err) ,
1304
1318
}
1305
1319
}
1306
1320
}
1321
+
1322
+ impl < ' a , T , I > Ptr < ' a , core:: cell:: UnsafeCell < T > , I >
1323
+ where
1324
+ T : ' a + ?Sized ,
1325
+ I : Invariants < Aliasing = Exclusive > ,
1326
+ {
1327
+ /// Converts this `Ptr` into a pointer to the underlying data.
1328
+ ///
1329
+ /// This call borrows the `UnsafeCell` mutably (at compile-time) which
1330
+ /// guarantees that we possess the only reference.
1331
+ ///
1332
+ /// This is like [`UnsafeCell::get_mut`], but for `Ptr`.
1333
+ ///
1334
+ /// [`UnsafeCell::get_mut`]: core::cell::UnsafeCell::get_mut
1335
+ #[ must_use]
1336
+ #[ inline( always) ]
1337
+ pub fn get_mut ( self ) -> Ptr < ' a , T , I > {
1338
+ // SAFETY:
1339
+ // - The closure uses an `as` cast, which preserves address range
1340
+ // and provenance.
1341
+ // - We require `I: Invariants<Aliasing = Exclusive>`, so we are not
1342
+ // required to uphold `UnsafeCell` equality.
1343
+ #[ allow( clippy:: as_conversions) ]
1344
+ let ptr = unsafe { self . cast_unsized ( |p| p as * mut T ) } ;
1345
+
1346
+ // SAFETY: `UnsafeCell<T>` has the same alignment as `T` [1],
1347
+ // and so if `self` is guaranteed to be aligned, then so is the
1348
+ // returned `Ptr`.
1349
+ //
1350
+ // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:
1351
+ //
1352
+ // `UnsafeCell<T>` has the same in-memory representation as
1353
+ // its inner type `T`. A consequence of this guarantee is that
1354
+ // it is possible to convert between `T` and `UnsafeCell<T>`.
1355
+ let ptr = unsafe { ptr. assume_alignment :: < I :: Alignment > ( ) } ;
1356
+
1357
+ // SAFETY: `UnsafeCell<T>` has the same bit validity as `T` [1], and
1358
+ // so if `self` has a particular validity invariant, then the same
1359
+ // holds of the returned `Ptr`. Technically the term
1360
+ // "representation" doesn't guarantee this, but the subsequent
1361
+ // sentence in the documentation makes it clear that this is the
1362
+ // intention.
1363
+ //
1364
+ // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:
1365
+ //
1366
+ // `UnsafeCell<T>` has the same in-memory representation as its
1367
+ // inner type `T`. A consequence of this guarantee is that it is
1368
+ // possible to convert between `T` and `UnsafeCell<T>`.
1369
+ let ptr = unsafe { ptr. assume_validity :: < I :: Validity > ( ) } ;
1370
+ ptr. unify_invariants ( )
1371
+ }
1372
+ }
1307
1373
}
1308
1374
1309
1375
/// Projections through the referent.
@@ -1467,16 +1533,17 @@ mod _project {
1467
1533
// its (inclusive) lower bound. Thus, no index is a member of both
1468
1534
// ranges.
1469
1535
1470
- // SAFETY: We never change invariants other than aliasing.
1471
- //
1472
- // By the preceding lemma, `left` and `right` do not alias. We do
1473
- // not construct any other `Ptr`s or references which alias `left`
1474
- // or `right`. Thus, the only `Ptr`s or references which alias
1475
- // `left` or `right` are outside of this method. By invariant,
1536
+ // SAFETY: By the preceding lemma, `left` and `right` do not alias.
1537
+ // We do not construct any other `Ptr`s or references which alias
1538
+ // `left` or `right`. Thus, the only `Ptr`s or references which
1539
+ // alias `left` or `right` are outside of this method. By invariant,
1476
1540
// `self` obeys the aliasing invariant `I::Aliasing` with respect to
1477
1541
// those other `Ptr`s or references, and so `left` and `right` do as
1478
1542
// well.
1479
- unsafe { ( left. assume_invariants :: < I > ( ) , right. assume_invariants :: < I > ( ) ) }
1543
+ let ( left, right) = unsafe {
1544
+ ( left. assume_aliasing :: < I :: Aliasing > ( ) , right. assume_aliasing :: < I :: Aliasing > ( ) )
1545
+ } ;
1546
+ ( left. unify_invariants ( ) , right. unify_invariants ( ) )
1480
1547
}
1481
1548
1482
1549
/// Iteratively projects the elements `Ptr<T>` from `Ptr<[T]>`.
0 commit comments