Skip to content

Commit e2e8462

Browse files
committed
Use !null pattern type in libcore
Use `!null` pattern type in libcore
1 parent 1a0e529 commit e2e8462

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
@@ -139,7 +139,12 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
139139
);
140140
// ... that contains a `NonNull`... (gladly, only a single field here)
141141
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
142-
let raw_ptr = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // the actual raw ptr
142+
let pat_ty = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // `*mut T is !null`
143+
let base = match *pat_ty.layout().ty.kind() {
144+
ty::Pat(base, _) => self.ecx().layout_of(base)?,
145+
_ => unreachable!(),
146+
};
147+
let raw_ptr = pat_ty.transmute(base, self.ecx())?; // The actual raw pointer
143148
// ... whose only field finally is a raw ptr we can dereference.
144149
self.visit_box(ty, &raw_ptr)?;
145150

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::{PointeeSized, 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;
@@ -69,13 +69,10 @@ use crate::{fmt, hash, intrinsics, mem, ptr};
6969
/// [null pointer optimization]: crate::option#representation
7070
#[stable(feature = "nonnull", since = "1.25.0")]
7171
#[repr(transparent)]
72-
#[rustc_layout_scalar_valid_range_start(1)]
7372
#[rustc_nonnull_optimization_guaranteed]
7473
#[rustc_diagnostic_item = "NonNull"]
7574
pub struct NonNull<T: PointeeSized> {
76-
// Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to
77-
// this is banned by <https://github.com/rust-lang/compiler-team/issues/807>.
78-
pointer: *const T,
75+
pointer: crate::pattern_type!(*const T is !null),
7976
}
8077

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

107104
/// Creates a new `NonNull` that is dangling, but well-aligned.
@@ -231,7 +228,7 @@ impl<T: PointeeSized> NonNull<T> {
231228
"NonNull::new_unchecked requires that the pointer is non-null",
232229
(ptr: *mut () = ptr as *mut ()) => !ptr.is_null()
233230
);
234-
NonNull { pointer: ptr as _ }
231+
NonNull { pointer: transmute(ptr) }
235232
}
236233
}
237234

@@ -274,7 +271,7 @@ impl<T: PointeeSized> NonNull<T> {
274271
#[inline]
275272
pub const fn from_ref(r: &T) -> Self {
276273
// SAFETY: A reference cannot be null.
277-
unsafe { NonNull { pointer: r as *const T } }
274+
unsafe { NonNull { pointer: transmute(r as *const T) } }
278275
}
279276

280277
/// Converts a mutable reference to a `NonNull` pointer.
@@ -283,7 +280,7 @@ impl<T: PointeeSized> NonNull<T> {
283280
#[inline]
284281
pub const fn from_mut(r: &mut T) -> Self {
285282
// SAFETY: A mutable reference cannot be null.
286-
unsafe { NonNull { pointer: r as *mut T } }
283+
unsafe { NonNull { pointer: transmute(r as *mut T) } }
287284
}
288285

289286
/// Performs the same functionality as [`std::ptr::from_raw_parts`], except that a
@@ -494,7 +491,7 @@ impl<T: PointeeSized> NonNull<T> {
494491
#[inline]
495492
pub const fn cast<U>(self) -> NonNull<U> {
496493
// SAFETY: `self` is a `NonNull` pointer which is necessarily non-null
497-
unsafe { NonNull { pointer: self.as_ptr() as *mut U } }
494+
unsafe { NonNull { pointer: transmute(self.as_ptr() as *mut U) } }
498495
}
499496

500497
/// Try to cast to a pointer of another type by checking alignment.
@@ -573,7 +570,7 @@ impl<T: PointeeSized> NonNull<T> {
573570
// Additionally safety contract of `offset` guarantees that the resulting pointer is
574571
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
575572
// construct `NonNull`.
576-
unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } }
573+
unsafe { NonNull { pointer: transmute(intrinsics::offset(self.as_ptr(), count)) } }
577574
}
578575

579576
/// Calculates the offset from a pointer in bytes.
@@ -597,7 +594,7 @@ impl<T: PointeeSized> NonNull<T> {
597594
// Additionally safety contract of `offset` guarantees that the resulting pointer is
598595
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
599596
// construct `NonNull`.
600-
unsafe { NonNull { pointer: self.as_ptr().byte_offset(count) } }
597+
unsafe { NonNull { pointer: transmute(self.as_ptr().byte_offset(count)) } }
601598
}
602599

603600
/// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
@@ -649,7 +646,7 @@ impl<T: PointeeSized> NonNull<T> {
649646
// Additionally safety contract of `offset` guarantees that the resulting pointer is
650647
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
651648
// construct `NonNull`.
652-
unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } }
649+
unsafe { NonNull { pointer: transmute(intrinsics::offset(self.as_ptr(), count)) } }
653650
}
654651

655652
/// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`).
@@ -673,7 +670,7 @@ impl<T: PointeeSized> NonNull<T> {
673670
// Additionally safety contract of `add` guarantees that the resulting pointer is pointing
674671
// to an allocation, there can't be an allocation at null, thus it's safe to construct
675672
// `NonNull`.
676-
unsafe { NonNull { pointer: self.as_ptr().byte_add(count) } }
673+
unsafe { NonNull { pointer: transmute(self.as_ptr().byte_add(count)) } }
677674
}
678675

679676
/// Subtracts an offset from a pointer (convenience for
@@ -755,7 +752,7 @@ impl<T: PointeeSized> NonNull<T> {
755752
// Additionally safety contract of `sub` guarantees that the resulting pointer is pointing
756753
// to an allocation, there can't be an allocation at null, thus it's safe to construct
757754
// `NonNull`.
758-
unsafe { NonNull { pointer: self.as_ptr().byte_sub(count) } }
755+
unsafe { NonNull { pointer: transmute(self.as_ptr().byte_sub(count)) } }
759756
}
760757

761758
/// 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)