Rollup merge of #109953 - thomcc:thomcc/typeid128, r=WaffleLapkin
Use 128 bits for TypeId hash Preliminary/Draft impl of https://github.com/rust-lang/compiler-team/issues/608 Prior art (probably incomplete list) - https://github.com/rust-lang/rust/pull/75923 - https://github.com/rust-lang/rust/pull/95845
This commit is contained in:
commit
8747c0ebea
@ -77,7 +77,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
|
|||||||
}
|
}
|
||||||
sym::type_id => {
|
sym::type_id => {
|
||||||
ensure_monomorphic_enough(tcx, tp_ty)?;
|
ensure_monomorphic_enough(tcx, tp_ty)?;
|
||||||
ConstValue::from_u64(tcx.type_id_hash(tp_ty).as_u64())
|
ConstValue::from_u128(tcx.type_id_hash(tp_ty).as_u128())
|
||||||
}
|
}
|
||||||
sym::variant_count => match tp_ty.kind() {
|
sym::variant_count => match tp_ty.kind() {
|
||||||
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
|
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
|
||||||
@ -169,7 +169,7 @@ pub fn emulate_intrinsic(
|
|||||||
let ty = match intrinsic_name {
|
let ty = match intrinsic_name {
|
||||||
sym::pref_align_of | sym::variant_count => self.tcx.types.usize,
|
sym::pref_align_of | sym::variant_count => self.tcx.types.usize,
|
||||||
sym::needs_drop => self.tcx.types.bool,
|
sym::needs_drop => self.tcx.types.bool,
|
||||||
sym::type_id => self.tcx.types.u64,
|
sym::type_id => self.tcx.types.u128,
|
||||||
sym::type_name => self.tcx.mk_static_str(),
|
sym::type_name => self.tcx.mk_static_str(),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
|
@ -217,7 +217,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
|||||||
sym::needs_drop => (1, Vec::new(), tcx.types.bool),
|
sym::needs_drop => (1, Vec::new(), tcx.types.bool),
|
||||||
|
|
||||||
sym::type_name => (1, Vec::new(), tcx.mk_static_str()),
|
sym::type_name => (1, Vec::new(), tcx.mk_static_str()),
|
||||||
sym::type_id => (1, Vec::new(), tcx.types.u64),
|
sym::type_id => (1, Vec::new(), tcx.types.u128),
|
||||||
sym::offset => (2, vec![param(0), param(1)], param(0)),
|
sym::offset => (2, vec![param(0), param(1)], param(0)),
|
||||||
sym::arith_offset => (
|
sym::arith_offset => (
|
||||||
1,
|
1,
|
||||||
|
@ -97,6 +97,10 @@ pub fn from_u64(i: u64) -> Self {
|
|||||||
ConstValue::Scalar(Scalar::from_u64(i))
|
ConstValue::Scalar(Scalar::from_u64(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_u128(i: u128) -> Self {
|
||||||
|
ConstValue::Scalar(Scalar::from_u128(i))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
|
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
|
||||||
ConstValue::Scalar(Scalar::from_target_usize(i, cx))
|
ConstValue::Scalar(Scalar::from_target_usize(i, cx))
|
||||||
}
|
}
|
||||||
@ -240,6 +244,11 @@ pub fn from_u64(i: u64) -> Self {
|
|||||||
Scalar::Int(i.into())
|
Scalar::Int(i.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_u128(i: u128) -> Self {
|
||||||
|
Scalar::Int(i.into())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
|
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
|
||||||
Self::from_uint(i, cx.data_layout().pointer_size)
|
Self::from_uint(i, cx.data_layout().pointer_size)
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use crate::ty::{GenericArgKind, SubstsRef};
|
use crate::ty::{GenericArgKind, SubstsRef};
|
||||||
use rustc_apfloat::Float as _;
|
use rustc_apfloat::Float as _;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||||
@ -129,7 +129,7 @@ fn disr_incr<'tcx>(&self, tcx: TyCtxt<'tcx>, val: Option<Discr<'tcx>>) -> Option
|
|||||||
impl<'tcx> TyCtxt<'tcx> {
|
impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Creates a hash of the type `Ty` which will be the same no matter what crate
|
/// Creates a hash of the type `Ty` which will be the same no matter what crate
|
||||||
/// context it's calculated within. This is used by the `type_id` intrinsic.
|
/// context it's calculated within. This is used by the `type_id` intrinsic.
|
||||||
pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash64 {
|
pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash128 {
|
||||||
// We want the type_id be independent of the types free regions, so we
|
// We want the type_id be independent of the types free regions, so we
|
||||||
// erase them. The erase_regions() call will also anonymize bound
|
// erase them. The erase_regions() call will also anonymize bound
|
||||||
// regions, which is desirable too.
|
// regions, which is desirable too.
|
||||||
|
@ -153,6 +153,7 @@
|
|||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
|
use crate::hash;
|
||||||
use crate::intrinsics;
|
use crate::intrinsics;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -662,10 +663,10 @@ pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
|
|||||||
/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
|
/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
|
||||||
/// noting that the hashes and ordering will vary between Rust releases. Beware
|
/// noting that the hashes and ordering will vary between Rust releases. Beware
|
||||||
/// of relying on them inside of your code!
|
/// of relying on them inside of your code!
|
||||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct TypeId {
|
pub struct TypeId {
|
||||||
t: u64,
|
t: u128,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -696,7 +697,31 @@ impl TypeId {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
|
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
|
||||||
pub const fn of<T: ?Sized + 'static>() -> TypeId {
|
pub const fn of<T: ?Sized + 'static>() -> TypeId {
|
||||||
TypeId { t: intrinsics::type_id::<T>() }
|
#[cfg(bootstrap)]
|
||||||
|
let t = intrinsics::type_id::<T>() as u128;
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
let t: u128 = intrinsics::type_id::<T>();
|
||||||
|
TypeId { t }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl hash::Hash for TypeId {
|
||||||
|
#[inline]
|
||||||
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
|
// We only hash the lower 64 bits of our (128 bit) internal numeric ID,
|
||||||
|
// because:
|
||||||
|
// - The hashing algorithm which backs `TypeId` is expected to be
|
||||||
|
// unbiased and high quality, meaning further mixing would be somewhat
|
||||||
|
// redundant compared to choosing (the lower) 64 bits arbitrarily.
|
||||||
|
// - `Hasher::finish` returns a u64 anyway, so the extra entropy we'd
|
||||||
|
// get from hashing the full value would probably not be useful
|
||||||
|
// (especially given the previous point about the lower 64 bits being
|
||||||
|
// high quality on their own).
|
||||||
|
// - It is correct to do so -- only hashing a subset of `self` is still
|
||||||
|
// with an `Eq` implementation that considers the entire value, as
|
||||||
|
// ours does.
|
||||||
|
(self.t as u64).hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1057,8 +1057,25 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
|||||||
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
|
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
|
#[cfg(bootstrap)]
|
||||||
pub fn type_id<T: ?Sized + 'static>() -> u64;
|
pub fn type_id<T: ?Sized + 'static>() -> u64;
|
||||||
|
|
||||||
|
/// Gets an identifier which is globally unique to the specified type. This
|
||||||
|
/// function will return the same value for a type regardless of whichever
|
||||||
|
/// crate it is invoked in.
|
||||||
|
///
|
||||||
|
/// Note that, unlike most intrinsics, this is safe to call;
|
||||||
|
/// it does not require an `unsafe` block.
|
||||||
|
/// Therefore, implementations must not require the user to uphold
|
||||||
|
/// any safety invariants.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
|
||||||
|
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
|
||||||
|
#[rustc_safe_intrinsic]
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub fn type_id<T: ?Sized + 'static>() -> u128;
|
||||||
|
|
||||||
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
|
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
|
||||||
/// This will statically either panic, or do nothing.
|
/// This will statically either panic, or do nothing.
|
||||||
///
|
///
|
||||||
|
Loading…
Reference in New Issue
Block a user