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