]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/print/mod.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / 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;
29967ef6 5use rustc_data_structures::sso::SsoHashSet;
dfeec247 6use rustc_hir::def_id::{CrateNum, DefId};
ba9703b0 7use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
532ac7d7
XL
8
9// `pretty` is a separate module only for organization.
10mod pretty;
11pub use self::pretty::*;
12
dc9dc135
XL
13// FIXME(eddyb) false positive, the lifetime parameters are used with `P: Printer<...>`.
14#[allow(unused_lifetimes)]
15pub trait Print<'tcx, P> {
532ac7d7
XL
16 type Output;
17 type Error;
18
19 fn print(&self, cx: P) -> Result<Self::Output, Self::Error>;
20}
21
22/// Interface for outputting user-facing "type-system entities"
23/// (paths, types, lifetimes, constants, etc.) as a side-effect
24/// (e.g. formatting, like `PrettyPrinter` implementors do) or by
25/// constructing some alternative representation (e.g. an AST),
26/// which the associated types allow passing through the methods.
27///
28/// For pretty-printing/formatting in particular, see `PrettyPrinter`.
e1599b0c
XL
29//
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
a2a8927a 40 fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
532ac7d7
XL
41
42 fn print_def_path(
43 self,
44 def_id: DefId,
e74abb32 45 substs: &'tcx [GenericArg<'tcx>],
532ac7d7
XL
46 ) -> Result<Self::Path, Self::Error> {
47 self.default_print_def_path(def_id, substs)
48 }
e1599b0c 49
532ac7d7
XL
50 fn print_impl_path(
51 self,
52 impl_def_id: DefId,
e74abb32 53 substs: &'tcx [GenericArg<'tcx>],
532ac7d7
XL
54 self_ty: Ty<'tcx>,
55 trait_ref: Option<ty::TraitRef<'tcx>>,
56 ) -> Result<Self::Path, Self::Error> {
57 self.default_print_impl_path(impl_def_id, substs, self_ty, trait_ref)
58 }
59
dfeec247 60 fn print_region(self, region: ty::Region<'_>) -> Result<Self::Region, Self::Error>;
532ac7d7 61
dfeec247 62 fn print_type(self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>;
532ac7d7
XL
63
64 fn print_dyn_existential(
65 self,
cdc7bbd5 66 predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
532ac7d7
XL
67 ) -> Result<Self::DynExistential, Self::Error>;
68
5099ac24 69 fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error>;
dc9dc135 70
dfeec247 71 fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error>;
e1599b0c 72
532ac7d7
XL
73 fn path_qualified(
74 self,
75 self_ty: Ty<'tcx>,
76 trait_ref: Option<ty::TraitRef<'tcx>>,
77 ) -> Result<Self::Path, Self::Error>;
78
79 fn path_append_impl(
80 self,
81 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
82 disambiguated_data: &DisambiguatedDefPathData,
83 self_ty: Ty<'tcx>,
84 trait_ref: Option<ty::TraitRef<'tcx>>,
85 ) -> Result<Self::Path, Self::Error>;
e1599b0c 86
532ac7d7
XL
87 fn path_append(
88 self,
89 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
90 disambiguated_data: &DisambiguatedDefPathData,
91 ) -> Result<Self::Path, Self::Error>;
e1599b0c 92
532ac7d7
XL
93 fn path_generic_args(
94 self,
95 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
e74abb32 96 args: &[GenericArg<'tcx>],
532ac7d7
XL
97 ) -> Result<Self::Path, Self::Error>;
98
74b04a01 99 // Defaults (should not be overridden):
532ac7d7 100
c295e0f8 101 #[instrument(skip(self), level = "debug")]
532ac7d7
XL
102 fn default_print_def_path(
103 self,
104 def_id: DefId,
e74abb32 105 substs: &'tcx [GenericArg<'tcx>],
532ac7d7 106 ) -> Result<Self::Path, Self::Error> {
532ac7d7 107 let key = self.tcx().def_key(def_id);
c295e0f8 108 debug!(?key);
532ac7d7
XL
109
110 match key.disambiguated_data.data {
111 DefPathData::CrateRoot => {
112 assert!(key.parent.is_none());
113 self.path_crate(def_id.krate)
114 }
115
116 DefPathData::Impl => {
117 let generics = self.tcx().generics_of(def_id);
118 let mut self_ty = self.tcx().type_of(def_id);
119 let mut impl_trait_ref = self.tcx().impl_trait_ref(def_id);
120 if substs.len() >= generics.count() {
121 self_ty = self_ty.subst(self.tcx(), substs);
122 impl_trait_ref = impl_trait_ref.subst(self.tcx(), substs);
123 }
124 self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
125 }
126
127 _ => {
128 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
129
130 let mut parent_substs = substs;
131 let mut trait_qualify_parent = false;
132 if !substs.is_empty() {
133 let generics = self.tcx().generics_of(def_id);
134 parent_substs = &substs[..generics.parent_count.min(substs.len())];
135
136 match key.disambiguated_data.data {
137 // Closures' own generics are only captures, don't print them.
138 DefPathData::ClosureExpr => {}
139
140 // If we have any generic arguments to print, we do that
141 // on top of the same path, but without its own generics.
dfeec247
XL
142 _ => {
143 if !generics.params.is_empty() && substs.len() >= generics.count() {
144 let args = self.generic_args_to_print(generics, substs);
145 return self.path_generic_args(
146 |cx| cx.print_def_path(def_id, parent_substs),
147 args,
148 );
149 }
532ac7d7
XL
150 }
151 }
152
153 // FIXME(eddyb) try to move this into the parent's printing
154 // logic, instead of doing it when printing the child.
dfeec247
XL
155 trait_qualify_parent = generics.has_self
156 && generics.parent == Some(parent_def_id)
157 && parent_substs.len() == generics.parent_count
158 && self.tcx().generics_of(parent_def_id).parent_count == 0;
532ac7d7
XL
159 }
160
161 self.path_append(
dfeec247
XL
162 |cx: Self| {
163 if trait_qualify_parent {
164 let trait_ref = ty::TraitRef::new(
165 parent_def_id,
166 cx.tcx().intern_substs(parent_substs),
167 );
168 cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
169 } else {
170 cx.print_def_path(parent_def_id, parent_substs)
171 }
532ac7d7
XL
172 },
173 &key.disambiguated_data,
174 )
175 }
176 }
177 }
178
179 fn generic_args_to_print(
180 &self,
181 generics: &'tcx ty::Generics,
e74abb32
XL
182 substs: &'tcx [GenericArg<'tcx>],
183 ) -> &'tcx [GenericArg<'tcx>] {
532ac7d7
XL
184 let mut own_params = generics.parent_count..generics.count();
185
186 // Don't print args for `Self` parameters (of traits).
187 if generics.has_self && own_params.start == 0 {
188 own_params.start = 1;
189 }
190
191 // Don't print args that are the defaults of their respective parameters.
dfeec247
XL
192 own_params.end -= generics
193 .params
194 .iter()
195 .rev()
cdc7bbd5
XL
196 .take_while(|param| match param.kind {
197 ty::GenericParamDefKind::Lifetime => false,
198 ty::GenericParamDefKind::Type { has_default, .. } => {
199 has_default
200 && substs[param.index as usize]
201 == GenericArg::from(
202 self.tcx().type_of(param.def_id).subst(self.tcx(), substs),
203 )
204 }
205 ty::GenericParamDefKind::Const { has_default } => {
206 has_default
207 && substs[param.index as usize]
208 == GenericArg::from(self.tcx().const_param_default(param.def_id))
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>,
29967ef6 274 visited: &mut SsoHashSet<Ty<'a>>,
6c58768f 275) -> Option<DefId> {
1b1a35ee 276 match *ty.kind() {
5e7ed085 277 ty::Adt(adt_def, _) => Some(adt_def.did()),
532ac7d7
XL
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 289 ty::Tuple(ref tys) => tys.iter().find_map(|ty| {
6c58768f
XL
290 if visited.insert(ty) {
291 return characteristic_def_id_of_type_cached(ty, visited);
292 }
293 return None;
294 }),
dfeec247
XL
295
296 ty::FnDef(def_id, _)
297 | ty::Closure(def_id, _)
298 | ty::Generator(def_id, _, _)
299 | ty::Foreign(def_id) => Some(def_id),
300
301 ty::Bool
302 | ty::Char
303 | ty::Int(_)
304 | ty::Uint(_)
305 | ty::Str
306 | ty::FnPtr(_)
307 | ty::Projection(_)
308 | ty::Placeholder(..)
dfeec247
XL
309 | ty::Param(_)
310 | ty::Opaque(..)
311 | ty::Infer(_)
312 | ty::Bound(..)
f035d41b 313 | ty::Error(_)
dfeec247
XL
314 | ty::GeneratorWitness(..)
315 | ty::Never
316 | ty::Float(_) => None,
532ac7d7
XL
317 }
318}
6c58768f 319pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
29967ef6 320 characteristic_def_id_of_type_cached(ty, &mut SsoHashSet::new())
6c58768f 321}
532ac7d7 322
dc9dc135 323impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'_> {
532ac7d7
XL
324 type Output = P::Region;
325 type Error = P::Error;
326 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
5099ac24 327 cx.print_region(*self)
532ac7d7
XL
328 }
329}
330
dc9dc135 331impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
532ac7d7
XL
332 type Output = P::Type;
333 type Error = P::Error;
334 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
5099ac24 335 cx.print_type(*self)
532ac7d7
XL
336 }
337}
338
fc512014 339impl<'tcx, P: Printer<'tcx>> Print<'tcx, P>
cdc7bbd5 340 for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>
fc512014 341{
532ac7d7
XL
342 type Output = P::DynExistential;
343 type Error = P::Error;
344 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
345 cx.print_dyn_existential(self)
346 }
347}
dc9dc135 348
5099ac24 349impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> {
dc9dc135
XL
350 type Output = P::Const;
351 type Error = P::Error;
352 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
5099ac24 353 cx.print_const(*self)
dc9dc135
XL
354 }
355}