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