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 {
35 fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
40 substs: &'tcx [Kind<'tcx>],
41 ) -> Result<Self::Path, Self::Error> {
42 self.default_print_def_path(def_id, substs)
47 substs: &'tcx [Kind<'tcx>],
49 trait_ref: Option<ty::TraitRef<'tcx>>,
50 ) -> Result<Self::Path, Self::Error> {
51 self.default_print_impl_path(impl_def_id, substs, self_ty, trait_ref)
56 region: ty::Region<'_>,
57 ) -> Result<Self::Region, Self::Error>;
62 ) -> Result<Self::Type, Self::Error>;
64 fn print_dyn_existential(
66 predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
67 ) -> Result<Self::DynExistential, Self::Error>;
72 ) -> Result<Self::Path, Self::Error>;
76 trait_ref: Option<ty::TraitRef<'tcx>>,
77 ) -> Result<Self::Path, Self::Error>;
81 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
82 disambiguated_data: &DisambiguatedDefPathData,
84 trait_ref: Option<ty::TraitRef<'tcx>>,
85 ) -> Result<Self::Path, Self::Error>;
88 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
89 disambiguated_data: &DisambiguatedDefPathData,
90 ) -> Result<Self::Path, Self::Error>;
93 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
95 ) -> Result<Self::Path, Self::Error>;
97 // Defaults (should not be overriden):
99 fn default_print_def_path(
102 substs: &'tcx [Kind<'tcx>],
103 ) -> Result<Self::Path, Self::Error> {
104 debug!("default_print_def_path: def_id={:?}, substs={:?}", def_id, substs);
105 let key = self.tcx().def_key(def_id);
106 debug!("default_print_def_path: key={:?}", key);
108 match key.disambiguated_data.data {
109 DefPathData::CrateRoot => {
110 assert!(key.parent.is_none());
111 self.path_crate(def_id.krate)
114 DefPathData::Impl => {
115 let generics = self.tcx().generics_of(def_id);
116 let mut self_ty = self.tcx().type_of(def_id);
117 let mut impl_trait_ref = self.tcx().impl_trait_ref(def_id);
118 if substs.len() >= generics.count() {
119 self_ty = self_ty.subst(self.tcx(), substs);
120 impl_trait_ref = impl_trait_ref.subst(self.tcx(), substs);
122 self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
126 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
128 let mut parent_substs = substs;
129 let mut trait_qualify_parent = false;
130 if !substs.is_empty() {
131 let generics = self.tcx().generics_of(def_id);
132 parent_substs = &substs[..generics.parent_count.min(substs.len())];
134 match key.disambiguated_data.data {
135 // Closures' own generics are only captures, don't print them.
136 DefPathData::ClosureExpr => {}
138 // If we have any generic arguments to print, we do that
139 // on top of the same path, but without its own generics.
140 _ => if !generics.params.is_empty() && substs.len() >= generics.count() {
141 let args = self.generic_args_to_print(generics, substs);
142 return self.path_generic_args(
143 |cx| cx.print_def_path(def_id, parent_substs),
149 // FIXME(eddyb) try to move this into the parent's printing
150 // logic, instead of doing it when printing the child.
151 trait_qualify_parent =
153 generics.parent == Some(parent_def_id) &&
154 parent_substs.len() == generics.parent_count &&
155 self.tcx().generics_of(parent_def_id).parent_count == 0;
159 |cx: Self| if trait_qualify_parent {
160 let trait_ref = ty::TraitRef::new(
162 cx.tcx().intern_substs(parent_substs),
164 cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
166 cx.print_def_path(parent_def_id, parent_substs)
168 &key.disambiguated_data,
174 fn generic_args_to_print(
176 generics: &'tcx ty::Generics,
177 substs: &'tcx [Kind<'tcx>],
178 ) -> &'tcx [Kind<'tcx>] {
179 let mut own_params = generics.parent_count..generics.count();
181 // Don't print args for `Self` parameters (of traits).
182 if generics.has_self && own_params.start == 0 {
183 own_params.start = 1;
186 // Don't print args that are the defaults of their respective parameters.
187 own_params.end -= generics.params.iter().rev().take_while(|param| {
189 ty::GenericParamDefKind::Lifetime => false,
190 ty::GenericParamDefKind::Type { has_default, .. } => {
191 has_default && substs[param.index as usize] == Kind::from(
192 self.tcx().type_of(param.def_id).subst(self.tcx(), substs)
195 ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
202 fn default_print_impl_path(
205 _substs: &'tcx [Kind<'tcx>],
207 impl_trait_ref: Option<ty::TraitRef<'tcx>>,
208 ) -> Result<Self::Path, Self::Error> {
209 debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
210 impl_def_id, self_ty, impl_trait_ref);
212 let key = self.tcx().def_key(impl_def_id);
213 let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
215 // Decide whether to print the parent path for the impl.
216 // Logically, since impls are global, it's never needed, but
217 // users may find it useful. Currently, we omit the parent if
218 // the impl is either in the same module as the self-type or
220 let in_self_mod = match characteristic_def_id_of_type(self_ty) {
222 Some(ty_def_id) => self.tcx().parent(ty_def_id) == Some(parent_def_id),
224 let in_trait_mod = match impl_trait_ref {
226 Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == Some(parent_def_id),
229 if !in_self_mod && !in_trait_mod {
230 // If the impl is not co-located with either self-type or
231 // trait-type, then fallback to a format that identifies
232 // the module more clearly.
233 self.path_append_impl(
234 |cx| cx.print_def_path(parent_def_id, &[]),
235 &key.disambiguated_data,
240 // Otherwise, try to give a good form that would be valid language
241 // syntax. Preferably using associated item notation.
242 self.path_qualified(self_ty, impl_trait_ref)
247 /// As a heuristic, when we see an impl, if we see that the
248 /// 'self type' is a type defined in the same module as the impl,
249 /// we can omit including the path to the impl itself. This
250 /// function tries to find a "characteristic `DefId`" for a
251 /// type. It's just a heuristic so it makes some questionable
252 /// decisions and we may want to adjust it later.
253 pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
255 ty::Adt(adt_def, _) => Some(adt_def.did),
257 ty::Dynamic(data, ..) => data.principal_def_id(),
259 ty::Array(subty, _) |
260 ty::Slice(subty) => characteristic_def_id_of_type(subty),
262 ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
264 ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
266 ty::Tuple(ref tys) => tys.iter()
267 .filter_map(|ty| characteristic_def_id_of_type(ty.expect_ty()))
270 ty::FnDef(def_id, _) |
271 ty::Closure(def_id, _) |
272 ty::Generator(def_id, _, _) |
273 ty::Foreign(def_id) => Some(def_id),
282 ty::Placeholder(..) |
283 ty::UnnormalizedProjection(..) |
289 ty::GeneratorWitness(..) |
291 ty::Float(_) => None,
295 impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for ty::RegionKind {
296 type Output = P::Region;
297 type Error = P::Error;
298 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
299 cx.print_region(self)
303 impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for ty::Region<'_> {
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<'tcx> {
312 type Output = P::Type;
313 type Error = P::Error;
314 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
319 impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P>
320 for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
322 type Output = P::DynExistential;
323 type Error = P::Error;
324 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
325 cx.print_dyn_existential(self)