]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_const_eval/src/util/type_name.rs
Auto merge of #107549 - Zoxc:rustc-shared, r=jyn514
[rust.git] / compiler / rustc_const_eval / src / util / type_name.rs
1 use rustc_data_structures::intern::Interned;
2 use rustc_hir::def_id::CrateNum;
3 use rustc_hir::definitions::DisambiguatedDefPathData;
4 use rustc_middle::ty::{
5     self,
6     print::{PrettyPrinter, Print, Printer},
7     subst::{GenericArg, GenericArgKind},
8     Ty, TyCtxt,
9 };
10 use std::fmt::Write;
11
12 struct AbsolutePathPrinter<'tcx> {
13     tcx: TyCtxt<'tcx>,
14     path: String,
15 }
16
17 impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
18     type Error = std::fmt::Error;
19
20     type Path = Self;
21     type Region = Self;
22     type Type = Self;
23     type DynExistential = Self;
24     type Const = Self;
25
26     fn tcx(&self) -> TyCtxt<'tcx> {
27         self.tcx
28     }
29
30     fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
31         Ok(self)
32     }
33
34     fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
35         match *ty.kind() {
36             // Types without identity.
37             ty::Bool
38             | ty::Char
39             | ty::Int(_)
40             | ty::Uint(_)
41             | ty::Float(_)
42             | ty::Str
43             | ty::Array(_, _)
44             | ty::Slice(_)
45             | ty::RawPtr(_)
46             | ty::Ref(_, _, _)
47             | ty::FnPtr(_)
48             | ty::Never
49             | ty::Tuple(_)
50             | ty::Dynamic(_, _, _) => self.pretty_print_type(ty),
51
52             // Placeholders (all printed as `_` to uniformize them).
53             ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {
54                 write!(self, "_")?;
55                 Ok(self)
56             }
57
58             // Types with identity (print the module path).
59             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
60             | ty::FnDef(def_id, substs)
61             | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
62             | ty::Closure(def_id, substs)
63             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
64             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
65
66             ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"),
67             ty::GeneratorWitnessMIR(..) => bug!("type_name: unexpected `GeneratorWitnessMIR`"),
68         }
69     }
70
71     fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
72         self.pretty_print_const(ct, false)
73     }
74
75     fn print_dyn_existential(
76         self,
77         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
78     ) -> Result<Self::DynExistential, Self::Error> {
79         self.pretty_print_dyn_existential(predicates)
80     }
81
82     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
83         self.path.push_str(self.tcx.crate_name(cnum).as_str());
84         Ok(self)
85     }
86
87     fn path_qualified(
88         self,
89         self_ty: Ty<'tcx>,
90         trait_ref: Option<ty::TraitRef<'tcx>>,
91     ) -> Result<Self::Path, Self::Error> {
92         self.pretty_path_qualified(self_ty, trait_ref)
93     }
94
95     fn path_append_impl(
96         self,
97         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
98         _disambiguated_data: &DisambiguatedDefPathData,
99         self_ty: Ty<'tcx>,
100         trait_ref: Option<ty::TraitRef<'tcx>>,
101     ) -> Result<Self::Path, Self::Error> {
102         self.pretty_path_append_impl(
103             |mut cx| {
104                 cx = print_prefix(cx)?;
105
106                 cx.path.push_str("::");
107
108                 Ok(cx)
109             },
110             self_ty,
111             trait_ref,
112         )
113     }
114
115     fn path_append(
116         mut self,
117         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
118         disambiguated_data: &DisambiguatedDefPathData,
119     ) -> Result<Self::Path, Self::Error> {
120         self = print_prefix(self)?;
121
122         write!(self.path, "::{}", disambiguated_data.data).unwrap();
123
124         Ok(self)
125     }
126
127     fn path_generic_args(
128         mut self,
129         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
130         args: &[GenericArg<'tcx>],
131     ) -> Result<Self::Path, Self::Error> {
132         self = print_prefix(self)?;
133         let args =
134             args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
135         if args.clone().next().is_some() {
136             self.generic_delimiters(|cx| cx.comma_sep(args))
137         } else {
138             Ok(self)
139         }
140     }
141 }
142
143 impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
144     fn should_print_region(&self, _region: ty::Region<'_>) -> bool {
145         false
146     }
147     fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
148     where
149         T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
150     {
151         if let Some(first) = elems.next() {
152             self = first.print(self)?;
153             for elem in elems {
154                 self.path.push_str(", ");
155                 self = elem.print(self)?;
156             }
157         }
158         Ok(self)
159     }
160
161     fn generic_delimiters(
162         mut self,
163         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
164     ) -> Result<Self, Self::Error> {
165         write!(self, "<")?;
166
167         self = f(self)?;
168
169         write!(self, ">")?;
170
171         Ok(self)
172     }
173
174     fn should_print_verbose(&self) -> bool {
175         // `std::any::type_name` should never print verbose type names
176         false
177     }
178 }
179
180 impl Write for AbsolutePathPrinter<'_> {
181     fn write_str(&mut self, s: &str) -> std::fmt::Result {
182         self.path.push_str(s);
183         Ok(())
184     }
185 }
186
187 pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String {
188     AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path
189 }