Skip to content

Commit 390adcb

Browse files
committed
impl<T> From<Option<&T>> for *const T
And same for *mut T
1 parent 3c554f5 commit 390adcb

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed

library/core/src/mem/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1182,7 +1182,7 @@ impl<T> fmt::Debug for Discriminant<T> {
11821182
/// // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)` `union`
11831183
/// // between `repr(C)` structs, each of which has the `u8` discriminant as its first
11841184
/// // field, so we can read the discriminant without offsetting the pointer.
1185-
/// unsafe { *<*const _>::from(self).cast::<u8>() }
1185+
/// unsafe { *(self as *const Enum).cast::<u8>() }
11861186
/// }
11871187
/// }
11881188
///

library/core/src/ptr/const_ptr.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,3 +1764,20 @@ impl<T: ?Sized> PartialOrd for *const T {
17641764
*self >= *other
17651765
}
17661766
}
1767+
1768+
#[stable(feature = "pointer_from_option_ref", since = "CURRENT_RUSTC_VERSION")]
1769+
impl<T> From<Option<&T>> for *const T {
1770+
/// Converts from an optional reference to a raw pointer, returning [`ptr::null`] if `x` is `None`.
1771+
///
1772+
/// Because of the [null pointer optimization][npo], this is a zero-cost transformation.
1773+
///
1774+
/// [npo]: https://doc.rust-lang.org/std/option/index.html#representation
1775+
/// [`ptr::null`]: crate::ptr::null()
1776+
#[inline]
1777+
fn from(x: Option<&T>) -> *const T {
1778+
match x {
1779+
Some(x) => x,
1780+
None => null(),
1781+
}
1782+
}
1783+
}

library/core/src/ptr/mut_ptr.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,3 +2203,20 @@ impl<T: ?Sized> PartialOrd for *mut T {
22032203
*self >= *other
22042204
}
22052205
}
2206+
2207+
#[stable(feature = "pointer_from_option_ref", since = "CURRENT_RUSTC_VERSION")]
2208+
impl<T> From<Option<&mut T>> for *mut T {
2209+
/// Converts from an optional mutable reference to a raw pointer, providing [`ptr::null_mut`] if it is `None`.
2210+
///
2211+
/// Because of the [null pointer optimization][npo], this is a zero-cost transformation.
2212+
///
2213+
/// [npo]: https://doc.rust-lang.org/std/option/index.html#representation
2214+
/// [`ptr::null_mut`]: crate::ptr::null_mut()
2215+
#[inline]
2216+
fn from(x: Option<&mut T>) -> *mut T {
2217+
match x {
2218+
Some(x) => x,
2219+
None => null_mut(),
2220+
}
2221+
}
2222+
}

library/core/tests/ptr.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,3 +1126,28 @@ fn test_const_copy() {
11261126
assert!(*ptr2 == 1);
11271127
};
11281128
}
1129+
1130+
#[test]
1131+
fn test_from_option_ref() {
1132+
let none_ref: Option<&i32> = None;
1133+
let some_ref: Option<&i32> = Some(&10);
1134+
1135+
let non_const_ptr: *const i32 = none_ref.into();
1136+
let some_const_ptr: *const i32 = some_ref.into();
1137+
1138+
assert!(non_const_ptr.is_null());
1139+
assert!(!some_const_ptr.is_null());
1140+
assert_eq!(unsafe { some_const_ptr.read() }, 10);
1141+
1142+
let mut val: i32 = 20;
1143+
let none_mut: Option<&mut i32> = None;
1144+
let some_mut: Option<&mut i32> = Some(&mut val);
1145+
1146+
let none_mut_ptr: *mut i32 = none_mut.into();
1147+
let some_mut_ptr: *mut i32 = some_mut.into();
1148+
1149+
assert!(none_mut_ptr.is_null());
1150+
assert!(!some_mut_ptr.is_null());
1151+
assert_eq!(unsafe { some_mut_ptr.replace(30) }, 20);
1152+
assert_eq!(unsafe { some_mut_ptr.read() }, 30);
1153+
}

0 commit comments

Comments
 (0)