diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index cf69c8fd8fda9..b6a7bcae93284 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -448,7 +448,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // a box with a non-zst allocator should not be directly dereferenced if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() { - let ptr = cg_base.extract_field(bx, 0).extract_field(bx, 0); + // Extract `Box` -> `Unique` -> `NonNull` -> `*const T` + let ptr = + cg_base.extract_field(bx, 0).extract_field(bx, 0).extract_field(bx, 0); ptr.deref(bx.cx()) } else { @@ -464,7 +466,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::ProjectionElem::Deref => { // a box with a non-zst allocator should not be directly dereferenced if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() { - let ptr = cg_base.project_field(bx, 0).project_field(bx, 0); + // Project `Box` -> `Unique` -> `NonNull` -> `*const T` + let ptr = + cg_base.project_field(bx, 0).project_field(bx, 0).project_field(bx, 0); bx.load_operand(ptr).deref(bx.cx()) } else { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6546a5244fd03..813f6ed58e7ff 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -119,12 +119,14 @@ #![feature(const_likely)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init)] +#![feature(const_nonnull_new)] #![feature(const_num_from_num)] #![feature(const_ops)] #![feature(const_option)] #![feature(const_option_ext)] #![feature(const_pin)] #![feature(const_replace)] +#![feature(const_ptr_as_ref)] #![feature(const_ptr_is_null)] #![feature(const_ptr_offset_from)] #![feature(const_ptr_read)] diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 29398cbeb238d..64616142b4188 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -1,8 +1,8 @@ use crate::convert::From; use crate::fmt; use crate::marker::{PhantomData, Unsize}; -use crate::mem; use crate::ops::{CoerceUnsized, DispatchFromDyn}; +use crate::ptr::NonNull; /// A wrapper around a raw non-null `*mut T` that indicates that the possessor /// of this wrapper owns the referent. Useful for building abstractions like @@ -32,9 +32,8 @@ use crate::ops::{CoerceUnsized, DispatchFromDyn}; )] #[doc(hidden)] #[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(1)] pub struct Unique { - pointer: *const T, + pointer: NonNull, // NOTE: this marker has no consequences for variance, but is necessary // for dropck to understand that we logically own a `T`. // @@ -71,9 +70,7 @@ impl Unique { #[must_use] #[inline] pub const fn dangling() -> Self { - // SAFETY: mem::align_of() returns a valid, non-null pointer. The - // conditions to call new_unchecked() are thus respected. - unsafe { Unique::new_unchecked(crate::ptr::invalid_mut::(mem::align_of::())) } + Self::from(NonNull::dangling()) } } @@ -87,15 +84,14 @@ impl Unique { #[inline] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { // SAFETY: the caller must guarantee that `ptr` is non-null. - unsafe { Unique { pointer: ptr as _, _marker: PhantomData } } + unsafe { Unique { pointer: NonNull::new_unchecked(ptr), _marker: PhantomData } } } /// Creates a new `Unique` if `ptr` is non-null. #[inline] pub const fn new(ptr: *mut T) -> Option { - if !ptr.is_null() { - // SAFETY: The pointer has already been checked and is not null. - Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }) + if let Some(pointer) = NonNull::new(ptr) { + Some(Unique { pointer, _marker: PhantomData }) } else { None } @@ -105,7 +101,7 @@ impl Unique { #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub const fn as_ptr(self) -> *mut T { - self.pointer as *mut T + self.pointer.as_ptr() } /// Dereferences the content. @@ -118,7 +114,7 @@ impl Unique { pub const unsafe fn as_ref(&self) -> &T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. - unsafe { &*self.as_ptr() } + unsafe { self.pointer.as_ref() } } /// Mutably dereferences the content. @@ -131,17 +127,14 @@ impl Unique { pub const unsafe fn as_mut(&mut self) -> &mut T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a mutable reference. - unsafe { &mut *self.as_ptr() } + unsafe { self.pointer.as_mut() } } /// Casts to a pointer of another type. #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub const fn cast(self) -> Unique { - // SAFETY: Unique::new_unchecked() creates a new unique and needs - // the given pointer to not be null. - // Since we are passing self as a pointer, it cannot be null. - unsafe { Unique::new_unchecked(self.as_ptr() as *mut U) } + Unique::from(self.pointer.cast()) } } @@ -184,7 +177,17 @@ impl const From<&mut T> for Unique { /// This conversion is infallible since references cannot be null. #[inline] fn from(reference: &mut T) -> Self { - // SAFETY: A mutable reference cannot be null - unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } } + Self::from(NonNull::from(reference)) + } +} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl const From> for Unique { + /// Converts a `NonNull` to a `Unique`. + /// + /// This conversion is infallible since `NonNull` cannot be null. + #[inline] + fn from(pointer: NonNull) -> Self { + Unique { pointer, _marker: PhantomData } } } diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index 33d26db547efc..0a52b8c976f6a 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -12,8 +12,10 @@ def unwrap_unique_or_non_null(unique_or_nonnull): # BACKCOMPAT: rust 1.32 # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067 + # BACKCOMPAT: rust 1.60 + # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f ptr = unique_or_nonnull["pointer"] - return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ZERO_FIELD] + return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ptr.type.fields()[0]] class EnumProvider: diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index 86dcc335e3cbf..35ac07f0db763 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -63,6 +63,8 @@ def from_uint(self, name, value): def unwrap_unique_or_non_null(unique_or_nonnull): # BACKCOMPAT: rust 1.32 # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067 + # BACKCOMPAT: rust 1.60 + # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f ptr = unique_or_nonnull.GetChildMemberWithName("pointer") return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0) @@ -268,7 +270,9 @@ class StdVecSyntheticProvider: struct RawVec { ptr: Unique, cap: usize, ... } rust 1.31.1: struct Unique { pointer: NonZero<*const T>, ... } rust 1.33.0: struct Unique { pointer: *const T, ... } + rust 1.62.0: struct Unique { pointer: NonNull, ... } struct NonZero(T) + struct NonNull { pointer: *const T } """ def __init__(self, valobj, dict): diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index d001f40fccbc7..83ca8ed932e46 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -7,7 +7,7 @@ buf.cap len - buf.ptr.pointer + buf.ptr.pointer.pointer @@ -24,7 +24,7 @@ - buf.ptr.pointer[i] + buf.ptr.pointer.pointer[i] i = (i + 1 == buf.cap ? 0 : i + 1) @@ -42,17 +42,17 @@ - {(char*)vec.buf.ptr.pointer,[vec.len]s8} - (char*)vec.buf.ptr.pointer,[vec.len]s8 + {(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8} + (char*)vec.buf.ptr.pointer.pointer,[vec.len]s8 vec.len vec.buf.cap - {(char*)vec.buf.ptr.pointer,[vec.len]s8} + {(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8} vec.len - (char*)vec.buf.ptr.pointer + (char*)vec.buf.ptr.pointer.pointer diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index fa8ee2d70bbab..643590fc97787 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -113,7 +113,7 @@ - Unique({(void*)pointer}: {pointer}) + Unique({(void*)pointer.pointer}: {pointer.pointer}) pointer diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis index eb2b9c848aa6f..4371b99531817 100644 --- a/src/etc/natvis/libstd.natvis +++ b/src/etc/natvis/libstd.natvis @@ -104,14 +104,14 @@ - {(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]} + {(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]} - {(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]} + {(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]} inner.inner.bytes.len - (char*)inner.inner.bytes.buf.ptr.pointer + (char*)inner.inner.bytes.buf.ptr.pointer.pointer diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff index 072ab5e8df4f7..074ad067ff899 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff @@ -35,7 +35,7 @@ + StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: {0x4 as *const u32}, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: NonNull:: { pointer: {0x4 as *const u32} }, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:33: 8:41 - // + user_ty: UserType(1) diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index 8b8a741ec12da..a055ae9864f5f 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -35,7 +35,7 @@ + StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: {0x4 as *const u32}, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: NonNull:: { pointer: {0x4 as *const u32} }, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:33: 8:41 - // + user_ty: UserType(1) diff --git a/src/test/ui/lint/lint-ctypes-enum.rs b/src/test/ui/lint/lint-ctypes-enum.rs index d7f947aa0f3bc..7c20608059398 100644 --- a/src/test/ui/lint/lint-ctypes-enum.rs +++ b/src/test/ui/lint/lint-ctypes-enum.rs @@ -67,7 +67,6 @@ extern "C" { fn option_fn(x: Option); fn nonnull(x: Option>); fn unique(x: Option>); - //~^ ERROR `extern` block uses type `Option>` fn nonzero_u8(x: Option); fn nonzero_u16(x: Option); fn nonzero_u32(x: Option); diff --git a/src/test/ui/lint/lint-ctypes-enum.stderr b/src/test/ui/lint/lint-ctypes-enum.stderr index f3991ab417752..1601bd9d62927 100644 --- a/src/test/ui/lint/lint-ctypes-enum.stderr +++ b/src/test/ui/lint/lint-ctypes-enum.stderr @@ -54,17 +54,8 @@ LL | | G, LL | | } | |_^ -error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:69:17 - | -LL | fn unique(x: Option>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum - = note: enum has no representation hint - error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:75:23 + --> $DIR/lint-ctypes-enum.rs:74:23 | LL | fn nonzero_u128(x: Option); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -72,7 +63,7 @@ LL | fn nonzero_u128(x: Option); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:82:23 + --> $DIR/lint-ctypes-enum.rs:81:23 | LL | fn nonzero_i128(x: Option); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -80,7 +71,7 @@ LL | fn nonzero_i128(x: Option); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:87:28 + --> $DIR/lint-ctypes-enum.rs:86:28 | LL | fn transparent_union(x: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -89,7 +80,7 @@ LL | fn transparent_union(x: Option>); = note: enum has no representation hint error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:89:20 + --> $DIR/lint-ctypes-enum.rs:88:20 | LL | fn repr_rust(x: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -98,7 +89,7 @@ LL | fn repr_rust(x: Option>); = note: enum has no representation hint error: `extern` block uses type `Result<(), NonZeroI32>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:90:20 + --> $DIR/lint-ctypes-enum.rs:89:20 | LL | fn no_result(x: Result<(), num::NonZeroI32>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -106,5 +97,5 @@ LL | fn no_result(x: Result<(), num::NonZeroI32>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index 9452e11e302e3..859403f202f51 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe` LL | _parse: >::Data, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: required because it appears within the type `*const SalsaStorage` + = note: required because it appears within the type `PhantomData` = note: required because it appears within the type `Unique` = note: required because it appears within the type `Box` note: required because it appears within the type `Runtime`