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