diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2020-06-18 15:20:39 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-18 15:20:39 -0700 |
| commit | 49ab0cab618d9d1cb49220d7c253556a56148283 (patch) | |
| tree | 7406d6dcc67933b6a2160892b29323ca3ea49a26 | |
| parent | 39f8784eb6056c21c120bfa93bbec73e19773727 (diff) | |
| parent | 0265e4e61bcd51b11f0b13b712245feb9c59ab50 (diff) | |
| download | rust-49ab0cab618d9d1cb49220d7c253556a56148283.tar.gz rust-49ab0cab618d9d1cb49220d7c253556a56148283.zip | |
Rollup merge of #72279 - RalfJung:raw-ref-macros, r=nikomatsakis
add raw_ref macros In https://github.com/rust-lang/rust/issues/64490, various people were in favor of exposing `&raw` as a macro first before making the actual syntax stable. So this PR (unstably) introduces those macros. I'll create the tracking issue if we're okay moving forward with this.
| -rw-r--r-- | src/libcore/ptr/mod.rs | 67 | ||||
| -rw-r--r-- | src/libstd/lib.rs | 1 |
2 files changed, 68 insertions, 0 deletions
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 1be05d5efff..172b23a8d5a 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 = "73394")] +#[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 = "73394")] +#[rustc_macro_transparency = "semitransparent"] +#[allow_internal_unstable(raw_ref_op)] +pub macro raw_mut($e:expr) { + &raw mut $e +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index d6493454db5..ef699ede2a1 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -298,6 +298,7 @@ #![feature(prelude_import)] #![feature(ptr_internals)] #![feature(raw)] +#![feature(raw_ref_macros)] #![feature(renamed_spin_loop)] #![feature(rustc_attrs)] #![feature(rustc_private)] |
