Skip to content

Commit 298f6b8

Browse files
committed
Use pseudocode to document transmute_ref
Partially addresses #1046.
1 parent 730f400 commit 298f6b8

File tree

1 file changed

+39
-28
lines changed

1 file changed

+39
-28
lines changed

src/lib.rs

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4418,14 +4418,25 @@ macro_rules! transmute {
44184418
/// Safely transmutes a mutable or immutable reference of one type to an
44194419
/// immutable reference of another type of the same size.
44204420
///
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+
/// ```
44264437
///
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.
44294440
///
44304441
/// # Examples
44314442
///
@@ -4550,9 +4561,10 @@ macro_rules! transmute_ref {
45504561
/// another type of the same size.
45514562
///
45524563
/// 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>()`.
45564568
///
45574569
/// The lifetime of the input type, `&mut T`, must be the same as or outlive the
45584570
/// lifetime of the output type, `&mut U`.
@@ -4617,9 +4629,9 @@ macro_rules! transmute_mut {
46174629
#[allow(unused, clippy::diverging_sub_expression)]
46184630
if false {
46194631
// 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`.
46234635

46244636
// We use immutable references here rather than mutable so that, if
46254637
// this macro is used in a const context (in which, as of this
@@ -4629,20 +4641,16 @@ macro_rules! transmute_mut {
46294641
struct AssertSrcIsSized<'a, T: ::core::marker::Sized>(&'a T);
46304642
struct AssertSrcIsFromBytes<'a, T: ?::core::marker::Sized + $crate::FromBytes>(&'a T);
46314643
struct AssertSrcIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T);
4632-
struct AssertSrcIsNoCell<'a, T: ?::core::marker::Sized + $crate::NoCell>(&'a T);
46334644
struct AssertDstIsSized<'a, T: ::core::marker::Sized>(&'a T);
46344645
struct AssertDstIsFromBytes<'a, T: ?::core::marker::Sized + $crate::FromBytes>(&'a T);
46354646
struct AssertDstIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T);
4636-
struct AssertDstIsNoCell<'a, T: ?::core::marker::Sized + $crate::NoCell>(&'a T);
46374647

46384648
if true {
46394649
let _ = AssertSrcIsSized(&*e);
46404650
} else if true {
46414651
let _ = AssertSrcIsFromBytes(&*e);
4642-
} else if true {
4643-
let _ = AssertSrcIsIntoBytes(&*e);
46444652
} else {
4645-
let _ = AssertSrcIsNoCell(&*e);
4653+
let _ = AssertSrcIsIntoBytes(&*e);
46464654
}
46474655

46484656
if true {
@@ -4653,13 +4661,9 @@ macro_rules! transmute_mut {
46534661
#[allow(unused, unreachable_code)]
46544662
let u = AssertDstIsFromBytes(loop {});
46554663
&mut *u.0
4656-
} else if true {
4657-
#[allow(unused, unreachable_code)]
4658-
let u = AssertDstIsIntoBytes(loop {});
4659-
&mut *u.0
46604664
} else {
46614665
#[allow(unused, unreachable_code)]
4662-
let u = AssertDstIsNoCell(loop {});
4666+
let u = AssertDstIsIntoBytes(loop {});
46634667
&mut *u.0
46644668
}
46654669
} else if false {
@@ -4682,11 +4686,10 @@ macro_rules! transmute_mut {
46824686
&mut u
46834687
} else {
46844688
// 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.
46904693
// - We know that `size_of::<Src>() == size_of::<Dst>()` thanks to
46914694
// the use of `assert_size_eq!` above.
46924695
// - We know that `align_of::<Src>() >= align_of::<Dst>()` thanks to
@@ -7418,6 +7421,14 @@ mod tests {
74187421
#[allow(clippy::useless_transmute)]
74197422
let y: &u8 = transmute_mut!(&mut x);
74207423
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);
74217432
}
74227433

74237434
#[test]

0 commit comments

Comments
 (0)