about summary refs log tree commit diff
path: root/src/libcore/ptr
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2020-06-12 18:17:30 +0200
committerRalf Jung <post@ralfj.de>2020-06-12 19:10:58 +0200
commitf0d2e78d39d0efdb431af0b59c498d532d8146e2 (patch)
treea81ded226be8bdd8aec8f5515d0a30887c04ef36 /src/libcore/ptr
parent59493917be3e87e1dfb44a9ccb66a9f9b17228e6 (diff)
downloadrust-f0d2e78d39d0efdb431af0b59c498d532d8146e2.tar.gz
rust-f0d2e78d39d0efdb431af0b59c498d532d8146e2.zip
add raw_ref macros
Diffstat (limited to 'src/libcore/ptr')
-rw-r--r--src/libcore/ptr/mod.rs67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index 777284ca5c0..199f08c3d50 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -1399,3 +1399,70 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
 fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
 fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
 fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
+
+/// Create a `const` raw pointer to a place, without creating an intermediate reference.
+///
+/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
+/// and points to initialized data. For cases where those requirements do not hold,
+/// raw pointers should be used instead. However, `&expr as *const _` creates a reference
+/// before casting it to a raw pointer, and that reference is subject to the same rules
+/// as all other references. This macro can create a raw pointer *without* creating
+/// a reference first.
+///
+/// # Example
+///
+/// ```
+/// #![feature(raw_ref_macros)]
+/// use std::ptr;
+///
+/// #[repr(packed)]
+/// struct Packed {
+///     f1: u8,
+///     f2: u16,
+/// }
+///
+/// let packed = Packed { f1: 1, f2: 2 };
+/// // `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
+/// let raw_f2 = ptr::raw_const!(packed.f2);
+/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
+/// ```
+#[unstable(feature = "raw_ref_macros", issue = "none")]
+#[rustc_macro_transparency = "semitransparent"]
+#[allow_internal_unstable(raw_ref_op)]
+pub macro raw_const($e:expr) {
+    &raw const $e
+}
+
+/// Create a `mut` raw pointer to a place, without creating an intermediate reference.
+///
+/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
+/// and points to initialized data. For cases where those requirements do not hold,
+/// raw pointers should be used instead. However, `&mut expr as *mut _` creates a reference
+/// before casting it to a raw pointer, and that reference is subject to the same rules
+/// as all other references. This macro can create a raw pointer *without* creating
+/// a reference first.
+///
+/// # Example
+///
+/// ```
+/// #![feature(raw_ref_macros)]
+/// use std::ptr;
+///
+/// #[repr(packed)]
+/// struct Packed {
+///     f1: u8,
+///     f2: u16,
+/// }
+///
+/// let mut packed = Packed { f1: 1, f2: 2 };
+/// // `&mut packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
+/// let raw_f2 = ptr::raw_mut!(packed.f2);
+/// unsafe { raw_f2.write_unaligned(42); }
+/// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference.
+/// ```
+#[unstable(feature = "raw_ref_macros", issue = "none")]
+#[rustc_macro_transparency = "semitransparent"]
+#[allow_internal_unstable(raw_ref_op)]
+pub macro raw_mut($e:expr) {
+    &raw mut $e
+}