1use std::debug_assert_matches;
2
3use rustc_abi::IntegerType;
4use rustc_data_structures::stable_hasher::StableHasher;
5use rustc_hashes::Hash128;
6use rustc_hir::def::DefKind;
7use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
8use rustc_span::symbol::{Symbol, sym};
9
10trait AbiHashStable<'tcx> {
11 fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher);
12}
13macro_rules! default_hash_impl {
14 ($($t:ty,)+) => {
15 $(impl<'tcx> AbiHashStable<'tcx> for $t {
16 #[inline]
17 fn abi_hash(&self, _tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
18 ::std::hash::Hash::hash(self, hasher);
19 }
20 })*
21 };
22}
23
24impl<'tcx> AbiHashStable<'tcx> for usize {
#[inline]
fn abi_hash(&self, _tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
::std::hash::Hash::hash(self, hasher);
}
}default_hash_impl! { u8, u64, usize, }
25
26impl<'tcx> AbiHashStable<'tcx> for bool {
27 #[inline]
28 fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
29 (if *self { 1u8 } else { 0u8 }).abi_hash(tcx, hasher);
30 }
31}
32
33impl<'tcx> AbiHashStable<'tcx> for str {
34 #[inline]
35 fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
36 self.as_bytes().abi_hash(tcx, hasher);
37 }
38}
39
40impl<'tcx> AbiHashStable<'tcx> for Symbol {
41 #[inline]
42 fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
43 self.as_str().abi_hash(tcx, hasher);
44 }
45}
46
47impl<'tcx, T: AbiHashStable<'tcx>> AbiHashStable<'tcx> for [T] {
48 fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
49 self.len().abi_hash(tcx, hasher);
50 for item in self {
51 item.abi_hash(tcx, hasher);
52 }
53 }
54}
55
56impl<'tcx> AbiHashStable<'tcx> for Ty<'tcx> {
57 fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
58 match self.kind() {
59 ty::Bool => sym::bool.abi_hash(tcx, hasher),
60 ty::Char => sym::char.abi_hash(tcx, hasher),
61 ty::Int(int_ty) => int_ty.name_str().abi_hash(tcx, hasher),
62 ty::Uint(uint_ty) => uint_ty.name_str().abi_hash(tcx, hasher),
63 ty::Float(float_ty) => float_ty.name_str().abi_hash(tcx, hasher),
64
65 ty::Adt(adt_def, args) => {
66 adt_def.is_struct().abi_hash(tcx, hasher);
67 adt_def.is_enum().abi_hash(tcx, hasher);
68 adt_def.is_union().abi_hash(tcx, hasher);
69
70 if let Some(align) = adt_def.repr().align {
71 align.bits().abi_hash(tcx, hasher);
72 }
73
74 if let Some(integer) = adt_def.repr().int {
75 match integer {
76 IntegerType::Pointer(sign) => sign.abi_hash(tcx, hasher),
77 IntegerType::Fixed(integer, sign) => {
78 integer.int_ty_str().abi_hash(tcx, hasher);
79 sign.abi_hash(tcx, hasher);
80 }
81 }
82 }
83
84 if let Some(pack) = adt_def.repr().pack {
85 pack.bits().abi_hash(tcx, hasher);
86 }
87
88 adt_def.repr().c().abi_hash(tcx, hasher);
89
90 for variant in adt_def.variants() {
91 variant.name.abi_hash(tcx, hasher);
92 for field in &variant.fields {
93 field.name.abi_hash(tcx, hasher);
94 let field_ty =
95 tcx.type_of(field.did).instantiate_identity().skip_norm_wip();
96 field_ty.abi_hash(tcx, hasher);
97 }
98 }
99 args.abi_hash(tcx, hasher);
100 }
101
102 ty::Tuple(args) if args.len() == 0 => {}
103
104 ty::Foreign(_)
106 | ty::Ref(_, _, _)
107 | ty::Str
108 | ty::Array(_, _)
109 | ty::Pat(_, _)
110 | ty::Slice(_)
111 | ty::RawPtr(_, _)
112 | ty::FnDef(_, _)
113 | ty::FnPtr(_, _)
114 | ty::Dynamic(_, _)
115 | ty::Closure(_, _)
116 | ty::CoroutineClosure(_, _)
117 | ty::Coroutine(_, _)
118 | ty::CoroutineWitness(_, _)
119 | ty::Never
120 | ty::Tuple(_)
121 | ty::Alias(_)
122 | ty::Param(_)
123 | ty::Bound(_, _)
124 | ty::Placeholder(_)
125 | ty::Infer(_)
126 | ty::UnsafeBinder(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
127
128 ty::Error(_) => {}
129 }
130 }
131}
132
133impl<'tcx> AbiHashStable<'tcx> for ty::FnSig<'tcx> {
134 fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
135 for ty in self.inputs_and_output {
136 ty.abi_hash(tcx, hasher);
137 }
138 self.safety().is_safe().abi_hash(tcx, hasher);
139 }
140}
141
142impl<'tcx> AbiHashStable<'tcx> for ty::GenericArg<'tcx> {
143 fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
144 self.kind().abi_hash(tcx, hasher);
145 }
146}
147
148impl<'tcx> AbiHashStable<'tcx> for ty::GenericArgKind<'tcx> {
149 fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
150 match self {
151 ty::GenericArgKind::Type(t) => t.abi_hash(tcx, hasher),
152 ty::GenericArgKind::Lifetime(_) | ty::GenericArgKind::Const(_) => ::core::panicking::panic("not implemented")unimplemented!(),
153 }
154 }
155}
156
157pub(crate) fn compute_hash_of_export_fn<'tcx>(
158 tcx: TyCtxt<'tcx>,
159 instance: Instance<'tcx>,
160) -> String {
161 let def_id = instance.def_id();
162 if true {
{
match tcx.def_kind(def_id) {
DefKind::Fn | DefKind::AssocFn => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"DefKind::Fn | DefKind::AssocFn",
::core::option::Option::None);
}
}
};
};debug_assert_matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn);
163
164 let args = instance.args;
165 let sig_ty = tcx.fn_sig(def_id).instantiate(tcx, args).skip_norm_wip();
166 let sig_ty = tcx.instantiate_bound_regions_with_erased(sig_ty);
167
168 let hash = {
169 let mut hasher = StableHasher::new();
170 sig_ty.abi_hash(tcx, &mut hasher);
171 hasher.finish::<Hash128>()
172 };
173
174 hash.as_u128().to_string()
175}