Skip to content

Commit 8747c0e

Browse files
authored
Rollup merge of rust-lang#109953 - thomcc:thomcc/typeid128, r=WaffleLapkin
Use 128 bits for TypeId hash Preliminary/Draft impl of rust-lang/compiler-team#608 Prior art (probably incomplete list) - rust-lang#75923 - rust-lang#95845
2 parents a0df04c + b512004 commit 8747c0e

File tree

6 files changed

+59
-8
lines changed

6 files changed

+59
-8
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
7777
}
7878
sym::type_id => {
7979
ensure_monomorphic_enough(tcx, tp_ty)?;
80-
ConstValue::from_u64(tcx.type_id_hash(tp_ty).as_u64())
80+
ConstValue::from_u128(tcx.type_id_hash(tp_ty).as_u128())
8181
}
8282
sym::variant_count => match tp_ty.kind() {
8383
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
@@ -169,7 +169,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
169169
let ty = match intrinsic_name {
170170
sym::pref_align_of | sym::variant_count => self.tcx.types.usize,
171171
sym::needs_drop => self.tcx.types.bool,
172-
sym::type_id => self.tcx.types.u64,
172+
sym::type_id => self.tcx.types.u128,
173173
sym::type_name => self.tcx.mk_static_str(),
174174
_ => bug!(),
175175
};

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
217217
sym::needs_drop => (1, Vec::new(), tcx.types.bool),
218218

219219
sym::type_name => (1, Vec::new(), tcx.mk_static_str()),
220-
sym::type_id => (1, Vec::new(), tcx.types.u64),
220+
sym::type_id => (1, Vec::new(), tcx.types.u128),
221221
sym::offset => (2, vec![param(0), param(1)], param(0)),
222222
sym::arith_offset => (
223223
1,

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

+9
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ impl<'tcx> ConstValue<'tcx> {
9797
ConstValue::Scalar(Scalar::from_u64(i))
9898
}
9999

100+
pub fn from_u128(i: u128) -> Self {
101+
ConstValue::Scalar(Scalar::from_u128(i))
102+
}
103+
100104
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
101105
ConstValue::Scalar(Scalar::from_target_usize(i, cx))
102106
}
@@ -240,6 +244,11 @@ impl<Prov> Scalar<Prov> {
240244
Scalar::Int(i.into())
241245
}
242246

247+
#[inline]
248+
pub fn from_u128(i: u128) -> Self {
249+
Scalar::Int(i.into())
250+
}
251+
243252
#[inline]
244253
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
245254
Self::from_uint(i, cx.data_layout().pointer_size)

compiler/rustc_middle/src/ty/util.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::ty::{
1111
use crate::ty::{GenericArgKind, SubstsRef};
1212
use rustc_apfloat::Float as _;
1313
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
14-
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
14+
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
1515
use rustc_errors::ErrorGuaranteed;
1616
use rustc_hir as hir;
1717
use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -129,7 +129,7 @@ impl IntTypeExt for IntegerType {
129129
impl<'tcx> TyCtxt<'tcx> {
130130
/// Creates a hash of the type `Ty` which will be the same no matter what crate
131131
/// context it's calculated within. This is used by the `type_id` intrinsic.
132-
pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash64 {
132+
pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash128 {
133133
// We want the type_id be independent of the types free regions, so we
134134
// erase them. The erase_regions() call will also anonymize bound
135135
// regions, which is desirable too.

library/core/src/any.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
#![stable(feature = "rust1", since = "1.0.0")]
154154

155155
use crate::fmt;
156+
use crate::hash;
156157
use crate::intrinsics;
157158

158159
///////////////////////////////////////////////////////////////////////////////
@@ -662,10 +663,10 @@ impl dyn Any + Send + Sync {
662663
/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
663664
/// noting that the hashes and ordering will vary between Rust releases. Beware
664665
/// of relying on them inside of your code!
665-
#[derive(Clone, Copy, Debug, Hash, Eq, PartialOrd, Ord)]
666+
#[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)]
666667
#[stable(feature = "rust1", since = "1.0.0")]
667668
pub struct TypeId {
668-
t: u64,
669+
t: u128,
669670
}
670671

671672
#[stable(feature = "rust1", since = "1.0.0")]
@@ -696,7 +697,31 @@ impl TypeId {
696697
#[stable(feature = "rust1", since = "1.0.0")]
697698
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
698699
pub const fn of<T: ?Sized + 'static>() -> TypeId {
699-
TypeId { t: intrinsics::type_id::<T>() }
700+
#[cfg(bootstrap)]
701+
let t = intrinsics::type_id::<T>() as u128;
702+
#[cfg(not(bootstrap))]
703+
let t: u128 = intrinsics::type_id::<T>();
704+
TypeId { t }
705+
}
706+
}
707+
708+
#[stable(feature = "rust1", since = "1.0.0")]
709+
impl hash::Hash for TypeId {
710+
#[inline]
711+
fn hash<H: hash::Hasher>(&self, state: &mut H) {
712+
// We only hash the lower 64 bits of our (128 bit) internal numeric ID,
713+
// because:
714+
// - The hashing algorithm which backs `TypeId` is expected to be
715+
// unbiased and high quality, meaning further mixing would be somewhat
716+
// redundant compared to choosing (the lower) 64 bits arbitrarily.
717+
// - `Hasher::finish` returns a u64 anyway, so the extra entropy we'd
718+
// get from hashing the full value would probably not be useful
719+
// (especially given the previous point about the lower 64 bits being
720+
// high quality on their own).
721+
// - It is correct to do so -- only hashing a subset of `self` is still
722+
// with an `Eq` implementation that considers the entire value, as
723+
// ours does.
724+
(self.t as u64).hash(state);
700725
}
701726
}
702727

library/core/src/intrinsics.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1057,8 +1057,25 @@ extern "rust-intrinsic" {
10571057
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
10581058
#[rustc_safe_intrinsic]
10591059
#[rustc_nounwind]
1060+
#[cfg(bootstrap)]
10601061
pub fn type_id<T: ?Sized + 'static>() -> u64;
10611062

1063+
/// Gets an identifier which is globally unique to the specified type. This
1064+
/// function will return the same value for a type regardless of whichever
1065+
/// crate it is invoked in.
1066+
///
1067+
/// Note that, unlike most intrinsics, this is safe to call;
1068+
/// it does not require an `unsafe` block.
1069+
/// Therefore, implementations must not require the user to uphold
1070+
/// any safety invariants.
1071+
///
1072+
/// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
1073+
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
1074+
#[rustc_safe_intrinsic]
1075+
#[rustc_nounwind]
1076+
#[cfg(not(bootstrap))]
1077+
pub fn type_id<T: ?Sized + 'static>() -> u128;
1078+
10621079
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
10631080
/// This will statically either panic, or do nothing.
10641081
///

0 commit comments

Comments
 (0)