1use std::fmt::Write;
2
3use rustc_data_structures::intern::Interned;
4use rustc_hir::def_id::CrateNum;
5use rustc_hir::definitions::DisambiguatedDefPathData;
6use rustc_middle::bug;
7use rustc_middle::ty::print::{PrettyPrinter, PrintError, Printer};
8use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt};
9
10struct TypeNamePrinter<'tcx> {
11 tcx: TyCtxt<'tcx>,
12 path: String,
13}
14
15impl<'tcx> Printer<'tcx> for TypeNamePrinter<'tcx> {
16 fn tcx(&self) -> TyCtxt<'tcx> {
17 self.tcx
18 }
19
20 fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
21 write!(self, "'_")
25 }
26
27 fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
28 match *ty.kind() {
29 ty::Bool
31 | ty::Char
32 | ty::Int(_)
33 | ty::Uint(_)
34 | ty::Float(_)
35 | ty::Str
36 | ty::Pat(_, _)
37 | ty::Array(_, _)
38 | ty::Slice(_)
39 | ty::RawPtr(_, _)
40 | ty::Ref(_, _, _)
41 | ty::FnPtr(..)
42 | ty::Never
43 | ty::Tuple(_)
44 | ty::Dynamic(_, _, _)
45 | ty::UnsafeBinder(_) => self.pretty_print_type(ty),
46
47 ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {
49 write!(self, "_")?;
50 Ok(())
51 }
52
53 ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), args)
55 | ty::FnDef(def_id, args)
56 | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
57 | ty::Closure(def_id, args)
58 | ty::CoroutineClosure(def_id, args)
59 | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args),
60 ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
61
62 ty::Alias(ty::Free, _) => bug!("type_name: unexpected free alias"),
63 ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"),
64 ty::CoroutineWitness(..) => bug!("type_name: unexpected `CoroutineWitness`"),
65 }
66 }
67
68 fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
69 self.pretty_print_const(ct, false)
70 }
71
72 fn print_dyn_existential(
73 &mut self,
74 predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
75 ) -> Result<(), PrintError> {
76 self.pretty_print_dyn_existential(predicates)
77 }
78
79 fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
80 self.path.push_str(self.tcx.crate_name(cnum).as_str());
81 Ok(())
82 }
83
84 fn print_path_with_qualified(
85 &mut self,
86 self_ty: Ty<'tcx>,
87 trait_ref: Option<ty::TraitRef<'tcx>>,
88 ) -> Result<(), PrintError> {
89 self.pretty_print_path_with_qualified(self_ty, trait_ref)
90 }
91
92 fn print_path_with_impl(
93 &mut self,
94 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
95 self_ty: Ty<'tcx>,
96 trait_ref: Option<ty::TraitRef<'tcx>>,
97 ) -> Result<(), PrintError> {
98 self.pretty_print_path_with_impl(
99 |cx| {
100 print_prefix(cx)?;
101
102 cx.path.push_str("::");
103
104 Ok(())
105 },
106 self_ty,
107 trait_ref,
108 )
109 }
110
111 fn print_path_with_simple(
112 &mut self,
113 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
114 disambiguated_data: &DisambiguatedDefPathData,
115 ) -> Result<(), PrintError> {
116 print_prefix(self)?;
117
118 write!(self.path, "::{}", disambiguated_data.data).unwrap();
119
120 Ok(())
121 }
122
123 fn print_path_with_generic_args(
124 &mut self,
125 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
126 args: &[GenericArg<'tcx>],
127 ) -> Result<(), PrintError> {
128 print_prefix(self)?;
129 if !args.is_empty() {
130 self.generic_delimiters(|cx| cx.comma_sep(args.iter().copied()))
131 } else {
132 Ok(())
133 }
134 }
135}
136
137impl<'tcx> PrettyPrinter<'tcx> for TypeNamePrinter<'tcx> {
138 fn should_print_optional_region(&self, _region: ty::Region<'_>) -> bool {
139 match _region.kind() {
143 ty::ReErased => false,
144 ty::ReBound(..) => true,
145 _ => unreachable!(),
146 }
147 }
148
149 fn generic_delimiters(
150 &mut self,
151 f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
152 ) -> Result<(), PrintError> {
153 write!(self, "<")?;
154
155 f(self)?;
156
157 write!(self, ">")?;
158
159 Ok(())
160 }
161
162 fn should_print_verbose(&self) -> bool {
163 false
165 }
166}
167
168impl Write for TypeNamePrinter<'_> {
169 fn write_str(&mut self, s: &str) -> std::fmt::Result {
170 self.path.push_str(s);
171 Ok(())
172 }
173}
174
175pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String {
176 let mut p = TypeNamePrinter { tcx, path: String::new() };
177 p.print_type(ty).unwrap();
178 p.path
179}