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};
6 use rustc_data_structures::fx::FxHashSet;
8 // `pretty` is a separate module only for organization.
10 pub use self::pretty::*;
14 pub trait Print<'gcx, 'tcx, P> {
18 fn print(&self, cx: P) -> Result<Self::Output, Self::Error>;
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.
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 {
38 fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
43 substs: &'tcx [Kind<'tcx>],
44 ) -> Result<Self::Path, Self::Error> {
45 self.default_print_def_path(def_id, substs)
50 substs: &'tcx [Kind<'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)
59 region: ty::Region<'_>,
60 ) -> Result<Self::Region, Self::Error>;
65 ) -> Result<Self::Type, Self::Error>;
67 fn print_dyn_existential(
69 predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
70 ) -> Result<Self::DynExistential, Self::Error>;
74 ct: &'tcx ty::Const<'tcx>,
75 ) -> Result<Self::Const, Self::Error>;
80 ) -> Result<Self::Path, Self::Error>;
84 trait_ref: Option<ty::TraitRef<'tcx>>,
85 ) -> Result<Self::Path, Self::Error>;
89 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
90 disambiguated_data: &DisambiguatedDefPathData,
92 trait_ref: Option<ty::TraitRef<'tcx>>,
93 ) -> Result<Self::Path, Self::Error>;
96 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
97 disambiguated_data: &DisambiguatedDefPathData,
98 ) -> Result<Self::Path, Self::Error>;
101 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
103 ) -> Result<Self::Path, Self::Error>;
105 // Defaults (should not be overriden):
107 fn default_print_def_path(
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);
116 match key.disambiguated_data.data {
117 DefPathData::CrateRoot => {
118 assert!(key.parent.is_none());
119 self.path_crate(def_id.krate)
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);
130 self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
134 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
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())];
142 match key.disambiguated_data.data {
143 // Closures' own generics are only captures, don't print them.
144 DefPathData::ClosureExpr => {}
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),
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 =
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;
167 |cx: Self| if trait_qualify_parent {
168 let trait_ref = ty::TraitRef::new(
170 cx.tcx().intern_substs(parent_substs),
172 cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
174 cx.print_def_path(parent_def_id, parent_substs)
176 &key.disambiguated_data,
182 fn generic_args_to_print(
184 generics: &'tcx ty::Generics,
185 substs: &'tcx [Kind<'tcx>],
186 ) -> &'tcx [Kind<'tcx>] {
187 let mut own_params = generics.parent_count..generics.count();
189 // Don't print args for `Self` parameters (of traits).
190 if generics.has_self && own_params.start == 0 {
191 own_params.start = 1;
194 // Don't print args that are the defaults of their respective parameters.
195 own_params.end -= generics.params.iter().rev().take_while(|param| {
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)
203 ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
210 fn default_print_impl_path(
213 _substs: &'tcx [Kind<'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);
220 let key = self.tcx().def_key(impl_def_id);
221 let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
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
228 let in_self_mod = match characteristic_def_id_of_type(self_ty) {
230 Some(ty_def_id) => self.tcx().parent(ty_def_id) == Some(parent_def_id),
232 let in_trait_mod = match impl_trait_ref {
234 Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == Some(parent_def_id),
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,
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)
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> {
263 ty::Adt(adt_def, _) => Some(adt_def.did),
265 ty::Dynamic(data, ..) => data.principal_def_id(),
267 ty::Array(subty, _) |
268 ty::Slice(subty) => characteristic_def_id_of_type(subty),
270 ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
272 ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
274 ty::Tuple(ref tys) => tys.iter()
275 .filter_map(|ty| characteristic_def_id_of_type(ty.expect_ty()))
278 ty::FnDef(def_id, _) |
279 ty::Closure(def_id, _) |
280 ty::Generator(def_id, _, _) |
281 ty::Foreign(def_id) => Some(def_id),
290 ty::Placeholder(..) |
291 ty::UnnormalizedProjection(..) |
297 ty::GeneratorWitness(..) |
299 ty::Float(_) => None,
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)
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)
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> {
327 impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P>
328 for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
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)
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> {