Skip to content

Commit 49ab0ca

Browse files
authored
Rollup merge of #72279 - RalfJung:raw-ref-macros, r=nikomatsakis
add raw_ref macros In #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.
2 parents 39f8784 + 0265e4e commit 49ab0ca

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

src/libcore/ptr/mod.rs

+67
Original file line numberDiff line numberDiff line change
@@ -1399,3 +1399,70 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
13991399
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
14001400
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
14011401
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
1402+
1403+
/// Create a `const` raw pointer to a place, without creating an intermediate reference.
1404+
///
1405+
/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
1406+
/// and points to initialized data. For cases where those requirements do not hold,
1407+
/// raw pointers should be used instead. However, `&expr as *const _` creates a reference
1408+
/// before casting it to a raw pointer, and that reference is subject to the same rules
1409+
/// as all other references. This macro can create a raw pointer *without* creating
1410+
/// a reference first.
1411+
///
1412+
/// # Example
1413+
///
1414+
/// ```
1415+
/// #![feature(raw_ref_macros)]
1416+
/// use std::ptr;
1417+
///
1418+
/// #[repr(packed)]
1419+
/// struct Packed {
1420+
/// f1: u8,
1421+
/// f2: u16,
1422+
/// }
1423+
///
1424+
/// let packed = Packed { f1: 1, f2: 2 };
1425+
/// // `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
1426+
/// let raw_f2 = ptr::raw_const!(packed.f2);
1427+
/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
1428+
/// ```
1429+
#[unstable(feature = "raw_ref_macros", issue = "73394")]
1430+
#[rustc_macro_transparency = "semitransparent"]
1431+
#[allow_internal_unstable(raw_ref_op)]
1432+
pub macro raw_const($e:expr) {
1433+
&raw const $e
1434+
}
1435+
1436+
/// Create a `mut` raw pointer to a place, without creating an intermediate reference.
1437+
///
1438+
/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
1439+
/// and points to initialized data. For cases where those requirements do not hold,
1440+
/// raw pointers should be used instead. However, `&mut expr as *mut _` creates a reference
1441+
/// before casting it to a raw pointer, and that reference is subject to the same rules
1442+
/// as all other references. This macro can create a raw pointer *without* creating
1443+
/// a reference first.
1444+
///
1445+
/// # Example
1446+
///
1447+
/// ```
1448+
/// #![feature(raw_ref_macros)]
1449+
/// use std::ptr;
1450+
///
1451+
/// #[repr(packed)]
1452+
/// struct Packed {
1453+
/// f1: u8,
1454+
/// f2: u16,
1455+
/// }
1456+
///
1457+
/// let mut packed = Packed { f1: 1, f2: 2 };
1458+
/// // `&mut packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
1459+
/// let raw_f2 = ptr::raw_mut!(packed.f2);
1460+
/// unsafe { raw_f2.write_unaligned(42); }
1461+
/// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference.
1462+
/// ```
1463+
#[unstable(feature = "raw_ref_macros", issue = "73394")]
1464+
#[rustc_macro_transparency = "semitransparent"]
1465+
#[allow_internal_unstable(raw_ref_op)]
1466+
pub macro raw_mut($e:expr) {
1467+
&raw mut $e
1468+
}

src/libstd/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@
298298
#![feature(prelude_import)]
299299
#![feature(ptr_internals)]
300300
#![feature(raw)]
301+
#![feature(raw_ref_macros)]
301302
#![feature(renamed_spin_loop)]
302303
#![feature(rustc_attrs)]
303304
#![feature(rustc_private)]

0 commit comments

Comments
 (0)