Skip to content

Commit cbc6ae6

Browse files
committed
Use !null pattern type in libcore
Use `!null` pattern type in libcore
1 parent 6f22992 commit cbc6ae6

File tree

52 files changed

+485
-393
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+485
-393
lines changed

compiler/rustc_const_eval/src/interpret/visitor.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,12 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
137137

138138
// ... that contains a `NonNull`... (gladly, only a single field here)
139139
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
140-
let raw_ptr = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // the actual raw ptr
140+
let pat_ty = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // `*mut T is !null`
141+
let base = match *pat_ty.layout().ty.kind() {
142+
ty::Pat(base, _) => self.ecx().layout_of(base)?,
143+
_ => unreachable!(),
144+
};
145+
let raw_ptr = pat_ty.transmute(base, self.ecx())?; // The actual raw pointer
141146

142147
// ... whose only field finally is a raw ptr we can dereference.
143148
self.visit_box(ty, &raw_ptr)?;

compiler/rustc_mir_transform/src/elaborate_box_derefs.rs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_index::{IndexVec, indexvec};
1010
use rustc_middle::mir::visit::MutVisitor;
1111
use rustc_middle::mir::*;
1212
use rustc_middle::span_bug;
13-
use rustc_middle::ty::{self, Ty, TyCtxt};
13+
use rustc_middle::ty::{self, PatternKind, Ty, TyCtxt};
1414

1515
use crate::patch::MirPatch;
1616

@@ -20,21 +20,27 @@ fn build_ptr_tys<'tcx>(
2020
pointee: Ty<'tcx>,
2121
unique_def: ty::AdtDef<'tcx>,
2222
nonnull_def: ty::AdtDef<'tcx>,
23-
) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
23+
) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
2424
let args = tcx.mk_args(&[pointee.into()]);
2525
let unique_ty = Ty::new_adt(tcx, unique_def, args);
2626
let nonnull_ty = Ty::new_adt(tcx, nonnull_def, args);
2727
let ptr_ty = Ty::new_imm_ptr(tcx, pointee);
28+
let pat_ty = Ty::new_pat(tcx, ptr_ty, tcx.mk_pat(PatternKind::NotNull));
2829

29-
(unique_ty, nonnull_ty, ptr_ty)
30+
(unique_ty, nonnull_ty, pat_ty, ptr_ty)
3031
}
3132

3233
/// Constructs the projection needed to access a Box's pointer
3334
pub(super) fn build_projection<'tcx>(
3435
unique_ty: Ty<'tcx>,
3536
nonnull_ty: Ty<'tcx>,
36-
) -> [PlaceElem<'tcx>; 2] {
37-
[PlaceElem::Field(FieldIdx::ZERO, unique_ty), PlaceElem::Field(FieldIdx::ZERO, nonnull_ty)]
37+
pat_ty: Ty<'tcx>,
38+
) -> [PlaceElem<'tcx>; 3] {
39+
[
40+
PlaceElem::Field(FieldIdx::ZERO, unique_ty),
41+
PlaceElem::Field(FieldIdx::ZERO, nonnull_ty),
42+
PlaceElem::Field(FieldIdx::ZERO, pat_ty),
43+
]
3844
}
3945

4046
struct ElaborateBoxDerefVisitor<'a, 'tcx> {
@@ -66,7 +72,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
6672
{
6773
let source_info = self.local_decls[place.local].source_info;
6874

69-
let (unique_ty, nonnull_ty, ptr_ty) =
75+
let (unique_ty, nonnull_ty, pat_ty, ptr_ty) =
7076
build_ptr_tys(tcx, boxed_ty, self.unique_def, self.nonnull_def);
7177

7278
let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
@@ -78,7 +84,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
7884
CastKind::Transmute,
7985
Operand::Copy(
8086
Place::from(place.local)
81-
.project_deeper(&build_projection(unique_ty, nonnull_ty), tcx),
87+
.project_deeper(&build_projection(unique_ty, nonnull_ty, pat_ty), tcx),
8288
),
8389
ptr_ty,
8490
),
@@ -101,7 +107,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
101107
&& let ty::Adt(box_adt, box_args) = Ty::new_box(tcx, pointee).kind()
102108
{
103109
let args = tcx.mk_args(&[pointee.into()]);
104-
let (unique_ty, nonnull_ty, ptr_ty) =
110+
let (unique_ty, nonnull_ty, pat_ty, ptr_ty) =
105111
build_ptr_tys(tcx, pointee, self.unique_def, self.nonnull_def);
106112
let adt_kind = |def: ty::AdtDef<'tcx>, args| {
107113
Box::new(AggregateKind::Adt(def.did(), VariantIdx::ZERO, args, None, None))
@@ -121,13 +127,20 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
121127
Rvalue::Cast(CastKind::Transmute, mutptr_to_u8.clone(), ptr_ty),
122128
);
123129

130+
let pat_ptr = self.patch.new_temp(pat_ty, source_info.span);
131+
self.patch.add_assign(
132+
location,
133+
pat_ptr.into(),
134+
Rvalue::Cast(CastKind::Transmute, Operand::Move(constptr.into()), pat_ty),
135+
);
136+
124137
let nonnull = self.patch.new_temp(nonnull_ty, source_info.span);
125138
self.patch.add_assign(
126139
location,
127140
nonnull.into(),
128141
Rvalue::Aggregate(
129142
adt_kind(self.nonnull_def, args),
130-
indexvec![Operand::Move(constptr.into())],
143+
indexvec![Operand::Move(pat_ptr.into())],
131144
),
132145
);
133146

@@ -199,10 +212,11 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
199212
let new_projections =
200213
new_projections.get_or_insert_with(|| base.projection.to_vec());
201214

202-
let (unique_ty, nonnull_ty, ptr_ty) =
215+
let (unique_ty, nonnull_ty, pat_ty, ptr_ty) =
203216
build_ptr_tys(tcx, boxed_ty, unique_def, nonnull_def);
204217

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

compiler/rustc_mir_transform/src/validate.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -669,24 +669,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
669669
let fail_out_of_bounds = |this: &mut Self, location| {
670670
this.fail(location, format!("Out of bounds field {f:?} for {parent_ty:?}"));
671671
};
672+
673+
let kind = match parent_ty.ty.kind() {
674+
&ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
675+
self.tcx.type_of(def_id).instantiate(self.tcx, args).kind()
676+
}
677+
kind => kind,
678+
};
679+
672680
let check_equal = |this: &mut Self, location, f_ty| {
673681
if !this.mir_assign_valid_types(ty, f_ty) {
674682
this.fail(
675683
location,
676684
format!(
677-
"Field projection `{place_ref:?}.{f:?}` specified type `{ty}`, but actual type is `{f_ty}`"
685+
"Field projection `{place_ref:?}.{f:?}` specified type `{ty}`, but actual field type of `{kind:?}` is `{f_ty}`"
678686
)
679687
)
680688
}
681689
};
682690

683-
let kind = match parent_ty.ty.kind() {
684-
&ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
685-
self.tcx.type_of(def_id).instantiate(self.tcx, args).kind()
686-
}
687-
kind => kind,
688-
};
689-
690691
match kind {
691692
ty::Tuple(fields) => {
692693
let Some(f_ty) = fields.get(f.as_usize()) else {

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::{Destruct, 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.
@@ -238,7 +235,7 @@ impl<T: PointeeSized> NonNull<T> {
238235
"NonNull::new_unchecked requires that the pointer is non-null",
239236
(ptr: *mut () = ptr as *mut ()) => !ptr.is_null()
240237
);
241-
NonNull { pointer: ptr as _ }
238+
NonNull { pointer: transmute(ptr) }
242239
}
243240
}
244241

@@ -281,7 +278,7 @@ impl<T: PointeeSized> NonNull<T> {
281278
#[inline]
282279
pub const fn from_ref(r: &T) -> Self {
283280
// SAFETY: A reference cannot be null.
284-
unsafe { NonNull { pointer: r as *const T } }
281+
unsafe { NonNull { pointer: transmute(r as *const T) } }
285282
}
286283

287284
/// Converts a mutable reference to a `NonNull` pointer.
@@ -290,7 +287,7 @@ impl<T: PointeeSized> NonNull<T> {
290287
#[inline]
291288
pub const fn from_mut(r: &mut T) -> Self {
292289
// SAFETY: A mutable reference cannot be null.
293-
unsafe { NonNull { pointer: r as *mut T } }
290+
unsafe { NonNull { pointer: transmute(r as *mut T) } }
294291
}
295292

296293
/// Performs the same functionality as [`std::ptr::from_raw_parts`], except that a
@@ -501,7 +498,7 @@ impl<T: PointeeSized> NonNull<T> {
501498
#[inline]
502499
pub const fn cast<U>(self) -> NonNull<U> {
503500
// SAFETY: `self` is a `NonNull` pointer which is necessarily non-null
504-
unsafe { NonNull { pointer: self.as_ptr() as *mut U } }
501+
unsafe { NonNull { pointer: transmute(self.as_ptr() as *mut U) } }
505502
}
506503

507504
/// Try to cast to a pointer of another type by checking alignment.
@@ -580,7 +577,7 @@ impl<T: PointeeSized> NonNull<T> {
580577
// Additionally safety contract of `offset` guarantees that the resulting pointer is
581578
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
582579
// construct `NonNull`.
583-
unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } }
580+
unsafe { NonNull { pointer: transmute(intrinsics::offset(self.as_ptr(), count)) } }
584581
}
585582

586583
/// Calculates the offset from a pointer in bytes.
@@ -604,7 +601,7 @@ impl<T: PointeeSized> NonNull<T> {
604601
// Additionally safety contract of `offset` guarantees that the resulting pointer is
605602
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
606603
// construct `NonNull`.
607-
unsafe { NonNull { pointer: self.as_ptr().byte_offset(count) } }
604+
unsafe { NonNull { pointer: transmute(self.as_ptr().byte_offset(count)) } }
608605
}
609606

610607
/// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
@@ -656,7 +653,7 @@ impl<T: PointeeSized> NonNull<T> {
656653
// Additionally safety contract of `offset` guarantees that the resulting pointer is
657654
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
658655
// construct `NonNull`.
659-
unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } }
656+
unsafe { NonNull { pointer: transmute(intrinsics::offset(self.as_ptr(), count)) } }
660657
}
661658

662659
/// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`).
@@ -680,7 +677,7 @@ impl<T: PointeeSized> NonNull<T> {
680677
// Additionally safety contract of `add` guarantees that the resulting pointer is pointing
681678
// to an allocation, there can't be an allocation at null, thus it's safe to construct
682679
// `NonNull`.
683-
unsafe { NonNull { pointer: self.as_ptr().byte_add(count) } }
680+
unsafe { NonNull { pointer: transmute(self.as_ptr().byte_add(count)) } }
684681
}
685682

686683
/// Subtracts an offset from a pointer (convenience for
@@ -762,7 +759,7 @@ impl<T: PointeeSized> NonNull<T> {
762759
// Additionally safety contract of `sub` guarantees that the resulting pointer is pointing
763760
// to an allocation, there can't be an allocation at null, thus it's safe to construct
764761
// `NonNull`.
765-
unsafe { NonNull { pointer: self.as_ptr().byte_sub(count) } }
762+
unsafe { NonNull { pointer: transmute(self.as_ptr().byte_sub(count)) } }
766763
}
767764

768765
/// 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-llvm/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/box_expr.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
fn main() {
88
// CHECK-LABEL: fn main(
99
// CHECK: [[ptr:_.*]] = move {{_.*}} as *const S (Transmute);
10-
// CHECK: [[nonnull:_.*]] = NonNull::<S> { pointer: move [[ptr]] };
10+
// CHECK: [[pat_ptr:_.*]] = move [[ptr]] as (*const S) is !null (Transmute);
11+
// CHECK: [[nonnull:_.*]] = NonNull::<S> { pointer: move [[pat_ptr]] };
1112
// CHECK: [[unique:_.*]] = Unique::<S> { pointer: move [[nonnull]], _marker: const PhantomData::<S> };
1213
// CHECK: [[box:_.*]] = Box::<S>(move [[unique]], const std::alloc::Global);
13-
// CHECK: [[ptr:_.*]] = copy (([[box]].0: std::ptr::Unique<S>).0: std::ptr::NonNull<S>) as *const S (Transmute);
14+
// CHECK: [[ptr:_.*]] = copy ((([[box]].0: std::ptr::Unique<S>).0: std::ptr::NonNull<S>).0: (*const S) is !null) as *const S (Transmute);
1415
// CHECK: (*[[ptr]]) = S::new() -> [return: [[ret:bb.*]], unwind: [[unwind:bb.*]]];
1516
// CHECK: [[ret]]: {
1617
// CHECK: [[box2:_.*]] = move [[box]];

tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
let mut _4: *mut u8;
1010
let mut _5: std::boxed::Box<i32>;
1111
let mut _6: *const i32;
12-
let mut _7: std::ptr::NonNull<i32>;
13-
let mut _8: std::ptr::Unique<i32>;
14-
let mut _9: *const i32;
12+
let mut _7: (*const i32) is !null;
13+
let mut _8: std::ptr::NonNull<i32>;
14+
let mut _9: std::ptr::Unique<i32>;
1515
let mut _10: *const i32;
16+
let mut _11: *const i32;
1617
scope 1 {
1718
debug x => _1;
1819
}
@@ -28,20 +29,20 @@
2829
bb1: {
2930
StorageLive(_5);
3031
- _6 = move _4 as *const i32 (Transmute);
31-
- _7 = NonNull::<i32> { pointer: move _6 };
32-
- _8 = Unique::<i32> { pointer: move _7, _marker: const PhantomData::<i32> };
32+
- _7 = move _6 as (*const i32) is !null (Transmute);
33+
- _8 = NonNull::<i32> { pointer: move _7 };
3334
+ _6 = copy _4 as *const i32 (PtrToPtr);
34-
+ _7 = NonNull::<i32> { pointer: copy _6 };
35-
+ _8 = Unique::<i32> { pointer: copy _7, _marker: const PhantomData::<i32> };
36-
_5 = Box::<i32>(move _8, const std::alloc::Global);
37-
- _9 = copy ((_5.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
38-
- (*_9) = const 42_i32;
39-
+ _9 = copy _6;
40-
+ (*_6) = const 42_i32;
35+
+ _7 = copy _4 as (*const i32) is !null (Transmute);
36+
+ _8 = NonNull::<i32> { pointer: copy _7 };
37+
_9 = Unique::<i32> { pointer: move _8, _marker: const PhantomData::<i32> };
38+
_5 = Box::<i32>(move _9, const std::alloc::Global);
39+
- _10 = copy (((_5.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>).0: (*const i32) is !null) as *const i32 (Transmute);
40+
+ _10 = copy _7 as *const i32 (Transmute);
41+
(*_10) = const 42_i32;
4142
_3 = move _5;
4243
StorageDead(_5);
43-
_10 = copy ((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
44-
_2 = copy (*_10);
44+
_11 = copy (((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>).0: (*const i32) is !null) as *const i32 (Transmute);
45+
_2 = copy (*_11);
4546
- _1 = Add(move _2, const 0_i32);
4647
- StorageDead(_2);
4748
+ _1 = copy _2;

0 commit comments

Comments
 (0)