1 use crate::ty
::subst
::{GenericArg, Subst}
;
2 use crate::ty
::{self, DefIdTree, Ty, TyCtxt}
;
4 use rustc_data_structures
::fx
::FxHashSet
;
5 use rustc_data_structures
::sso
::SsoHashSet
;
6 use rustc_hir
::def_id
::{CrateNum, DefId}
;
7 use rustc_hir
::definitions
::{DefPathData, DisambiguatedDefPathData}
;
9 // `pretty` is a separate module only for organization.
11 pub use self::pretty
::*;
13 // FIXME(eddyb) false positive, the lifetime parameters are used with `P: Printer<...>`.
14 #[allow(unused_lifetimes)]
15 pub trait Print
<'tcx
, P
> {
19 fn print(&self, cx
: P
) -> Result
<Self::Output
, Self::Error
>;
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.
28 /// For pretty-printing/formatting in particular, see `PrettyPrinter`.
30 // FIXME(eddyb) find a better name; this is more general than "printing".
31 pub trait Printer
<'tcx
>: Sized
{
40 fn tcx(&'a
self) -> TyCtxt
<'tcx
>;
45 substs
: &'tcx
[GenericArg
<'tcx
>],
46 ) -> Result
<Self::Path
, Self::Error
> {
47 self.default_print_def_path(def_id
, substs
)
53 substs
: &'tcx
[GenericArg
<'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
)
60 fn print_region(self, region
: ty
::Region
<'_
>) -> Result
<Self::Region
, Self::Error
>;
62 fn print_type(self, ty
: Ty
<'tcx
>) -> Result
<Self::Type
, Self::Error
>;
64 fn print_dyn_existential(
66 predicates
: &'tcx ty
::List
<ty
::Binder
<ty
::ExistentialPredicate
<'tcx
>>>,
67 ) -> Result
<Self::DynExistential
, Self::Error
>;
69 fn print_const(self, ct
: &'tcx ty
::Const
<'tcx
>) -> Result
<Self::Const
, Self::Error
>;
71 fn path_crate(self, cnum
: CrateNum
) -> 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
>;
89 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
90 disambiguated_data
: &DisambiguatedDefPathData
,
91 ) -> Result
<Self::Path
, Self::Error
>;
95 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
96 args
: &[GenericArg
<'tcx
>],
97 ) -> Result
<Self::Path
, Self::Error
>;
99 // Defaults (should not be overridden):
101 fn default_print_def_path(
104 substs
: &'tcx
[GenericArg
<'tcx
>],
105 ) -> Result
<Self::Path
, Self::Error
> {
106 debug
!("default_print_def_path: def_id={:?}, substs={:?}", def_id
, substs
);
107 let key
= self.tcx().def_key(def_id
);
108 debug
!("default_print_def_path: key={:?}", key
);
110 match key
.disambiguated_data
.data
{
111 DefPathData
::CrateRoot
=> {
112 assert
!(key
.parent
.is_none());
113 self.path_crate(def_id
.krate
)
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
);
124 self.print_impl_path(def_id
, substs
, self_ty
, impl_trait_ref
)
128 let parent_def_id
= DefId { index: key.parent.unwrap(), ..def_id }
;
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())];
136 match key
.disambiguated_data
.data
{
137 // Closures' own generics are only captures, don't print them.
138 DefPathData
::ClosureExpr
=> {}
140 // If we have any generic arguments to print, we do that
141 // on top of the same path, but without its own generics.
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
),
153 // FIXME(eddyb) try to move this into the parent's printing
154 // logic, instead of doing it when printing the child.
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;
163 if trait_qualify_parent
{
164 let trait_ref
= ty
::TraitRef
::new(
166 cx
.tcx().intern_substs(parent_substs
),
168 cx
.path_qualified(trait_ref
.self_ty(), Some(trait_ref
))
170 cx
.print_def_path(parent_def_id
, parent_substs
)
173 &key
.disambiguated_data
,
179 fn generic_args_to_print(
181 generics
: &'tcx ty
::Generics
,
182 substs
: &'tcx
[GenericArg
<'tcx
>],
183 ) -> &'tcx
[GenericArg
<'tcx
>] {
184 let mut own_params
= generics
.parent_count
..generics
.count();
186 // Don't print args for `Self` parameters (of traits).
187 if generics
.has_self
&& own_params
.start
== 0 {
188 own_params
.start
= 1;
191 // Don't print args that are the defaults of their respective parameters.
192 own_params
.end
-= generics
196 .take_while(|param
| {
198 ty
::GenericParamDefKind
::Lifetime
=> false,
199 ty
::GenericParamDefKind
::Type { has_default, .. }
=> {
201 && substs
[param
.index
as usize]
203 self.tcx().type_of(param
.def_id
).subst(self.tcx(), substs
),
206 ty
::GenericParamDefKind
::Const
=> false, // FIXME(const_generics_defaults)
214 fn default_print_impl_path(
217 _substs
: &'tcx
[GenericArg
<'tcx
>],
219 impl_trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
220 ) -> Result
<Self::Path
, Self::Error
> {
222 "default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
223 impl_def_id
, self_ty
, impl_trait_ref
226 let key
= self.tcx().def_key(impl_def_id
);
227 let parent_def_id
= DefId { index: key.parent.unwrap(), ..impl_def_id }
;
229 // Decide whether to print the parent path for the impl.
230 // Logically, since impls are global, it's never needed, but
231 // users may find it useful. Currently, we omit the parent if
232 // the impl is either in the same module as the self-type or
234 let in_self_mod
= match characteristic_def_id_of_type(self_ty
) {
236 Some(ty_def_id
) => self.tcx().parent(ty_def_id
) == Some(parent_def_id
),
238 let in_trait_mod
= match impl_trait_ref
{
240 Some(trait_ref
) => self.tcx().parent(trait_ref
.def_id
) == Some(parent_def_id
),
243 if !in_self_mod
&& !in_trait_mod
{
244 // If the impl is not co-located with either self-type or
245 // trait-type, then fallback to a format that identifies
246 // the module more clearly.
247 self.path_append_impl(
248 |cx
| cx
.print_def_path(parent_def_id
, &[]),
249 &key
.disambiguated_data
,
254 // Otherwise, try to give a good form that would be valid language
255 // syntax. Preferably using associated item notation.
256 self.path_qualified(self_ty
, impl_trait_ref
)
261 /// As a heuristic, when we see an impl, if we see that the
262 /// 'self type' is a type defined in the same module as the impl,
263 /// we can omit including the path to the impl itself. This
264 /// function tries to find a "characteristic `DefId`" for a
265 /// type. It's just a heuristic so it makes some questionable
266 /// decisions and we may want to adjust it later.
268 /// Visited set is needed to avoid full iteration over
269 /// deeply nested tuples that have no DefId.
270 fn characteristic_def_id_of_type_cached
<'a
>(
272 visited
: &mut SsoHashSet
<Ty
<'a
>>,
275 ty
::Adt(adt_def
, _
) => Some(adt_def
.did
),
277 ty
::Dynamic(data
, ..) => data
.principal_def_id(),
279 ty
::Array(subty
, _
) | ty
::Slice(subty
) => {
280 characteristic_def_id_of_type_cached(subty
, visited
)
283 ty
::RawPtr(mt
) => characteristic_def_id_of_type_cached(mt
.ty
, visited
),
285 ty
::Ref(_
, ty
, _
) => characteristic_def_id_of_type_cached(ty
, visited
),
287 ty
::Tuple(ref tys
) => tys
.iter().find_map(|ty
| {
288 let ty
= ty
.expect_ty();
289 if visited
.insert(ty
) {
290 return characteristic_def_id_of_type_cached(ty
, visited
);
296 | ty
::Closure(def_id
, _
)
297 | ty
::Generator(def_id
, _
, _
)
298 | ty
::Foreign(def_id
) => Some(def_id
),
307 | ty
::Placeholder(..)
313 | ty
::GeneratorWitness(..)
315 | ty
::Float(_
) => None
,
318 pub fn characteristic_def_id_of_type(ty
: Ty
<'_
>) -> Option
<DefId
> {
319 characteristic_def_id_of_type_cached(ty
, &mut SsoHashSet
::new())
322 impl<'tcx
, P
: Printer
<'tcx
>> Print
<'tcx
, P
> for ty
::RegionKind
{
323 type Output
= P
::Region
;
324 type Error
= P
::Error
;
325 fn print(&self, cx
: P
) -> Result
<Self::Output
, Self::Error
> {
326 cx
.print_region(self)
330 impl<'tcx
, P
: Printer
<'tcx
>> Print
<'tcx
, P
> for ty
::Region
<'_
> {
331 type Output
= P
::Region
;
332 type Error
= P
::Error
;
333 fn print(&self, cx
: P
) -> Result
<Self::Output
, Self::Error
> {
334 cx
.print_region(self)
338 impl<'tcx
, P
: Printer
<'tcx
>> Print
<'tcx
, P
> for Ty
<'tcx
> {
339 type Output
= P
::Type
;
340 type Error
= P
::Error
;
341 fn print(&self, cx
: P
) -> Result
<Self::Output
, Self::Error
> {
346 impl<'tcx
, P
: Printer
<'tcx
>> Print
<'tcx
, P
>
347 for &'tcx ty
::List
<ty
::Binder
<ty
::ExistentialPredicate
<'tcx
>>>
349 type Output
= P
::DynExistential
;
350 type Error
= P
::Error
;
351 fn print(&self, cx
: P
) -> Result
<Self::Output
, Self::Error
> {
352 cx
.print_dyn_existential(self)
356 impl<'tcx
, P
: Printer
<'tcx
>> Print
<'tcx
, P
> for &'tcx ty
::Const
<'tcx
> {
357 type Output
= P
::Const
;
358 type Error
= P
::Error
;
359 fn print(&self, cx
: P
) -> Result
<Self::Output
, Self::Error
> {