Skip to content

Commit 7655372

Browse files
committed
Unify the miri and ctfe type id equality checks
1 parent 30c02f1 commit 7655372

File tree

9 files changed

+121
-41
lines changed

9 files changed

+121
-41
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::borrow::{Borrow, Cow};
22
use std::fmt;
33
use std::hash::Hash;
44

5-
use rustc_abi::{Align, FieldIdx, Size};
5+
use rustc_abi::{Align, Size};
66
use rustc_ast::Mutability;
77
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
88
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -403,22 +403,6 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
403403
let cmp = ecx.guaranteed_cmp(a, b)?;
404404
ecx.write_scalar(Scalar::from_u8(cmp), dest)?;
405405
}
406-
sym::type_id_eq => {
407-
let a = ecx.project_field(&args[0], FieldIdx::ZERO)?;
408-
let b = ecx.project_field(&args[1], FieldIdx::ZERO)?;
409-
410-
let a = ecx.project_index(&a, 0)?;
411-
let a = ecx.deref_pointer(&a)?;
412-
let (a, offset_a, _) = ecx.ptr_get_alloc_id(a.ptr(), 0)?;
413-
let GlobalAlloc::Type { ty: a } = ecx.tcx.global_alloc(a) else { bug!() };
414-
415-
let b = ecx.project_index(&b, 0)?;
416-
let b = ecx.deref_pointer(&b)?;
417-
let (b, offset_b, _) = ecx.ptr_get_alloc_id(b.ptr(), 0)?;
418-
let GlobalAlloc::Type { ty: b } = ecx.tcx.global_alloc(b) else { bug!() };
419-
420-
ecx.write_scalar(Scalar::from_bool(a == b && offset_a == offset_b), dest)?;
421-
}
422406
sym::const_allocate => {
423407
let size = ecx.read_scalar(&args[0])?.to_target_usize(ecx)?;
424408
let align = ecx.read_scalar(&args[1])?.to_target_usize(ecx)?;

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::assert_matches::assert_matches;
66

77
use rustc_abi::{FieldIdx, Size};
88
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
9+
use rustc_middle::mir::interpret::GlobalAlloc;
910
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
1011
use rustc_middle::ty::layout::TyAndLayout;
1112
use rustc_middle::ty::{Ty, TyCtxt};
@@ -92,6 +93,47 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
9293
ensure_monomorphic_enough(tcx, tp_ty)?;
9394
self.write_type_id(tp_ty, dest)?;
9495
}
96+
sym::type_id_eq => {
97+
let a_fields = self.project_field(&args[0], FieldIdx::ZERO)?;
98+
let b_fields = self.project_field(&args[1], FieldIdx::ZERO)?;
99+
100+
let mut a_fields = self.project_array_fields(&a_fields)?;
101+
102+
let mut b_fields = self.project_array_fields(&b_fields)?;
103+
104+
let (_idx, a) = a_fields
105+
.next(self)?
106+
.expect("we know the layout of TypeId has at least 2 array elements");
107+
let a = self.deref_pointer(&a)?;
108+
let (a, offset_a, _) = self.ptr_get_alloc_id(a.ptr(), 0)?;
109+
let GlobalAlloc::Type { ty: a } = self.tcx.global_alloc(a) else { bug!() };
110+
111+
let (_idx, b) = b_fields
112+
.next(self)?
113+
.expect("we know the layout of TypeId has at least 2 array elements");
114+
let b = self.deref_pointer(&b)?;
115+
let (b, offset_b, _) = self.ptr_get_alloc_id(b.ptr(), 0)?;
116+
let GlobalAlloc::Type { ty: b } = self.tcx.global_alloc(b) else { bug!() };
117+
118+
let provenance_matches = a == b;
119+
120+
if offset_a != offset_b && provenance_matches {
121+
throw_ub_format!("modifying `TypeId` internals is not permitted")
122+
}
123+
124+
while let Some((_, a)) = a_fields.next(self)? {
125+
let (_, b) = b_fields.next(self)?.unwrap();
126+
127+
let a = self.read_target_usize(&a)?;
128+
let b = self.read_target_usize(&b)?;
129+
130+
if a != b && provenance_matches {
131+
throw_ub_format!("modifying `TypeId` internals is not permitted")
132+
}
133+
}
134+
135+
self.write_scalar(Scalar::from_bool(provenance_matches), dest)?;
136+
}
95137
sym::variant_count => {
96138
let tp_ty = instance.args.type_at(0);
97139
let ty = match tp_ty.kind() {

compiler/rustc_const_eval/src/interpret/projection.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,11 @@ where
296296
base: &'a P,
297297
) -> InterpResult<'tcx, ArrayIterator<'a, 'tcx, M::Provenance, P>> {
298298
let abi::FieldsShape::Array { stride, .. } = base.layout().fields else {
299-
span_bug!(self.cur_span(), "project_array_fields: expected an array layout");
299+
span_bug!(
300+
self.cur_span(),
301+
"project_array_fields: expected an array layout, got {:#?}",
302+
base.layout()
303+
);
300304
};
301305
let len = base.len(self)?;
302306
let field_layout = base.layout().field(self, 0);

src/tools/miri/src/intrinsics/mod.rs

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod simd;
66
use std::ops::Neg;
77

88
use rand::Rng;
9-
use rustc_abi::{FieldIdx, Size};
9+
use rustc_abi::Size;
1010
use rustc_apfloat::ieee::{IeeeFloat, Semantics};
1111
use rustc_apfloat::{self, Float, Round};
1212
use rustc_middle::mir;
@@ -461,28 +461,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
461461
// Make these a NOP, so we get the better Miri-native error messages.
462462
}
463463

464-
"type_id_eq" => {
465-
let [a, b] = check_intrinsic_arg_count(args)?;
466-
467-
let a = this.project_field(a, FieldIdx::ZERO)?;
468-
let mut a = this.project_array_fields(&a)?;
469-
let b = this.project_field(b, FieldIdx::ZERO)?;
470-
let mut b = this.project_array_fields(&b)?;
471-
472-
while let Some((_, a)) = a.next(this)? {
473-
let (_, b) = b.next(this)?.unwrap();
474-
475-
let a = this.read_pointer(&a)?;
476-
let b = this.read_pointer(&b)?;
477-
478-
if a != b {
479-
this.write_int(0, dest)?;
480-
return interp_ok(EmulateItemResult::NeedsReturn);
481-
}
482-
}
483-
this.write_int(1, dest)?;
484-
}
485-
486464
_ => return interp_ok(EmulateItemResult::NotSupported),
487465
}
488466

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0080]: pointer not dereferenceable: pointer must point to some allocation, but got 0xffffffff[noalloc] which is a dangling pointer (it has no provenance)
2+
--> $DIR/const_transmute_type_id2.rs:10:13
3+
|
4+
LL | assert!(a == b);
5+
| ^^^^^^ evaluation of `_` failed inside this call
6+
|
7+
note: inside `<TypeId as PartialEq>::eq`
8+
--> $SRC_DIR/core/src/any.rs:LL:COL
9+
note: inside `<TypeId as PartialEq>::eq::ct`
10+
--> $SRC_DIR/core/src/any.rs:LL:COL
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0080`.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0080]: pointer not dereferenceable: pointer must point to some allocation, but got 0xffffffffffffffff[noalloc] which is a dangling pointer (it has no provenance)
2+
--> $DIR/const_transmute_type_id2.rs:10:13
3+
|
4+
LL | assert!(a == b);
5+
| ^^^^^^ evaluation of `_` failed inside this call
6+
|
7+
note: inside `<TypeId as PartialEq>::eq`
8+
--> $SRC_DIR/core/src/any.rs:LL:COL
9+
note: inside `<TypeId as PartialEq>::eq::ct`
10+
--> $SRC_DIR/core/src/any.rs:LL:COL
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0080`.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ stderr-per-bitwidth
2+
3+
#![feature(const_type_id, const_trait_impl)]
4+
5+
use std::any::TypeId;
6+
7+
const _: () = {
8+
let a: TypeId = unsafe { std::mem::transmute(u128::MAX) };
9+
let b: TypeId = unsafe { std::mem::transmute(u128::MAX) };
10+
assert!(a == b);
11+
//~^ ERROR: pointer must point to some allocation
12+
};
13+
14+
fn main() {}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![feature(const_type_id, const_trait_impl)]
2+
3+
use std::any::TypeId;
4+
5+
const _: () = {
6+
let a = TypeId::of::<()>();
7+
let mut b = TypeId::of::<()>();
8+
unsafe {
9+
let ptr = &mut b as *mut TypeId as *mut usize;
10+
std::ptr::write(ptr.offset(1), 999);
11+
}
12+
assert!(a == b);
13+
//~^ ERROR: modifying `TypeId` internals is not permitted
14+
};
15+
16+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0080]: modifying `TypeId` internals is not permitted
2+
--> $DIR/const_transmute_type_id3.rs:12:13
3+
|
4+
LL | assert!(a == b);
5+
| ^^^^^^ evaluation of `_` failed inside this call
6+
|
7+
note: inside `<TypeId as PartialEq>::eq`
8+
--> $SRC_DIR/core/src/any.rs:LL:COL
9+
note: inside `<TypeId as PartialEq>::eq::ct`
10+
--> $SRC_DIR/core/src/any.rs:LL:COL
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)