rustc_const_eval/util/
type_name.rs1use 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, GenericArgKind, 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 Ok(())
24 }
25
26 fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
27 match *ty.kind() {
28 ty::Bool
30 | ty::Char
31 | ty::Int(_)
32 | ty::Uint(_)
33 | ty::Float(_)
34 | ty::Str
35 | ty::Pat(_, _)
36 | ty::Array(_, _)
37 | ty::Slice(_)
38 | ty::RawPtr(_, _)
39 | ty::Ref(_, _, _)
40 | ty::FnPtr(..)
41 | ty::Never
42 | ty::Tuple(_)
43 | ty::Dynamic(_, _, _)
44 | ty::UnsafeBinder(_) => self.pretty_print_type(ty),
45
46 ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {
48 write!(self, "_")?;
49 Ok(())
50 }
51
52 ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), args)
54 | ty::FnDef(def_id, args)
55 | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
56 | ty::Closure(def_id, args)
57 | ty::CoroutineClosure(def_id, args)
58 | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args),
59 ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
60
61 ty::Alias(ty::Free, _) => bug!("type_name: unexpected free alias"),
62 ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"),
63 ty::CoroutineWitness(..) => bug!("type_name: unexpected `CoroutineWitness`"),
64 }
65 }
66
67 fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
68 self.pretty_print_const(ct, false)
69 }
70
71 fn print_dyn_existential(
72 &mut self,
73 predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
74 ) -> Result<(), PrintError> {
75 self.pretty_print_dyn_existential(predicates)
76 }
77
78 fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
79 self.path.push_str(self.tcx.crate_name(cnum).as_str());
80 Ok(())
81 }
82
83 fn print_path_with_qualified(
84 &mut self,
85 self_ty: Ty<'tcx>,
86 trait_ref: Option<ty::TraitRef<'tcx>>,
87 ) -> Result<(), PrintError> {
88 self.pretty_print_path_with_qualified(self_ty, trait_ref)
89 }
90
91 fn print_path_with_impl(
92 &mut self,
93 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
94 self_ty: Ty<'tcx>,
95 trait_ref: Option<ty::TraitRef<'tcx>>,
96 ) -> Result<(), PrintError> {
97 self.pretty_print_path_with_impl(
98 |cx| {
99 print_prefix(cx)?;
100
101 cx.path.push_str("::");
102
103 Ok(())
104 },
105 self_ty,
106 trait_ref,
107 )
108 }
109
110 fn print_path_with_simple(
111 &mut self,
112 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
113 disambiguated_data: &DisambiguatedDefPathData,
114 ) -> Result<(), PrintError> {
115 print_prefix(self)?;
116
117 write!(self.path, "::{}", disambiguated_data.data).unwrap();
118
119 Ok(())
120 }
121
122 fn print_path_with_generic_args(
123 &mut self,
124 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
125 args: &[GenericArg<'tcx>],
126 ) -> Result<(), PrintError> {
127 print_prefix(self)?;
128 let args =
129 args.iter().cloned().filter(|arg| !matches!(arg.kind(), GenericArgKind::Lifetime(_)));
130 if args.clone().next().is_some() {
131 self.generic_delimiters(|cx| cx.comma_sep(args))
132 } else {
133 Ok(())
134 }
135 }
136}
137
138impl<'tcx> PrettyPrinter<'tcx> for TypeNamePrinter<'tcx> {
139 fn should_print_region(&self, _region: ty::Region<'_>) -> bool {
140 false
141 }
142
143 fn generic_delimiters(
144 &mut self,
145 f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
146 ) -> Result<(), PrintError> {
147 write!(self, "<")?;
148
149 f(self)?;
150
151 write!(self, ">")?;
152
153 Ok(())
154 }
155
156 fn should_print_verbose(&self) -> bool {
157 false
159 }
160}
161
162impl Write for TypeNamePrinter<'_> {
163 fn write_str(&mut self, s: &str) -> std::fmt::Result {
164 self.path.push_str(s);
165 Ok(())
166 }
167}
168
169pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String {
170 let mut p = TypeNamePrinter { tcx, path: String::new() };
171 p.print_type(ty).unwrap();
172 p.path
173}