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