Skip to content

Commit ac8b118

Browse files
committed
Auto merge of #96010 - eduardosm:Unique-on-top-of-NonNull, r=m-ou-se,tmiasko
Implement `core::ptr::Unique` on top of `NonNull` Removes the use `rustc_layout_scalar_valid_range_start` and some `unsafe` blocks.
2 parents 43a71dc + 7ba0292 commit ac8b118

13 files changed

+56
-51
lines changed

compiler/rustc_codegen_ssa/src/mir/place.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
448448

449449
// a box with a non-zst allocator should not be directly dereferenced
450450
if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
451-
let ptr = cg_base.extract_field(bx, 0).extract_field(bx, 0);
451+
// Extract `Box<T>` -> `Unique<T>` -> `NonNull<T>` -> `*const T`
452+
let ptr =
453+
cg_base.extract_field(bx, 0).extract_field(bx, 0).extract_field(bx, 0);
452454

453455
ptr.deref(bx.cx())
454456
} else {
@@ -464,7 +466,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
464466
mir::ProjectionElem::Deref => {
465467
// a box with a non-zst allocator should not be directly dereferenced
466468
if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
467-
let ptr = cg_base.project_field(bx, 0).project_field(bx, 0);
469+
// Project `Box<T>` -> `Unique<T>` -> `NonNull<T>` -> `*const T`
470+
let ptr =
471+
cg_base.project_field(bx, 0).project_field(bx, 0).project_field(bx, 0);
468472

469473
bx.load_operand(ptr).deref(bx.cx())
470474
} else {

library/core/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,14 @@
120120
#![feature(const_maybe_uninit_uninit_array)]
121121
#![feature(const_maybe_uninit_as_mut_ptr)]
122122
#![feature(const_maybe_uninit_assume_init)]
123+
#![feature(const_nonnull_new)]
123124
#![feature(const_num_from_num)]
124125
#![feature(const_ops)]
125126
#![feature(const_option)]
126127
#![feature(const_option_ext)]
127128
#![feature(const_pin)]
128129
#![feature(const_replace)]
130+
#![feature(const_ptr_as_ref)]
129131
#![feature(const_ptr_is_null)]
130132
#![feature(const_ptr_offset_from)]
131133
#![feature(const_ptr_read)]

library/core/src/ptr/unique.rs

+22-19
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::convert::From;
22
use crate::fmt;
33
use crate::marker::{PhantomData, Unsize};
4-
use crate::mem;
54
use crate::ops::{CoerceUnsized, DispatchFromDyn};
5+
use crate::ptr::NonNull;
66

77
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
88
/// of this wrapper owns the referent. Useful for building abstractions like
@@ -32,9 +32,8 @@ use crate::ops::{CoerceUnsized, DispatchFromDyn};
3232
)]
3333
#[doc(hidden)]
3434
#[repr(transparent)]
35-
#[rustc_layout_scalar_valid_range_start(1)]
3635
pub struct Unique<T: ?Sized> {
37-
pointer: *const T,
36+
pointer: NonNull<T>,
3837
// NOTE: this marker has no consequences for variance, but is necessary
3938
// for dropck to understand that we logically own a `T`.
4039
//
@@ -71,9 +70,7 @@ impl<T: Sized> Unique<T> {
7170
#[must_use]
7271
#[inline]
7372
pub const fn dangling() -> Self {
74-
// SAFETY: mem::align_of() returns a valid, non-null pointer. The
75-
// conditions to call new_unchecked() are thus respected.
76-
unsafe { Unique::new_unchecked(crate::ptr::invalid_mut::<T>(mem::align_of::<T>())) }
73+
Self::from(NonNull::dangling())
7774
}
7875
}
7976

@@ -87,15 +84,14 @@ impl<T: ?Sized> Unique<T> {
8784
#[inline]
8885
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
8986
// SAFETY: the caller must guarantee that `ptr` is non-null.
90-
unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }
87+
unsafe { Unique { pointer: NonNull::new_unchecked(ptr), _marker: PhantomData } }
9188
}
9289

9390
/// Creates a new `Unique` if `ptr` is non-null.
9491
#[inline]
9592
pub const fn new(ptr: *mut T) -> Option<Self> {
96-
if !ptr.is_null() {
97-
// SAFETY: The pointer has already been checked and is not null.
98-
Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
93+
if let Some(pointer) = NonNull::new(ptr) {
94+
Some(Unique { pointer, _marker: PhantomData })
9995
} else {
10096
None
10197
}
@@ -105,7 +101,7 @@ impl<T: ?Sized> Unique<T> {
105101
#[must_use = "`self` will be dropped if the result is not used"]
106102
#[inline]
107103
pub const fn as_ptr(self) -> *mut T {
108-
self.pointer as *mut T
104+
self.pointer.as_ptr()
109105
}
110106

111107
/// Dereferences the content.
@@ -118,7 +114,7 @@ impl<T: ?Sized> Unique<T> {
118114
pub const unsafe fn as_ref(&self) -> &T {
119115
// SAFETY: the caller must guarantee that `self` meets all the
120116
// requirements for a reference.
121-
unsafe { &*self.as_ptr() }
117+
unsafe { self.pointer.as_ref() }
122118
}
123119

124120
/// Mutably dereferences the content.
@@ -131,17 +127,14 @@ impl<T: ?Sized> Unique<T> {
131127
pub const unsafe fn as_mut(&mut self) -> &mut T {
132128
// SAFETY: the caller must guarantee that `self` meets all the
133129
// requirements for a mutable reference.
134-
unsafe { &mut *self.as_ptr() }
130+
unsafe { self.pointer.as_mut() }
135131
}
136132

137133
/// Casts to a pointer of another type.
138134
#[must_use = "`self` will be dropped if the result is not used"]
139135
#[inline]
140136
pub const fn cast<U>(self) -> Unique<U> {
141-
// SAFETY: Unique::new_unchecked() creates a new unique and needs
142-
// the given pointer to not be null.
143-
// Since we are passing self as a pointer, it cannot be null.
144-
unsafe { Unique::new_unchecked(self.as_ptr() as *mut U) }
137+
Unique::from(self.pointer.cast())
145138
}
146139
}
147140

@@ -184,7 +177,17 @@ impl<T: ?Sized> const From<&mut T> for Unique<T> {
184177
/// This conversion is infallible since references cannot be null.
185178
#[inline]
186179
fn from(reference: &mut T) -> Self {
187-
// SAFETY: A mutable reference cannot be null
188-
unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
180+
Self::from(NonNull::from(reference))
181+
}
182+
}
183+
184+
#[unstable(feature = "ptr_internals", issue = "none")]
185+
impl<T: ?Sized> const From<NonNull<T>> for Unique<T> {
186+
/// Converts a `NonNull<T>` to a `Unique<T>`.
187+
///
188+
/// This conversion is infallible since `NonNull` cannot be null.
189+
#[inline]
190+
fn from(pointer: NonNull<T>) -> Self {
191+
Unique { pointer, _marker: PhantomData }
189192
}
190193
}

src/etc/gdb_providers.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
def unwrap_unique_or_non_null(unique_or_nonnull):
1313
# BACKCOMPAT: rust 1.32
1414
# https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
15+
# BACKCOMPAT: rust 1.60
16+
# https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f
1517
ptr = unique_or_nonnull["pointer"]
16-
return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ZERO_FIELD]
18+
return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ptr.type.fields()[0]]
1719

1820

1921
class EnumProvider:

src/etc/lldb_providers.py

+4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ def from_uint(self, name, value):
6363
def unwrap_unique_or_non_null(unique_or_nonnull):
6464
# BACKCOMPAT: rust 1.32
6565
# https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
66+
# BACKCOMPAT: rust 1.60
67+
# https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f
6668
ptr = unique_or_nonnull.GetChildMemberWithName("pointer")
6769
return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0)
6870

@@ -268,7 +270,9 @@ class StdVecSyntheticProvider:
268270
struct RawVec<T> { ptr: Unique<T>, cap: usize, ... }
269271
rust 1.31.1: struct Unique<T: ?Sized> { pointer: NonZero<*const T>, ... }
270272
rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }
273+
rust 1.62.0: struct Unique<T: ?Sized> { pointer: NonNull<T>, ... }
271274
struct NonZero<T>(T)
275+
struct NonNull<T> { pointer: *const T }
272276
"""
273277

274278
def __init__(self, valobj, dict):

src/etc/natvis/liballoc.natvis

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<Item Name="[capacity]" ExcludeView="simple">buf.cap</Item>
88
<ArrayItems>
99
<Size>len</Size>
10-
<ValuePointer>buf.ptr.pointer</ValuePointer>
10+
<ValuePointer>buf.ptr.pointer.pointer</ValuePointer>
1111
</ArrayItems>
1212
</Expand>
1313
</Type>
@@ -24,7 +24,7 @@
2424
<If Condition="i == head">
2525
<Break/>
2626
</If>
27-
<Item>buf.ptr.pointer[i]</Item>
27+
<Item>buf.ptr.pointer.pointer[i]</Item>
2828
<Exec>i = (i + 1 == buf.cap ? 0 : i + 1)</Exec>
2929
</Loop>
3030
</CustomListItems>
@@ -42,17 +42,17 @@
4242
</Expand>
4343
</Type>
4444
<Type Name="alloc::string::String">
45-
<DisplayString>{(char*)vec.buf.ptr.pointer,[vec.len]s8}</DisplayString>
46-
<StringView>(char*)vec.buf.ptr.pointer,[vec.len]s8</StringView>
45+
<DisplayString>{(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8}</DisplayString>
46+
<StringView>(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8</StringView>
4747
<Expand>
4848
<Item Name="[len]" ExcludeView="simple">vec.len</Item>
4949
<Item Name="[capacity]" ExcludeView="simple">vec.buf.cap</Item>
5050
<Synthetic Name="[chars]">
51-
<DisplayString>{(char*)vec.buf.ptr.pointer,[vec.len]s8}</DisplayString>
51+
<DisplayString>{(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8}</DisplayString>
5252
<Expand>
5353
<ArrayItems>
5454
<Size>vec.len</Size>
55-
<ValuePointer>(char*)vec.buf.ptr.pointer</ValuePointer>
55+
<ValuePointer>(char*)vec.buf.ptr.pointer.pointer</ValuePointer>
5656
</ArrayItems>
5757
</Expand>
5858
</Synthetic>

src/etc/natvis/libcore.natvis

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
</Type>
114114

115115
<Type Name="core::ptr::unique::Unique&lt;*&gt;">
116-
<DisplayString>Unique({(void*)pointer}: {pointer})</DisplayString>
116+
<DisplayString>Unique({(void*)pointer.pointer}: {pointer.pointer})</DisplayString>
117117
<Expand>
118118
<ExpandedItem>pointer</ExpandedItem>
119119
</Expand>

src/etc/natvis/libstd.natvis

+3-3
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,14 @@
104104
</Type>
105105

106106
<Type Name="std::ffi::os_str::OsString">
107-
<DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]}</DisplayString>
107+
<DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString>
108108
<Expand>
109109
<Synthetic Name="[chars]">
110-
<DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]}</DisplayString>
110+
<DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString>
111111
<Expand>
112112
<ArrayItems>
113113
<Size>inner.inner.bytes.len</Size>
114-
<ValuePointer>(char*)inner.inner.bytes.buf.ptr.pointer</ValuePointer>
114+
<ValuePointer>(char*)inner.inner.bytes.buf.ptr.pointer.pointer</ValuePointer>
115115
</ArrayItems>
116116
</Expand>
117117
</Synthetic>

src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
+ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
3636
+ _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
3737
+ Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
38-
+ ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
38+
+ ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: NonNull::<u32> { pointer: {0x4 as *const u32} }, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
3939
// mir::Constant
4040
- // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
4141
- // + user_ty: UserType(1)

src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
+ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
3636
+ _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
3737
+ Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
38-
+ ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
38+
+ ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: NonNull::<u32> { pointer: {0x4 as *const u32} }, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
3939
// mir::Constant
4040
- // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
4141
- // + user_ty: UserType(1)

src/test/ui/lint/lint-ctypes-enum.rs

-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ extern "C" {
6767
fn option_fn(x: Option<extern "C" fn()>);
6868
fn nonnull(x: Option<std::ptr::NonNull<u8>>);
6969
fn unique(x: Option<std::ptr::Unique<u8>>);
70-
//~^ ERROR `extern` block uses type `Option<Unique<u8>>`
7170
fn nonzero_u8(x: Option<num::NonZeroU8>);
7271
fn nonzero_u16(x: Option<num::NonZeroU16>);
7372
fn nonzero_u32(x: Option<num::NonZeroU32>);

src/test/ui/lint/lint-ctypes-enum.stderr

+6-15
Original file line numberDiff line numberDiff line change
@@ -54,33 +54,24 @@ LL | | G,
5454
LL | | }
5555
| |_^
5656

57-
error: `extern` block uses type `Option<Unique<u8>>`, which is not FFI-safe
58-
--> $DIR/lint-ctypes-enum.rs:69:17
59-
|
60-
LL | fn unique(x: Option<std::ptr::Unique<u8>>);
61-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
62-
|
63-
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
64-
= note: enum has no representation hint
65-
6657
error: `extern` block uses type `u128`, which is not FFI-safe
67-
--> $DIR/lint-ctypes-enum.rs:75:23
58+
--> $DIR/lint-ctypes-enum.rs:74:23
6859
|
6960
LL | fn nonzero_u128(x: Option<num::NonZeroU128>);
7061
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
7162
|
7263
= note: 128-bit integers don't currently have a known stable ABI
7364

7465
error: `extern` block uses type `i128`, which is not FFI-safe
75-
--> $DIR/lint-ctypes-enum.rs:82:23
66+
--> $DIR/lint-ctypes-enum.rs:81:23
7667
|
7768
LL | fn nonzero_i128(x: Option<num::NonZeroI128>);
7869
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
7970
|
8071
= note: 128-bit integers don't currently have a known stable ABI
8172

8273
error: `extern` block uses type `Option<TransparentUnion<NonZeroU8>>`, which is not FFI-safe
83-
--> $DIR/lint-ctypes-enum.rs:87:28
74+
--> $DIR/lint-ctypes-enum.rs:86:28
8475
|
8576
LL | fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
8677
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -89,7 +80,7 @@ LL | fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
8980
= note: enum has no representation hint
9081

9182
error: `extern` block uses type `Option<Rust<NonZeroU8>>`, which is not FFI-safe
92-
--> $DIR/lint-ctypes-enum.rs:89:20
83+
--> $DIR/lint-ctypes-enum.rs:88:20
9384
|
9485
LL | fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
9586
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -98,13 +89,13 @@ LL | fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
9889
= note: enum has no representation hint
9990

10091
error: `extern` block uses type `Result<(), NonZeroI32>`, which is not FFI-safe
101-
--> $DIR/lint-ctypes-enum.rs:90:20
92+
--> $DIR/lint-ctypes-enum.rs:89:20
10293
|
10394
LL | fn no_result(x: Result<(), num::NonZeroI32>);
10495
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
10596
|
10697
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
10798
= note: enum has no representation hint
10899

109-
error: aborting due to 9 previous errors
100+
error: aborting due to 8 previous errors
110101

src/test/ui/traits/cycle-cache-err-60010.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
44
LL | _parse: <ParseQuery as Query<RootDatabase>>::Data,
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: required because it appears within the type `*const SalsaStorage`
7+
= note: required because it appears within the type `PhantomData<SalsaStorage>`
88
= note: required because it appears within the type `Unique<SalsaStorage>`
99
= note: required because it appears within the type `Box<SalsaStorage>`
1010
note: required because it appears within the type `Runtime<RootDatabase>`

0 commit comments

Comments
 (0)