Skip to content

Commit 3b571c7

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

File tree

57 files changed

+545
-405
lines changed

Some content is hidden

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

57 files changed

+545
-405
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_codegen_ssa/src/base.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rustc_middle::mir::interpret::ErrorHandled;
2727
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions};
2828
use rustc_middle::query::Providers;
2929
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
30-
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
30+
use rustc_middle::ty::{self, Instance, PatternKind, Ty, TyCtxt};
3131
use rustc_middle::{bug, span_bug};
3232
use rustc_session::Session;
3333
use rustc_session::config::{self, CrateType, EntryFnType};
@@ -274,6 +274,13 @@ pub(crate) fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
274274
let src_ty = src.layout.ty;
275275
let dst_ty = dst.layout.ty;
276276
match (src_ty.kind(), dst_ty.kind()) {
277+
(&ty::Pat(s, sp), &ty::Pat(d, dp))
278+
if let (PatternKind::NotNull, PatternKind::NotNull) = (*sp, *dp) =>
279+
{
280+
let src = src.project_type(bx, s);
281+
let dst = dst.project_type(bx, d);
282+
coerce_unsized_into(bx, src, dst)
283+
}
277284
(&ty::Ref(..), &ty::Ref(..) | &ty::RawPtr(..)) | (&ty::RawPtr(..), &ty::RawPtr(..)) => {
278285
let (base, info) = match bx.load_operand(src).val {
279286
OperandValue::Pair(base, info) => unsize_ptr(bx, base, src_ty, dst_ty, Some(info)),

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: 21 additions & 12 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,9 @@ 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+
// We skip the pointer type by directly transmuting from the `*const u8` of
111+
// `ShallowInitBox` to the pattern type that will get placed inside `NonNull`
112+
let (unique_ty, nonnull_ty, pat_ty, _ptr_ty) =
105113
build_ptr_tys(tcx, pointee, self.unique_def, self.nonnull_def);
106114
let adt_kind = |def: ty::AdtDef<'tcx>, args| {
107115
Box::new(AggregateKind::Adt(def.did(), VariantIdx::ZERO, args, None, None))
@@ -114,11 +122,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
114122
}))
115123
};
116124

117-
let constptr = self.patch.new_temp(ptr_ty, source_info.span);
125+
let constptr = self.patch.new_temp(pat_ty, source_info.span);
118126
self.patch.add_assign(
119127
location,
120128
constptr.into(),
121-
Rvalue::Cast(CastKind::Transmute, mutptr_to_u8.clone(), ptr_ty),
129+
Rvalue::Cast(CastKind::Transmute, mutptr_to_u8.clone(), pat_ty),
122130
);
123131

124132
let nonnull = self.patch.new_temp(nonnull_ty, source_info.span);
@@ -199,10 +207,11 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
199207
let new_projections =
200208
new_projections.get_or_insert_with(|| base.projection.to_vec());
201209

202-
let (unique_ty, nonnull_ty, ptr_ty) =
210+
let (unique_ty, nonnull_ty, pat_ty, ptr_ty) =
203211
build_ptr_tys(tcx, boxed_ty, unique_def, nonnull_def);
204212

205-
new_projections.extend_from_slice(&build_projection(unique_ty, nonnull_ty));
213+
new_projections
214+
.extend_from_slice(&build_projection(unique_ty, nonnull_ty, pat_ty));
206215
// While we can't project into `NonNull<_>` in a basic block
207216
// due to MCP#807, this is debug info where it's fine.
208217
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)