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