Skip to content

Commit 21d085a

Browse files
committed
core: Add functions core::ptr::dangling/_mut() -> *T
Add functions to create a dangling aligned non-null raw pointer. The use case is to fix all the places we use "1 as *mut T" is used, in particular in the slice iterators. The aligned pointer has a value like 0x1, 0x4, 0x8 etc. depending on the alignment of the pointed-to type. It is useful when a non-null pointer is required like in references, slices, boxes, and other places. NOTE: This changes the observable behaviour of slice iterators. Previously, it would always yield 0x1 pointers (as references) for ZST, including types like `[SomeType; 0]`. They now use an aligned non-null pointer. Expose std::ptr::dangling/_mut as new unstable functions with intent on later stabilization, because if this low level trick is needed in collections, the rest of the Rust ecosystem will need them as well.
1 parent f28df20 commit 21d085a

File tree

7 files changed

+33
-13
lines changed

7 files changed

+33
-13
lines changed

src/liballoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
#![feature(pattern)]
110110
#![feature(placement_in_syntax)]
111111
#![feature(placement_new_protocol)]
112+
#![feature(ptr_dangling)]
112113
#![feature(rustc_attrs)]
113114
#![feature(shared)]
114115
#![feature(slice_get_slice)]

src/liballoc/vec.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2344,7 +2344,7 @@ impl<T> Iterator for IntoIter<T> {
23442344

23452345
// Use a non-null pointer value
23462346
// (self.ptr might be null because of wrapping)
2347-
Some(ptr::read(1 as *mut T))
2347+
Some(ptr::read(ptr::dangling()))
23482348
} else {
23492349
let old = self.ptr;
23502350
self.ptr = self.ptr.offset(1);
@@ -2384,7 +2384,7 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
23842384

23852385
// Use a non-null pointer value
23862386
// (self.end might be null because of wrapping)
2387-
Some(ptr::read(1 as *mut T))
2387+
Some(ptr::read(ptr::dangling()))
23882388
} else {
23892389
self.end = self.end.offset(-1);
23902390

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
#![feature(unboxed_closures)]
9292
#![feature(untagged_unions)]
9393
#![feature(unwind_attributes)]
94+
#![feature(const_align_of)]
9495
#![feature(const_min_value)]
9596
#![feature(const_max_value)]
9697
#![feature(const_atomic_bool_new)]

src/libcore/ptr.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -2083,6 +2083,24 @@ impl<T: ?Sized> PartialEq for *mut T {
20832083
#[stable(feature = "rust1", since = "1.0.0")]
20842084
impl<T: ?Sized> Eq for *mut T {}
20852085

2086+
#[unstable(feature = "ptr_dangling", issue = "45557")]
2087+
#[rustc_const_unstable(feature = "const_ptr_dangling")]
2088+
/// Returns a const raw pointer that is dangling, but well-aligned and not null.
2089+
///
2090+
/// This is used where a non-null pointer is required.
2091+
pub const fn dangling<T>() -> *const T {
2092+
mem::align_of::<T>() as *const T
2093+
}
2094+
2095+
#[unstable(feature = "ptr_dangling", issue = "45557")]
2096+
#[rustc_const_unstable(feature = "const_ptr_dangling_mut")]
2097+
/// Returns a mut raw pointer that is dangling, but well-aligned and not null.
2098+
///
2099+
/// This is used where a non-null pointer is required.
2100+
pub const fn dangling_mut<T>() -> *mut T {
2101+
mem::align_of::<T>() as *mut T
2102+
}
2103+
20862104
/// Compare raw pointers for equality.
20872105
///
20882106
/// This is the same as using the `==` operator, but less generic:
@@ -2325,8 +2343,7 @@ impl<T: Sized> Unique<T> {
23252343
/// `Vec::new` does.
23262344
pub fn empty() -> Self {
23272345
unsafe {
2328-
let ptr = mem::align_of::<T>() as *mut T;
2329-
Unique::new_unchecked(ptr)
2346+
Unique::new_unchecked(dangling_mut())
23302347
}
23312348
}
23322349
}
@@ -2460,8 +2477,7 @@ impl<T: Sized> Shared<T> {
24602477
/// `Vec::new` does.
24612478
pub fn empty() -> Self {
24622479
unsafe {
2463-
let ptr = mem::align_of::<T>() as *mut T;
2464-
Shared::new_unchecked(ptr)
2480+
Shared::new_unchecked(dangling_mut())
24652481
}
24662482
}
24672483
}

src/libcore/slice/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ macro_rules! make_ref {
244244
let ptr = $ptr;
245245
if size_from_ptr(ptr) == 0 {
246246
// Use a non-null pointer value
247-
&*(1 as *mut _)
247+
&*ptr::dangling()
248248
} else {
249249
&*ptr
250250
}
@@ -257,7 +257,7 @@ macro_rules! make_ref_mut {
257257
let ptr = $ptr;
258258
if size_from_ptr(ptr) == 0 {
259259
// Use a non-null pointer value
260-
&mut *(1 as *mut _)
260+
&mut *(ptr::dangling_mut())
261261
} else {
262262
&mut *ptr
263263
}
@@ -279,7 +279,7 @@ impl<T> SliceExt for [T] {
279279
fn iter(&self) -> Iter<T> {
280280
unsafe {
281281
let p = if mem::size_of::<T>() == 0 {
282-
1 as *const _
282+
ptr::dangling()
283283
} else {
284284
let p = self.as_ptr();
285285
assume(!p.is_null());
@@ -443,7 +443,7 @@ impl<T> SliceExt for [T] {
443443
fn iter_mut(&mut self) -> IterMut<T> {
444444
unsafe {
445445
let p = if mem::size_of::<T>() == 0 {
446-
1 as *mut _
446+
ptr::dangling_mut()
447447
} else {
448448
let p = self.as_mut_ptr();
449449
assume(!p.is_null());
@@ -1259,7 +1259,7 @@ macro_rules! make_slice {
12591259
let diff = ($end as usize).wrapping_sub(start as usize);
12601260
if size_from_ptr(start) == 0 {
12611261
// use a non-null pointer value
1262-
unsafe { from_raw_parts(1 as *const _, diff) }
1262+
unsafe { from_raw_parts(ptr::dangling(), diff) }
12631263
} else {
12641264
let len = diff / size_from_ptr(start);
12651265
unsafe { from_raw_parts(start, len) }
@@ -1273,7 +1273,7 @@ macro_rules! make_mut_slice {
12731273
let diff = ($end as usize).wrapping_sub(start as usize);
12741274
if size_from_ptr(start) == 0 {
12751275
// use a non-null pointer value
1276-
unsafe { from_raw_parts_mut(1 as *mut _, diff) }
1276+
unsafe { from_raw_parts_mut(ptr::dangling_mut(), diff) }
12771277
} else {
12781278
let len = diff / size_from_ptr(start);
12791279
unsafe { from_raw_parts_mut(start, len) }

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#![feature(match_default_bindings)]
5656
#![feature(never_type)]
5757
#![feature(nonzero)]
58+
#![feature(ptr_dangling)]
5859
#![feature(quote)]
5960
#![feature(refcell_replace_swap)]
6061
#![feature(rustc_diagnostic_macros)]

src/librustc/ty/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use std::rc::Rc;
4646
use std::slice;
4747
use std::vec::IntoIter;
4848
use std::mem;
49+
use std::ptr;
4950
use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
5051
use syntax::attr;
5152
use syntax::ext::hygiene::{Mark, SyntaxContext};
@@ -572,7 +573,7 @@ impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<Ty<'tcx>> {}
572573
impl<T> Slice<T> {
573574
pub fn empty<'a>() -> &'a Slice<T> {
574575
unsafe {
575-
mem::transmute(slice::from_raw_parts(0x1 as *const T, 0))
576+
mem::transmute(slice::from_raw_parts(ptr::dangling::<T>(), 0))
576577
}
577578
}
578579
}

0 commit comments

Comments
 (0)