mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
175 lines
5.5 KiB
Rust
175 lines
5.5 KiB
Rust
use std::debug_assert_matches;
|
|
|
|
use rustc_abi::IntegerType;
|
|
use rustc_data_structures::stable_hasher::StableHasher;
|
|
use rustc_hashes::Hash128;
|
|
use rustc_hir::def::DefKind;
|
|
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
|
use rustc_span::symbol::{Symbol, sym};
|
|
|
|
trait AbiHashStable<'tcx> {
|
|
fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher);
|
|
}
|
|
macro_rules! default_hash_impl {
|
|
($($t:ty,)+) => {
|
|
$(impl<'tcx> AbiHashStable<'tcx> for $t {
|
|
#[inline]
|
|
fn abi_hash(&self, _tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
|
|
::std::hash::Hash::hash(self, hasher);
|
|
}
|
|
})*
|
|
};
|
|
}
|
|
|
|
default_hash_impl! { u8, u64, usize, }
|
|
|
|
impl<'tcx> AbiHashStable<'tcx> for bool {
|
|
#[inline]
|
|
fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
|
|
(if *self { 1u8 } else { 0u8 }).abi_hash(tcx, hasher);
|
|
}
|
|
}
|
|
|
|
impl<'tcx> AbiHashStable<'tcx> for str {
|
|
#[inline]
|
|
fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
|
|
self.as_bytes().abi_hash(tcx, hasher);
|
|
}
|
|
}
|
|
|
|
impl<'tcx> AbiHashStable<'tcx> for Symbol {
|
|
#[inline]
|
|
fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
|
|
self.as_str().abi_hash(tcx, hasher);
|
|
}
|
|
}
|
|
|
|
impl<'tcx, T: AbiHashStable<'tcx>> AbiHashStable<'tcx> for [T] {
|
|
fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
|
|
self.len().abi_hash(tcx, hasher);
|
|
for item in self {
|
|
item.abi_hash(tcx, hasher);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'tcx> AbiHashStable<'tcx> for Ty<'tcx> {
|
|
fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
|
|
match self.kind() {
|
|
ty::Bool => sym::bool.abi_hash(tcx, hasher),
|
|
ty::Char => sym::char.abi_hash(tcx, hasher),
|
|
ty::Int(int_ty) => int_ty.name_str().abi_hash(tcx, hasher),
|
|
ty::Uint(uint_ty) => uint_ty.name_str().abi_hash(tcx, hasher),
|
|
ty::Float(float_ty) => float_ty.name_str().abi_hash(tcx, hasher),
|
|
|
|
ty::Adt(adt_def, args) => {
|
|
adt_def.is_struct().abi_hash(tcx, hasher);
|
|
adt_def.is_enum().abi_hash(tcx, hasher);
|
|
adt_def.is_union().abi_hash(tcx, hasher);
|
|
|
|
if let Some(align) = adt_def.repr().align {
|
|
align.bits().abi_hash(tcx, hasher);
|
|
}
|
|
|
|
if let Some(integer) = adt_def.repr().int {
|
|
match integer {
|
|
IntegerType::Pointer(sign) => sign.abi_hash(tcx, hasher),
|
|
IntegerType::Fixed(integer, sign) => {
|
|
integer.int_ty_str().abi_hash(tcx, hasher);
|
|
sign.abi_hash(tcx, hasher);
|
|
}
|
|
}
|
|
}
|
|
|
|
if let Some(pack) = adt_def.repr().pack {
|
|
pack.bits().abi_hash(tcx, hasher);
|
|
}
|
|
|
|
adt_def.repr().c().abi_hash(tcx, hasher);
|
|
|
|
for variant in adt_def.variants() {
|
|
variant.name.abi_hash(tcx, hasher);
|
|
for field in &variant.fields {
|
|
field.name.abi_hash(tcx, hasher);
|
|
let field_ty = tcx.type_of(field.did).instantiate_identity();
|
|
field_ty.abi_hash(tcx, hasher);
|
|
}
|
|
}
|
|
args.abi_hash(tcx, hasher);
|
|
}
|
|
|
|
ty::Tuple(args) if args.len() == 0 => {}
|
|
|
|
// FIXME: Not yet supported.
|
|
ty::Foreign(_)
|
|
| ty::Ref(_, _, _)
|
|
| ty::Str
|
|
| ty::Array(_, _)
|
|
| ty::Pat(_, _)
|
|
| ty::Slice(_)
|
|
| ty::RawPtr(_, _)
|
|
| ty::FnDef(_, _)
|
|
| ty::FnPtr(_, _)
|
|
| ty::Dynamic(_, _)
|
|
| ty::Closure(_, _)
|
|
| ty::CoroutineClosure(_, _)
|
|
| ty::Coroutine(_, _)
|
|
| ty::CoroutineWitness(_, _)
|
|
| ty::Never
|
|
| ty::Tuple(_)
|
|
| ty::Alias(_)
|
|
| ty::Param(_)
|
|
| ty::Bound(_, _)
|
|
| ty::Placeholder(_)
|
|
| ty::Infer(_)
|
|
| ty::UnsafeBinder(_) => unreachable!(),
|
|
|
|
ty::Error(_) => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'tcx> AbiHashStable<'tcx> for ty::FnSig<'tcx> {
|
|
fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
|
|
for ty in self.inputs_and_output {
|
|
ty.abi_hash(tcx, hasher);
|
|
}
|
|
self.safety().is_safe().abi_hash(tcx, hasher);
|
|
}
|
|
}
|
|
|
|
impl<'tcx> AbiHashStable<'tcx> for ty::GenericArg<'tcx> {
|
|
fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
|
|
self.kind().abi_hash(tcx, hasher);
|
|
}
|
|
}
|
|
|
|
impl<'tcx> AbiHashStable<'tcx> for ty::GenericArgKind<'tcx> {
|
|
fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
|
|
match self {
|
|
ty::GenericArgKind::Type(t) => t.abi_hash(tcx, hasher),
|
|
ty::GenericArgKind::Lifetime(_) | ty::GenericArgKind::Const(_) => unimplemented!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn compute_hash_of_export_fn<'tcx>(
|
|
tcx: TyCtxt<'tcx>,
|
|
instance: Instance<'tcx>,
|
|
) -> String {
|
|
let def_id = instance.def_id();
|
|
debug_assert_matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn);
|
|
|
|
let args = instance.args;
|
|
let sig_ty = tcx.fn_sig(def_id).instantiate(tcx, args);
|
|
let sig_ty = tcx.instantiate_bound_regions_with_erased(sig_ty);
|
|
|
|
let hash = {
|
|
let mut hasher = StableHasher::new();
|
|
sig_ty.abi_hash(tcx, &mut hasher);
|
|
hasher.finish::<Hash128>()
|
|
};
|
|
|
|
hash.as_u128().to_string()
|
|
}
|