Skip to content

Commit 2e8cece

Browse files
committed
Only mark the first pointer-width bytes of TypeIdwith provenance
1 parent 9d6f08f commit 2e8cece

File tree

12 files changed

+65
-158
lines changed

12 files changed

+65
-158
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
use std::cmp::Ordering;
44

55
use cranelift_module::*;
6-
use rustc_abi::Align;
7-
use rustc_const_eval::interpret::{AllocInit, Allocation, alloc_range};
86
use rustc_data_structures::fx::FxHashSet;
97
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
108
use rustc_middle::mir::interpret::{AllocId, GlobalAlloc, Scalar, read_target_uint};
@@ -177,11 +175,11 @@ pub(crate) fn codegen_const_value<'tcx>(
177175
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
178176
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
179177
}
180-
GlobalAlloc::Type { ty: type_id_ty, segment } => {
178+
GlobalAlloc::Type { .. } => {
181179
return CValue::const_val(
182180
fx,
183181
layout,
184-
type_id_segment(fx.tcx, type_id_ty, segment),
182+
ScalarInt::try_from_target_usize(offset.bytes(), fx.tcx).unwrap(),
185183
);
186184
}
187185
GlobalAlloc::Static(def_id) => {
@@ -221,23 +219,6 @@ pub(crate) fn codegen_const_value<'tcx>(
221219
}
222220
}
223221

224-
fn type_id_segment<'tcx>(tcx: TyCtxt<'tcx>, type_id_ty: Ty<'tcx>, segment: u8) -> ScalarInt {
225-
let type_id = tcx.type_id_hash(type_id_ty).as_u128();
226-
let mut alloc: Allocation =
227-
Allocation::new(Size::from_bytes(16), Align::from_bytes(8).unwrap(), AllocInit::Uninit, ());
228-
alloc
229-
.write_scalar(
230-
&tcx,
231-
alloc_range(Size::ZERO, Size::from_bytes(16)),
232-
Scalar::from_u128(type_id),
233-
)
234-
.unwrap();
235-
let pointer_size = tcx.data_layout.pointer_size;
236-
let offset = pointer_size * u64::from(segment);
237-
let value = alloc.read_scalar(&tcx, alloc_range(offset, pointer_size), false).unwrap();
238-
value.to_scalar_int().unwrap()
239-
}
240-
241222
fn pointer_for_allocation<'tcx>(
242223
fx: &mut FunctionCx<'_, '_, 'tcx>,
243224
alloc_id: AllocId,
@@ -498,16 +479,9 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
498479
.principal()
499480
.map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
500481
),
501-
GlobalAlloc::Type { ty, segment } => {
502-
let val = type_id_segment(tcx, ty, segment);
503-
let Init::Bytes { contents } = &mut data.init else { unreachable!() };
504-
let start = offset.bytes_usize();
505-
let ptr_size = tcx.data_layout.pointer_size;
506-
let src = val.to_bits(ptr_size);
507-
let src = u128::to_le_bytes(src);
508-
let len = ptr_size.bytes_usize();
509-
assert!(src[len..].iter().all(|b| *b == 0));
510-
contents[start..(start + len)].copy_from_slice(&src[..len]);
482+
GlobalAlloc::Type { .. } => {
483+
// Nothing to do, the bytes/offset of this pointer have already been written together with all other bytes,
484+
// so we just need to drop this provenance.
511485
continue;
512486
}
513487
GlobalAlloc::Static(def_id) => {

compiler/rustc_codegen_cranelift/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ extern crate rustc_middle;
2020
extern crate rustc_abi;
2121
extern crate rustc_ast;
2222
extern crate rustc_codegen_ssa;
23-
extern crate rustc_const_eval;
2423
extern crate rustc_data_structures;
2524
extern crate rustc_errors;
2625
extern crate rustc_fs_util;

compiler/rustc_codegen_gcc/src/common.rs

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use gccjit::{LValue, RValue, ToRValue, Type};
22
use rustc_abi::Primitive::Pointer;
3-
use rustc_abi::{self as abi, Align, HasDataLayout, Size};
3+
use rustc_abi::{self as abi, HasDataLayout};
44
use rustc_codegen_ssa::traits::{
55
BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods,
66
};
7-
use rustc_const_eval::interpret::{AllocInit, Allocation, alloc_range};
87
use rustc_middle::mir::Mutability;
98
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
109
use rustc_middle::ty::layout::LayoutOf;
@@ -303,28 +302,8 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
303302
let init = self.const_data_from_alloc(alloc);
304303
self.static_addr_of(init, alloc.inner().align, None)
305304
}
306-
GlobalAlloc::Type { ty: type_id_ty, segment } => {
307-
let type_id = self.tcx.type_id_hash(type_id_ty).as_u128();
308-
let mut alloc: Allocation = Allocation::new(
309-
Size::from_bytes(16),
310-
Align::from_bytes(8).unwrap(),
311-
AllocInit::Uninit,
312-
(),
313-
);
314-
alloc
315-
.write_scalar(
316-
&self.tcx,
317-
alloc_range(Size::ZERO, Size::from_bytes(16)),
318-
Scalar::from_u128(type_id),
319-
)
320-
.unwrap();
321-
let pointer_size = self.tcx.data_layout.pointer_size;
322-
let offset = pointer_size * u64::from(segment);
323-
let value = alloc
324-
.read_scalar(&self.tcx, alloc_range(offset, pointer_size), false)
325-
.unwrap();
326-
let data = value.to_bits(pointer_size).unwrap() as u64;
327-
let val = self.const_usize(data);
305+
GlobalAlloc::Type { .. } => {
306+
let val = self.const_usize(offset.bytes());
328307
return self.context.new_cast(None, val, ty);
329308
}
330309
GlobalAlloc::Static(def_id) => {

compiler/rustc_codegen_gcc/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ extern crate rustc_apfloat;
4141
extern crate rustc_ast;
4242
extern crate rustc_attr_data_structures;
4343
extern crate rustc_codegen_ssa;
44-
extern crate rustc_const_eval;
4544
extern crate rustc_data_structures;
4645
extern crate rustc_errors;
4746
extern crate rustc_fluent_macro;

compiler/rustc_codegen_llvm/src/common.rs

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,15 @@ use std::borrow::Borrow;
44

55
use libc::{c_char, c_uint};
66
use rustc_abi::Primitive::Pointer;
7-
use rustc_abi::{self as abi, Align, HasDataLayout as _, Size};
7+
use rustc_abi::{self as abi, HasDataLayout as _};
88
use rustc_ast::Mutability;
99
use rustc_codegen_ssa::common::TypeKind;
1010
use rustc_codegen_ssa::traits::*;
1111
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1212
use rustc_hashes::Hash128;
1313
use rustc_hir::def_id::DefId;
1414
use rustc_middle::bug;
15-
use rustc_middle::mir::interpret::{
16-
AllocInit, Allocation, ConstAllocation, GlobalAlloc, Scalar, alloc_range,
17-
};
15+
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
1816
use rustc_middle::ty::TyCtxt;
1917
use rustc_session::cstore::DllImport;
2018
use tracing::debug;
@@ -326,28 +324,9 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
326324
assert!(!self.tcx.is_thread_local_static(def_id));
327325
self.get_static(def_id)
328326
}
329-
GlobalAlloc::Type { ty, segment } => {
330-
let type_id = self.tcx.type_id_hash(ty).as_u128();
331-
let mut alloc: Allocation = Allocation::new(
332-
Size::from_bytes(16),
333-
Align::from_bytes(8).unwrap(),
334-
AllocInit::Uninit,
335-
(),
336-
);
337-
alloc
338-
.write_scalar(
339-
&self.tcx,
340-
alloc_range(Size::ZERO, Size::from_bytes(16)),
341-
Scalar::from_u128(type_id),
342-
)
343-
.unwrap();
344-
let pointer_size = self.tcx.data_layout.pointer_size;
345-
let offset = pointer_size * u64::from(segment);
346-
let value = alloc
347-
.read_scalar(&self.tcx, alloc_range(offset, pointer_size), false)
348-
.unwrap();
349-
let data = value.to_bits(pointer_size).unwrap() as u64;
350-
let llval = self.const_usize(data);
327+
GlobalAlloc::Type { .. } => {
328+
// Drop the provenance, the offset contains the bytes of the hash
329+
let llval = self.const_usize(offset.bytes());
351330
return unsafe { llvm::LLVMConstIntToPtr(llval, llty) };
352331
}
353332
};

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -406,33 +406,20 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
406406
sym::type_id_eq => {
407407
let a = ecx.project_field(&args[0], FieldIdx::ZERO)?;
408408
let b = ecx.project_field(&args[1], FieldIdx::ZERO)?;
409-
let mut eq = true;
410-
for index in 0..(16 / ecx.tcx.data_layout.pointer_size.bytes()) {
411-
let a = ecx.project_index(&a, index)?;
412-
let a = ecx.deref_pointer(&a)?;
413-
let (a, offset) = a.ptr().into_parts();
414-
assert_eq!(offset, Size::ZERO);
415-
let a = a.unwrap().alloc_id();
416-
let GlobalAlloc::Type { ty: a, segment: a_segment } = ecx.tcx.global_alloc(a)
417-
else {
418-
bug!()
419-
};
420-
let b = ecx.project_index(&b, index)?;
421-
let b = ecx.deref_pointer(&b)?;
422-
let (b, offset) = b.ptr().into_parts();
423-
assert_eq!(offset, Size::ZERO);
424-
let b = b.unwrap().alloc_id();
425-
let GlobalAlloc::Type { ty: b, segment: b_segment } = ecx.tcx.global_alloc(b)
426-
else {
427-
bug!()
428-
};
429-
430-
eq &= a == b && a_segment == b_segment;
431-
if !eq {
432-
break;
433-
}
434-
}
435-
ecx.write_scalar(Scalar::from_bool(eq), dest)?;
409+
410+
let a = ecx.project_index(&a, 0)?;
411+
let a = ecx.deref_pointer(&a)?;
412+
let (a, offset_a) = a.ptr().into_parts();
413+
let a = a.unwrap().alloc_id();
414+
let GlobalAlloc::Type { ty: a } = ecx.tcx.global_alloc(a) else { bug!() };
415+
416+
let b = ecx.project_index(&b, 0)?;
417+
let b = ecx.deref_pointer(&b)?;
418+
let (b, offset_b) = b.ptr().into_parts();
419+
let b = b.unwrap().alloc_id();
420+
let GlobalAlloc::Type { ty: b } = ecx.tcx.global_alloc(b) else { bug!() };
421+
422+
ecx.write_scalar(Scalar::from_bool(a == b && offset_a == offset_b), dest)?;
436423
}
437424
sym::const_allocate => {
438425
let size = ecx.read_scalar(&args[0])?.to_target_usize(ecx)?;

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,26 @@ pub(crate) fn alloc_type_id<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> AllocId {
3636
let align = tcx.data_layout.pointer_align;
3737
let mut alloc = Allocation::new(size, *align, AllocInit::Uninit, ());
3838
let ptr_size = tcx.data_layout.pointer_size;
39-
for step in 0..size.bytes() / ptr_size.bytes() {
40-
let offset = ptr_size * step;
41-
let alloc_id = tcx.reserve_and_set_type_id_alloc(ty, step.try_into().unwrap());
42-
let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
43-
let val = Scalar::from_pointer(ptr, &tcx);
44-
alloc.write_scalar(&tcx, alloc_range(offset, ptr_size), val).unwrap();
45-
}
39+
let type_id_hash = tcx.type_id_hash(ty).as_u128();
40+
alloc
41+
.write_scalar(
42+
&tcx,
43+
alloc_range(Size::ZERO, Size::from_bytes(16)),
44+
Scalar::from_u128(type_id_hash),
45+
)
46+
.unwrap();
47+
48+
// Give the first pointer-size bytes provenance that knows about the type id
49+
50+
let alloc_id = tcx.reserve_and_set_type_id_alloc(ty);
51+
let offset = alloc
52+
.read_scalar(&tcx, alloc_range(Size::ZERO, ptr_size), false)
53+
.unwrap()
54+
.to_target_usize(&tcx)
55+
.unwrap();
56+
let ptr = Pointer::new(alloc_id.into(), Size::from_bytes(offset));
57+
let val = Scalar::from_pointer(ptr, &tcx);
58+
alloc.write_scalar(&tcx, alloc_range(Size::ZERO, ptr_size), val).unwrap();
4659

4760
alloc.mutability = Mutability::Not;
4861

compiler/rustc_const_eval/src/interpret/memory.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,8 +1211,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> {
12111211
Some(GlobalAlloc::VTable(ty, dyn_ty)) => {
12121212
write!(fmt, " (vtable: impl {dyn_ty} for {ty})")?;
12131213
}
1214-
Some(GlobalAlloc::Type { ty, segment }) => {
1215-
write!(fmt, " (typeid segment {segment } for {ty})")?;
1214+
Some(GlobalAlloc::Type { ty }) => {
1215+
write!(fmt, " (typeid for {ty})")?;
12161216
}
12171217
Some(GlobalAlloc::Static(did)) => {
12181218
write!(fmt, " (static: {})", self.ecx.tcx.def_path_str(did))?;

compiler/rustc_middle/src/mir/interpret/mod.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,10 @@ pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<'tcx>>(
128128
ty.encode(encoder);
129129
poly_trait_ref.encode(encoder);
130130
}
131-
GlobalAlloc::Type { ty, segment } => {
131+
GlobalAlloc::Type { ty } => {
132132
trace!("encoding {alloc_id:?} with {ty:#?}");
133133
AllocDiscriminant::Type.encode(encoder);
134134
ty.encode(encoder);
135-
segment.encode(encoder);
136135
}
137136
GlobalAlloc::Static(did) => {
138137
assert!(!tcx.is_thread_local_static(did));
@@ -238,9 +237,8 @@ impl<'s> AllocDecodingSession<'s> {
238237
AllocDiscriminant::Type => {
239238
trace!("creating typeid alloc ID");
240239
let ty = Decodable::decode(decoder);
241-
let segment = Decodable::decode(decoder);
242-
trace!("decoded typid: {ty:?} ({segment})");
243-
decoder.interner().reserve_and_set_type_id_alloc(ty, segment)
240+
trace!("decoded typid: {ty:?}");
241+
decoder.interner().reserve_and_set_type_id_alloc(ty)
244242
}
245243
AllocDiscriminant::Static => {
246244
trace!("creating extern static alloc ID");
@@ -272,9 +270,9 @@ pub enum GlobalAlloc<'tcx> {
272270
Static(DefId),
273271
/// The alloc ID points to memory.
274272
Memory(ConstAllocation<'tcx>),
275-
/// A pointer-sized segment of a type id. On 64 bit systems, the 128 bit type id
273+
/// The first pointer-sized segment of a type id. On 64 bit systems, the 128 bit type id
276274
/// is split into two segments, on 32 bit systems there are 4 segments, and so on.
277-
Type { ty: Ty<'tcx>, segment: u8 },
275+
Type { ty: Ty<'tcx> },
278276
}
279277

280278
impl<'tcx> GlobalAlloc<'tcx> {
@@ -508,8 +506,8 @@ impl<'tcx> TyCtxt<'tcx> {
508506
}
509507

510508
/// Generates an [AllocId] for a [core::mem::type_info::TypeId]. Will get deduplicated.
511-
pub fn reserve_and_set_type_id_alloc(self, ty: Ty<'tcx>, segment: u8) -> AllocId {
512-
self.reserve_and_set_dedup(GlobalAlloc::Type { ty, segment }, 0)
509+
pub fn reserve_and_set_type_id_alloc(self, ty: Ty<'tcx>) -> AllocId {
510+
self.reserve_and_set_dedup(GlobalAlloc::Type { ty }, 0)
513511
}
514512

515513
/// Interns the `Allocation` and return a new `AllocId`, even if there's already an identical

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,9 +1621,7 @@ pub fn write_allocations<'tcx>(
16211621
Some(GlobalAlloc::VTable(ty, dyn_ty)) => {
16221622
write!(w, " (vtable: impl {dyn_ty} for {ty})")?
16231623
}
1624-
Some(GlobalAlloc::Type { ty, segment }) => {
1625-
write!(w, " (typeid segment {segment} for {ty})")?
1626-
}
1624+
Some(GlobalAlloc::Type { ty }) => write!(w, " (typeid for {ty})")?,
16271625
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
16281626
write!(w, " (static: {}", tcx.def_path_str(did))?;
16291627
if body.phase <= MirPhase::Runtime(RuntimePhase::PostCleanup)

library/core/src/any.rs

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ impl dyn Any + Send + Sync {
709709
#[stable(feature = "rust1", since = "1.0.0")]
710710
#[lang = "type_id"]
711711
pub struct TypeId {
712-
data: [*const (); 16 / size_of::<usize>()],
712+
pub(crate) data: [*const (); 16 / size_of::<usize>()],
713713
}
714714

715715
// SAFETY: the raw pointer is always an integer
@@ -724,30 +724,7 @@ unsafe impl Sync for TypeId {}
724724
impl const PartialEq for TypeId {
725725
#[inline]
726726
fn eq(&self, other: &Self) -> bool {
727-
const fn ct(a: &TypeId, b: &TypeId) -> bool {
728-
crate::intrinsics::type_id_eq(*a, *b)
729-
}
730-
731-
#[inline]
732-
fn rt(a: &TypeId, b: &TypeId) -> bool {
733-
a.data == b.data
734-
}
735-
736-
core::intrinsics::const_eval_select((self, other), ct, rt)
737-
}
738-
739-
#[inline]
740-
fn ne(&self, other: &Self) -> bool {
741-
const fn ct(a: &TypeId, b: &TypeId) -> bool {
742-
!crate::intrinsics::type_id_eq(*a, *b)
743-
}
744-
745-
#[inline]
746-
fn rt(a: &TypeId, b: &TypeId) -> bool {
747-
a.data != b.data
748-
}
749-
750-
core::intrinsics::const_eval_select((self, other), ct, rt)
727+
crate::intrinsics::type_id_eq(*self, *other)
751728
}
752729
}
753730

library/core/src/intrinsics/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2728,8 +2728,12 @@ pub const fn type_id<T: ?Sized + 'static>() -> crate::any::TypeId;
27282728
#[rustc_nounwind]
27292729
#[unstable(feature = "core_intrinsics", issue = "none")]
27302730
#[rustc_intrinsic]
2731-
pub const fn type_id_eq(_a: crate::any::TypeId, _b: crate::any::TypeId) -> bool {
2732-
panic!("type_id_eq should only be used from const eval")
2731+
// The intrinsic is always overridden by CTFE and we don't want to limit the default body to
2732+
// const operations only, as that would require transmuting the raw pointers to usize because
2733+
// you can't do that cast in CTFE.
2734+
#[rustc_do_not_const_check]
2735+
pub const fn type_id_eq(a: crate::any::TypeId, b: crate::any::TypeId) -> bool {
2736+
a.data == b.data
27332737
}
27342738

27352739
/// Lowers in MIR to `Rvalue::Aggregate` with `AggregateKind::RawPtr`.

0 commit comments

Comments
 (0)