@@ -1216,7 +1216,7 @@ impl<T> Unalign<T> {
1216
1216
/// Attempts to return a reference to the wrapped `T`, failing if `self` is
1217
1217
/// not properly aligned.
1218
1218
///
1219
- /// If `self` does not satisfy `mem:: align_of::<T>()`, then it is unsound to
1219
+ /// If `self` does not satisfy `align_of::<T>()`, then it is unsound to
1220
1220
/// return a reference to the wrapped `T`, and `try_deref` returns `None`.
1221
1221
///
1222
1222
/// If `T: Unaligned`, then `Unalign<T>` implements [`Deref`], and callers
@@ -1234,7 +1234,7 @@ impl<T> Unalign<T> {
1234
1234
/// Attempts to return a mutable reference to the wrapped `T`, failing if
1235
1235
/// `self` is not properly aligned.
1236
1236
///
1237
- /// If `self` does not satisfy `mem:: align_of::<T>()`, then it is unsound to
1237
+ /// If `self` does not satisfy `align_of::<T>()`, then it is unsound to
1238
1238
/// return a reference to the wrapped `T`, and `try_deref_mut` returns
1239
1239
/// `None`.
1240
1240
///
@@ -1257,7 +1257,7 @@ impl<T> Unalign<T> {
1257
1257
///
1258
1258
/// # Safety
1259
1259
///
1260
- /// If `self` does not satisfy `mem:: align_of::<T>()`, then
1260
+ /// If `self` does not satisfy `align_of::<T>()`, then
1261
1261
/// `self.deref_unchecked()` may cause undefined behavior.
1262
1262
pub const unsafe fn deref_unchecked ( & self ) -> & T {
1263
1263
// SAFETY: `self.get_ptr()` returns a raw pointer to a valid `T` at the
@@ -1276,7 +1276,7 @@ impl<T> Unalign<T> {
1276
1276
///
1277
1277
/// # Safety
1278
1278
///
1279
- /// If `self` does not satisfy `mem:: align_of::<T>()`, then
1279
+ /// If `self` does not satisfy `align_of::<T>()`, then
1280
1280
/// `self.deref_mut_unchecked()` may cause undefined behavior.
1281
1281
pub unsafe fn deref_mut_unchecked ( & mut self ) -> & mut T {
1282
1282
// SAFETY: `self.get_mut_ptr()` returns a raw pointer to a valid `T` at
@@ -1463,6 +1463,165 @@ macro_rules! transmute {
1463
1463
} }
1464
1464
}
1465
1465
1466
+ /// A type whose size is equal to `align_of::<T>()`.
1467
+ #[ doc( hidden) ]
1468
+ #[ allow( missing_debug_implementations) ]
1469
+ #[ repr( C ) ]
1470
+ pub struct AlignOf < T > {
1471
+ // This field ensures that:
1472
+ // - The size is always at least 1 (the minimum possible alignment).
1473
+ // - If the alignment is greater than 1, Rust has to round up to the next
1474
+ // multiple of it in order to make sure that `Align`'s size is a multiple
1475
+ // of that alignment. Without this field, its size could be 0, which is a
1476
+ // valid multiple of any alignment.
1477
+ _u : u8 ,
1478
+ _a : [ T ; 0 ] ,
1479
+ }
1480
+
1481
+ impl < T > AlignOf < T > {
1482
+ #[ doc( hidden) ]
1483
+ pub fn into_t ( self ) -> T {
1484
+ unreachable ! ( )
1485
+ }
1486
+ }
1487
+
1488
+ /// A type whose size is equal to `max(align_of::<T>(), align_of::<U>())`.
1489
+ #[ doc( hidden) ]
1490
+ #[ allow( missing_debug_implementations) ]
1491
+ #[ repr( C ) ]
1492
+ pub union MaxAlignsOf < T , U > {
1493
+ _t : ManuallyDrop < AlignOf < T > > ,
1494
+ _u : ManuallyDrop < AlignOf < U > > ,
1495
+ }
1496
+
1497
+ impl < T , U > MaxAlignsOf < T , U > {
1498
+ #[ doc( hidden) ]
1499
+ pub fn new ( _t : T , _u : U ) -> MaxAlignsOf < T , U > {
1500
+ unreachable ! ( )
1501
+ }
1502
+ }
1503
+
1504
+ /// Safely transmutes an immutable reference of one type to an immutable
1505
+ /// reference of another type of the same size.
1506
+ ///
1507
+ /// The expression `$e` must have a concrete type, `&T`, where `T: Sized +
1508
+ /// AsBytes`. The `transmute_ref!` expression must also have a concrete type,
1509
+ /// `&U` (`U` is inferred from the calling context), where `U: Sized +
1510
+ /// FromBytes`. It must be the case that `align_of::<T>() >= align_of::<U>()`.
1511
+ ///
1512
+ /// The lifetime of the input type, `&T`, must be the same as or outlive the
1513
+ /// lifetime of the output type, `&U`.
1514
+ ///
1515
+ /// # Alignment increase error message
1516
+ ///
1517
+ /// Because of limitations on macros, the error message generated when
1518
+ /// `transmute_ref!` is used to transmute from a type of lower alignment to a
1519
+ /// type of higher alignment is somewhat confusing. For example, the following
1520
+ /// code:
1521
+ ///
1522
+ /// ```rust,compile_fail
1523
+ /// const INCREASE_ALIGNMENT: &u16 = zerocopy::transmute_ref!(&[0u8; 2]);
1524
+ /// ```
1525
+ ///
1526
+ /// ...generates the following error:
1527
+ ///
1528
+ /// ```text
1529
+ /// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
1530
+ /// --> src/lib.rs:1524:34
1531
+ /// |
1532
+ /// 5 | const INCREASE_ALIGNMENT: &u16 = zerocopy::transmute_ref!(&[0u8; 2]);
1533
+ /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1534
+ /// |
1535
+ /// = note: source type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
1536
+ /// = note: target type: `AlignOf<[u8; 2]>` (8 bits)
1537
+ /// = note: this error originates in the macro `zerocopy::transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
1538
+ /// ```
1539
+ ///
1540
+ /// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
1541
+ /// align_of::<T>()`, which is equivalent to `align_of::<T>() <
1542
+ /// align_of::<U>()`.
1543
+ #[ macro_export]
1544
+ macro_rules! transmute_ref {
1545
+ ( $e: expr) => { {
1546
+ // NOTE: This must be a macro (rather than a function with trait bounds)
1547
+ // because there's no way, in a generic context, to enforce that two
1548
+ // types have the same size or alignment. `core::mem::transmute` uses
1549
+ // compiler magic to enforce size equality so long as the types are
1550
+ // concrete. We use `Align` to create a type whose size is equal
1551
+ // to the alignment of another type so that we can use `transmute` to
1552
+ // check alignment as well.
1553
+
1554
+ let e = $e;
1555
+ #[ allow( unused, clippy:: diverging_sub_expression) ]
1556
+ if false {
1557
+ // This branch, though never taken, ensures that the type of `e` is
1558
+ // `&T` where `T: 't + Sized + AsBytes`, that the type of this macro
1559
+ // expression is `&U` where `U: 'u + Sized + FromBytes`, and that
1560
+ // `'t` outlives `'u`.
1561
+ const fn transmute<' u, ' t: ' u, T : ' t + Sized + $crate:: AsBytes , U : ' u + Sized + $crate:: FromBytes >( _t: & ' t T ) -> & ' u U {
1562
+ unreachable!( )
1563
+ }
1564
+ transmute( e)
1565
+ } else if false {
1566
+ // This branch, though never taken, ensures that `size_of::<T>() ==
1567
+ // size_of::<U>()`.
1568
+
1569
+ // `t` is inferred to have type `T` because it's assigned to `e` (of
1570
+ // type `&T`) as `&t`.
1571
+ let mut t = unreachable!( ) ;
1572
+ e = & t;
1573
+
1574
+ // `u` is inferred to have type `U` because it's used as `&u` as the
1575
+ // value returned from this branch.
1576
+ //
1577
+ // SAFETY: This code is never run.
1578
+ let u = unsafe { $crate:: __real_transmute( t) } ;
1579
+ & u
1580
+ } else if false {
1581
+ // This branch, though never taken, ensures that the alignment of
1582
+ // `T` is greater than or equal to to the alignment of `U`.
1583
+
1584
+ // `t` is inferred to have type `T` because it's assigned to `e` (of
1585
+ // type `&T`) as `&t`.
1586
+ let mut t = unreachable!( ) ;
1587
+ e = & t;
1588
+
1589
+ // `u` is inferred to have type `U` because it's used as `&u` as the
1590
+ // value returned from this branch.
1591
+ let mut u = unreachable!( ) ;
1592
+
1593
+ // `max_aligns` is inferred to have type `MaxAlignsOf<T, U>` because
1594
+ // of the inferred types of `t` and `u`.
1595
+ let max_aligns = $crate:: MaxAlignsOf :: new( t, u) ;
1596
+ // The type wildcard in this bound is inferred to be `T` because
1597
+ // `align_of.into_t()` is assigned to `t` (which has type `T`).
1598
+ //
1599
+ // This transmute will only compile successfully if
1600
+ // `max(align_of::<T>(), align_of::<U>()) == align_of::<T>()` - in
1601
+ // other words, if `align_of::<T>() >= align_of::<U>()`.
1602
+ //
1603
+ // SAFETY: This code is never run.
1604
+ let align_of: $crate:: AlignOf <_> = unsafe { $crate:: __real_transmute( max_aligns) } ;
1605
+ t = align_of. into_t( ) ;
1606
+
1607
+ & u
1608
+ } else {
1609
+ // SAFETY: `core::mem::transmute` ensures that `T` and `U` have the
1610
+ // same size. We know this transmute is safe thanks to the `AsBytes`
1611
+ // and `FromBytes` bounds enforced by the `false` branch.
1612
+ //
1613
+ // We use `$crate::__real_transmute` because we know it will always
1614
+ // be available for crates which are using the 2015 edition of Rust.
1615
+ // By contrast, if we were to use `std::mem::transmute`, this macro
1616
+ // would not work for such crates in `no_std` contexts, and if we
1617
+ // were to use `core::mem::transmute`, this macro would not work in
1618
+ // `std` contexts in which `core` was not manually imported. This is
1619
+ // not a problem for 2018 edition crates.
1620
+ unsafe { $crate:: __real_transmute( e) }
1621
+ }
1622
+ } }
1623
+ }
1624
+
1466
1625
/// A length- and alignment-checked reference to a byte slice which can safely
1467
1626
/// be reinterpreted as another type.
1468
1627
///
@@ -2320,11 +2479,11 @@ impl<T: ?Sized> AsAddress for *mut T {
2320
2479
}
2321
2480
}
2322
2481
2323
- /// Is `t` aligned to `mem:: align_of::<U>()`?
2482
+ /// Is `t` aligned to `align_of::<U>()`?
2324
2483
#[ inline( always) ]
2325
2484
fn aligned_to < T : AsAddress , U > ( t : T ) -> bool {
2326
- // `mem:: align_of::<U>()` is guaranteed to return a non-zero value, which in
2327
- // turn guarantees that this mod operation will not panic.
2485
+ // `align_of::<U>()` is guaranteed to return a non-zero value, which in turn
2486
+ // guarantees that this mod operation will not panic.
2328
2487
#[ allow( clippy:: arithmetic_side_effects) ]
2329
2488
let remainder = t. addr ( ) % mem:: align_of :: < U > ( ) ;
2330
2489
remainder == 0
@@ -3195,6 +3354,49 @@ mod tests {
3195
3354
assert_eq ! ( X , ARRAY_OF_ARRAYS ) ;
3196
3355
}
3197
3356
3357
+ #[ test]
3358
+ fn test_size_is_align ( ) {
3359
+ macro_rules! test {
3360
+ ( $ty: ty) => {
3361
+ assert_eq!( mem:: size_of:: <AlignOf <$ty>>( ) , mem:: align_of:: <$ty>( ) ) ;
3362
+ } ;
3363
+ }
3364
+
3365
+ test ! ( ( ) ) ;
3366
+ test ! ( u8 ) ;
3367
+ test ! ( AU64 ) ;
3368
+ test ! ( [ AU64 ; 2 ] ) ;
3369
+ }
3370
+
3371
+ #[ test]
3372
+ fn test_transmute_ref ( ) {
3373
+ // Test that memory is transmuted as expected.
3374
+ let array_of_u8s = [ 0u8 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ;
3375
+ let array_of_arrays = [ [ 0 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] , [ 6 , 7 ] ] ;
3376
+ let x: & [ [ u8 ; 2 ] ; 4 ] = transmute_ref ! ( & array_of_u8s) ;
3377
+ assert_eq ! ( * x, array_of_arrays) ;
3378
+ let x: & [ u8 ; 8 ] = transmute_ref ! ( & array_of_arrays) ;
3379
+ assert_eq ! ( * x, array_of_u8s) ;
3380
+
3381
+ // Test that `transmute_ref!` is legal in a const context.
3382
+ const ARRAY_OF_U8S : [ u8 ; 8 ] = [ 0u8 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ;
3383
+ const ARRAY_OF_ARRAYS : [ [ u8 ; 2 ] ; 4 ] = [ [ 0 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] , [ 6 , 7 ] ] ;
3384
+ #[ allow( clippy:: redundant_static_lifetimes) ]
3385
+ const X : & ' static [ [ u8 ; 2 ] ; 4 ] = transmute_ref ! ( & ARRAY_OF_U8S ) ;
3386
+ assert_eq ! ( * X , ARRAY_OF_ARRAYS ) ;
3387
+
3388
+ // Test that it's legal to transmute a reference while shrinking the
3389
+ // lifetime (note that `X` has the lifetime `'static`).
3390
+ let x: & [ u8 ; 8 ] = transmute_ref ! ( X ) ;
3391
+ assert_eq ! ( * x, ARRAY_OF_U8S ) ;
3392
+
3393
+ // Test that `transmute_ref!` supports decreasing alignment.
3394
+ let u = AU64 ( 0 ) ;
3395
+ let array = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
3396
+ let x: & [ u8 ; 8 ] = transmute_ref ! ( & u) ;
3397
+ assert_eq ! ( * x, array) ;
3398
+ }
3399
+
3198
3400
#[ test]
3199
3401
fn test_address ( ) {
3200
3402
// Test that the `Deref` and `DerefMut` implementations return a
0 commit comments