@@ -4418,14 +4418,25 @@ macro_rules! transmute {
4418
4418
/// Safely transmutes a mutable or immutable reference of one type to an
4419
4419
/// immutable reference of another type of the same size.
4420
4420
///
4421
- /// The expression `$e` must have a concrete type, `&T` or `&mut T`, where `T:
4422
- /// Sized + IntoBytes`. The `transmute_ref!` expression must also have a
4423
- /// concrete type, `&U` (`U` is inferred from the calling context), where `U:
4424
- /// Sized + FromBytes`. It must be the case that `align_of::<T>() >=
4425
- /// align_of::<U>()`.
4421
+ /// This macro behaves like an invocation of this function:
4422
+ ///
4423
+ /// ```ignore
4424
+ /// const fn transmute_ref<'src, 'dst, Src, Dst>(src: &'src Src) -> &'dst Dst
4425
+ /// where
4426
+ /// 'src: 'dst,
4427
+ /// Src: IntoBytes + NoCell,
4428
+ /// Dst: FromBytes + NoCell,
4429
+ /// size_of::<Src>() == size_of::<Dst>(),
4430
+ /// align_of::<Src>() >= align_of::<Dst>(),
4431
+ /// {
4432
+ /// # /*
4433
+ /// ...
4434
+ /// # */
4435
+ /// }
4436
+ /// ```
4426
4437
///
4427
- /// The lifetime of the input type, `&T` or `&mut T`, must be the same as or
4428
- /// outlive the lifetime of the output type, `&U` .
4438
+ /// However, unlike a function, this macro can only be invoked when the types of
4439
+ /// `Src` and `Dst` are completely concrete .
4429
4440
///
4430
4441
/// # Examples
4431
4442
///
@@ -4550,9 +4561,10 @@ macro_rules! transmute_ref {
4550
4561
/// another type of the same size.
4551
4562
///
4552
4563
/// The expression `$e` must have a concrete type, `&mut T`, where `T: Sized +
4553
- /// IntoBytes`. The `transmute_mut!` expression must also have a concrete type,
4554
- /// `&mut U` (`U` is inferred from the calling context), where `U: Sized +
4555
- /// FromBytes`. It must be the case that `align_of::<T>() >= align_of::<U>()`.
4564
+ /// FromBytes + IntoBytes`. The `transmute_mut!` expression must also have a
4565
+ /// concrete type, `&mut U` (`U` is inferred from the calling context), where
4566
+ /// `U: Sized + FromBytes + IntoBytes`. It must be the case that
4567
+ /// `align_of::<T>() >= align_of::<U>()`.
4556
4568
///
4557
4569
/// The lifetime of the input type, `&mut T`, must be the same as or outlive the
4558
4570
/// lifetime of the output type, `&mut U`.
@@ -4617,9 +4629,9 @@ macro_rules! transmute_mut {
4617
4629
#[ allow( unused, clippy:: diverging_sub_expression) ]
4618
4630
if false {
4619
4631
// This branch, though never taken, ensures that the type of `e` is
4620
- // `&mut T` where `T: 't + Sized + FromBytes + IntoBytes + NoCell`
4621
- // and that the type of this macro expression is `&mut U` where `U:
4622
- // 'u + Sized + FromBytes + IntoBytes + NoCell `.
4632
+ // `&mut T` where `T: 't + Sized + FromBytes + IntoBytes` and that
4633
+ // the type of this macro expression is `&mut U` where `U: 'u +
4634
+ // Sized + FromBytes + IntoBytes`.
4623
4635
4624
4636
// We use immutable references here rather than mutable so that, if
4625
4637
// this macro is used in a const context (in which, as of this
@@ -4629,20 +4641,16 @@ macro_rules! transmute_mut {
4629
4641
struct AssertSrcIsSized <' a, T : :: core:: marker:: Sized >( & ' a T ) ;
4630
4642
struct AssertSrcIsFromBytes <' a, T : ?:: core:: marker:: Sized + $crate:: FromBytes >( & ' a T ) ;
4631
4643
struct AssertSrcIsIntoBytes <' a, T : ?:: core:: marker:: Sized + $crate:: IntoBytes >( & ' a T ) ;
4632
- struct AssertSrcIsNoCell <' a, T : ?:: core:: marker:: Sized + $crate:: NoCell >( & ' a T ) ;
4633
4644
struct AssertDstIsSized <' a, T : :: core:: marker:: Sized >( & ' a T ) ;
4634
4645
struct AssertDstIsFromBytes <' a, T : ?:: core:: marker:: Sized + $crate:: FromBytes >( & ' a T ) ;
4635
4646
struct AssertDstIsIntoBytes <' a, T : ?:: core:: marker:: Sized + $crate:: IntoBytes >( & ' a T ) ;
4636
- struct AssertDstIsNoCell <' a, T : ?:: core:: marker:: Sized + $crate:: NoCell >( & ' a T ) ;
4637
4647
4638
4648
if true {
4639
4649
let _ = AssertSrcIsSized ( & * e) ;
4640
4650
} else if true {
4641
4651
let _ = AssertSrcIsFromBytes ( & * e) ;
4642
- } else if true {
4643
- let _ = AssertSrcIsIntoBytes ( & * e) ;
4644
4652
} else {
4645
- let _ = AssertSrcIsNoCell ( & * e) ;
4653
+ let _ = AssertSrcIsIntoBytes ( & * e) ;
4646
4654
}
4647
4655
4648
4656
if true {
@@ -4653,13 +4661,9 @@ macro_rules! transmute_mut {
4653
4661
#[ allow( unused, unreachable_code) ]
4654
4662
let u = AssertDstIsFromBytes ( loop { } ) ;
4655
4663
& mut * u. 0
4656
- } else if true {
4657
- #[ allow( unused, unreachable_code) ]
4658
- let u = AssertDstIsIntoBytes ( loop { } ) ;
4659
- & mut * u. 0
4660
4664
} else {
4661
4665
#[ allow( unused, unreachable_code) ]
4662
- let u = AssertDstIsNoCell ( loop { } ) ;
4666
+ let u = AssertDstIsIntoBytes ( loop { } ) ;
4663
4667
& mut * u. 0
4664
4668
}
4665
4669
} else if false {
@@ -4682,11 +4686,10 @@ macro_rules! transmute_mut {
4682
4686
& mut u
4683
4687
} else {
4684
4688
// SAFETY: For source type `Src` and destination type `Dst`:
4685
- // - We know that `Src: FromBytes + IntoBytes + NoCell` and `Dst:
4686
- // FromBytes + IntoBytes + NoCell` thanks to the uses of
4687
- // `AssertSrcIsFromBytes`, `AssertSrcIsIntoBytes`,
4688
- // `AssertSrcIsNoCell`, `AssertDstIsFromBytes`,
4689
- // `AssertDstIsIntoBytes`, and `AssertDstIsNoCell` above.
4689
+ // - We know that `Src: FromBytes + IntoBytes` and `Dst: FromBytes +
4690
+ // IntoBytes` thanks to the uses of `AssertSrcIsFromBytes`,
4691
+ // `AssertSrcIsIntoBytes`, `AssertDstIsFromBytes`, and
4692
+ // `AssertDstIsIntoBytes` above.
4690
4693
// - We know that `size_of::<Src>() == size_of::<Dst>()` thanks to
4691
4694
// the use of `assert_size_eq!` above.
4692
4695
// - We know that `align_of::<Src>() >= align_of::<Dst>()` thanks to
@@ -7418,6 +7421,14 @@ mod tests {
7418
7421
#[ allow( clippy:: useless_transmute) ]
7419
7422
let y: & u8 = transmute_mut ! ( & mut x) ;
7420
7423
assert_eq ! ( * y, 0 ) ;
7424
+
7425
+ // Test that the referents can contain `UnsafeCell`s.
7426
+ let mut src = AtomicU8 :: new ( 42 ) ;
7427
+ {
7428
+ let dst: & mut AtomicI8 = transmute_mut ! ( & mut src) ;
7429
+ * dst. get_mut ( ) += 1 ;
7430
+ }
7431
+ assert_eq ! ( src. into_inner( ) , 43 ) ;
7421
7432
}
7422
7433
7423
7434
#[ test]
0 commit comments