Skip to content

Commit b329461

Browse files
committed
Use !null pattern type in libcore
Use `!null` pattern type in libcore
1 parent 926b32c commit b329461

File tree

30 files changed

+222
-186
lines changed

30 files changed

+222
-186
lines changed

compiler/rustc_const_eval/src/interpret/visitor.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,12 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
160160
);
161161
// ... that contains a `NonNull`... (gladly, only a single field here)
162162
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
163-
let raw_ptr = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // the actual raw ptr
163+
let pat_ty = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // `*mut T is !null`
164+
let base = match *pat_ty.layout().ty.kind() {
165+
ty::Pat(base, _) => self.ecx().layout_of(base)?,
166+
_ => unreachable!(),
167+
};
168+
let raw_ptr = pat_ty.transmute(base, self.ecx())?; // The actual raw pointer
164169
// ... whose only field finally is a raw ptr we can dereference.
165170
self.visit_box(ty, &raw_ptr)?;
166171

compiler/rustc_mir_transform/src/elaborate_box_derefs.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId;
77
use rustc_middle::mir::visit::MutVisitor;
88
use rustc_middle::mir::*;
99
use rustc_middle::span_bug;
10-
use rustc_middle::ty::{Ty, TyCtxt};
10+
use rustc_middle::ty::{PatternKind, Ty, TyCtxt};
1111

1212
use crate::patch::MirPatch;
1313

@@ -17,13 +17,14 @@ fn build_ptr_tys<'tcx>(
1717
pointee: Ty<'tcx>,
1818
unique_did: DefId,
1919
nonnull_did: DefId,
20-
) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
20+
) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
2121
let args = tcx.mk_args(&[pointee.into()]);
2222
let unique_ty = tcx.type_of(unique_did).instantiate(tcx, args);
2323
let nonnull_ty = tcx.type_of(nonnull_did).instantiate(tcx, args);
2424
let ptr_ty = Ty::new_imm_ptr(tcx, pointee);
25+
let pat_ty = Ty::new_pat(tcx, ptr_ty, tcx.mk_pat(PatternKind::NotNull));
2526

26-
(unique_ty, nonnull_ty, ptr_ty)
27+
(unique_ty, nonnull_ty, pat_ty, ptr_ty)
2728
}
2829

2930
/// Constructs the projection needed to access a Box's pointer
@@ -63,7 +64,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
6364
{
6465
let source_info = self.local_decls[place.local].source_info;
6566

66-
let (unique_ty, nonnull_ty, ptr_ty) =
67+
let (unique_ty, nonnull_ty, _pat_ty, ptr_ty) =
6768
build_ptr_tys(tcx, boxed_ty, self.unique_did, self.nonnull_did);
6869

6970
let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
@@ -130,10 +131,11 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
130131
let new_projections =
131132
new_projections.get_or_insert_with(|| base.projection.to_vec());
132133

133-
let (unique_ty, nonnull_ty, ptr_ty) =
134+
let (unique_ty, nonnull_ty, pat_ty, ptr_ty) =
134135
build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did);
135136

136137
new_projections.extend_from_slice(&build_projection(unique_ty, nonnull_ty));
138+
new_projections.push(PlaceElem::Field(FieldIdx::ZERO, pat_ty));
137139
// While we can't project into `NonNull<_>` in a basic block
138140
// due to MCP#807, this is debug info where it's fine.
139141
new_projections.push(PlaceElem::Field(FieldIdx::ZERO, ptr_ty));

library/core/src/ptr/non_null.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::cmp::Ordering;
22
use crate::marker::Unsize;
3-
use crate::mem::{MaybeUninit, SizedTypeProperties};
3+
use crate::mem::{MaybeUninit, SizedTypeProperties, transmute};
44
use crate::num::NonZero;
55
use crate::ops::{CoerceUnsized, DispatchFromDyn};
66
use crate::pin::PinCoerceUnsized;
@@ -64,13 +64,10 @@ use crate::{fmt, hash, intrinsics, mem, ptr};
6464
/// [null pointer optimization]: crate::option#representation
6565
#[stable(feature = "nonnull", since = "1.25.0")]
6666
#[repr(transparent)]
67-
#[rustc_layout_scalar_valid_range_start(1)]
6867
#[rustc_nonnull_optimization_guaranteed]
6968
#[rustc_diagnostic_item = "NonNull"]
7069
pub struct NonNull<T: ?Sized> {
71-
// Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to
72-
// this is banned by <https://github.com/rust-lang/compiler-team/issues/807>.
73-
pointer: *const T,
70+
pointer: crate::pattern_type!(*const T is !null),
7471
}
7572

7673
/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
@@ -94,9 +91,9 @@ impl<T: Sized> NonNull<T> {
9491
#[must_use]
9592
#[inline]
9693
pub const fn without_provenance(addr: NonZero<usize>) -> Self {
97-
let pointer = crate::ptr::without_provenance(addr.get());
94+
let pointer: *const T = crate::ptr::without_provenance(addr.get());
9895
// SAFETY: we know `addr` is non-zero.
99-
unsafe { NonNull { pointer } }
96+
unsafe { NonNull { pointer: transmute(pointer) } }
10097
}
10198

10299
/// Creates a new `NonNull` that is dangling, but well-aligned.
@@ -226,7 +223,7 @@ impl<T: ?Sized> NonNull<T> {
226223
"NonNull::new_unchecked requires that the pointer is non-null",
227224
(ptr: *mut () = ptr as *mut ()) => !ptr.is_null()
228225
);
229-
NonNull { pointer: ptr as _ }
226+
NonNull { pointer: transmute(ptr) }
230227
}
231228
}
232229

@@ -269,7 +266,7 @@ impl<T: ?Sized> NonNull<T> {
269266
#[inline]
270267
pub const fn from_ref(r: &T) -> Self {
271268
// SAFETY: A reference cannot be null.
272-
unsafe { NonNull { pointer: r as *const T } }
269+
unsafe { NonNull { pointer: transmute(r as *const T) } }
273270
}
274271

275272
/// Converts a mutable reference to a `NonNull` pointer.
@@ -278,7 +275,7 @@ impl<T: ?Sized> NonNull<T> {
278275
#[inline]
279276
pub const fn from_mut(r: &mut T) -> Self {
280277
// SAFETY: A mutable reference cannot be null.
281-
unsafe { NonNull { pointer: r as *mut T } }
278+
unsafe { NonNull { pointer: transmute(r as *mut T) } }
282279
}
283280

284281
/// Performs the same functionality as [`std::ptr::from_raw_parts`], except that a
@@ -489,7 +486,7 @@ impl<T: ?Sized> NonNull<T> {
489486
#[inline]
490487
pub const fn cast<U>(self) -> NonNull<U> {
491488
// SAFETY: `self` is a `NonNull` pointer which is necessarily non-null
492-
unsafe { NonNull { pointer: self.as_ptr() as *mut U } }
489+
unsafe { NonNull { pointer: transmute(self.as_ptr() as *mut U) } }
493490
}
494491

495492
/// Try to cast to a pointer of another type by checking aligment.
@@ -568,7 +565,7 @@ impl<T: ?Sized> NonNull<T> {
568565
// Additionally safety contract of `offset` guarantees that the resulting pointer is
569566
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
570567
// construct `NonNull`.
571-
unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } }
568+
unsafe { NonNull { pointer: transmute(intrinsics::offset(self.as_ptr(), count)) } }
572569
}
573570

574571
/// Calculates the offset from a pointer in bytes.
@@ -592,7 +589,7 @@ impl<T: ?Sized> NonNull<T> {
592589
// Additionally safety contract of `offset` guarantees that the resulting pointer is
593590
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
594591
// construct `NonNull`.
595-
unsafe { NonNull { pointer: self.as_ptr().byte_offset(count) } }
592+
unsafe { NonNull { pointer: transmute(self.as_ptr().byte_offset(count)) } }
596593
}
597594

598595
/// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
@@ -644,7 +641,7 @@ impl<T: ?Sized> NonNull<T> {
644641
// Additionally safety contract of `offset` guarantees that the resulting pointer is
645642
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
646643
// construct `NonNull`.
647-
unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } }
644+
unsafe { NonNull { pointer: transmute(intrinsics::offset(self.as_ptr(), count)) } }
648645
}
649646

650647
/// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`).
@@ -668,7 +665,7 @@ impl<T: ?Sized> NonNull<T> {
668665
// Additionally safety contract of `add` guarantees that the resulting pointer is pointing
669666
// to an allocation, there can't be an allocation at null, thus it's safe to construct
670667
// `NonNull`.
671-
unsafe { NonNull { pointer: self.as_ptr().byte_add(count) } }
668+
unsafe { NonNull { pointer: transmute(self.as_ptr().byte_add(count)) } }
672669
}
673670

674671
/// Subtracts an offset from a pointer (convenience for
@@ -750,7 +747,7 @@ impl<T: ?Sized> NonNull<T> {
750747
// Additionally safety contract of `sub` guarantees that the resulting pointer is pointing
751748
// to an allocation, there can't be an allocation at null, thus it's safe to construct
752749
// `NonNull`.
753-
unsafe { NonNull { pointer: self.as_ptr().byte_sub(count) } }
750+
unsafe { NonNull { pointer: transmute(self.as_ptr().byte_sub(count)) } }
754751
}
755752

756753
/// Calculates the distance between two pointers within the same allocation. The returned value is in

library/std/src/os/unix/io/tests.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ use crate::os::unix::io::RawFd;
22

33
#[test]
44
fn test_raw_fd_layout() {
5-
// `OwnedFd` and `BorrowedFd` use `rustc_layout_scalar_valid_range_start`
6-
// and `rustc_layout_scalar_valid_range_end`, with values that depend on
5+
// `OwnedFd` and `BorrowedFd` use pattern types, with ranges that depend on
76
// the bit width of `RawFd`. If this ever changes, those values will need
87
// to be updated.
98
assert_eq!(size_of::<RawFd>(), 4);

library/std/src/os/wasi/io/tests.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ use crate::os::wasi::io::RawFd;
22

33
#[test]
44
fn test_raw_fd_layout() {
5-
// `OwnedFd` and `BorrowedFd` use `rustc_layout_scalar_valid_range_start`
6-
// and `rustc_layout_scalar_valid_range_end`, with values that depend on
5+
// `OwnedFd` and `BorrowedFd` use pattern types with ranges that depend on
76
// the bit width of `RawFd`. If this ever changes, those values will need
87
// to be updated.
98
assert_eq!(size_of::<RawFd>(), 4);

src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
242242
loop {
243243
ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty);
244244
return match *ty.kind() {
245+
ty::Pat(base, _) => {
246+
ty = base;
247+
continue;
248+
},
245249
ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => {
246250
ReducedTy::TypeErasure { raw_ptr_only: false }
247251
},

tests/codegen/loads.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub fn load_raw_pointer<'a>(x: &*const i32) -> *const i32 {
5858
// CHECK-LABEL: @load_box
5959
#[no_mangle]
6060
pub fn load_box<'a>(x: Box<Box<i32>>) -> Box<i32> {
61-
// CHECK: load ptr, ptr %{{.*}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
61+
// CHECK: load ptr, ptr %{{.*}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !noundef !{{[0-9]+}}
6262
*x
6363
}
6464

tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
StorageLive(_1);
1414
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
1515
- _2 = copy ((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>) as *const Never (Transmute);
16-
+ _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
17-
+ _2 = const std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} }} as *const Never (Transmute);
16+
+ _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
17+
+ _2 = const std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }} as *const Never (Transmute);
1818
unreachable;
1919
}
2020
}

tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
StorageLive(_1);
1414
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
1515
- _2 = copy ((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>) as *const Never (Transmute);
16-
+ _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
17-
+ _2 = const std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} }} as *const Never (Transmute);
16+
+ _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
17+
+ _2 = const std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }} as *const Never (Transmute);
1818
unreachable;
1919
}
2020
}

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
2222
}
2323
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
24-
let _7: *const [bool; 0];
24+
let mut _7: (*const [bool; 0]) is !null;
2525
scope 10 {
2626
}
2727
scope 11 (inlined NonZero::<usize>::get) {
@@ -47,17 +47,17 @@
4747
StorageLive(_6);
4848
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
4949
StorageLive(_7);
50-
_7 = const {0x1 as *const [bool; 0]};
51-
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
50+
_7 = const {0x1 as *const [bool; 0]} is !null;
51+
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }};
5252
StorageDead(_7);
5353
StorageDead(_6);
54-
_4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
54+
_4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }};
5555
StorageDead(_5);
56-
_3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
56+
_3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }};
5757
StorageDead(_4);
58-
_2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
58+
_2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
5959
StorageDead(_3);
60-
_1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
60+
_1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
6161
StorageDead(_2);
6262
_0 = const ();
6363
drop(_1) -> [return: bb1, unwind unreachable];

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
2222
}
2323
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
24-
let _7: *const [bool; 0];
24+
let mut _7: (*const [bool; 0]) is !null;
2525
scope 10 {
2626
}
2727
scope 11 (inlined NonZero::<usize>::get) {
@@ -47,17 +47,17 @@
4747
StorageLive(_6);
4848
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
4949
StorageLive(_7);
50-
_7 = const {0x1 as *const [bool; 0]};
51-
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
50+
_7 = const {0x1 as *const [bool; 0]} is !null;
51+
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }};
5252
StorageDead(_7);
5353
StorageDead(_6);
54-
_4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
54+
_4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }};
5555
StorageDead(_5);
56-
_3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
56+
_3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }};
5757
StorageDead(_4);
58-
_2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
58+
_2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
5959
StorageDead(_3);
60-
_1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
60+
_1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
6161
StorageDead(_2);
6262
_0 = const ();
6363
drop(_1) -> [return: bb1, unwind: bb2];

0 commit comments

Comments
 (0)