]> git.proxmox.com Git - rustc.git/blame - src/librustc/ty/print/mod.rs
New upstream version 1.38.0+dfsg1
[rustc.git] / src / librustc / ty / print / mod.rs
CommitLineData
532ac7d7
XL
1use crate::hir::map::{DefPathData, DisambiguatedDefPathData};
2use crate::hir::def_id::{CrateNum, DefId};
3use crate::ty::{self, DefIdTree, Ty, TyCtxt};
4use crate::ty::subst::{Kind, Subst};
5
6use rustc_data_structures::fx::FxHashSet;
7
8// `pretty` is a separate module only for organization.
9mod pretty;
10pub use self::pretty::*;
11
dc9dc135
XL
12pub mod obsolete;
13
14// FIXME(eddyb) false positive, the lifetime parameters are used with `P: Printer<...>`.
15#[allow(unused_lifetimes)]
16pub trait Print<'tcx, P> {
532ac7d7
XL
17 type Output;
18 type Error;
19
20 fn print(&self, cx: P) -> Result<Self::Output, Self::Error>;
21}
22
23/// Interface for outputting user-facing "type-system entities"
24/// (paths, types, lifetimes, constants, etc.) as a side-effect
25/// (e.g. formatting, like `PrettyPrinter` implementors do) or by
26/// constructing some alternative representation (e.g. an AST),
27/// which the associated types allow passing through the methods.
28///
29/// For pretty-printing/formatting in particular, see `PrettyPrinter`.
30// FIXME(eddyb) find a better name, this is more general than "printing".
dc9dc135 31pub trait Printer<'tcx>: Sized {
532ac7d7
XL
32 type Error;
33
34 type Path;
35 type Region;
36 type Type;
37 type DynExistential;
dc9dc135 38 type Const;
532ac7d7 39
dc9dc135 40 fn tcx(&'a self) -> TyCtxt<'tcx>;
532ac7d7
XL
41
42 fn print_def_path(
43 self,
44 def_id: DefId,
45 substs: &'tcx [Kind<'tcx>],
46 ) -> Result<Self::Path, Self::Error> {
47 self.default_print_def_path(def_id, substs)
48 }
49 fn print_impl_path(
50 self,
51 impl_def_id: DefId,
52 substs: &'tcx [Kind<'tcx>],
53 self_ty: Ty<'tcx>,
54 trait_ref: Option<ty::TraitRef<'tcx>>,
55 ) -> Result<Self::Path, Self::Error> {
56 self.default_print_impl_path(impl_def_id, substs, self_ty, trait_ref)
57 }
58
59 fn print_region(
60 self,
61 region: ty::Region<'_>,
62 ) -> Result<Self::Region, Self::Error>;
63
64 fn print_type(
65 self,
66 ty: Ty<'tcx>,
67 ) -> Result<Self::Type, Self::Error>;
68
69 fn print_dyn_existential(
70 self,
71 predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
72 ) -> Result<Self::DynExistential, Self::Error>;
73
dc9dc135
XL
74 fn print_const(
75 self,
76 ct: &'tcx ty::Const<'tcx>,
77 ) -> Result<Self::Const, Self::Error>;
78
532ac7d7
XL
79 fn path_crate(
80 self,
81 cnum: CrateNum,
82 ) -> Result<Self::Path, Self::Error>;
83 fn path_qualified(
84 self,
85 self_ty: Ty<'tcx>,
86 trait_ref: Option<ty::TraitRef<'tcx>>,
87 ) -> Result<Self::Path, Self::Error>;
88
89 fn path_append_impl(
90 self,
91 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
92 disambiguated_data: &DisambiguatedDefPathData,
93 self_ty: Ty<'tcx>,
94 trait_ref: Option<ty::TraitRef<'tcx>>,
95 ) -> Result<Self::Path, Self::Error>;
96 fn path_append(
97 self,
98 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
99 disambiguated_data: &DisambiguatedDefPathData,
100 ) -> Result<Self::Path, Self::Error>;
101 fn path_generic_args(
102 self,
103 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
104 args: &[Kind<'tcx>],
105 ) -> Result<Self::Path, Self::Error>;
106
107 // Defaults (should not be overriden):
108
109 fn default_print_def_path(
110 self,
111 def_id: DefId,
112 substs: &'tcx [Kind<'tcx>],
113 ) -> Result<Self::Path, Self::Error> {
114 debug!("default_print_def_path: def_id={:?}, substs={:?}", def_id, substs);
115 let key = self.tcx().def_key(def_id);
116 debug!("default_print_def_path: key={:?}", key);
117
118 match key.disambiguated_data.data {
119 DefPathData::CrateRoot => {
120 assert!(key.parent.is_none());
121 self.path_crate(def_id.krate)
122 }
123
124 DefPathData::Impl => {
125 let generics = self.tcx().generics_of(def_id);
126 let mut self_ty = self.tcx().type_of(def_id);
127 let mut impl_trait_ref = self.tcx().impl_trait_ref(def_id);
128 if substs.len() >= generics.count() {
129 self_ty = self_ty.subst(self.tcx(), substs);
130 impl_trait_ref = impl_trait_ref.subst(self.tcx(), substs);
131 }
132 self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
133 }
134
135 _ => {
136 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
137
138 let mut parent_substs = substs;
139 let mut trait_qualify_parent = false;
140 if !substs.is_empty() {
141 let generics = self.tcx().generics_of(def_id);
142 parent_substs = &substs[..generics.parent_count.min(substs.len())];
143
144 match key.disambiguated_data.data {
145 // Closures' own generics are only captures, don't print them.
146 DefPathData::ClosureExpr => {}
147
148 // If we have any generic arguments to print, we do that
149 // on top of the same path, but without its own generics.
150 _ => if !generics.params.is_empty() && substs.len() >= generics.count() {
151 let args = self.generic_args_to_print(generics, substs);
152 return self.path_generic_args(
153 |cx| cx.print_def_path(def_id, parent_substs),
154 args,
155 );
156 }
157 }
158
159 // FIXME(eddyb) try to move this into the parent's printing
160 // logic, instead of doing it when printing the child.
161 trait_qualify_parent =
162 generics.has_self &&
163 generics.parent == Some(parent_def_id) &&
164 parent_substs.len() == generics.parent_count &&
165 self.tcx().generics_of(parent_def_id).parent_count == 0;
166 }
167
168 self.path_append(
169 |cx: Self| if trait_qualify_parent {
170 let trait_ref = ty::TraitRef::new(
171 parent_def_id,
172 cx.tcx().intern_substs(parent_substs),
173 );
174 cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
175 } else {
176 cx.print_def_path(parent_def_id, parent_substs)
177 },
178 &key.disambiguated_data,
179 )
180 }
181 }
182 }
183
184 fn generic_args_to_print(
185 &self,
186 generics: &'tcx ty::Generics,
187 substs: &'tcx [Kind<'tcx>],
188 ) -> &'tcx [Kind<'tcx>] {
189 let mut own_params = generics.parent_count..generics.count();
190
191 // Don't print args for `Self` parameters (of traits).
192 if generics.has_self && own_params.start == 0 {
193 own_params.start = 1;
194 }
195
196 // Don't print args that are the defaults of their respective parameters.
197 own_params.end -= generics.params.iter().rev().take_while(|param| {
198 match param.kind {
199 ty::GenericParamDefKind::Lifetime => false,
200 ty::GenericParamDefKind::Type { has_default, .. } => {
201 has_default && substs[param.index as usize] == Kind::from(
202 self.tcx().type_of(param.def_id).subst(self.tcx(), substs)
203 )
204 }
205 ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
206 }
207 }).count();
208
209 &substs[own_params]
210 }
211
212 fn default_print_impl_path(
213 self,
214 impl_def_id: DefId,
215 _substs: &'tcx [Kind<'tcx>],
216 self_ty: Ty<'tcx>,
217 impl_trait_ref: Option<ty::TraitRef<'tcx>>,
218 ) -> Result<Self::Path, Self::Error> {
219 debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
220 impl_def_id, self_ty, impl_trait_ref);
221
222 let key = self.tcx().def_key(impl_def_id);
223 let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
224
225 // Decide whether to print the parent path for the impl.
226 // Logically, since impls are global, it's never needed, but
227 // users may find it useful. Currently, we omit the parent if
228 // the impl is either in the same module as the self-type or
229 // as the trait.
230 let in_self_mod = match characteristic_def_id_of_type(self_ty) {
231 None => false,
232 Some(ty_def_id) => self.tcx().parent(ty_def_id) == Some(parent_def_id),
233 };
234 let in_trait_mod = match impl_trait_ref {
235 None => false,
236 Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == Some(parent_def_id),
237 };
238
239 if !in_self_mod && !in_trait_mod {
240 // If the impl is not co-located with either self-type or
241 // trait-type, then fallback to a format that identifies
242 // the module more clearly.
243 self.path_append_impl(
244 |cx| cx.print_def_path(parent_def_id, &[]),
245 &key.disambiguated_data,
246 self_ty,
247 impl_trait_ref,
248 )
249 } else {
250 // Otherwise, try to give a good form that would be valid language
251 // syntax. Preferably using associated item notation.
252 self.path_qualified(self_ty, impl_trait_ref)
253 }
254 }
255}
256
257/// As a heuristic, when we see an impl, if we see that the
258/// 'self type' is a type defined in the same module as the impl,
259/// we can omit including the path to the impl itself. This
260/// function tries to find a "characteristic `DefId`" for a
261/// type. It's just a heuristic so it makes some questionable
262/// decisions and we may want to adjust it later.
263pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
264 match ty.sty {
265 ty::Adt(adt_def, _) => Some(adt_def.did),
266
267 ty::Dynamic(data, ..) => data.principal_def_id(),
268
269 ty::Array(subty, _) |
270 ty::Slice(subty) => characteristic_def_id_of_type(subty),
271
272 ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
273
274 ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
275
276 ty::Tuple(ref tys) => tys.iter()
48663c56 277 .filter_map(|ty| characteristic_def_id_of_type(ty.expect_ty()))
532ac7d7
XL
278 .next(),
279
280 ty::FnDef(def_id, _) |
281 ty::Closure(def_id, _) |
282 ty::Generator(def_id, _, _) |
283 ty::Foreign(def_id) => Some(def_id),
284
285 ty::Bool |
286 ty::Char |
287 ty::Int(_) |
288 ty::Uint(_) |
289 ty::Str |
290 ty::FnPtr(_) |
291 ty::Projection(_) |
292 ty::Placeholder(..) |
293 ty::UnnormalizedProjection(..) |
294 ty::Param(_) |
295 ty::Opaque(..) |
296 ty::Infer(_) |
297 ty::Bound(..) |
298 ty::Error |
299 ty::GeneratorWitness(..) |
300 ty::Never |
301 ty::Float(_) => None,
302 }
303}
304
dc9dc135 305impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::RegionKind {
532ac7d7
XL
306 type Output = P::Region;
307 type Error = P::Error;
308 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
309 cx.print_region(self)
310 }
311}
312
dc9dc135 313impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'_> {
532ac7d7
XL
314 type Output = P::Region;
315 type Error = P::Error;
316 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
317 cx.print_region(self)
318 }
319}
320
dc9dc135 321impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
532ac7d7
XL
322 type Output = P::Type;
323 type Error = P::Error;
324 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
325 cx.print_type(self)
326 }
327}
328
dc9dc135 329impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
532ac7d7
XL
330 type Output = P::DynExistential;
331 type Error = P::Error;
332 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
333 cx.print_dyn_existential(self)
334 }
335}
dc9dc135
XL
336
337impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::Const<'tcx> {
338 type Output = P::Const;
339 type Error = P::Error;
340 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
341 cx.print_const(self)
342 }
343}