Skip to content

Commit 97baf41

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

File tree

56 files changed

+558
-411
lines changed

Some content is hidden

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

56 files changed

+558
-411
lines changed

compiler/rustc_codegen_cranelift/example/mini_core.rs

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,38 @@
88
rustc_attrs,
99
rustc_private,
1010
transparent_unions,
11+
pattern_types,
1112
auto_traits,
1213
freeze_impls,
1314
thread_local
1415
)]
1516
#![no_core]
1617
#![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)]
1718

19+
#[lang = "pointee_trait"]
20+
pub trait Pointee: PointeeSized {
21+
#[lang = "metadata_type"]
22+
// needed so that layout_of will return `TooGeneric` instead of `Unknown`
23+
// when asked for the layout of `*const T`. Which is important for making
24+
// transmutes between raw pointers (and especially pattern types of raw pointers)
25+
// work.
26+
type Metadata: Copy + Sync + Unpin + Freeze;
27+
}
28+
29+
#[lang = "dyn_metadata"]
30+
pub struct DynMetadata<Dyn: PointeeSized> {
31+
_vtable_ptr: NonNull<VTable>,
32+
_phantom: PhantomData<Dyn>,
33+
}
34+
35+
unsafe extern "C" {
36+
/// Opaque type for accessing vtables.
37+
///
38+
/// Private implementation detail of `DynMetadata::size_of` etc.
39+
/// There is conceptually not actually any Abstract Machine memory behind this pointer.
40+
type VTable;
41+
}
42+
1843
#[lang = "pointee_sized"]
1944
pub trait PointeeSized {}
2045

@@ -105,7 +130,7 @@ unsafe impl<'a, T: PointeeSized> Sync for &'a T {}
105130
unsafe impl<T: Sync, const N: usize> Sync for [T; N] {}
106131

107132
#[lang = "freeze"]
108-
unsafe auto trait Freeze {}
133+
pub unsafe auto trait Freeze {}
109134

110135
unsafe impl<T: PointeeSized> Freeze for PhantomData<T> {}
111136
unsafe impl<T: PointeeSized> Freeze for *const T {}
@@ -568,10 +593,24 @@ pub trait Deref {
568593
fn deref(&self) -> &Self::Target;
569594
}
570595

596+
#[rustc_builtin_macro(pattern_type)]
597+
#[macro_export]
598+
macro_rules! pattern_type {
599+
($($arg:tt)*) => {
600+
/* compiler built-in */
601+
};
602+
}
603+
604+
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<pattern_type!(*const U is !null)> for pattern_type!(*const T is !null) where
605+
T: Unsize<U>
606+
{
607+
}
608+
609+
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<pattern_type!(U is !null)> for pattern_type!(T is !null) {}
610+
571611
#[repr(transparent)]
572-
#[rustc_layout_scalar_valid_range_start(1)]
573612
#[rustc_nonnull_optimization_guaranteed]
574-
pub struct NonNull<T: PointeeSized>(pub *const T);
613+
pub struct NonNull<T: PointeeSized>(pub pattern_type!(*const T is !null));
575614

576615
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
577616
impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
@@ -598,7 +637,16 @@ impl<T> Box<T> {
598637
let size = size_of::<T>();
599638
let ptr = libc::malloc(size);
600639
intrinsics::copy(&val as *const T as *const u8, ptr, size);
601-
Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global)
640+
Box(
641+
Unique {
642+
pointer: NonNull(intrinsics::transmute::<
643+
*mut u8,
644+
pattern_type!(*const T is !null),
645+
>(ptr)),
646+
_marker: PhantomData,
647+
},
648+
Global,
649+
)
602650
}
603651
}
604652
}
@@ -607,7 +655,9 @@ impl<T: ?Sized, A> Drop for Box<T, A> {
607655
fn drop(&mut self) {
608656
// inner value is dropped by compiler
609657
unsafe {
610-
libc::free(self.0.pointer.0 as *mut u8);
658+
libc::free(intrinsics::transmute::<pattern_type!(*const T is !null), *const T>(
659+
self.0.pointer.0,
660+
) as *mut u8);
611661
}
612662
}
613663
}

compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
extern_types,
77
thread_local,
88
repr_simd,
9+
pattern_types,
910
rustc_private
1011
)]
1112
#![no_core]
@@ -159,7 +160,10 @@ extern "C" fn bool_struct_in_11(_arg0: bool_11) {}
159160

160161
#[allow(unreachable_code)] // FIXME false positive
161162
fn main() {
162-
take_unique(Unique { pointer: unsafe { NonNull(1 as *mut ()) }, _marker: PhantomData });
163+
take_unique(Unique {
164+
pointer: unsafe { NonNull(intrinsics::transmute(1 as *mut ())) },
165+
_marker: PhantomData,
166+
});
163167
take_f32(0.1);
164168

165169
call_return_u128_pair();
@@ -225,7 +229,12 @@ fn main() {
225229
let noisy_unsized_drop = const { intrinsics::needs_drop::<NoisyDropUnsized>() };
226230
assert!(noisy_unsized_drop);
227231

228-
Unique { pointer: NonNull(1 as *mut &str), _marker: PhantomData } as Unique<dyn SomeTrait>;
232+
Unique {
233+
pointer: NonNull(intrinsics::transmute::<_, pattern_type!(*const &str is !null)>(
234+
1 as *mut &str,
235+
)),
236+
_marker: PhantomData,
237+
} as Unique<dyn SomeTrait>;
229238

230239
struct MyDst<T: ?Sized>(T);
231240

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_middle/src/ty/layout.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_session::config::OptLevel;
1717
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
1818
use rustc_target::callconv::FnAbi;
1919
use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi};
20-
use tracing::debug;
20+
use tracing::{debug, instrument, trace};
2121
use {rustc_abi as abi, rustc_hir as hir};
2222

2323
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
@@ -376,6 +376,7 @@ pub enum SizeSkeleton<'tcx> {
376376
}
377377

378378
impl<'tcx> SizeSkeleton<'tcx> {
379+
#[instrument(level = "trace", skip(tcx, typing_env), ret)]
379380
pub fn compute(
380381
ty: Ty<'tcx>,
381382
tcx: TyCtxt<'tcx>,
@@ -425,6 +426,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
425426
},
426427
|| {},
427428
);
429+
trace!(?tail);
428430

429431
match tail.kind() {
430432
ty::Param(_) | ty::Alias(ty::Projection | ty::Inherent, _) => {

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 {

0 commit comments

Comments
 (0)