Skip to main content

rustc_middle/ty/print/
mod.rs

1use hir::def::Namespace;
2use rustc_data_structures::fx::FxHashSet;
3use rustc_data_structures::sso::SsoHashSet;
4use rustc_hir as hir;
5use rustc_hir::def_id::{CrateNum, DefId};
6use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
7use tracing::{debug, instrument, trace};
8
9use crate::ty::{self, GenericArg, Ty, TyCtxt};
10
11// `pretty` is a separate module only for organization.
12mod pretty;
13pub use self::pretty::*;
14use super::Lift;
15
16pub type PrintError = std::fmt::Error;
17
18pub trait Print<'tcx, P> {
19    fn print(&self, p: &mut P) -> Result<(), PrintError>;
20}
21
22/// A trait that "prints" user-facing type system entities: paths, types, lifetimes, constants,
23/// etc. "Printing" here means building up a representation of the entity's path, usually as a
24/// `String` (e.g. "std::io::Read") or a `Vec<Symbol>` (e.g. `[sym::std, sym::io, sym::Read]`). The
25/// representation is built up by appending one or more pieces. The specific details included in
26/// the built-up representation depend on the purpose of the printer. The more advanced printers
27/// also rely on the `PrettyPrinter` sub-trait.
28pub trait Printer<'tcx>: Sized {
29    fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
30
31    /// Appends a representation of an entity with a normal path, e.g. "std::io::Read".
32    fn print_def_path(
33        &mut self,
34        def_id: DefId,
35        args: &'tcx [GenericArg<'tcx>],
36    ) -> Result<(), PrintError> {
37        self.default_print_def_path(def_id, args)
38    }
39
40    /// Like `print_def_path`, but for `DefPathData::Impl`.
41    fn print_impl_path(
42        &mut self,
43        impl_def_id: DefId,
44        args: &'tcx [GenericArg<'tcx>],
45    ) -> Result<(), PrintError> {
46        let tcx = self.tcx();
47        let self_ty = tcx.type_of(impl_def_id);
48        let impl_trait_ref = tcx.impl_opt_trait_ref(impl_def_id);
49        let (self_ty, impl_trait_ref) = if tcx.generics_of(impl_def_id).count() <= args.len() {
50            (
51                self_ty.instantiate(tcx, args).skip_norm_wip(),
52                impl_trait_ref
53                    .map(|impl_trait_ref| impl_trait_ref.instantiate(tcx, args).skip_norm_wip()),
54            )
55        } else {
56            // We are probably printing a nested item inside of an impl.
57            // Use the identity substitutions for the impl.
58            (
59                self_ty.instantiate_identity().skip_norm_wip(),
60                impl_trait_ref
61                    .map(|impl_trait_ref| impl_trait_ref.instantiate_identity().skip_norm_wip()),
62            )
63        };
64
65        self.default_print_impl_path(impl_def_id, self_ty, impl_trait_ref)
66    }
67
68    /// Appends a representation of a region.
69    fn print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), PrintError>;
70
71    /// Appends a representation of a type.
72    fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError>;
73
74    /// Appends a representation of a list of `PolyExistentialPredicate`s.
75    fn print_dyn_existential(
76        &mut self,
77        predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
78    ) -> Result<(), PrintError>;
79
80    /// Appends a representation of a const.
81    fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError>;
82
83    /// Appends a representation of a crate name, e.g. `std`, or even ``.
84    fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError>;
85
86    /// Appends a representation of a (full or partial) simple path, in two parts. `print_prefix`,
87    /// when called, appends the representation of the leading segments. The rest of the method
88    /// appends the representation of the final segment, the details of which are in
89    /// `disambiguated_data`.
90    ///
91    /// E.g. `std::io` + `Read` -> `std::io::Read`.
92    fn print_path_with_simple(
93        &mut self,
94        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
95        disambiguated_data: &DisambiguatedDefPathData,
96    ) -> Result<(), PrintError>;
97
98    /// Similar to `print_path_with_simple`, but the final segment is an `impl` segment.
99    ///
100    /// E.g. `slice` + `<impl [T]>` -> `slice::<impl [T]>`, which may then be further appended to,
101    /// giving a longer path representation such as `slice::<impl [T]>::to_vec_in::ConvertVec`.
102    fn print_path_with_impl(
103        &mut self,
104        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
105        self_ty: Ty<'tcx>,
106        trait_ref: Option<ty::TraitRef<'tcx>>,
107    ) -> Result<(), PrintError>;
108
109    /// Appends a representation of a path ending in generic args, in two parts. `print_prefix`,
110    /// when called, appends the leading segments. The rest of the method appends the
111    /// representation of the generic args. (Some printers choose to skip appending the generic
112    /// args.)
113    ///
114    /// E.g. `ImplementsTraitForUsize` + `<usize>` -> `ImplementsTraitForUsize<usize>`.
115    fn print_path_with_generic_args(
116        &mut self,
117        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
118        args: &[GenericArg<'tcx>],
119    ) -> Result<(), PrintError>;
120
121    /// Appends a representation of a qualified path segment, e.g. `<OsString as From<&T>>`.
122    /// If `trait_ref` is `None`, it may fall back to simpler forms, e.g. `<Vec<T>>` or just `Foo`.
123    fn print_path_with_qualified(
124        &mut self,
125        self_ty: Ty<'tcx>,
126        trait_ref: Option<ty::TraitRef<'tcx>>,
127    ) -> Result<(), PrintError>;
128
129    fn print_coroutine_with_kind(
130        &mut self,
131        def_id: DefId,
132        parent_args: &'tcx [GenericArg<'tcx>],
133        kind: Ty<'tcx>,
134    ) -> Result<(), PrintError> {
135        self.print_path_with_generic_args(|p| p.print_def_path(def_id, parent_args), &[kind.into()])
136    }
137
138    fn reset_path(&mut self) -> Result<(), PrintError> {
139        Ok(())
140    }
141
142    fn should_omit_parent_def_path(&self, _parent_def_id: DefId) -> bool {
143        false
144    }
145
146    // Defaults (should not be overridden):
147    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("default_print_def_path",
                                    "rustc_middle::ty::print", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/print/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(147u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_middle::ty::print"),
                                    ::tracing_core::field::FieldSet::new(&["def_id", "args"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&args)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Result<(), PrintError> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let key = self.tcx().def_key(def_id);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/ty/print/mod.rs:154",
                                    "rustc_middle::ty::print", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/print/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(154u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_middle::ty::print"),
                                    ::tracing_core::field::FieldSet::new(&["key"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&key) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            match key.disambiguated_data.data {
                DefPathData::CrateRoot => {
                    if !key.parent.is_none() {
                        ::core::panicking::panic("assertion failed: key.parent.is_none()")
                    };
                    self.print_crate_name(def_id.krate)
                }
                DefPathData::Impl => self.print_impl_path(def_id, args),
                _ => {
                    let parent_def_id =
                        DefId { index: key.parent.unwrap(), ..def_id };
                    let mut parent_args = args;
                    let mut trait_qualify_parent = false;
                    if !args.is_empty() {
                        let generics = self.tcx().generics_of(def_id);
                        parent_args =
                            &args[..generics.parent_count.min(args.len())];
                        match key.disambiguated_data.data {
                            DefPathData::Closure => {
                                if let Some(hir::CoroutineKind::Desugared(_,
                                            hir::CoroutineSource::Closure)) =
                                            self.tcx().coroutine_kind(def_id) &&
                                        args.len() > parent_args.len() {
                                    return self.print_coroutine_with_kind(def_id, parent_args,
                                            args[parent_args.len()].expect_ty());
                                } else {}
                            }
                            DefPathData::SyntheticCoroutineBody => {}
                            DefPathData::AnonConst => {}
                            _ => {
                                if !generics.is_own_empty() &&
                                        args.len() >= generics.count() {
                                    let args = generics.own_args_no_defaults(self.tcx(), args);
                                    return self.print_path_with_generic_args(|p|
                                                p.print_def_path(def_id, parent_args), args);
                                }
                            }
                        }
                        trait_qualify_parent =
                            generics.has_self && generics.parent == Some(parent_def_id)
                                    && parent_args.len() == generics.parent_count &&
                                self.tcx().generics_of(parent_def_id).parent_count == 0;
                    }
                    let omit_parent =
                        #[allow(non_exhaustive_omitted_patterns)] match key.disambiguated_data.data
                                {
                                DefPathData::TypeNs(..) => true,
                                _ => false,
                            } && self.should_omit_parent_def_path(parent_def_id);
                    self.print_path_with_simple(|p: &mut Self|
                            {
                                if omit_parent {
                                    p.reset_path()?;
                                    Ok(())
                                } else if trait_qualify_parent {
                                    let trait_ref =
                                        ty::TraitRef::new(p.tcx(), parent_def_id,
                                            parent_args.iter().copied());
                                    p.print_path_with_qualified(trait_ref.self_ty(),
                                        Some(trait_ref))
                                } else { p.print_def_path(parent_def_id, parent_args) }
                            }, &key.disambiguated_data)
                }
            }
        }
    }
}#[instrument(skip(self), level = "debug")]
148    fn default_print_def_path(
149        &mut self,
150        def_id: DefId,
151        args: &'tcx [GenericArg<'tcx>],
152    ) -> Result<(), PrintError> {
153        let key = self.tcx().def_key(def_id);
154        debug!(?key);
155
156        match key.disambiguated_data.data {
157            DefPathData::CrateRoot => {
158                assert!(key.parent.is_none());
159                self.print_crate_name(def_id.krate)
160            }
161
162            DefPathData::Impl => self.print_impl_path(def_id, args),
163
164            _ => {
165                let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
166
167                let mut parent_args = args;
168                let mut trait_qualify_parent = false;
169                if !args.is_empty() {
170                    let generics = self.tcx().generics_of(def_id);
171                    parent_args = &args[..generics.parent_count.min(args.len())];
172
173                    match key.disambiguated_data.data {
174                        DefPathData::Closure => {
175                            // We need to additionally print the `kind` field of a coroutine if
176                            // it is desugared from a coroutine-closure.
177                            if let Some(hir::CoroutineKind::Desugared(
178                                _,
179                                hir::CoroutineSource::Closure,
180                            )) = self.tcx().coroutine_kind(def_id)
181                                && args.len() > parent_args.len()
182                            {
183                                return self.print_coroutine_with_kind(
184                                    def_id,
185                                    parent_args,
186                                    args[parent_args.len()].expect_ty(),
187                                );
188                            } else {
189                                // Closures' own generics are only captures, don't print them.
190                            }
191                        }
192                        DefPathData::SyntheticCoroutineBody => {
193                            // Synthetic coroutine bodies have no distinct generics, since like
194                            // closures they're all just internal state of the coroutine.
195                        }
196                        // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
197                        // Anon consts doesn't have their own generics, and inline consts' own
198                        // generics are their inferred types, so don't print them.
199                        DefPathData::AnonConst => {}
200
201                        // If we have any generic arguments to print, we do that
202                        // on top of the same path, but without its own generics.
203                        _ => {
204                            if !generics.is_own_empty() && args.len() >= generics.count() {
205                                let args = generics.own_args_no_defaults(self.tcx(), args);
206                                return self.print_path_with_generic_args(
207                                    |p| p.print_def_path(def_id, parent_args),
208                                    args,
209                                );
210                            }
211                        }
212                    }
213
214                    // FIXME(eddyb) try to move this into the parent's printing
215                    // logic, instead of doing it when printing the child.
216                    trait_qualify_parent = generics.has_self
217                        && generics.parent == Some(parent_def_id)
218                        && parent_args.len() == generics.parent_count
219                        && self.tcx().generics_of(parent_def_id).parent_count == 0;
220                }
221
222                let omit_parent = matches!(key.disambiguated_data.data, DefPathData::TypeNs(..))
223                    && self.should_omit_parent_def_path(parent_def_id);
224
225                self.print_path_with_simple(
226                    |p: &mut Self| {
227                        if omit_parent {
228                            p.reset_path()?;
229                            Ok(())
230                        } else if trait_qualify_parent {
231                            let trait_ref = ty::TraitRef::new(
232                                p.tcx(),
233                                parent_def_id,
234                                parent_args.iter().copied(),
235                            );
236                            p.print_path_with_qualified(trait_ref.self_ty(), Some(trait_ref))
237                        } else {
238                            p.print_def_path(parent_def_id, parent_args)
239                        }
240                    },
241                    &key.disambiguated_data,
242                )
243            }
244        }
245    }
246
247    fn default_print_impl_path(
248        &mut self,
249        impl_def_id: DefId,
250        self_ty: Ty<'tcx>,
251        impl_trait_ref: Option<ty::TraitRef<'tcx>>,
252    ) -> Result<(), PrintError> {
253        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/ty/print/mod.rs:253",
                        "rustc_middle::ty::print", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/print/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(253u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::ty::print"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("default_print_impl_path: impl_def_id={0:?}, self_ty={1}, impl_trait_ref={2:?}",
                                                    impl_def_id, self_ty, impl_trait_ref) as &dyn Value))])
            });
    } else { ; }
};debug!(
254            "default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
255            impl_def_id, self_ty, impl_trait_ref
256        );
257
258        let key = self.tcx().def_key(impl_def_id);
259        let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
260
261        // Decide whether to print the parent path for the impl.
262        // Logically, since impls are global, it's never needed, but
263        // users may find it useful. Currently, we omit the parent if
264        // the impl is either in the same module as the self-type or
265        // as the trait.
266        let in_self_mod = match characteristic_def_id_of_type(self_ty) {
267            None => false,
268            Some(ty_def_id) => self.tcx().parent(ty_def_id) == parent_def_id,
269        };
270        let in_trait_mod = match impl_trait_ref {
271            None => false,
272            Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == parent_def_id,
273        };
274
275        if !in_self_mod && !in_trait_mod {
276            // If the impl is not co-located with either self-type or
277            // trait-type, then fallback to a format that identifies
278            // the module more clearly.
279            self.print_path_with_impl(
280                |p| p.print_def_path(parent_def_id, &[]),
281                self_ty,
282                impl_trait_ref,
283            )
284        } else {
285            // Otherwise, try to give a good form that would be valid language
286            // syntax. Preferably using associated item notation.
287            self.print_path_with_qualified(self_ty, impl_trait_ref)
288        }
289    }
290}
291
292/// As a heuristic, when we see an impl, if we see that the
293/// 'self type' is a type defined in the same module as the impl,
294/// we can omit including the path to the impl itself. This
295/// function tries to find a "characteristic `DefId`" for a
296/// type. It's just a heuristic so it makes some questionable
297/// decisions and we may want to adjust it later.
298///
299/// Visited set is needed to avoid full iteration over
300/// deeply nested tuples that have no DefId.
301fn characteristic_def_id_of_type_cached<'a>(
302    ty: Ty<'a>,
303    visited: &mut SsoHashSet<Ty<'a>>,
304) -> Option<DefId> {
305    match *ty.kind() {
306        ty::Adt(adt_def, _) => Some(adt_def.did()),
307
308        ty::Dynamic(data, ..) => data.principal_def_id(),
309
310        ty::Pat(subty, _) | ty::Array(subty, _) | ty::Slice(subty) => {
311            characteristic_def_id_of_type_cached(subty, visited)
312        }
313
314        ty::RawPtr(ty, _) => characteristic_def_id_of_type_cached(ty, visited),
315
316        ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited),
317
318        ty::Tuple(tys) => tys.iter().find_map(|ty| {
319            if visited.insert(ty) {
320                return characteristic_def_id_of_type_cached(ty, visited);
321            }
322            return None;
323        }),
324
325        ty::FnDef(def_id, _)
326        | ty::Closure(def_id, _)
327        | ty::CoroutineClosure(def_id, _)
328        | ty::Coroutine(def_id, _)
329        | ty::CoroutineWitness(def_id, _)
330        | ty::Foreign(def_id) => Some(def_id),
331
332        ty::Bool
333        | ty::Char
334        | ty::Int(_)
335        | ty::Uint(_)
336        | ty::Str
337        | ty::FnPtr(..)
338        | ty::UnsafeBinder(_)
339        | ty::Alias(..)
340        | ty::Placeholder(..)
341        | ty::Param(_)
342        | ty::Infer(_)
343        | ty::Bound(..)
344        | ty::Error(_)
345        | ty::Never
346        | ty::Float(_) => None,
347    }
348}
349pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
350    characteristic_def_id_of_type_cached(ty, &mut SsoHashSet::new())
351}
352
353impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> {
354    fn print(&self, p: &mut P) -> Result<(), PrintError> {
355        p.print_region(*self)
356    }
357}
358
359impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
360    fn print(&self, p: &mut P) -> Result<(), PrintError> {
361        p.print_type(*self)
362    }
363}
364
365impl<'tcx, P: Printer<'tcx> + std::fmt::Write> Print<'tcx, P> for ty::Instance<'tcx> {
366    fn print(&self, cx: &mut P) -> Result<(), PrintError> {
367        cx.print_def_path(self.def_id(), self.args)?;
368        match self.def {
369            ty::InstanceKind::Item(_) => {}
370            ty::InstanceKind::VTableShim(_) => cx.write_str(" - shim(vtable)")?,
371            ty::InstanceKind::ReifyShim(_, None) => cx.write_str(" - shim(reify)")?,
372            ty::InstanceKind::ReifyShim(_, Some(ty::ReifyReason::FnPtr)) => {
373                cx.write_str(" - shim(reify-fnptr)")?
374            }
375            ty::InstanceKind::ReifyShim(_, Some(ty::ReifyReason::Vtable)) => {
376                cx.write_str(" - shim(reify-vtable)")?
377            }
378            ty::InstanceKind::ThreadLocalShim(_) => cx.write_str(" - shim(tls)")?,
379            ty::InstanceKind::Intrinsic(_) => cx.write_str(" - intrinsic")?,
380            ty::InstanceKind::Virtual(_, num) => cx.write_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" - virtual#{0}", num))
    })format!(" - virtual#{num}"))?,
381            ty::InstanceKind::FnPtrShim(_, ty) => cx.write_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" - shim({0})", ty))
    })format!(" - shim({ty})"))?,
382            ty::InstanceKind::ClosureOnceShim { .. } => cx.write_str(" - shim")?,
383            ty::InstanceKind::ConstructCoroutineInClosureShim { .. } => cx.write_str(" - shim")?,
384            ty::InstanceKind::DropGlue(_, None) => cx.write_str(" - shim(None)")?,
385            ty::InstanceKind::DropGlue(_, Some(ty)) => {
386                cx.write_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" - shim(Some({0}))", ty))
    })format!(" - shim(Some({ty}))"))?
387            }
388            ty::InstanceKind::CloneShim(_, ty) => cx.write_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" - shim({0})", ty))
    })format!(" - shim({ty})"))?,
389            ty::InstanceKind::FnPtrAddrShim(_, ty) => cx.write_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" - shim({0})", ty))
    })format!(" - shim({ty})"))?,
390            ty::InstanceKind::FutureDropPollShim(_, proxy_ty, impl_ty) => {
391                cx.write_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" - dropshim({0}-{1})", proxy_ty,
                impl_ty))
    })format!(" - dropshim({proxy_ty}-{impl_ty})"))?
392            }
393            ty::InstanceKind::AsyncDropGlue(_, ty) => cx.write_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" - shim({0})", ty))
    })format!(" - shim({ty})"))?,
394            ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) => {
395                cx.write_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" - shim(Some({0}))", ty))
    })format!(" - shim(Some({ty}))"))?
396            }
397        };
398        Ok(())
399    }
400}
401
402impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
403    fn print(&self, p: &mut P) -> Result<(), PrintError> {
404        p.print_dyn_existential(self)
405    }
406}
407
408impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> {
409    fn print(&self, p: &mut P) -> Result<(), PrintError> {
410        p.print_const(*self)
411    }
412}
413
414impl<T> rustc_type_ir::ir_print::IrPrint<T> for TyCtxt<'_>
415where
416    T: Copy + for<'a, 'tcx> Lift<TyCtxt<'tcx>, Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>>,
417{
418    fn print(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
419        ty::tls::with(|tcx| {
420            let mut p = FmtPrinter::new(tcx, Namespace::TypeNS);
421            tcx.lift(*t).expect("could not lift for printing").print(&mut p)?;
422            fmt.write_str(&p.into_buffer())?;
423            Ok(())
424        })
425    }
426
427    fn print_debug(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
428        { let _guard = NoTrimmedGuard::new(); Self::print(t, fmt) }with_no_trimmed_paths!(Self::print(t, fmt))
429    }
430}