1use std::fmt::Write;
2use std::hash::Hasher;
3use std::iter;
4use std::ops::Range;
5
6use rustc_abi::{ExternAbi, Integer};
7use rustc_data_structures::base_n::ToBaseN;
8use rustc_data_structures::either::Either;
9use rustc_data_structures::fx::FxHashMap;
10use rustc_data_structures::intern::Interned;
11use rustc_data_structures::stable_hash::StableHasher;
12use rustc_hashes::Hash64;
13use rustc_hir as hir;
14use rustc_hir::def::CtorKind;
15use rustc_hir::def_id::{CrateNum, DefId};
16use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
17use rustc_middle::ty::layout::IntegerExt;
18use rustc_middle::ty::print::{Print, PrintError, Printer};
19use rustc_middle::ty::{
20 self, FloatTy, GenericArg, GenericArgKind, Instance, IntTy, ReifyReason, Ty, TyCtxt,
21 TypeVisitable, TypeVisitableExt, UintTy, Unnormalized,
22};
23use rustc_span::{bug, sym};
24
25pub(super) fn mangle<'tcx>(
26 tcx: TyCtxt<'tcx>,
27 instance: Instance<'tcx>,
28 instantiating_crate: Option<CrateNum>,
29 is_exportable: bool,
30) -> String {
31 let def_id = instance.def_id();
32 let args = tcx.normalize_erasing_regions(
34 ty::TypingEnv::fully_monomorphized(),
35 Unnormalized::new_wip(instance.args),
36 );
37
38 let prefix = "_R";
39 let mut p: V0SymbolMangler<'_> = V0SymbolMangler {
40 tcx,
41 start_offset: prefix.len(),
42 is_exportable,
43 paths: FxHashMap::default(),
44 types: FxHashMap::default(),
45 consts: FxHashMap::default(),
46 binders: ::alloc::vec::Vec::new()vec![],
47 out: String::from(prefix),
48 };
49
50 let shim_kind = match instance.def {
52 ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(_)) => Some("tls"),
53 ty::InstanceKind::Shim(ty::ShimKind::VTable(_)) => Some("vtable"),
54 ty::InstanceKind::Shim(ty::ShimKind::Reify(_, None)) => Some("reify"),
55 ty::InstanceKind::Shim(ty::ShimKind::Reify(_, Some(ReifyReason::FnPtr))) => {
56 Some("reify_fnptr")
57 }
58 ty::InstanceKind::Shim(ty::ShimKind::Reify(_, Some(ReifyReason::Vtable))) => {
59 Some("reify_vtable")
60 }
61
62 ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure {
65 receiver_by_ref: true,
66 ..
67 }) => Some("by_move"),
68 ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure {
69 receiver_by_ref: false,
70 ..
71 }) => Some("by_ref"),
72 ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(_, _, _)) => Some("drop"),
73 _ => None,
74 };
75
76 if let ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(_, ty)) = instance.def {
77 let ty::Coroutine(_, cor_args) = ty.kind() else {
78 ::rustc_span::macros::bug_impl(None, format_args!("impossible case reached"),
Location::caller());bug!();
79 };
80 let drop_ty = cor_args.first().unwrap().expect_ty();
81 p.print_def_path(def_id, p.tcx().mk_args(&[GenericArg::from(drop_ty)])).unwrap()
82 } else if let Some(shim_kind) = shim_kind {
83 p.path_append_ns(|p| p.print_def_path(def_id, args), 'S', 0, shim_kind).unwrap()
84 } else {
85 p.print_def_path(def_id, args).unwrap()
86 };
87 if let Some(instantiating_crate) = instantiating_crate {
88 p.print_def_path(instantiating_crate.as_def_id(), ty::GenericArgs::empty()).unwrap();
89 }
90 std::mem::take(&mut p.out)
91}
92
93pub fn mangle_cgu<'tcx>(tcx: TyCtxt<'tcx>, krate: CrateNum, cgu_name: Either<u64, &str>) -> String {
94 let prefix = "_R";
95 let mut p: V0SymbolMangler<'_> = V0SymbolMangler {
96 tcx,
97 start_offset: prefix.len(),
98 is_exportable: false,
99 paths: FxHashMap::default(),
100 types: FxHashMap::default(),
101 consts: FxHashMap::default(),
102 binders: ::alloc::vec::Vec::new()vec![],
103 out: String::from(prefix),
104 };
105
106 match cgu_name {
107 Either::Left(cgu_index) => {
108 p.path_append_ns(
110 |p| p.print_def_path(krate.as_def_id(), ty::GenericArgs::empty()),
111 'S',
112 cgu_index,
113 "cgu",
114 )
115 .unwrap();
116 }
117 Either::Right(name) => {
118 p.out.push('I');
120 p.path_append_ns(
121 |p| p.print_def_path(krate.as_def_id(), ty::GenericArgs::empty()),
122 'S',
123 0,
124 "cgu",
125 )
126 .unwrap();
127 p.push("KRe");
128
129 for byte in name.as_bytes() {
130 let _ = p.out.write_fmt(format_args!("{0:02x}", byte))write!(p.out, "{byte:02x}");
131 }
132
133 p.push("_E");
134 }
135 }
136
137 std::mem::take(&mut p.out)
138}
139
140pub fn eh_personality_symbol<'tcx>(tcx: TyCtxt<'tcx>) -> String {
141 mangle_internal_symbol(tcx, "rust_eh_personality")
142}
143
144pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> String {
145 match item_name {
146 "rust_eh_personality" => return item_name.to_owned(),
153 "__isPlatformVersionAtLeast" | "__isOSVersionAtLeast" => return item_name.to_owned(),
156 _ => {}
157 }
158
159 let prefix = "_R";
160 let mut p: V0SymbolMangler<'_> = V0SymbolMangler {
161 tcx,
162 start_offset: prefix.len(),
163 is_exportable: false,
164 paths: FxHashMap::default(),
165 types: FxHashMap::default(),
166 consts: FxHashMap::default(),
167 binders: ::alloc::vec::Vec::new()vec![],
168 out: String::from(prefix),
169 };
170
171 p.path_append_ns(
172 |p| {
173 p.push("C");
174 p.push_disambiguator_fixed_len({
175 let mut hasher = StableHasher::new();
176 hasher.write(tcx.sess.cfg_version.as_bytes());
182
183 hasher.finish()
184 });
185 p.push_ident("__rustc");
186 Ok(())
187 },
188 'v',
189 0,
190 item_name,
191 )
192 .unwrap();
193
194 std::mem::take(&mut p.out)
195}
196
197pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
198 tcx: TyCtxt<'tcx>,
199 trait_ref: ty::ExistentialTraitRef<'tcx>,
200) -> String {
201 let mut p = V0SymbolMangler {
203 tcx,
204 start_offset: 0,
205 is_exportable: false,
206 paths: FxHashMap::default(),
207 types: FxHashMap::default(),
208 consts: FxHashMap::default(),
209 binders: ::alloc::vec::Vec::new()vec![],
210 out: String::new(),
211 };
212 p.print_def_path(trait_ref.def_id, ty::GenericArgs::empty()).unwrap();
213 std::mem::take(&mut p.out)
214}
215
216struct BinderLevel {
217 lifetime_depths: Range<u32>,
228}
229
230struct V0SymbolMangler<'tcx> {
231 tcx: TyCtxt<'tcx>,
232 binders: Vec<BinderLevel>,
233 out: String,
234 is_exportable: bool,
235
236 start_offset: usize,
238 paths: FxHashMap<(DefId, ty::GenericArgs<'tcx>), usize>,
240 types: FxHashMap<Ty<'tcx>, usize>,
241 consts: FxHashMap<ty::Const<'tcx>, usize>,
242}
243
244impl<'tcx> V0SymbolMangler<'tcx> {
245 fn push(&mut self, s: &str) {
246 self.out.push_str(s);
247 }
248
249 fn push_integer_62(&mut self, x: u64) {
255 push_integer_62(x, &mut self.out)
256 }
257
258 fn push_opt_integer_62(&mut self, tag: &str, x: u64) {
263 if let Some(x) = x.checked_sub(1) {
264 self.push(tag);
265 self.push_integer_62(x);
266 }
267 }
268
269 fn push_disambiguator(&mut self, dis: u64) {
270 self.push_opt_integer_62("s", dis);
271 }
272
273 fn push_disambiguator_fixed_len(&mut self, dis: Hash64) {
278 let x = dis.as_u64();
279 if let Some(x) = x.checked_sub(1) {
280 self.push("s");
281 if let Some(x) = x.checked_sub(1) {
282 self.out.push_str(&x.to_base_fixed_len(62));
283 }
284 self.out.push('_');
285 }
286 }
287
288 fn push_ident(&mut self, ident: &str) {
289 push_ident(ident, &mut self.out)
290 }
291
292 fn path_append_ns(
293 &mut self,
294 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
295 ns: char,
296 disambiguator: u64,
297 name: &str,
298 ) -> Result<(), PrintError> {
299 self.push("N");
300 self.out.push(ns);
301 print_prefix(self)?;
302 self.push_disambiguator(disambiguator);
303 self.push_ident(name);
304 Ok(())
305 }
306
307 fn print_backref(&mut self, i: usize) -> Result<(), PrintError> {
308 self.push("B");
309 self.push_integer_62((i - self.start_offset) as u64);
310 Ok(())
311 }
312
313 fn wrap_binder<T>(
314 &mut self,
315 value: &ty::Binder<'tcx, T>,
316 print_value: impl FnOnce(&mut Self, &T) -> Result<(), PrintError>,
317 ) -> Result<(), PrintError>
318 where
319 T: TypeVisitable<TyCtxt<'tcx>>,
320 {
321 let mut lifetime_depths =
322 self.binders.last().map(|b| b.lifetime_depths.end).map_or(0..0, |i| i..i);
323
324 let lifetimes = value
326 .bound_vars()
327 .iter()
328 .filter(|var| #[allow(non_exhaustive_omitted_patterns)] match var {
ty::BoundVariableKind::Region(..) => true,
_ => false,
}matches!(var, ty::BoundVariableKind::Region(..)))
329 .count() as u32;
330
331 self.push_opt_integer_62("G", lifetimes as u64);
332 lifetime_depths.end += lifetimes;
333
334 self.binders.push(BinderLevel { lifetime_depths });
335 print_value(self, value.as_ref().skip_binder())?;
336 self.binders.pop();
337
338 Ok(())
339 }
340
341 fn print_pat(&mut self, pat: ty::Pattern<'tcx>) -> Result<(), std::fmt::Error> {
342 Ok(match *pat {
343 ty::PatternKind::Range { start, end } => {
344 self.push("R");
345 self.print_const(start)?;
346 self.print_const(end)?;
347 }
348 ty::PatternKind::NotNull => {
349 self.tcx.types.unit.print(self)?;
350 }
351 ty::PatternKind::Or(patterns) => {
352 self.push("O");
353 for pat in patterns {
354 self.print_pat(pat)?;
355 }
356 self.push("E");
357 }
358 })
359 }
360}
361
362impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> {
363 fn tcx(&self) -> TyCtxt<'tcx> {
364 self.tcx
365 }
366
367 fn print_def_path(
368 &mut self,
369 def_id: DefId,
370 args: ty::GenericArgs<'tcx>,
371 ) -> Result<(), PrintError> {
372 if let Some(&i) = self.paths.get(&(def_id, args)) {
373 return self.print_backref(i);
374 }
375 let start = self.out.len();
376
377 self.default_print_def_path(def_id, args)?;
378
379 if !args.iter().any(|k| k.has_escaping_bound_vars()) {
382 self.paths.insert((def_id, args), start);
383 }
384 Ok(())
385 }
386
387 fn print_impl_path(
388 &mut self,
389 impl_def_id: DefId,
390 args: ty::GenericArgs<'tcx>,
391 ) -> Result<(), PrintError> {
392 let key = self.tcx.def_key(impl_def_id);
393 let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
394
395 let self_ty = self.tcx.type_of(impl_def_id);
396 let impl_trait_ref = self.tcx.impl_opt_trait_ref(impl_def_id);
397 let generics = self.tcx.generics_of(impl_def_id);
398 let (typing_env, mut self_ty, mut impl_trait_ref) = if generics.count() > args.len()
412 || &args.as_slice()[..generics.count()]
413 == self
414 .tcx
415 .erase_and_anonymize_regions(ty::GenericArgs::identity_for_item(
416 self.tcx,
417 impl_def_id,
418 ))
419 .as_slice()
420 {
421 (
422 ty::TypingEnv::post_analysis(self.tcx, impl_def_id),
423 self_ty.instantiate_identity().skip_norm_wip(),
424 impl_trait_ref
425 .map(|impl_trait_ref| impl_trait_ref.instantiate_identity().skip_norm_wip()),
426 )
427 } else {
428 if !(!args.has_non_region_param() && !args.has_free_regions()) {
{
::core::panicking::panic_fmt(format_args!("should not be mangling partially substituted polymorphic instance: {0:?} {1:?}",
impl_def_id, args));
}
};assert!(
429 !args.has_non_region_param() && !args.has_free_regions(),
430 "should not be mangling partially substituted \
431 polymorphic instance: {impl_def_id:?} {args:?}"
432 );
433 (
434 ty::TypingEnv::fully_monomorphized(),
435 self_ty.instantiate(self.tcx, args).skip_norm_wip(),
436 impl_trait_ref.map(|impl_trait_ref| {
437 impl_trait_ref.instantiate(self.tcx, args).skip_norm_wip()
438 }),
439 )
440 };
441
442 match &mut impl_trait_ref {
443 Some(impl_trait_ref) => {
444 {
match (&impl_trait_ref.self_ty(), &self_ty) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(impl_trait_ref.self_ty(), self_ty);
445 *impl_trait_ref = self
446 .tcx
447 .normalize_erasing_regions(typing_env, Unnormalized::new_wip(*impl_trait_ref));
448 self_ty = impl_trait_ref.self_ty();
449 }
450 None => {
451 self_ty =
452 self.tcx.normalize_erasing_regions(typing_env, Unnormalized::new_wip(self_ty));
453 }
454 }
455
456 self.push(match impl_trait_ref {
457 Some(_) => "X",
458 None => "M",
459 });
460
461 if impl_trait_ref.is_some() && args.iter().any(|a| a.has_non_region_param()) {
464 self.print_path_with_generic_args(
465 |this| {
466 this.path_append_ns(
467 |p| p.print_def_path(parent_def_id, ty::GenericArgs::empty()),
468 'I',
469 key.disambiguated_data.disambiguator as u64,
470 "",
471 )
472 },
473 args,
474 )?;
475 } else {
476 let exported_impl_order = self.tcx.stable_order_of_exportable_impls(impl_def_id.krate);
477 let disambiguator = match self.is_exportable {
478 true => exported_impl_order[&impl_def_id] as u64,
479 false => {
480 exported_impl_order.len() as u64 + key.disambiguated_data.disambiguator as u64
481 }
482 };
483 self.push_disambiguator(disambiguator);
484 self.print_def_path(parent_def_id, ty::GenericArgs::empty())?;
485 }
486
487 self_ty.print(self)?;
488
489 if let Some(trait_ref) = impl_trait_ref {
490 self.print_def_path(trait_ref.def_id, trait_ref.args)?;
491 }
492
493 Ok(())
494 }
495
496 fn print_region(&mut self, region: ty::Region<'_>) -> Result<(), PrintError> {
497 let i = match region.kind() {
498 ty::ReErased => 0,
501
502 ty::ReBound(
505 ty::BoundVarIndexKind::Bound(debruijn),
506 ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon },
507 ) => {
508 let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
509 let depth = binder.lifetime_depths.start + var.as_u32();
510
511 1 + (self.binders.last().unwrap().lifetime_depths.end - 1 - depth)
512 }
513
514 _ => ::rustc_span::macros::bug_impl(None,
format_args!("symbol_names: non-erased region `{0:?}`", region),
Location::caller())bug!("symbol_names: non-erased region `{:?}`", region),
515 };
516 self.push("L");
517 self.push_integer_62(i as u64);
518 Ok(())
519 }
520
521 fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
522 let basic_type = match ty.kind() {
524 ty::Bool => "b",
525 ty::Char => "c",
526 ty::Str => "e",
527 ty::Int(IntTy::I8) => "a",
528 ty::Int(IntTy::I16) => "s",
529 ty::Int(IntTy::I32) => "l",
530 ty::Int(IntTy::I64) => "x",
531 ty::Int(IntTy::I128) => "n",
532 ty::Int(IntTy::Isize) => "i",
533 ty::Uint(UintTy::U8) => "h",
534 ty::Uint(UintTy::U16) => "t",
535 ty::Uint(UintTy::U32) => "m",
536 ty::Uint(UintTy::U64) => "y",
537 ty::Uint(UintTy::U128) => "o",
538 ty::Uint(UintTy::Usize) => "j",
539 ty::Float(FloatTy::F16) => "C3f16",
540 ty::Float(FloatTy::F32) => "f",
541 ty::Float(FloatTy::F64) => "d",
542 ty::Float(FloatTy::F128) => "C4f128",
543 ty::Never => "z",
544
545 ty::Tuple(_) if ty.is_unit() => "u",
546
547 ty::Param(_) => "p",
550
551 _ => "",
552 };
553 if !basic_type.is_empty() {
554 self.push(basic_type);
555 return Ok(());
556 }
557
558 if let Some(&i) = self.types.get(&ty) {
559 return self.print_backref(i);
560 }
561 let start = self.out.len();
562
563 match *ty.kind() {
564 ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Never => {
566 ::core::panicking::unreachable_default_msg()unreachable!()
567 }
568 ty::Tuple(_) if ty.is_unit() => ::core::panicking::unreachable_default_msg()unreachable!(),
569 ty::Param(_) => ::core::panicking::unreachable_default_msg()unreachable!(),
570
571 ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => ::rustc_span::macros::bug_impl(None, format_args!("impossible case reached"),
Location::caller())bug!(),
572
573 ty::Ref(r, ty, mutbl) => {
574 self.push(match mutbl {
575 hir::Mutability::Not => "R",
576 hir::Mutability::Mut => "Q",
577 });
578 if !r.is_erased() {
579 r.print(self)?;
580 }
581 ty.print(self)?;
582 }
583
584 ty::RawPtr(ty, mutbl) => {
585 self.push(match mutbl {
586 hir::Mutability::Not => "P",
587 hir::Mutability::Mut => "O",
588 });
589 ty.print(self)?;
590 }
591
592 ty::Pat(ty, pat) => {
593 self.push("W");
594 ty.print(self)?;
595 self.print_pat(pat)?;
596 }
597
598 ty::Array(ty, len) => {
599 self.push("A");
600 ty.print(self)?;
601 self.print_const(len)?;
602 }
603 ty::Slice(ty) => {
604 self.push("S");
605 ty.print(self)?;
606 }
607
608 ty::Tuple(tys) => {
609 self.push("T");
610 for ty in tys.iter() {
611 ty.print(self)?;
612 }
613 self.push("E");
614 }
615
616 ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), args)
618 | ty::Closure(def_id, args)
619 | ty::CoroutineClosure(def_id, args)
620 | ty::Coroutine(def_id, args) => {
621 self.print_def_path(def_id, args)?;
622 }
623
624 ty::FnDef(def_id, args) => {
625 self.print_def_path(def_id, args.no_bound_vars().unwrap())?
626 }
627
628 ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) => {
631 self.print_def_path(def_id, args)?;
632 }
633
634 ty::Foreign(def_id) => {
635 self.print_def_path(def_id, ty::GenericArgs::empty())?;
636 }
637
638 ty::FnPtr(sig_tys, hdr) => {
639 let splatted_arg_index = hdr.splatted().map(usize::from);
640 let sig = sig_tys.with(hdr);
641 self.push("F");
642 self.wrap_binder(&sig, |p, sig| {
643 if sig.safety().is_unsafe() {
644 p.push("U");
645 }
646 match sig.abi() {
647 ExternAbi::Rust => {}
648 ExternAbi::C { unwind: false } => p.push("KC"),
649 abi => {
650 p.push("K");
651 let name = abi.as_str();
652 if name.contains('-') {
653 p.push_ident(&name.replace('-', "_"));
654 } else {
655 p.push_ident(name);
656 }
657 }
658 }
659 for (i, &ty) in sig.inputs().iter().enumerate() {
660 if splatted_arg_index == Some(i) {
661 p.push("w");
667 }
668 ty.print(p)?;
669 }
670 if sig.c_variadic() {
671 p.push("v");
672 }
673 p.push("E");
674 sig.output().print(p)
675 })?;
676 }
677
678 ty::UnsafeBinder(..) => ::core::panicking::unimplemented_default_msg()unimplemented!(),
680
681 ty::Dynamic(predicates, r) => {
682 self.push("D");
683 self.print_dyn_existential(predicates)?;
684 r.print(self)?;
685 }
686
687 ty::Alias(..) => ::rustc_span::macros::bug_impl(None,
format_args!("symbol_names: unexpected alias"), Location::caller())bug!("symbol_names: unexpected alias"),
688 ty::CoroutineWitness(..) => ::rustc_span::macros::bug_impl(None,
format_args!("symbol_names: unexpected `CoroutineWitness`"),
Location::caller())bug!("symbol_names: unexpected `CoroutineWitness`"),
689 }
690
691 if !ty.has_escaping_bound_vars() {
694 self.types.insert(ty, start);
695 }
696 Ok(())
697 }
698
699 fn print_dyn_existential(
700 &mut self,
701 predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
702 ) -> Result<(), PrintError> {
703 self.wrap_binder(&predicates[0], |p, _| {
730 for predicate in predicates.iter() {
731 match predicate.as_ref().skip_binder() {
736 ty::ExistentialPredicate::Trait(trait_ref) => {
737 let trait_ref =
741 trait_ref.with_self_ty(p.tcx, p.tcx.types.trait_object_dummy_self);
742 p.print_def_path(trait_ref.def_id, trait_ref.args)?;
743 }
744 ty::ExistentialPredicate::Projection(projection) => {
745 let name = p.tcx.associated_item(projection.def_id).name();
746 p.push("p");
747 p.push_ident(name.as_str());
748 match projection.term.kind() {
749 ty::TermKind::Ty(ty) => ty.print(p),
750 ty::TermKind::Const(c) => {
751 p.push("K");
752 c.print(p)
753 }
754 }?;
755 }
756 ty::ExistentialPredicate::AutoTrait(def_id) => {
757 p.print_def_path(*def_id, ty::GenericArgs::empty())?;
758 }
759 }
760 }
761 Ok(())
762 })?;
763
764 self.push("E");
765 Ok(())
766 }
767
768 fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
769 let cv = match ct.kind() {
771 ty::ConstKind::Value(cv) => cv,
772
773 ty::ConstKind::Param(_) => {
776 self.push("p");
778 return Ok(());
779 }
780
781 ty::ConstKind::Alias(_, ty::AliasConst { kind, args, .. }) => match kind {
784 ty::AliasConstKind::Projection { def_id }
785 | ty::AliasConstKind::InherentSelf { def_id }
786 | ty::AliasConstKind::InherentImpl { def_id }
787 | ty::AliasConstKind::Free { def_id }
788 | ty::AliasConstKind::Anon { def_id } => {
789 return self.print_def_path(def_id, args);
790 }
791 },
792
793 ty::ConstKind::Expr(_)
794 | ty::ConstKind::Infer(_)
795 | ty::ConstKind::Bound(..)
796 | ty::ConstKind::Placeholder(_)
797 | ty::ConstKind::Error(_) => ::rustc_span::macros::bug_impl(None, format_args!("impossible case reached"),
Location::caller())bug!(),
798 };
799
800 if let Some(&i) = self.consts.get(&ct) {
801 self.print_backref(i)?;
802 return Ok(());
803 }
804
805 let ty::Value { ty: ct_ty, valtree } = cv;
806 let start = self.out.len();
807
808 match ct_ty.kind() {
809 ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
810 ct_ty.print(self)?;
811
812 let mut bits = cv
813 .try_to_bits(self.tcx, ty::TypingEnv::fully_monomorphized())
814 .expect("expected const to be monomorphic");
815
816 if let ty::Int(ity) = ct_ty.kind() {
818 let val =
819 Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
820 if val < 0 {
821 self.push("n");
822 }
823 bits = val.unsigned_abs();
824 }
825
826 let _ = self.out.write_fmt(format_args!("{0:x}_", bits))write!(self.out, "{bits:x}_");
827 }
828
829 ty::Str => {
831 let tcx = self.tcx();
832 let ref_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, ct_ty);
835 let cv = ty::Value { ty: ref_ty, valtree };
836 let slice = cv.try_to_raw_bytes(tcx).unwrap_or_else(|| {
837 ::rustc_span::macros::bug_impl(None,
format_args!("expected to get raw bytes from valtree {0:?} for type {1}",
valtree, ct_ty), Location::caller())bug!("expected to get raw bytes from valtree {:?} for type {:}", valtree, ct_ty)
838 });
839 let s = std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter");
840
841 self.push("e");
843
844 for byte in s.bytes() {
846 let _ = self.out.write_fmt(format_args!("{0:02x}", byte))write!(self.out, "{byte:02x}");
847 }
848
849 self.push("_");
850 }
851
852 ty::Ref(_, _, mutbl) => {
855 self.push(match mutbl {
856 hir::Mutability::Not => "R",
857 hir::Mutability::Mut => "Q",
858 });
859
860 let pointee_ty =
861 ct_ty.builtin_deref(true).expect("tried to dereference on non-ptr type");
862 let dereferenced_const = ty::Const::new_value(self.tcx, valtree, pointee_ty);
863 dereferenced_const.print(self)?;
864 }
865
866 ty::Array(..) | ty::Tuple(..) | ty::Slice(_) => {
867 let fields = cv.to_branch().iter().copied();
868
869 let print_field_list = |this: &mut Self| {
870 for field in fields.clone() {
871 field.print(this)?;
872 }
873 this.push("E");
874 Ok(())
875 };
876
877 match *ct_ty.kind() {
878 ty::Array(..) | ty::Slice(_) => {
879 self.push("A");
880 print_field_list(self)?;
881 }
882 ty::Tuple(..) => {
883 self.push("T");
884 print_field_list(self)?;
885 }
886 _ => ::core::panicking::unreachable_default_msg()unreachable!(),
887 }
888 }
889 ty::Adt(def, args) => {
890 let contents = cv.destructure_adt_const();
891 let fields = contents.fields.iter().copied();
892
893 let print_field_list = |this: &mut Self| {
894 for field in fields.clone() {
895 field.print(this)?;
896 }
897 this.push("E");
898 Ok(())
899 };
900
901 let variant_idx = contents.variant;
902 let variant_def = &def.variant(variant_idx);
903
904 self.push("V");
905 self.print_def_path(variant_def.def_id, *args)?;
906
907 match variant_def.ctor_kind() {
908 Some(CtorKind::Const) => {
909 self.push("U");
910 }
911 Some(CtorKind::Fn) => {
912 self.push("T");
913 print_field_list(self)?;
914 }
915 None => {
916 self.push("S");
917 for (field_def, field) in iter::zip(&variant_def.fields, fields) {
918 let disambiguated_field =
922 self.tcx.def_key(field_def.did).disambiguated_data;
923 let field_name = disambiguated_field.data.get_opt_name();
924 self.push_disambiguator(disambiguated_field.disambiguator as u64);
925 self.push_ident(field_name.unwrap().as_str());
926
927 field.print(self)?;
928 }
929 self.push("E");
930 }
931 }
932 }
933 _ => {
934 ::rustc_span::macros::bug_impl(None,
format_args!("symbol_names: unsupported constant of type `{0}` ({1:?})",
ct_ty, ct), Location::caller());bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct_ty, ct);
935 }
936 }
937
938 if !ct.has_escaping_bound_vars() {
941 self.consts.insert(ct, start);
942 }
943 Ok(())
944 }
945
946 fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
947 self.push("C");
948 if !self.is_exportable {
949 let stable_crate_id = self.tcx.stable_crate_id(cnum);
950 self.push_disambiguator_fixed_len(stable_crate_id.as_hash());
951 }
952 let name = self.tcx.crate_name(cnum);
953 self.push_ident(name.as_str());
954 Ok(())
955 }
956
957 fn print_path_with_qualified(
958 &mut self,
959 self_ty: Ty<'tcx>,
960 trait_ref: Option<ty::TraitRef<'tcx>>,
961 ) -> Result<(), PrintError> {
962 if !trait_ref.is_some() {
::core::panicking::panic("assertion failed: trait_ref.is_some()")
};assert!(trait_ref.is_some());
963 let trait_ref = trait_ref.unwrap();
964
965 self.push("Y");
966 self_ty.print(self)?;
967 self.print_def_path(trait_ref.def_id, trait_ref.args)
968 }
969
970 fn print_path_with_impl(
971 &mut self,
972 _: impl FnOnce(&mut Self) -> Result<(), PrintError>,
973 _: Ty<'tcx>,
974 _: Option<ty::TraitRef<'tcx>>,
975 ) -> Result<(), PrintError> {
976 ::core::panicking::unreachable_default_msg()unreachable!()
978 }
979
980 fn print_path_with_simple(
981 &mut self,
982 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
983 disambiguated_data: &DisambiguatedDefPathData,
984 ) -> Result<(), PrintError> {
985 let ns = match disambiguated_data.data {
986 DefPathData::ForeignMod => return print_prefix(self),
989
990 DefPathData::TypeNs(_) => 't',
992 DefPathData::ValueNs(_) => 'v',
993 DefPathData::Closure => 'C',
994 DefPathData::Ctor => 'c',
995 DefPathData::AnonConst => 'K',
996 DefPathData::OpaqueTy => 'i',
997 DefPathData::SyntheticCoroutineBody => 's',
998 DefPathData::NestedStatic => 'n',
999 DefPathData::GlobalAsm => 'a',
1000
1001 DefPathData::CrateRoot
1003 | DefPathData::Use
1004 | DefPathData::Impl
1005 | DefPathData::MacroNs(_)
1006 | DefPathData::LifetimeNs(_)
1007 | DefPathData::OpaqueLifetime(_)
1008 | DefPathData::AnonAssocTy(..)
1009 | DefPathData::TestBinderConstraints => {
1010 ::rustc_span::macros::bug_impl(None,
format_args!("symbol_names: unexpected DefPathData: {0:?}",
disambiguated_data.data), Location::caller())bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
1011 }
1012 };
1013
1014 let name = disambiguated_data.data.get_opt_name();
1015
1016 self.path_append_ns(
1017 print_prefix,
1018 ns,
1019 disambiguated_data.disambiguator as u64,
1020 name.unwrap_or(sym::empty).as_str(),
1021 )
1022 }
1023
1024 fn print_path_with_generic_args(
1025 &mut self,
1026 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
1027 args: ty::GenericArgs<'tcx>,
1028 ) -> Result<(), PrintError> {
1029 let print_regions = args.iter().any(|arg| match arg.kind() {
1031 GenericArgKind::Lifetime(r) => !r.is_erased(),
1032 _ => false,
1033 });
1034 let args = args.iter().filter(|arg| match arg.kind() {
1035 GenericArgKind::Lifetime(_) => print_regions,
1036 _ => true,
1037 });
1038
1039 if args.clone().next().is_none() {
1040 return print_prefix(self);
1041 }
1042
1043 self.push("I");
1044 print_prefix(self)?;
1045 for arg in args {
1046 match arg.kind() {
1047 GenericArgKind::Lifetime(lt) => {
1048 lt.print(self)?;
1049 }
1050 GenericArgKind::Type(ty) => {
1051 ty.print(self)?;
1052 }
1053 GenericArgKind::Const(c) => {
1054 self.push("K");
1055 c.print(self)?;
1056 }
1057 }
1058 }
1059 self.push("E");
1060
1061 Ok(())
1062 }
1063}
1064pub(crate) fn push_integer_62(x: u64, output: &mut String) {
1070 if let Some(x) = x.checked_sub(1) {
1071 output.push_str(&x.to_base(62));
1072 }
1073 output.push('_');
1074}
1075
1076pub(crate) fn encode_integer_62(x: u64) -> String {
1077 let mut output = String::new();
1078 push_integer_62(x, &mut output);
1079 output
1080}
1081
1082pub(crate) fn push_ident(ident: &str, output: &mut String) {
1083 let mut use_punycode = false;
1084 for b in ident.bytes() {
1085 match b {
1086 b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' => {}
1087 0x80..=0xff => use_punycode = true,
1088 _ => ::rustc_span::macros::bug_impl(None,
format_args!("symbol_names: bad byte {0} in ident {1:?}", b, ident),
Location::caller())bug!("symbol_names: bad byte {} in ident {:?}", b, ident),
1089 }
1090 }
1091
1092 let punycode_string;
1093 let ident = if use_punycode {
1094 output.push('u');
1095
1096 let mut punycode_bytes = match punycode::encode(ident) {
1098 Ok(s) => s.into_bytes(),
1099 Err(()) => ::rustc_span::macros::bug_impl(None,
format_args!("symbol_names: punycode encoding failed for ident {0:?}",
ident), Location::caller())bug!("symbol_names: punycode encoding failed for ident {:?}", ident),
1100 };
1101
1102 if let Some(c) = punycode_bytes.iter_mut().rfind(|&&mut c| c == b'-') {
1104 *c = b'_';
1105 }
1106
1107 punycode_string = String::from_utf8(punycode_bytes).unwrap();
1109 &punycode_string
1110 } else {
1111 ident
1112 };
1113
1114 let _ = output.write_fmt(format_args!("{0}", ident.len()))write!(output, "{}", ident.len());
1115
1116 if let Some('_' | '0'..='9') = ident.chars().next() {
1118 output.push('_');
1119 }
1120
1121 output.push_str(ident);
1122}