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::*;
12 pub trait Print<'gcx, 'tcx, P> {
16 fn print(&self, cx: P) -> Result<Self::Output, Self::Error>;
19 /// Interface for outputting user-facing "type-system entities"
20 /// (paths, types, lifetimes, constants, etc.) as a side-effect
21 /// (e.g. formatting, like `PrettyPrinter` implementors do) or by
22 /// constructing some alternative representation (e.g. an AST),
23 /// which the associated types allow passing through the methods.
25 /// For pretty-printing/formatting in particular, see `PrettyPrinter`.
26 // FIXME(eddyb) find a better name, this is more general than "printing".
27 pub trait Printer<'gcx: 'tcx, 'tcx>: Sized {
36 fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
41 substs: &'tcx [Kind<'tcx>],
42 ) -> Result<Self::Path, Self::Error> {
43 self.default_print_def_path(def_id, substs)
48 substs: &'tcx [Kind<'tcx>],
50 trait_ref: Option<ty::TraitRef<'tcx>>,
51 ) -> Result<Self::Path, Self::Error> {
52 self.default_print_impl_path(impl_def_id, substs, self_ty, trait_ref)
57 region: ty::Region<'_>,
58 ) -> Result<Self::Region, Self::Error>;
63 ) -> Result<Self::Type, Self::Error>;
65 fn print_dyn_existential(
67 predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
68 ) -> Result<Self::DynExistential, Self::Error>;
72 ct: &'tcx ty::Const<'tcx>,
73 ) -> Result<Self::Const, Self::Error>;
78 ) -> Result<Self::Path, Self::Error>;
82 trait_ref: Option<ty::TraitRef<'tcx>>,
83 ) -> Result<Self::Path, Self::Error>;
87 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
88 disambiguated_data: &DisambiguatedDefPathData,
90 trait_ref: Option<ty::TraitRef<'tcx>>,
91 ) -> Result<Self::Path, Self::Error>;
94 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
95 disambiguated_data: &DisambiguatedDefPathData,
96 ) -> Result<Self::Path, Self::Error>;
99 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
101 ) -> Result<Self::Path, Self::Error>;
103 // Defaults (should not be overriden):
105 fn default_print_def_path(
108 substs: &'tcx [Kind<'tcx>],
109 ) -> Result<Self::Path, Self::Error> {
110 debug!("default_print_def_path: def_id={:?}, substs={:?}", def_id, substs);
111 let key = self.tcx().def_key(def_id);
112 debug!("default_print_def_path: key={:?}", key);
114 match key.disambiguated_data.data {
115 DefPathData::CrateRoot => {
116 assert!(key.parent.is_none());
117 self.path_crate(def_id.krate)
120 DefPathData::Impl => {
121 let generics = self.tcx().generics_of(def_id);
122 let mut self_ty = self.tcx().type_of(def_id);
123 let mut impl_trait_ref = self.tcx().impl_trait_ref(def_id);
124 if substs.len() >= generics.count() {
125 self_ty = self_ty.subst(self.tcx(), substs);
126 impl_trait_ref = impl_trait_ref.subst(self.tcx(), substs);
128 self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
132 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
134 let mut parent_substs = substs;
135 let mut trait_qualify_parent = false;
136 if !substs.is_empty() {
137 let generics = self.tcx().generics_of(def_id);
138 parent_substs = &substs[..generics.parent_count.min(substs.len())];
140 match key.disambiguated_data.data {
141 // Closures' own generics are only captures, don't print them.
142 DefPathData::ClosureExpr => {}
144 // If we have any generic arguments to print, we do that
145 // on top of the same path, but without its own generics.
146 _ => if !generics.params.is_empty() && substs.len() >= generics.count() {
147 let args = self.generic_args_to_print(generics, substs);
148 return self.path_generic_args(
149 |cx| cx.print_def_path(def_id, parent_substs),
155 // FIXME(eddyb) try to move this into the parent's printing
156 // logic, instead of doing it when printing the child.
157 trait_qualify_parent =
159 generics.parent == Some(parent_def_id) &&
160 parent_substs.len() == generics.parent_count &&
161 self.tcx().generics_of(parent_def_id).parent_count == 0;
165 |cx: Self| if trait_qualify_parent {
166 let trait_ref = ty::TraitRef::new(
168 cx.tcx().intern_substs(parent_substs),
170 cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
172 cx.print_def_path(parent_def_id, parent_substs)
174 &key.disambiguated_data,
180 fn generic_args_to_print(
182 generics: &'tcx ty::Generics,
183 substs: &'tcx [Kind<'tcx>],
184 ) -> &'tcx [Kind<'tcx>] {
185 let mut own_params = generics.parent_count..generics.count();
187 // Don't print args for `Self` parameters (of traits).
188 if generics.has_self && own_params.start == 0 {
189 own_params.start = 1;
192 // Don't print args that are the defaults of their respective parameters.
193 own_params.end -= generics.params.iter().rev().take_while(|param| {
195 ty::GenericParamDefKind::Lifetime => false,
196 ty::GenericParamDefKind::Type { has_default, .. } => {
197 has_default && substs[param.index as usize] == Kind::from(
198 self.tcx().type_of(param.def_id).subst(self.tcx(), substs)
201 ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
208 fn default_print_impl_path(
211 _substs: &'tcx [Kind<'tcx>],
213 impl_trait_ref: Option<ty::TraitRef<'tcx>>,
214 ) -> Result<Self::Path, Self::Error> {
215 debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
216 impl_def_id, self_ty, impl_trait_ref);
218 let key = self.tcx().def_key(impl_def_id);
219 let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
221 // Decide whether to print the parent path for the impl.
222 // Logically, since impls are global, it's never needed, but
223 // users may find it useful. Currently, we omit the parent if
224 // the impl is either in the same module as the self-type or
226 let in_self_mod = match characteristic_def_id_of_type(self_ty) {
228 Some(ty_def_id) => self.tcx().parent(ty_def_id) == Some(parent_def_id),
230 let in_trait_mod = match impl_trait_ref {
232 Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == Some(parent_def_id),
235 if !in_self_mod && !in_trait_mod {
236 // If the impl is not co-located with either self-type or
237 // trait-type, then fallback to a format that identifies
238 // the module more clearly.
239 self.path_append_impl(
240 |cx| cx.print_def_path(parent_def_id, &[]),
241 &key.disambiguated_data,
246 // Otherwise, try to give a good form that would be valid language
247 // syntax. Preferably using associated item notation.
248 self.path_qualified(self_ty, impl_trait_ref)
253 /// As a heuristic, when we see an impl, if we see that the
254 /// 'self type' is a type defined in the same module as the impl,
255 /// we can omit including the path to the impl itself. This
256 /// function tries to find a "characteristic `DefId`" for a
257 /// type. It's just a heuristic so it makes some questionable
258 /// decisions and we may want to adjust it later.
259 pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
261 ty::Adt(adt_def, _) => Some(adt_def.did),
263 ty::Dynamic(data, ..) => data.principal_def_id(),
265 ty::Array(subty, _) |
266 ty::Slice(subty) => characteristic_def_id_of_type(subty),
268 ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
270 ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
272 ty::Tuple(ref tys) => tys.iter()
273 .filter_map(|ty| characteristic_def_id_of_type(ty.expect_ty()))
276 ty::FnDef(def_id, _) |
277 ty::Closure(def_id, _) |
278 ty::Generator(def_id, _, _) |
279 ty::Foreign(def_id) => Some(def_id),
288 ty::Placeholder(..) |
289 ty::UnnormalizedProjection(..) |
295 ty::GeneratorWitness(..) |
297 ty::Float(_) => None,
301 impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for ty::RegionKind {
302 type Output = P::Region;
303 type Error = P::Error;
304 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
305 cx.print_region(self)
309 impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for ty::Region<'_> {
310 type Output = P::Region;
311 type Error = P::Error;
312 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
313 cx.print_region(self)
317 impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for Ty<'tcx> {
318 type Output = P::Type;
319 type Error = P::Error;
320 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
325 impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P>
326 for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
328 type Output = P::DynExistential;
329 type Error = P::Error;
330 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
331 cx.print_dyn_existential(self)
335 impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for &'tcx ty::Const<'tcx> {
336 type Output = P::Const;
337 type Error = P::Error;
338 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {