rustc_symbol_mangling/
export.rs

1use std::assert_matches::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
24default_hash_impl! { i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, 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 String {
41    #[inline]
42    fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
43        self[..].abi_hash(tcx, hasher);
44    }
45}
46
47impl<'tcx> AbiHashStable<'tcx> for Symbol {
48    #[inline]
49    fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
50        self.as_str().abi_hash(tcx, hasher);
51    }
52}
53
54impl<'tcx, T: AbiHashStable<'tcx>> AbiHashStable<'tcx> for [T] {
55    fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
56        self.len().abi_hash(tcx, hasher);
57        for item in self {
58            item.abi_hash(tcx, hasher);
59        }
60    }
61}
62
63impl<'tcx> AbiHashStable<'tcx> for Ty<'tcx> {
64    fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
65        match self.kind() {
66            ty::Bool => sym::bool.abi_hash(tcx, hasher),
67            ty::Char => sym::char.abi_hash(tcx, hasher),
68            ty::Int(int_ty) => int_ty.name_str().abi_hash(tcx, hasher),
69            ty::Uint(uint_ty) => uint_ty.name_str().abi_hash(tcx, hasher),
70            ty::Float(float_ty) => float_ty.name_str().abi_hash(tcx, hasher),
71
72            ty::Adt(adt_def, args) => {
73                adt_def.is_struct().abi_hash(tcx, hasher);
74                adt_def.is_enum().abi_hash(tcx, hasher);
75                adt_def.is_union().abi_hash(tcx, hasher);
76
77                if let Some(align) = adt_def.repr().align {
78                    align.bits().abi_hash(tcx, hasher);
79                }
80
81                if let Some(integer) = adt_def.repr().int {
82                    match integer {
83                        IntegerType::Pointer(sign) => sign.abi_hash(tcx, hasher),
84                        IntegerType::Fixed(integer, sign) => {
85                            integer.int_ty_str().abi_hash(tcx, hasher);
86                            sign.abi_hash(tcx, hasher);
87                        }
88                    }
89                }
90
91                if let Some(pack) = adt_def.repr().pack {
92                    pack.bits().abi_hash(tcx, hasher);
93                }
94
95                adt_def.repr().c().abi_hash(tcx, hasher);
96
97                for variant in adt_def.variants() {
98                    variant.name.abi_hash(tcx, hasher);
99                    for field in &variant.fields {
100                        field.name.abi_hash(tcx, hasher);
101                        let field_ty = tcx.type_of(field.did).instantiate_identity();
102                        field_ty.abi_hash(tcx, hasher);
103                    }
104                }
105                args.abi_hash(tcx, hasher);
106            }
107
108            ty::Tuple(args) if args.len() == 0 => {}
109
110            // FIXME: Not yet supported.
111            ty::Foreign(_)
112            | ty::Ref(_, _, _)
113            | ty::Str
114            | ty::Array(_, _)
115            | ty::Pat(_, _)
116            | ty::Slice(_)
117            | ty::RawPtr(_, _)
118            | ty::FnDef(_, _)
119            | ty::FnPtr(_, _)
120            | ty::Dynamic(_, _, _)
121            | ty::Closure(_, _)
122            | ty::CoroutineClosure(_, _)
123            | ty::Coroutine(_, _)
124            | ty::CoroutineWitness(_, _)
125            | ty::Never
126            | ty::Tuple(_)
127            | ty::Alias(_, _)
128            | ty::Param(_)
129            | ty::Bound(_, _)
130            | ty::Placeholder(_)
131            | ty::Infer(_)
132            | ty::UnsafeBinder(_) => unreachable!(),
133
134            ty::Error(_) => {}
135        }
136    }
137}
138
139impl<'tcx> AbiHashStable<'tcx> for ty::FnSig<'tcx> {
140    fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
141        for ty in self.inputs_and_output {
142            ty.abi_hash(tcx, hasher);
143        }
144        self.safety.is_safe().abi_hash(tcx, hasher);
145    }
146}
147
148impl<'tcx> AbiHashStable<'tcx> for ty::GenericArg<'tcx> {
149    fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
150        self.unpack().abi_hash(tcx, hasher);
151    }
152}
153
154impl<'tcx> AbiHashStable<'tcx> for ty::GenericArgKind<'tcx> {
155    fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
156        match self {
157            ty::GenericArgKind::Type(t) => t.abi_hash(tcx, hasher),
158            ty::GenericArgKind::Lifetime(_) | ty::GenericArgKind::Const(_) => unimplemented!(),
159        }
160    }
161}
162
163pub(crate) fn compute_hash_of_export_fn<'tcx>(
164    tcx: TyCtxt<'tcx>,
165    instance: Instance<'tcx>,
166) -> String {
167    let def_id = instance.def_id();
168    debug_assert_matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn);
169
170    let args = instance.args;
171    let sig_ty = tcx.fn_sig(def_id).instantiate(tcx, args);
172    let sig_ty = tcx.instantiate_bound_regions_with_erased(sig_ty);
173
174    let hash = {
175        let mut hasher = StableHasher::new();
176        sig_ty.abi_hash(tcx, &mut hasher);
177        hasher.finish::<Hash128>()
178    };
179
180    hash.as_u128().to_string()
181}