Skip to content

Commit a0b3c54

Browse files
committed
Use !null pattern type in libcore
Use `!null` pattern type in libcore
1 parent 96da85c commit a0b3c54

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
@@ -156,7 +156,12 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
156156
);
157157
// ... that contains a `NonNull`... (gladly, only a single field here)
158158
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
159-
let raw_ptr = self.ecx().project_field(&nonnull_ptr, 0)?; // the actual raw ptr
159+
let pat_ty = self.ecx().project_field(&nonnull_ptr, 0)?; // `*mut T is !null`
160+
let base = match *pat_ty.layout().ty.kind() {
161+
ty::Pat(base, _) => self.ecx().layout_of(base)?,
162+
_ => unreachable!(),
163+
};
164+
let raw_ptr = pat_ty.transmute(base, self.ecx())?; // The actual raw pointer
160165
// ... whose only field finally is a raw ptr we can dereference.
161166
self.visit_box(ty, &raw_ptr)?;
162167

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.
@@ -93,9 +90,9 @@ impl<T: Sized> NonNull<T> {
9390
#[must_use]
9491
#[inline]
9592
pub const fn without_provenance(addr: NonZero<usize>) -> Self {
96-
let pointer = crate::ptr::without_provenance(addr.get());
93+
let pointer: *const T = crate::ptr::without_provenance(addr.get());
9794
// SAFETY: we know `addr` is non-zero.
98-
unsafe { NonNull { pointer } }
95+
unsafe { NonNull { pointer: transmute(pointer) } }
9996
}
10097

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

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

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

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

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

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

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

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

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

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