Skip to content

Commit b1f3a26

Browse files
authored
Rollup merge of rust-lang#133651 - scottmcm:nonnull-nonzero-no-field-projection, r=oli-obk
Update `NonZero` and `NonNull` to not field-project (per MCP#807) rust-lang/compiler-team#807 (comment) was accepted, so this is the first PR towards moving the library to not using field projections into `[rustc_layout_scalar_valid_range_*]` types. `NonZero` was already using `transmute` nearly everywhere, so there are very few changes to it. `NonNull` needed more changes, but they're mostly simple, changing `.pointer` to `.as_ptr()`. r? libs cc rust-lang#133324, which will tidy up some of the MIR from this a bit more, but isn't a blocker.
2 parents 7203611 + a748abb commit b1f3a26

File tree

2 files changed

+58
-29
lines changed

2 files changed

+58
-29
lines changed

core/src/num/nonzero.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed {
3737
macro_rules! impl_zeroable_primitive {
3838
($($NonZeroInner:ident ( $primitive:ty )),+ $(,)?) => {
3939
mod private {
40+
use super::*;
41+
4042
#[unstable(
4143
feature = "nonzero_internals",
4244
reason = "implementation detail which may disappear or be replaced at any time",
@@ -45,7 +47,11 @@ macro_rules! impl_zeroable_primitive {
4547
pub trait Sealed {}
4648

4749
$(
48-
#[derive(Debug, Clone, Copy, PartialEq)]
50+
// This inner type is never shown directly, so intentionally does not have Debug
51+
#[expect(missing_debug_implementations)]
52+
// Since this struct is non-generic and derives Copy,
53+
// the derived Clone is `*self` and thus doesn't field-project.
54+
#[derive(Clone, Copy)]
4955
#[repr(transparent)]
5056
#[rustc_layout_scalar_valid_range_start(1)]
5157
#[rustc_nonnull_optimization_guaranteed]
@@ -55,6 +61,16 @@ macro_rules! impl_zeroable_primitive {
5561
issue = "none"
5662
)]
5763
pub struct $NonZeroInner($primitive);
64+
65+
// This is required to allow matching a constant. We don't get it from a derive
66+
// because the derived `PartialEq` would do a field projection, which is banned
67+
// by <https://github.com/rust-lang/compiler-team/issues/807>.
68+
#[unstable(
69+
feature = "nonzero_internals",
70+
reason = "implementation detail which may disappear or be replaced at any time",
71+
issue = "none"
72+
)]
73+
impl StructuralPartialEq for $NonZeroInner {}
5874
)+
5975
}
6076

@@ -172,7 +188,7 @@ where
172188
{
173189
#[inline]
174190
fn clone(&self) -> Self {
175-
Self(self.0)
191+
*self
176192
}
177193
}
178194

@@ -440,15 +456,21 @@ where
440456
#[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")]
441457
#[inline]
442458
pub const fn get(self) -> T {
443-
// FIXME: This can be changed to simply `self.0` once LLVM supports `!range` metadata
444-
// for function arguments: https://github.com/llvm/llvm-project/issues/76628
445-
//
446459
// Rustc can set range metadata only if it loads `self` from
447460
// memory somewhere. If the value of `self` was from by-value argument
448461
// of some not-inlined function, LLVM don't have range metadata
449462
// to understand that the value cannot be zero.
450463
//
451-
// For now, using the transmute `assume`s the range at runtime.
464+
// Using the transmute `assume`s the range at runtime.
465+
//
466+
// Even once LLVM supports `!range` metadata for function arguments
467+
// (see <https://github.com/llvm/llvm-project/issues/76628>), this can't
468+
// be `.0` because MCP#807 bans field-projecting into `scalar_valid_range`
469+
// types, and it arguably wouldn't want to be anyway because if this is
470+
// MIR-inlined, there's no opportunity to put that argument metadata anywhere.
471+
//
472+
// The good answer here will eventually be pattern types, which will hopefully
473+
// allow it to go back to `.0`, maybe with a cast of some sort.
452474
//
453475
// SAFETY: `ZeroablePrimitive` guarantees that the size and bit validity
454476
// of `.0` is such that this transmute is sound.

core/src/ptr/non_null.rs

+30-23
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::pin::PinCoerceUnsized;
77
use crate::ptr::Unique;
88
use crate::slice::{self, SliceIndex};
99
use crate::ub_checks::assert_unsafe_precondition;
10-
use crate::{fmt, hash, intrinsics, ptr};
10+
use crate::{fmt, hash, intrinsics, mem, ptr};
1111

1212
/// `*mut T` but non-zero and [covariant].
1313
///
@@ -69,6 +69,8 @@ use crate::{fmt, hash, intrinsics, ptr};
6969
#[rustc_nonnull_optimization_guaranteed]
7070
#[rustc_diagnostic_item = "NonNull"]
7171
pub struct NonNull<T: ?Sized> {
72+
// Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to
73+
// this is banned by <https://github.com/rust-lang/compiler-team/issues/807>.
7274
pointer: *const T,
7375
}
7476

@@ -282,7 +284,7 @@ impl<T: ?Sized> NonNull<T> {
282284
pub fn addr(self) -> NonZero<usize> {
283285
// SAFETY: The pointer is guaranteed by the type to be non-null,
284286
// meaning that the address will be non-zero.
285-
unsafe { NonZero::new_unchecked(self.pointer.addr()) }
287+
unsafe { NonZero::new_unchecked(self.as_ptr().addr()) }
286288
}
287289

288290
/// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of
@@ -296,7 +298,7 @@ impl<T: ?Sized> NonNull<T> {
296298
#[stable(feature = "strict_provenance", since = "1.84.0")]
297299
pub fn with_addr(self, addr: NonZero<usize>) -> Self {
298300
// SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero.
299-
unsafe { NonNull::new_unchecked(self.pointer.with_addr(addr.get()) as *mut _) }
301+
unsafe { NonNull::new_unchecked(self.as_ptr().with_addr(addr.get()) as *mut _) }
300302
}
301303

302304
/// Creates a new pointer by mapping `self`'s address to a new one, preserving the
@@ -335,7 +337,12 @@ impl<T: ?Sized> NonNull<T> {
335337
#[must_use]
336338
#[inline(always)]
337339
pub const fn as_ptr(self) -> *mut T {
338-
self.pointer as *mut T
340+
// This is a transmute for the same reasons as `NonZero::get`.
341+
342+
// SAFETY: `NonNull` is `transparent` over a `*const T`, and `*const T`
343+
// and `*mut T` have the same layout, so transitively we can transmute
344+
// our `NonNull` to a `*mut T` directly.
345+
unsafe { mem::transmute::<Self, *mut T>(self) }
339346
}
340347

341348
/// Returns a shared reference to the value. If the value may be uninitialized, [`as_uninit_ref`]
@@ -484,7 +491,7 @@ impl<T: ?Sized> NonNull<T> {
484491
// Additionally safety contract of `offset` guarantees that the resulting pointer is
485492
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
486493
// construct `NonNull`.
487-
unsafe { NonNull { pointer: intrinsics::offset(self.pointer, count) } }
494+
unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } }
488495
}
489496

490497
/// Calculates the offset from a pointer in bytes.
@@ -508,7 +515,7 @@ impl<T: ?Sized> NonNull<T> {
508515
// Additionally safety contract of `offset` guarantees that the resulting pointer is
509516
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
510517
// construct `NonNull`.
511-
unsafe { NonNull { pointer: self.pointer.byte_offset(count) } }
518+
unsafe { NonNull { pointer: self.as_ptr().byte_offset(count) } }
512519
}
513520

514521
/// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
@@ -560,7 +567,7 @@ impl<T: ?Sized> NonNull<T> {
560567
// Additionally safety contract of `offset` guarantees that the resulting pointer is
561568
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
562569
// construct `NonNull`.
563-
unsafe { NonNull { pointer: intrinsics::offset(self.pointer, count) } }
570+
unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } }
564571
}
565572

566573
/// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`).
@@ -584,7 +591,7 @@ impl<T: ?Sized> NonNull<T> {
584591
// Additionally safety contract of `add` guarantees that the resulting pointer is pointing
585592
// to an allocation, there can't be an allocation at null, thus it's safe to construct
586593
// `NonNull`.
587-
unsafe { NonNull { pointer: self.pointer.byte_add(count) } }
594+
unsafe { NonNull { pointer: self.as_ptr().byte_add(count) } }
588595
}
589596

590597
/// Subtracts an offset from a pointer (convenience for
@@ -666,7 +673,7 @@ impl<T: ?Sized> NonNull<T> {
666673
// Additionally safety contract of `sub` guarantees that the resulting pointer is pointing
667674
// to an allocation, there can't be an allocation at null, thus it's safe to construct
668675
// `NonNull`.
669-
unsafe { NonNull { pointer: self.pointer.byte_sub(count) } }
676+
unsafe { NonNull { pointer: self.as_ptr().byte_sub(count) } }
670677
}
671678

672679
/// Calculates the distance between two pointers within the same allocation. The returned value is in
@@ -763,7 +770,7 @@ impl<T: ?Sized> NonNull<T> {
763770
T: Sized,
764771
{
765772
// SAFETY: the caller must uphold the safety contract for `offset_from`.
766-
unsafe { self.pointer.offset_from(origin.pointer) }
773+
unsafe { self.as_ptr().offset_from(origin.as_ptr()) }
767774
}
768775

769776
/// Calculates the distance between two pointers within the same allocation. The returned value is in
@@ -781,7 +788,7 @@ impl<T: ?Sized> NonNull<T> {
781788
#[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
782789
pub const unsafe fn byte_offset_from<U: ?Sized>(self, origin: NonNull<U>) -> isize {
783790
// SAFETY: the caller must uphold the safety contract for `byte_offset_from`.
784-
unsafe { self.pointer.byte_offset_from(origin.pointer) }
791+
unsafe { self.as_ptr().byte_offset_from(origin.as_ptr()) }
785792
}
786793

787794
// N.B. `wrapping_offset``, `wrapping_add`, etc are not implemented because they can wrap to null
@@ -856,7 +863,7 @@ impl<T: ?Sized> NonNull<T> {
856863
T: Sized,
857864
{
858865
// SAFETY: the caller must uphold the safety contract for `sub_ptr`.
859-
unsafe { self.pointer.sub_ptr(subtracted.pointer) }
866+
unsafe { self.as_ptr().sub_ptr(subtracted.as_ptr()) }
860867
}
861868

862869
/// Calculates the distance between two pointers within the same allocation, *where it's known that
@@ -875,7 +882,7 @@ impl<T: ?Sized> NonNull<T> {
875882
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
876883
pub const unsafe fn byte_sub_ptr<U: ?Sized>(self, origin: NonNull<U>) -> usize {
877884
// SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`.
878-
unsafe { self.pointer.byte_sub_ptr(origin.pointer) }
885+
unsafe { self.as_ptr().byte_sub_ptr(origin.as_ptr()) }
879886
}
880887

881888
/// Reads the value from `self` without moving it. This leaves the
@@ -893,7 +900,7 @@ impl<T: ?Sized> NonNull<T> {
893900
T: Sized,
894901
{
895902
// SAFETY: the caller must uphold the safety contract for `read`.
896-
unsafe { ptr::read(self.pointer) }
903+
unsafe { ptr::read(self.as_ptr()) }
897904
}
898905

899906
/// Performs a volatile read of the value from `self` without moving it. This
@@ -914,7 +921,7 @@ impl<T: ?Sized> NonNull<T> {
914921
T: Sized,
915922
{
916923
// SAFETY: the caller must uphold the safety contract for `read_volatile`.
917-
unsafe { ptr::read_volatile(self.pointer) }
924+
unsafe { ptr::read_volatile(self.as_ptr()) }
918925
}
919926

920927
/// Reads the value from `self` without moving it. This leaves the
@@ -934,7 +941,7 @@ impl<T: ?Sized> NonNull<T> {
934941
T: Sized,
935942
{
936943
// SAFETY: the caller must uphold the safety contract for `read_unaligned`.
937-
unsafe { ptr::read_unaligned(self.pointer) }
944+
unsafe { ptr::read_unaligned(self.as_ptr()) }
938945
}
939946

940947
/// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
@@ -954,7 +961,7 @@ impl<T: ?Sized> NonNull<T> {
954961
T: Sized,
955962
{
956963
// SAFETY: the caller must uphold the safety contract for `copy`.
957-
unsafe { ptr::copy(self.pointer, dest.as_ptr(), count) }
964+
unsafe { ptr::copy(self.as_ptr(), dest.as_ptr(), count) }
958965
}
959966

960967
/// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
@@ -974,7 +981,7 @@ impl<T: ?Sized> NonNull<T> {
974981
T: Sized,
975982
{
976983
// SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`.
977-
unsafe { ptr::copy_nonoverlapping(self.pointer, dest.as_ptr(), count) }
984+
unsafe { ptr::copy_nonoverlapping(self.as_ptr(), dest.as_ptr(), count) }
978985
}
979986

980987
/// Copies `count * size_of<T>` bytes from `src` to `self`. The source
@@ -994,7 +1001,7 @@ impl<T: ?Sized> NonNull<T> {
9941001
T: Sized,
9951002
{
9961003
// SAFETY: the caller must uphold the safety contract for `copy`.
997-
unsafe { ptr::copy(src.pointer, self.as_ptr(), count) }
1004+
unsafe { ptr::copy(src.as_ptr(), self.as_ptr(), count) }
9981005
}
9991006

10001007
/// Copies `count * size_of<T>` bytes from `src` to `self`. The source
@@ -1014,7 +1021,7 @@ impl<T: ?Sized> NonNull<T> {
10141021
T: Sized,
10151022
{
10161023
// SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`.
1017-
unsafe { ptr::copy_nonoverlapping(src.pointer, self.as_ptr(), count) }
1024+
unsafe { ptr::copy_nonoverlapping(src.as_ptr(), self.as_ptr(), count) }
10181025
}
10191026

10201027
/// Executes the destructor (if any) of the pointed-to value.
@@ -1201,7 +1208,7 @@ impl<T: ?Sized> NonNull<T> {
12011208

12021209
{
12031210
// SAFETY: `align` has been checked to be a power of 2 above.
1204-
unsafe { ptr::align_offset(self.pointer, align) }
1211+
unsafe { ptr::align_offset(self.as_ptr(), align) }
12051212
}
12061213
}
12071214

@@ -1229,7 +1236,7 @@ impl<T: ?Sized> NonNull<T> {
12291236
where
12301237
T: Sized,
12311238
{
1232-
self.pointer.is_aligned()
1239+
self.as_ptr().is_aligned()
12331240
}
12341241

12351242
/// Returns whether the pointer is aligned to `align`.
@@ -1266,7 +1273,7 @@ impl<T: ?Sized> NonNull<T> {
12661273
#[must_use]
12671274
#[unstable(feature = "pointer_is_aligned_to", issue = "96284")]
12681275
pub fn is_aligned_to(self, align: usize) -> bool {
1269-
self.pointer.is_aligned_to(align)
1276+
self.as_ptr().is_aligned_to(align)
12701277
}
12711278
}
12721279

0 commit comments

Comments
 (0)