bytemuck/transparent.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
use super::*;
/// A trait which indicates that a type is a `#[repr(transparent)]` wrapper
/// around the `Inner` value.
///
/// This allows safely copy transmuting between the `Inner` type and the
/// `TransparentWrapper` type. Functions like `wrap_{}` convert from the inner
/// type to the wrapper type and `peel_{}` functions do the inverse conversion
/// from the wrapper type to the inner type. We deliberately do not call the
/// wrapper-removing methods "unwrap" because at this point that word is too
/// strongly tied to the Option/ Result methods.
///
/// # Safety
///
/// The safety contract of `TransparentWrapper` is relatively simple:
///
/// For a given `Wrapper` which implements `TransparentWrapper<Inner>`:
///
/// 1. `Wrapper` must be a wrapper around `Inner` with an identical data
/// representations. This either means that it must be a
/// `#[repr(transparent)]` struct which contains a either a field of type
/// `Inner` (or a field of some other transparent wrapper for `Inner`) as
/// the only non-ZST field.
///
/// 2. Any fields *other* than the `Inner` field must be trivially constructable
/// ZSTs, for example `PhantomData`, `PhantomPinned`, etc. (When deriving
/// `TransparentWrapper` on a type with ZST fields, the ZST fields must be
/// [`Zeroable`]).
///
/// 3. The `Wrapper` may not impose additional alignment requirements over
/// `Inner`.
/// - Note: this is currently guaranteed by `repr(transparent)`, but there
/// have been discussions of lifting it, so it's stated here explicitly.
///
/// 4. All functions on `TransparentWrapper` **may not** be overridden.
///
/// ## Caveats
///
/// If the wrapper imposes additional constraints upon the inner type which are
/// required for safety, it's responsible for ensuring those still hold -- this
/// generally requires preventing access to instances of the inner type, as
/// implementing `TransparentWrapper<U> for T` means anybody can call
/// `T::cast_ref(any_instance_of_u)`.
///
/// For example, it would be invalid to implement TransparentWrapper for `str`
/// to implement `TransparentWrapper` around `[u8]` because of this.
///
/// # Examples
///
/// ## Basic
///
/// ```
/// use bytemuck::TransparentWrapper;
/// # #[derive(Default)]
/// # struct SomeStruct(u32);
///
/// #[repr(transparent)]
/// struct MyWrapper(SomeStruct);
///
/// unsafe impl TransparentWrapper<SomeStruct> for MyWrapper {}
///
/// // interpret a reference to &SomeStruct as a &MyWrapper
/// let thing = SomeStruct::default();
/// let inner_ref: &MyWrapper = MyWrapper::wrap_ref(&thing);
///
/// // Works with &mut too.
/// let mut mut_thing = SomeStruct::default();
/// let inner_mut: &mut MyWrapper = MyWrapper::wrap_mut(&mut mut_thing);
///
/// # let _ = (inner_ref, inner_mut); // silence warnings
/// ```
///
/// ## Use with dynamically sized types
///
/// ```
/// use bytemuck::TransparentWrapper;
///
/// #[repr(transparent)]
/// struct Slice<T>([T]);
///
/// unsafe impl<T> TransparentWrapper<[T]> for Slice<T> {}
///
/// let s = Slice::wrap_ref(&[1u32, 2, 3]);
/// assert_eq!(&s.0, &[1, 2, 3]);
///
/// let mut buf = [1, 2, 3u8];
/// let sm = Slice::wrap_mut(&mut buf);
/// ```
///
/// ## Deriving
///
/// When deriving, the non-wrapped fields must uphold all the normal
/// requirements, and must also be `Zeroable`.
#[cfg_attr(feature = "derive", doc = "```")]
#[cfg_attr(
not(feature = "derive"),
doc = "```ignore
// This example requires the `derive` feature."
)]
/// use bytemuck::TransparentWrapper;
/// use std::marker::PhantomData;
///
/// #[derive(TransparentWrapper)]
/// #[repr(transparent)]
/// #[transparent(usize)]
/// struct Wrapper<T: ?Sized>(usize, PhantomData<T>); // PhantomData<T> implements Zeroable for all T
/// ```
///
/// Here, an error will occur, because `MyZst` does not implement `Zeroable`.
#[cfg_attr(feature = "derive", doc = "```compile_fail")]
#[cfg_attr(
not(feature = "derive"),
doc = "```ignore
// This example requires the `derive` feature."
)]
/// use bytemuck::TransparentWrapper;
/// struct MyZst;
///
/// #[derive(TransparentWrapper)]
/// #[repr(transparent)]
/// #[transparent(usize)]
/// struct Wrapper(usize, MyZst); // MyZst does not implement Zeroable
/// ```
pub unsafe trait TransparentWrapper<Inner: ?Sized> {
/// Convert the inner type into the wrapper type.
#[inline]
fn wrap(s: Inner) -> Self
where
Self: Sized,
Inner: Sized,
{
assert!(size_of::<Inner>() == size_of::<Self>());
assert!(align_of::<Inner>() == align_of::<Self>());
// SAFETY: The unsafe contract requires that `Self` and `Inner` have
// identical representations.
unsafe { transmute!(s) }
}
/// Convert a reference to the inner type into a reference to the wrapper
/// type.
#[inline]
fn wrap_ref(s: &Inner) -> &Self {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(size_of::<*const Inner>() == size_of::<*const Self>());
unsafe {
// A pointer cast doesn't work here because rustc can't tell that
// the vtables match (because of the `?Sized` restriction relaxation).
// A `transmute` doesn't work because the sizes are unspecified.
//
// SAFETY: The unsafe contract requires that these two have
// identical representations.
let inner_ptr = s as *const Inner;
let wrapper_ptr: *const Self = transmute!(inner_ptr);
&*wrapper_ptr
}
}
/// Convert a mutable reference to the inner type into a mutable reference to
/// the wrapper type.
#[inline]
fn wrap_mut(s: &mut Inner) -> &mut Self {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is about the best we can do on stable.
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
unsafe {
// A pointer cast doesn't work here because rustc can't tell that
// the vtables match (because of the `?Sized` restriction relaxation).
// A `transmute` doesn't work because the sizes are unspecified.
//
// SAFETY: The unsafe contract requires that these two have
// identical representations.
let inner_ptr = s as *mut Inner;
let wrapper_ptr: *mut Self = transmute!(inner_ptr);
&mut *wrapper_ptr
}
}
/// Convert a slice to the inner type into a slice to the wrapper type.
#[inline]
fn wrap_slice(s: &[Inner]) -> &[Self]
where
Self: Sized,
Inner: Sized,
{
assert!(size_of::<Inner>() == size_of::<Self>());
assert!(align_of::<Inner>() == align_of::<Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
unsafe { core::slice::from_raw_parts(s.as_ptr() as *const Self, s.len()) }
}
/// Convert a mutable slice to the inner type into a mutable slice to the
/// wrapper type.
#[inline]
fn wrap_slice_mut(s: &mut [Inner]) -> &mut [Self]
where
Self: Sized,
Inner: Sized,
{
assert!(size_of::<Inner>() == size_of::<Self>());
assert!(align_of::<Inner>() == align_of::<Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
unsafe {
core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Self, s.len())
}
}
/// Convert the wrapper type into the inner type.
#[inline]
fn peel(s: Self) -> Inner
where
Self: Sized,
Inner: Sized,
{
assert!(size_of::<Inner>() == size_of::<Self>());
assert!(align_of::<Inner>() == align_of::<Self>());
// SAFETY: The unsafe contract requires that `Self` and `Inner` have
// identical representations.
unsafe { transmute!(s) }
}
/// Convert a reference to the wrapper type into a reference to the inner
/// type.
#[inline]
fn peel_ref(s: &Self) -> &Inner {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is about the best we can do on stable.
assert!(size_of::<*const Inner>() == size_of::<*const Self>());
unsafe {
// A pointer cast doesn't work here because rustc can't tell that
// the vtables match (because of the `?Sized` restriction relaxation).
// A `transmute` doesn't work because the sizes are unspecified.
//
// SAFETY: The unsafe contract requires that these two have
// identical representations.
let wrapper_ptr = s as *const Self;
let inner_ptr: *const Inner = transmute!(wrapper_ptr);
&*inner_ptr
}
}
/// Convert a mutable reference to the wrapper type into a mutable reference
/// to the inner type.
#[inline]
fn peel_mut(s: &mut Self) -> &mut Inner {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is about the best we can do on stable.
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
unsafe {
// A pointer cast doesn't work here because rustc can't tell that
// the vtables match (because of the `?Sized` restriction relaxation).
// A `transmute` doesn't work because the sizes are unspecified.
//
// SAFETY: The unsafe contract requires that these two have
// identical representations.
let wrapper_ptr = s as *mut Self;
let inner_ptr: *mut Inner = transmute!(wrapper_ptr);
&mut *inner_ptr
}
}
/// Convert a slice to the wrapped type into a slice to the inner type.
#[inline]
fn peel_slice(s: &[Self]) -> &[Inner]
where
Self: Sized,
Inner: Sized,
{
assert!(size_of::<Inner>() == size_of::<Self>());
assert!(align_of::<Inner>() == align_of::<Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
unsafe { core::slice::from_raw_parts(s.as_ptr() as *const Inner, s.len()) }
}
/// Convert a mutable slice to the wrapped type into a mutable slice to the
/// inner type.
#[inline]
fn peel_slice_mut(s: &mut [Self]) -> &mut [Inner]
where
Self: Sized,
Inner: Sized,
{
assert!(size_of::<Inner>() == size_of::<Self>());
assert!(align_of::<Inner>() == align_of::<Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
unsafe {
core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Inner, s.len())
}
}
}
unsafe impl<T> TransparentWrapper<T> for core::num::Wrapping<T> {}
#[cfg(feature = "transparentwrapper_extra")]
#[cfg_attr(
feature = "nightly_docs",
doc(cfg(feature = "transparentwrapper_extra"))
)]
unsafe impl<T> TransparentWrapper<T> for core::num::Saturating<T> {}
// Note that `Reverse` existed since Rust 1.19.0, but was only made `#[repr(transparent)]`
// in Rust 1.52.0 (PR: https://github.com/rust-lang/rust/pull/81879), so we have it under
// the same feature as `Saturating`, which was stabilized in Rust 1.74.0, so that this
// impl cannot be used on a version before 1.52.0 where it would be unsound.
#[cfg(feature = "transparentwrapper_extra")]
#[cfg_attr(
feature = "nightly_docs",
doc(cfg(feature = "transparentwrapper_extra"))
)]
unsafe impl<T> TransparentWrapper<T> for core::cmp::Reverse<T> {}