rustc_middle/ty/print/
pretty.rs

1use std::cell::Cell;
2use std::fmt::{self, Write as _};
3use std::iter;
4use std::ops::{Deref, DerefMut};
5
6use rustc_abi::{ExternAbi, Size};
7use rustc_apfloat::Float;
8use rustc_apfloat::ieee::{Double, Half, Quad, Single};
9use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
10use rustc_data_structures::unord::UnordMap;
11use rustc_hir as hir;
12use rustc_hir::LangItem;
13use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
14use rustc_hir::def_id::{CRATE_DEF_ID, DefIdMap, DefIdSet, LOCAL_CRATE, ModDefId};
15use rustc_hir::definitions::{DefKey, DefPathDataName};
16use rustc_macros::{Lift, extension};
17use rustc_session::Limit;
18use rustc_session::cstore::{ExternCrate, ExternCrateSource};
19use rustc_span::{FileNameDisplayPreference, Ident, Symbol, kw, sym};
20use rustc_type_ir::{Upcast as _, elaborate};
21use smallvec::SmallVec;
22
23// `pretty` is a separate module only for organization.
24use super::*;
25use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
26use crate::query::{IntoQueryParam, Providers};
27use crate::ty::{
28    ConstInt, Expr, GenericArgKind, ParamConst, ScalarInt, Term, TermKind, TraitPredicate,
29    TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
30};
31
32macro_rules! p {
33    (@$lit:literal) => {
34        write!(scoped_cx!(), $lit)?
35    };
36    (@write($($data:expr),+)) => {
37        write!(scoped_cx!(), $($data),+)?
38    };
39    (@print($x:expr)) => {
40        $x.print(scoped_cx!())?
41    };
42    (@$method:ident($($arg:expr),*)) => {
43        scoped_cx!().$method($($arg),*)?
44    };
45    ($($elem:tt $(($($args:tt)*))?),+) => {{
46        $(p!(@ $elem $(($($args)*))?);)+
47    }};
48}
49macro_rules! define_scoped_cx {
50    ($cx:ident) => {
51        macro_rules! scoped_cx {
52            () => {
53                $cx
54            };
55        }
56    };
57}
58
59thread_local! {
60    static FORCE_IMPL_FILENAME_LINE: Cell<bool> = const { Cell::new(false) };
61    static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
62    static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
63    static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
64    static REDUCED_QUERIES: Cell<bool> = const { Cell::new(false) };
65    static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
66}
67
68macro_rules! define_helper {
69    ($($(#[$a:meta])* fn $name:ident($helper:ident, $tl:ident);)+) => {
70        $(
71            #[must_use]
72            pub struct $helper(bool);
73
74            impl $helper {
75                pub fn new() -> $helper {
76                    $helper($tl.with(|c| c.replace(true)))
77                }
78            }
79
80            $(#[$a])*
81            pub macro $name($e:expr) {
82                {
83                    let _guard = $helper::new();
84                    $e
85                }
86            }
87
88            impl Drop for $helper {
89                fn drop(&mut self) {
90                    $tl.with(|c| c.set(self.0))
91                }
92            }
93
94            pub fn $name() -> bool {
95                $tl.with(|c| c.get())
96            }
97        )+
98    }
99}
100
101define_helper!(
102    /// Avoids running select queries during any prints that occur
103    /// during the closure. This may alter the appearance of some
104    /// types (e.g. forcing verbose printing for opaque types).
105    /// This method is used during some queries (e.g. `explicit_item_bounds`
106    /// for opaque types), to ensure that any debug printing that
107    /// occurs during the query computation does not end up recursively
108    /// calling the same query.
109    fn with_reduced_queries(ReducedQueriesGuard, REDUCED_QUERIES);
110    /// Force us to name impls with just the filename/line number. We
111    /// normally try to use types. But at some points, notably while printing
112    /// cycle errors, this can result in extra or suboptimal error output,
113    /// so this variable disables that check.
114    fn with_forced_impl_filename_line(ForcedImplGuard, FORCE_IMPL_FILENAME_LINE);
115    /// Adds the `crate::` prefix to paths where appropriate.
116    fn with_crate_prefix(CratePrefixGuard, SHOULD_PREFIX_WITH_CRATE);
117    /// Prevent path trimming if it is turned on. Path trimming affects `Display` impl
118    /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
119    /// if no other `Vec` is found.
120    fn with_no_trimmed_paths(NoTrimmedGuard, NO_TRIMMED_PATH);
121    fn with_forced_trimmed_paths(ForceTrimmedGuard, FORCE_TRIMMED_PATH);
122    /// Prevent selection of visible paths. `Display` impl of DefId will prefer
123    /// visible (public) reexports of types as paths.
124    fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
125);
126
127/// Avoids running any queries during prints.
128pub macro with_no_queries($e:expr) {{
129    $crate::ty::print::with_reduced_queries!($crate::ty::print::with_forced_impl_filename_line!(
130        $crate::ty::print::with_no_trimmed_paths!($crate::ty::print::with_no_visible_paths!(
131            $crate::ty::print::with_forced_impl_filename_line!($e)
132        ))
133    ))
134}}
135
136/// The "region highlights" are used to control region printing during
137/// specific error messages. When a "region highlight" is enabled, it
138/// gives an alternate way to print specific regions. For now, we
139/// always print those regions using a number, so something like "`'0`".
140///
141/// Regions not selected by the region highlight mode are presently
142/// unaffected.
143#[derive(Copy, Clone, Default)]
144pub struct RegionHighlightMode<'tcx> {
145    /// If enabled, when we see the selected region, use "`'N`"
146    /// instead of the ordinary behavior.
147    highlight_regions: [Option<(ty::Region<'tcx>, usize)>; 3],
148
149    /// If enabled, when printing a "free region" that originated from
150    /// the given `ty::BoundRegionKind`, print it as "`'1`". Free regions that would ordinarily
151    /// have names print as normal.
152    ///
153    /// This is used when you have a signature like `fn foo(x: &u32,
154    /// y: &'a u32)` and we want to give a name to the region of the
155    /// reference `x`.
156    highlight_bound_region: Option<(ty::BoundRegionKind, usize)>,
157}
158
159impl<'tcx> RegionHighlightMode<'tcx> {
160    /// If `region` and `number` are both `Some`, invokes
161    /// `highlighting_region`.
162    pub fn maybe_highlighting_region(
163        &mut self,
164        region: Option<ty::Region<'tcx>>,
165        number: Option<usize>,
166    ) {
167        if let Some(k) = region {
168            if let Some(n) = number {
169                self.highlighting_region(k, n);
170            }
171        }
172    }
173
174    /// Highlights the region inference variable `vid` as `'N`.
175    pub fn highlighting_region(&mut self, region: ty::Region<'tcx>, number: usize) {
176        let num_slots = self.highlight_regions.len();
177        let first_avail_slot =
178            self.highlight_regions.iter_mut().find(|s| s.is_none()).unwrap_or_else(|| {
179                bug!("can only highlight {} placeholders at a time", num_slots,)
180            });
181        *first_avail_slot = Some((region, number));
182    }
183
184    /// Convenience wrapper for `highlighting_region`.
185    pub fn highlighting_region_vid(
186        &mut self,
187        tcx: TyCtxt<'tcx>,
188        vid: ty::RegionVid,
189        number: usize,
190    ) {
191        self.highlighting_region(ty::Region::new_var(tcx, vid), number)
192    }
193
194    /// Returns `Some(n)` with the number to use for the given region, if any.
195    fn region_highlighted(&self, region: ty::Region<'tcx>) -> Option<usize> {
196        self.highlight_regions.iter().find_map(|h| match h {
197            Some((r, n)) if *r == region => Some(*n),
198            _ => None,
199        })
200    }
201
202    /// Highlight the given bound region.
203    /// We can only highlight one bound region at a time. See
204    /// the field `highlight_bound_region` for more detailed notes.
205    pub fn highlighting_bound_region(&mut self, br: ty::BoundRegionKind, number: usize) {
206        assert!(self.highlight_bound_region.is_none());
207        self.highlight_bound_region = Some((br, number));
208    }
209}
210
211/// Trait for printers that pretty-print using `fmt::Write` to the printer.
212pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
213    /// Like `print_def_path` but for value paths.
214    fn print_value_path(
215        &mut self,
216        def_id: DefId,
217        args: &'tcx [GenericArg<'tcx>],
218    ) -> Result<(), PrintError> {
219        self.print_def_path(def_id, args)
220    }
221
222    fn in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
223    where
224        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
225    {
226        value.as_ref().skip_binder().print(self)
227    }
228
229    fn wrap_binder<T, F: FnOnce(&T, &mut Self) -> Result<(), fmt::Error>>(
230        &mut self,
231        value: &ty::Binder<'tcx, T>,
232        f: F,
233    ) -> Result<(), PrintError>
234    where
235        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
236    {
237        f(value.as_ref().skip_binder(), self)
238    }
239
240    /// Prints comma-separated elements.
241    fn comma_sep<T>(&mut self, mut elems: impl Iterator<Item = T>) -> Result<(), PrintError>
242    where
243        T: Print<'tcx, Self>,
244    {
245        if let Some(first) = elems.next() {
246            first.print(self)?;
247            for elem in elems {
248                self.write_str(", ")?;
249                elem.print(self)?;
250            }
251        }
252        Ok(())
253    }
254
255    /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument
256    fn typed_value(
257        &mut self,
258        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
259        t: impl FnOnce(&mut Self) -> Result<(), PrintError>,
260        conversion: &str,
261    ) -> Result<(), PrintError> {
262        self.write_str("{")?;
263        f(self)?;
264        self.write_str(conversion)?;
265        t(self)?;
266        self.write_str("}")?;
267        Ok(())
268    }
269
270    /// Prints `(...)` around what `f` prints.
271    fn parenthesized(
272        &mut self,
273        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
274    ) -> Result<(), PrintError> {
275        self.write_str("(")?;
276        f(self)?;
277        self.write_str(")")?;
278        Ok(())
279    }
280
281    /// Prints `(...)` around what `f` prints if `parenthesized` is true, otherwise just prints `f`.
282    fn maybe_parenthesized(
283        &mut self,
284        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
285        parenthesized: bool,
286    ) -> Result<(), PrintError> {
287        if parenthesized {
288            self.parenthesized(f)?;
289        } else {
290            f(self)?;
291        }
292        Ok(())
293    }
294
295    /// Prints `<...>` around what `f` prints.
296    fn generic_delimiters(
297        &mut self,
298        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
299    ) -> Result<(), PrintError>;
300
301    /// Returns `true` if the region should be printed in
302    /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`.
303    /// This is typically the case for all non-`'_` regions.
304    fn should_print_region(&self, region: ty::Region<'tcx>) -> bool;
305
306    fn reset_type_limit(&mut self) {}
307
308    // Defaults (should not be overridden):
309
310    /// If possible, this returns a global path resolving to `def_id` that is visible
311    /// from at least one local module, and returns `true`. If the crate defining `def_id` is
312    /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
313    fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
314        if with_no_visible_paths() {
315            return Ok(false);
316        }
317
318        let mut callers = Vec::new();
319        self.try_print_visible_def_path_recur(def_id, &mut callers)
320    }
321
322    // Given a `DefId`, produce a short name. For types and traits, it prints *only* its name,
323    // For associated items on traits it prints out the trait's name and the associated item's name.
324    // For enum variants, if they have an unique name, then we only print the name, otherwise we
325    // print the enum name and the variant name. Otherwise, we do not print anything and let the
326    // caller use the `print_def_path` fallback.
327    fn force_print_trimmed_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
328        let key = self.tcx().def_key(def_id);
329        let visible_parent_map = self.tcx().visible_parent_map(());
330        let kind = self.tcx().def_kind(def_id);
331
332        let get_local_name = |this: &Self, name, def_id, key: DefKey| {
333            if let Some(visible_parent) = visible_parent_map.get(&def_id)
334                && let actual_parent = this.tcx().opt_parent(def_id)
335                && let DefPathData::TypeNs(_) = key.disambiguated_data.data
336                && Some(*visible_parent) != actual_parent
337            {
338                this.tcx()
339                    // FIXME(typed_def_id): Further propagate ModDefId
340                    .module_children(ModDefId::new_unchecked(*visible_parent))
341                    .iter()
342                    .filter(|child| child.res.opt_def_id() == Some(def_id))
343                    .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore)
344                    .map(|child| child.ident.name)
345                    .unwrap_or(name)
346            } else {
347                name
348            }
349        };
350        if let DefKind::Variant = kind
351            && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id)
352        {
353            // If `Assoc` is unique, we don't want to talk about `Trait::Assoc`.
354            self.write_str(get_local_name(self, *symbol, def_id, key).as_str())?;
355            return Ok(true);
356        }
357        if let Some(symbol) = key.get_opt_name() {
358            if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = kind
359                && let Some(parent) = self.tcx().opt_parent(def_id)
360                && let parent_key = self.tcx().def_key(parent)
361                && let Some(symbol) = parent_key.get_opt_name()
362            {
363                // Trait
364                self.write_str(get_local_name(self, symbol, parent, parent_key).as_str())?;
365                self.write_str("::")?;
366            } else if let DefKind::Variant = kind
367                && let Some(parent) = self.tcx().opt_parent(def_id)
368                && let parent_key = self.tcx().def_key(parent)
369                && let Some(symbol) = parent_key.get_opt_name()
370            {
371                // Enum
372
373                // For associated items and variants, we want the "full" path, namely, include
374                // the parent type in the path. For example, `Iterator::Item`.
375                self.write_str(get_local_name(self, symbol, parent, parent_key).as_str())?;
376                self.write_str("::")?;
377            } else if let DefKind::Struct
378            | DefKind::Union
379            | DefKind::Enum
380            | DefKind::Trait
381            | DefKind::TyAlias
382            | DefKind::Fn
383            | DefKind::Const
384            | DefKind::Static { .. } = kind
385            {
386            } else {
387                // If not covered above, like for example items out of `impl` blocks, fallback.
388                return Ok(false);
389            }
390            self.write_str(get_local_name(self, symbol, def_id, key).as_str())?;
391            return Ok(true);
392        }
393        Ok(false)
394    }
395
396    /// Try to see if this path can be trimmed to a unique symbol name.
397    fn try_print_trimmed_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
398        if with_forced_trimmed_paths() && self.force_print_trimmed_def_path(def_id)? {
399            return Ok(true);
400        }
401        if self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
402            && self.tcx().sess.opts.trimmed_def_paths
403            && !with_no_trimmed_paths()
404            && !with_crate_prefix()
405            && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id)
406        {
407            write!(self, "{}", Ident::with_dummy_span(*symbol))?;
408            Ok(true)
409        } else {
410            Ok(false)
411        }
412    }
413
414    /// Does the work of `try_print_visible_def_path`, building the
415    /// full definition path recursively before attempting to
416    /// post-process it into the valid and visible version that
417    /// accounts for re-exports.
418    ///
419    /// This method should only be called by itself or
420    /// `try_print_visible_def_path`.
421    ///
422    /// `callers` is a chain of visible_parent's leading to `def_id`,
423    /// to support cycle detection during recursion.
424    ///
425    /// This method returns false if we can't print the visible path, so
426    /// `print_def_path` can fall back on the item's real definition path.
427    fn try_print_visible_def_path_recur(
428        &mut self,
429        def_id: DefId,
430        callers: &mut Vec<DefId>,
431    ) -> Result<bool, PrintError> {
432        debug!("try_print_visible_def_path: def_id={:?}", def_id);
433
434        // If `def_id` is a direct or injected extern crate, return the
435        // path to the crate followed by the path to the item within the crate.
436        if let Some(cnum) = def_id.as_crate_root() {
437            if cnum == LOCAL_CRATE {
438                self.path_crate(cnum)?;
439                return Ok(true);
440            }
441
442            // In local mode, when we encounter a crate other than
443            // LOCAL_CRATE, execution proceeds in one of two ways:
444            //
445            // 1. For a direct dependency, where user added an
446            //    `extern crate` manually, we put the `extern
447            //    crate` as the parent. So you wind up with
448            //    something relative to the current crate.
449            // 2. For an extern inferred from a path or an indirect crate,
450            //    where there is no explicit `extern crate`, we just prepend
451            //    the crate name.
452            match self.tcx().extern_crate(cnum) {
453                Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) {
454                    (ExternCrateSource::Extern(def_id), LOCAL_CRATE) => {
455                        // NOTE(eddyb) the only reason `span` might be dummy,
456                        // that we're aware of, is that it's the `std`/`core`
457                        // `extern crate` injected by default.
458                        // FIXME(eddyb) find something better to key this on,
459                        // or avoid ending up with `ExternCrateSource::Extern`,
460                        // for the injected `std`/`core`.
461                        if span.is_dummy() {
462                            self.path_crate(cnum)?;
463                            return Ok(true);
464                        }
465
466                        // Disable `try_print_trimmed_def_path` behavior within
467                        // the `print_def_path` call, to avoid infinite recursion
468                        // in cases where the `extern crate foo` has non-trivial
469                        // parents, e.g. it's nested in `impl foo::Trait for Bar`
470                        // (see also issues #55779 and #87932).
471                        with_no_visible_paths!(self.print_def_path(def_id, &[])?);
472
473                        return Ok(true);
474                    }
475                    (ExternCrateSource::Path, LOCAL_CRATE) => {
476                        self.path_crate(cnum)?;
477                        return Ok(true);
478                    }
479                    _ => {}
480                },
481                None => {
482                    self.path_crate(cnum)?;
483                    return Ok(true);
484                }
485            }
486        }
487
488        if def_id.is_local() {
489            return Ok(false);
490        }
491
492        let visible_parent_map = self.tcx().visible_parent_map(());
493
494        let mut cur_def_key = self.tcx().def_key(def_id);
495        debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
496
497        // For a constructor, we want the name of its parent rather than <unnamed>.
498        if let DefPathData::Ctor = cur_def_key.disambiguated_data.data {
499            let parent = DefId {
500                krate: def_id.krate,
501                index: cur_def_key
502                    .parent
503                    .expect("`DefPathData::Ctor` / `VariantData` missing a parent"),
504            };
505
506            cur_def_key = self.tcx().def_key(parent);
507        }
508
509        let Some(visible_parent) = visible_parent_map.get(&def_id).cloned() else {
510            return Ok(false);
511        };
512
513        let actual_parent = self.tcx().opt_parent(def_id);
514        debug!(
515            "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}",
516            visible_parent, actual_parent,
517        );
518
519        let mut data = cur_def_key.disambiguated_data.data;
520        debug!(
521            "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
522            data, visible_parent, actual_parent,
523        );
524
525        match data {
526            // In order to output a path that could actually be imported (valid and visible),
527            // we need to handle re-exports correctly.
528            //
529            // For example, take `std::os::unix::process::CommandExt`, this trait is actually
530            // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
531            //
532            // `std::os::unix` reexports the contents of `std::sys::unix::ext`. `std::sys` is
533            // private so the "true" path to `CommandExt` isn't accessible.
534            //
535            // In this case, the `visible_parent_map` will look something like this:
536            //
537            // (child) -> (parent)
538            // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
539            // `std::sys::unix::ext::process` -> `std::sys::unix::ext`
540            // `std::sys::unix::ext` -> `std::os`
541            //
542            // This is correct, as the visible parent of `std::sys::unix::ext` is in fact
543            // `std::os`.
544            //
545            // When printing the path to `CommandExt` and looking at the `cur_def_key` that
546            // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
547            // to the parent - resulting in a mangled path like
548            // `std::os::ext::process::CommandExt`.
549            //
550            // Instead, we must detect that there was a re-export and instead print `unix`
551            // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
552            // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
553            // the visible parent (`std::os`). If these do not match, then we iterate over
554            // the children of the visible parent (as was done when computing
555            // `visible_parent_map`), looking for the specific child we currently have and then
556            // have access to the re-exported name.
557            DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => {
558                // Item might be re-exported several times, but filter for the one
559                // that's public and whose identifier isn't `_`.
560                let reexport = self
561                    .tcx()
562                    // FIXME(typed_def_id): Further propagate ModDefId
563                    .module_children(ModDefId::new_unchecked(visible_parent))
564                    .iter()
565                    .filter(|child| child.res.opt_def_id() == Some(def_id))
566                    .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore)
567                    .map(|child| child.ident.name);
568
569                if let Some(new_name) = reexport {
570                    *name = new_name;
571                } else {
572                    // There is no name that is public and isn't `_`, so bail.
573                    return Ok(false);
574                }
575            }
576            // Re-exported `extern crate` (#43189).
577            DefPathData::CrateRoot => {
578                data = DefPathData::TypeNs(self.tcx().crate_name(def_id.krate));
579            }
580            _ => {}
581        }
582        debug!("try_print_visible_def_path: data={:?}", data);
583
584        if callers.contains(&visible_parent) {
585            return Ok(false);
586        }
587        callers.push(visible_parent);
588        // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid
589        // knowing ahead of time whether the entire path will succeed or not.
590        // To support printers that do not implement `PrettyPrinter`, a `Vec` or
591        // linked list on the stack would need to be built, before any printing.
592        match self.try_print_visible_def_path_recur(visible_parent, callers)? {
593            false => return Ok(false),
594            true => {}
595        }
596        callers.pop();
597        self.path_append(|_| Ok(()), &DisambiguatedDefPathData { data, disambiguator: 0 })?;
598        Ok(true)
599    }
600
601    fn pretty_path_qualified(
602        &mut self,
603        self_ty: Ty<'tcx>,
604        trait_ref: Option<ty::TraitRef<'tcx>>,
605    ) -> Result<(), PrintError> {
606        if trait_ref.is_none() {
607            // Inherent impls. Try to print `Foo::bar` for an inherent
608            // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
609            // anything other than a simple path.
610            match self_ty.kind() {
611                ty::Adt(..)
612                | ty::Foreign(_)
613                | ty::Bool
614                | ty::Char
615                | ty::Str
616                | ty::Int(_)
617                | ty::Uint(_)
618                | ty::Float(_) => {
619                    return self_ty.print(self);
620                }
621
622                _ => {}
623            }
624        }
625
626        self.generic_delimiters(|cx| {
627            define_scoped_cx!(cx);
628
629            p!(print(self_ty));
630            if let Some(trait_ref) = trait_ref {
631                p!(" as ", print(trait_ref.print_only_trait_path()));
632            }
633            Ok(())
634        })
635    }
636
637    fn pretty_path_append_impl(
638        &mut self,
639        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
640        self_ty: Ty<'tcx>,
641        trait_ref: Option<ty::TraitRef<'tcx>>,
642    ) -> Result<(), PrintError> {
643        print_prefix(self)?;
644
645        self.generic_delimiters(|cx| {
646            define_scoped_cx!(cx);
647
648            p!("impl ");
649            if let Some(trait_ref) = trait_ref {
650                p!(print(trait_ref.print_only_trait_path()), " for ");
651            }
652            p!(print(self_ty));
653
654            Ok(())
655        })
656    }
657
658    fn pretty_print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
659        define_scoped_cx!(self);
660
661        match *ty.kind() {
662            ty::Bool => p!("bool"),
663            ty::Char => p!("char"),
664            ty::Int(t) => p!(write("{}", t.name_str())),
665            ty::Uint(t) => p!(write("{}", t.name_str())),
666            ty::Float(t) => p!(write("{}", t.name_str())),
667            ty::Pat(ty, pat) => {
668                p!("(", print(ty), ") is ", write("{pat:?}"))
669            }
670            ty::RawPtr(ty, mutbl) => {
671                p!(write("*{} ", mutbl.ptr_str()));
672                p!(print(ty))
673            }
674            ty::Ref(r, ty, mutbl) => {
675                p!("&");
676                if self.should_print_region(r) {
677                    p!(print(r), " ");
678                }
679                p!(print(ty::TypeAndMut { ty, mutbl }))
680            }
681            ty::Never => p!("!"),
682            ty::Tuple(tys) => {
683                p!("(", comma_sep(tys.iter()));
684                if tys.len() == 1 {
685                    p!(",");
686                }
687                p!(")")
688            }
689            ty::FnDef(def_id, args) => {
690                if with_reduced_queries() {
691                    p!(print_def_path(def_id, args));
692                } else {
693                    let mut sig = self.tcx().fn_sig(def_id).instantiate(self.tcx(), args);
694                    if self.tcx().codegen_fn_attrs(def_id).safe_target_features {
695                        p!("#[target_features] ");
696                        sig = sig.map_bound(|mut sig| {
697                            sig.safety = hir::Safety::Safe;
698                            sig
699                        });
700                    }
701                    p!(print(sig), " {{", print_value_path(def_id, args), "}}");
702                }
703            }
704            ty::FnPtr(ref sig_tys, hdr) => p!(print(sig_tys.with(hdr))),
705            ty::UnsafeBinder(ref bound_ty) => {
706                // FIXME(unsafe_binders): Make this print `unsafe<>` rather than `for<>`.
707                self.wrap_binder(bound_ty, |ty, cx| cx.pretty_print_type(*ty))?;
708            }
709            ty::Infer(infer_ty) => {
710                if self.should_print_verbose() {
711                    p!(write("{:?}", ty.kind()));
712                    return Ok(());
713                }
714
715                if let ty::TyVar(ty_vid) = infer_ty {
716                    if let Some(name) = self.ty_infer_name(ty_vid) {
717                        p!(write("{}", name))
718                    } else {
719                        p!(write("{}", infer_ty))
720                    }
721                } else {
722                    p!(write("{}", infer_ty))
723                }
724            }
725            ty::Error(_) => p!("{{type error}}"),
726            ty::Param(ref param_ty) => p!(print(param_ty)),
727            ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
728                ty::BoundTyKind::Anon => {
729                    rustc_type_ir::debug_bound_var(self, debruijn, bound_ty.var)?
730                }
731                ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
732                    true => p!(write("{:?}", ty.kind())),
733                    false => p!(write("{s}")),
734                },
735            },
736            ty::Adt(def, args) => {
737                p!(print_def_path(def.did(), args));
738            }
739            ty::Dynamic(data, r, repr) => {
740                let print_r = self.should_print_region(r);
741                if print_r {
742                    p!("(");
743                }
744                match repr {
745                    ty::Dyn => p!("dyn "),
746                    ty::DynStar => p!("dyn* "),
747                }
748                p!(print(data));
749                if print_r {
750                    p!(" + ", print(r), ")");
751                }
752            }
753            ty::Foreign(def_id) => {
754                p!(print_def_path(def_id, &[]));
755            }
756            ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ref data) => {
757                p!(print(data))
758            }
759            ty::Placeholder(placeholder) => match placeholder.bound.kind {
760                ty::BoundTyKind::Anon => p!(write("{placeholder:?}")),
761                ty::BoundTyKind::Param(_, name) => match self.should_print_verbose() {
762                    true => p!(write("{:?}", ty.kind())),
763                    false => p!(write("{name}")),
764                },
765            },
766            ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
767                // We use verbose printing in 'NO_QUERIES' mode, to
768                // avoid needing to call `predicates_of`. This should
769                // only affect certain debug messages (e.g. messages printed
770                // from `rustc_middle::ty` during the computation of `tcx.predicates_of`),
771                // and should have no effect on any compiler output.
772                // [Unless `-Zverbose-internals` is used, e.g. in the output of
773                // `tests/ui/nll/ty-outlives/impl-trait-captures.rs`, for
774                // example.]
775                if self.should_print_verbose() {
776                    // FIXME(eddyb) print this with `print_def_path`.
777                    p!(write("Opaque({:?}, {})", def_id, args.print_as_list()));
778                    return Ok(());
779                }
780
781                let parent = self.tcx().parent(def_id);
782                match self.tcx().def_kind(parent) {
783                    DefKind::TyAlias | DefKind::AssocTy => {
784                        // NOTE: I know we should check for NO_QUERIES here, but it's alright.
785                        // `type_of` on a type alias or assoc type should never cause a cycle.
786                        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
787                            *self.tcx().type_of(parent).instantiate_identity().kind()
788                        {
789                            if d == def_id {
790                                // If the type alias directly starts with the `impl` of the
791                                // opaque type we're printing, then skip the `::{opaque#1}`.
792                                p!(print_def_path(parent, args));
793                                return Ok(());
794                            }
795                        }
796                        // Complex opaque type, e.g. `type Foo = (i32, impl Debug);`
797                        p!(print_def_path(def_id, args));
798                        return Ok(());
799                    }
800                    _ => {
801                        if with_reduced_queries() {
802                            p!(print_def_path(def_id, &[]));
803                            return Ok(());
804                        } else {
805                            return self.pretty_print_opaque_impl_type(def_id, args);
806                        }
807                    }
808                }
809            }
810            ty::Str => p!("str"),
811            ty::Coroutine(did, args) => {
812                p!("{{");
813                let coroutine_kind = self.tcx().coroutine_kind(did).unwrap();
814                let should_print_movability = self.should_print_verbose()
815                    || matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
816
817                if should_print_movability {
818                    match coroutine_kind.movability() {
819                        hir::Movability::Movable => {}
820                        hir::Movability::Static => p!("static "),
821                    }
822                }
823
824                if !self.should_print_verbose() {
825                    p!(write("{}", coroutine_kind));
826                    if coroutine_kind.is_fn_like() {
827                        // If we are printing an `async fn` coroutine type, then give the path
828                        // of the fn, instead of its span, because that will in most cases be
829                        // more helpful for the reader than just a source location.
830                        //
831                        // This will look like:
832                        //    {async fn body of some_fn()}
833                        let did_of_the_fn_item = self.tcx().parent(did);
834                        p!(" of ", print_def_path(did_of_the_fn_item, args), "()");
835                    } else if let Some(local_did) = did.as_local() {
836                        let span = self.tcx().def_span(local_did);
837                        p!(write(
838                            "@{}",
839                            // This may end up in stderr diagnostics but it may also be emitted
840                            // into MIR. Hence we use the remapped path if available
841                            self.tcx().sess.source_map().span_to_embeddable_string(span)
842                        ));
843                    } else {
844                        p!("@", print_def_path(did, args));
845                    }
846                } else {
847                    p!(print_def_path(did, args));
848                    p!(
849                        " upvar_tys=",
850                        print(args.as_coroutine().tupled_upvars_ty()),
851                        " resume_ty=",
852                        print(args.as_coroutine().resume_ty()),
853                        " yield_ty=",
854                        print(args.as_coroutine().yield_ty()),
855                        " return_ty=",
856                        print(args.as_coroutine().return_ty()),
857                        " witness=",
858                        print(args.as_coroutine().witness())
859                    );
860                }
861
862                p!("}}")
863            }
864            ty::CoroutineWitness(did, args) => {
865                p!(write("{{"));
866                if !self.tcx().sess.verbose_internals() {
867                    p!("coroutine witness");
868                    if let Some(did) = did.as_local() {
869                        let span = self.tcx().def_span(did);
870                        p!(write(
871                            "@{}",
872                            // This may end up in stderr diagnostics but it may also be emitted
873                            // into MIR. Hence we use the remapped path if available
874                            self.tcx().sess.source_map().span_to_embeddable_string(span)
875                        ));
876                    } else {
877                        p!(write("@"), print_def_path(did, args));
878                    }
879                } else {
880                    p!(print_def_path(did, args));
881                }
882
883                p!("}}")
884            }
885            ty::Closure(did, args) => {
886                p!(write("{{"));
887                if !self.should_print_verbose() {
888                    p!(write("closure"));
889                    if self.should_truncate() {
890                        write!(self, "@...}}")?;
891                        return Ok(());
892                    } else {
893                        if let Some(did) = did.as_local() {
894                            if self.tcx().sess.opts.unstable_opts.span_free_formats {
895                                p!("@", print_def_path(did.to_def_id(), args));
896                            } else {
897                                let span = self.tcx().def_span(did);
898                                let preference = if with_forced_trimmed_paths() {
899                                    FileNameDisplayPreference::Short
900                                } else {
901                                    FileNameDisplayPreference::Remapped
902                                };
903                                p!(write(
904                                    "@{}",
905                                    // This may end up in stderr diagnostics but it may also be emitted
906                                    // into MIR. Hence we use the remapped path if available
907                                    self.tcx().sess.source_map().span_to_string(span, preference)
908                                ));
909                            }
910                        } else {
911                            p!(write("@"), print_def_path(did, args));
912                        }
913                    }
914                } else {
915                    p!(print_def_path(did, args));
916                    p!(
917                        " closure_kind_ty=",
918                        print(args.as_closure().kind_ty()),
919                        " closure_sig_as_fn_ptr_ty=",
920                        print(args.as_closure().sig_as_fn_ptr_ty()),
921                        " upvar_tys=",
922                        print(args.as_closure().tupled_upvars_ty())
923                    );
924                }
925                p!("}}");
926            }
927            ty::CoroutineClosure(did, args) => {
928                p!(write("{{"));
929                if !self.should_print_verbose() {
930                    match self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(did)).unwrap()
931                    {
932                        hir::CoroutineKind::Desugared(
933                            hir::CoroutineDesugaring::Async,
934                            hir::CoroutineSource::Closure,
935                        ) => p!("async closure"),
936                        hir::CoroutineKind::Desugared(
937                            hir::CoroutineDesugaring::AsyncGen,
938                            hir::CoroutineSource::Closure,
939                        ) => p!("async gen closure"),
940                        hir::CoroutineKind::Desugared(
941                            hir::CoroutineDesugaring::Gen,
942                            hir::CoroutineSource::Closure,
943                        ) => p!("gen closure"),
944                        _ => unreachable!(
945                            "coroutine from coroutine-closure should have CoroutineSource::Closure"
946                        ),
947                    }
948                    if let Some(did) = did.as_local() {
949                        if self.tcx().sess.opts.unstable_opts.span_free_formats {
950                            p!("@", print_def_path(did.to_def_id(), args));
951                        } else {
952                            let span = self.tcx().def_span(did);
953                            let preference = if with_forced_trimmed_paths() {
954                                FileNameDisplayPreference::Short
955                            } else {
956                                FileNameDisplayPreference::Remapped
957                            };
958                            p!(write(
959                                "@{}",
960                                // This may end up in stderr diagnostics but it may also be emitted
961                                // into MIR. Hence we use the remapped path if available
962                                self.tcx().sess.source_map().span_to_string(span, preference)
963                            ));
964                        }
965                    } else {
966                        p!(write("@"), print_def_path(did, args));
967                    }
968                } else {
969                    p!(print_def_path(did, args));
970                    p!(
971                        " closure_kind_ty=",
972                        print(args.as_coroutine_closure().kind_ty()),
973                        " signature_parts_ty=",
974                        print(args.as_coroutine_closure().signature_parts_ty()),
975                        " upvar_tys=",
976                        print(args.as_coroutine_closure().tupled_upvars_ty()),
977                        " coroutine_captures_by_ref_ty=",
978                        print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()),
979                        " coroutine_witness_ty=",
980                        print(args.as_coroutine_closure().coroutine_witness_ty())
981                    );
982                }
983                p!("}}");
984            }
985            ty::Array(ty, sz) => p!("[", print(ty), "; ", print(sz), "]"),
986            ty::Slice(ty) => p!("[", print(ty), "]"),
987        }
988
989        Ok(())
990    }
991
992    fn pretty_print_opaque_impl_type(
993        &mut self,
994        def_id: DefId,
995        args: ty::GenericArgsRef<'tcx>,
996    ) -> Result<(), PrintError> {
997        let tcx = self.tcx();
998
999        // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1000        // by looking up the projections associated with the def_id.
1001        let bounds = tcx.explicit_item_bounds(def_id);
1002
1003        let mut traits = FxIndexMap::default();
1004        let mut fn_traits = FxIndexMap::default();
1005        let mut has_sized_bound = false;
1006        let mut has_negative_sized_bound = false;
1007        let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new();
1008
1009        for (predicate, _) in bounds.iter_instantiated_copied(tcx, args) {
1010            let bound_predicate = predicate.kind();
1011
1012            match bound_predicate.skip_binder() {
1013                ty::ClauseKind::Trait(pred) => {
1014                    // Don't print `+ Sized`, but rather `+ ?Sized` if absent.
1015                    if tcx.is_lang_item(pred.def_id(), LangItem::Sized) {
1016                        match pred.polarity {
1017                            ty::PredicatePolarity::Positive => {
1018                                has_sized_bound = true;
1019                                continue;
1020                            }
1021                            ty::PredicatePolarity::Negative => has_negative_sized_bound = true,
1022                        }
1023                    }
1024
1025                    self.insert_trait_and_projection(
1026                        bound_predicate.rebind(pred),
1027                        None,
1028                        &mut traits,
1029                        &mut fn_traits,
1030                    );
1031                }
1032                ty::ClauseKind::Projection(pred) => {
1033                    let proj = bound_predicate.rebind(pred);
1034                    let trait_ref = proj.map_bound(|proj| TraitPredicate {
1035                        trait_ref: proj.projection_term.trait_ref(tcx),
1036                        polarity: ty::PredicatePolarity::Positive,
1037                    });
1038
1039                    self.insert_trait_and_projection(
1040                        trait_ref,
1041                        Some((proj.item_def_id(), proj.term())),
1042                        &mut traits,
1043                        &mut fn_traits,
1044                    );
1045                }
1046                ty::ClauseKind::TypeOutlives(outlives) => {
1047                    lifetimes.push(outlives.1);
1048                }
1049                _ => {}
1050            }
1051        }
1052
1053        write!(self, "impl ")?;
1054
1055        let mut first = true;
1056        // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
1057        let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !has_sized_bound;
1058
1059        for ((bound_args, is_async), entry) in fn_traits {
1060            write!(self, "{}", if first { "" } else { " + " })?;
1061            write!(self, "{}", if paren_needed { "(" } else { "" })?;
1062
1063            let trait_def_id = if is_async {
1064                tcx.async_fn_trait_kind_to_def_id(entry.kind).expect("expected AsyncFn lang items")
1065            } else {
1066                tcx.fn_trait_kind_to_def_id(entry.kind).expect("expected Fn lang items")
1067            };
1068
1069            if let Some(return_ty) = entry.return_ty {
1070                self.wrap_binder(&bound_args, |args, cx| {
1071                    define_scoped_cx!(cx);
1072                    p!(write("{}", tcx.item_name(trait_def_id)));
1073                    p!("(");
1074
1075                    for (idx, ty) in args.iter().enumerate() {
1076                        if idx > 0 {
1077                            p!(", ");
1078                        }
1079                        p!(print(ty));
1080                    }
1081
1082                    p!(")");
1083                    if let Some(ty) = return_ty.skip_binder().as_type() {
1084                        if !ty.is_unit() {
1085                            p!(" -> ", print(return_ty));
1086                        }
1087                    }
1088                    p!(write("{}", if paren_needed { ")" } else { "" }));
1089
1090                    first = false;
1091                    Ok(())
1092                })?;
1093            } else {
1094                // Otherwise, render this like a regular trait.
1095                traits.insert(
1096                    bound_args.map_bound(|args| ty::TraitPredicate {
1097                        polarity: ty::PredicatePolarity::Positive,
1098                        trait_ref: ty::TraitRef::new(tcx, trait_def_id, [Ty::new_tup(tcx, args)]),
1099                    }),
1100                    FxIndexMap::default(),
1101                );
1102            }
1103        }
1104
1105        // Print the rest of the trait types (that aren't Fn* family of traits)
1106        for (trait_pred, assoc_items) in traits {
1107            write!(self, "{}", if first { "" } else { " + " })?;
1108
1109            self.wrap_binder(&trait_pred, |trait_pred, cx| {
1110                define_scoped_cx!(cx);
1111
1112                if trait_pred.polarity == ty::PredicatePolarity::Negative {
1113                    p!("!");
1114                }
1115                p!(print(trait_pred.trait_ref.print_only_trait_name()));
1116
1117                let generics = tcx.generics_of(trait_pred.def_id());
1118                let own_args = generics.own_args_no_defaults(tcx, trait_pred.trait_ref.args);
1119
1120                if !own_args.is_empty() || !assoc_items.is_empty() {
1121                    let mut first = true;
1122
1123                    for ty in own_args {
1124                        if first {
1125                            p!("<");
1126                            first = false;
1127                        } else {
1128                            p!(", ");
1129                        }
1130                        p!(print(ty));
1131                    }
1132
1133                    for (assoc_item_def_id, term) in assoc_items {
1134                        // Skip printing `<{coroutine@} as Coroutine<_>>::Return` from async blocks,
1135                        // unless we can find out what coroutine return type it comes from.
1136                        let term = if let Some(ty) = term.skip_binder().as_type()
1137                            && let ty::Alias(ty::Projection, proj) = ty.kind()
1138                            && let Some(assoc) = tcx.opt_associated_item(proj.def_id)
1139                            && assoc
1140                                .trait_container(tcx)
1141                                .is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Coroutine))
1142                            && assoc.name == rustc_span::sym::Return
1143                        {
1144                            if let ty::Coroutine(_, args) = args.type_at(0).kind() {
1145                                let return_ty = args.as_coroutine().return_ty();
1146                                if !return_ty.is_ty_var() {
1147                                    return_ty.into()
1148                                } else {
1149                                    continue;
1150                                }
1151                            } else {
1152                                continue;
1153                            }
1154                        } else {
1155                            term.skip_binder()
1156                        };
1157
1158                        if first {
1159                            p!("<");
1160                            first = false;
1161                        } else {
1162                            p!(", ");
1163                        }
1164
1165                        p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name));
1166
1167                        match term.unpack() {
1168                            TermKind::Ty(ty) => p!(print(ty)),
1169                            TermKind::Const(c) => p!(print(c)),
1170                        };
1171                    }
1172
1173                    if !first {
1174                        p!(">");
1175                    }
1176                }
1177
1178                first = false;
1179                Ok(())
1180            })?;
1181        }
1182
1183        let add_sized = has_sized_bound && (first || has_negative_sized_bound);
1184        let add_maybe_sized = !has_sized_bound && !has_negative_sized_bound;
1185        if add_sized || add_maybe_sized {
1186            if !first {
1187                write!(self, " + ")?;
1188            }
1189            if add_maybe_sized {
1190                write!(self, "?")?;
1191            }
1192            write!(self, "Sized")?;
1193        }
1194
1195        if !with_forced_trimmed_paths() {
1196            for re in lifetimes {
1197                write!(self, " + ")?;
1198                self.print_region(re)?;
1199            }
1200        }
1201
1202        if self.tcx().features().return_type_notation()
1203            && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
1204                self.tcx().opt_rpitit_info(def_id)
1205            && let ty::Alias(_, alias_ty) =
1206                self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind()
1207            && alias_ty.def_id == def_id
1208            && let generics = self.tcx().generics_of(fn_def_id)
1209            // FIXME(return_type_notation): We only support lifetime params for now.
1210            && generics.own_params.iter().all(|param| matches!(param.kind, ty::GenericParamDefKind::Lifetime))
1211        {
1212            let num_args = generics.count();
1213            write!(self, " {{ ")?;
1214            self.print_def_path(fn_def_id, &args[..num_args])?;
1215            write!(self, "(..) }}")?;
1216        }
1217
1218        Ok(())
1219    }
1220
1221    /// Insert the trait ref and optionally a projection type associated with it into either the
1222    /// traits map or fn_traits map, depending on if the trait is in the Fn* family of traits.
1223    fn insert_trait_and_projection(
1224        &mut self,
1225        trait_pred: ty::PolyTraitPredicate<'tcx>,
1226        proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>,
1227        traits: &mut FxIndexMap<
1228            ty::PolyTraitPredicate<'tcx>,
1229            FxIndexMap<DefId, ty::Binder<'tcx, Term<'tcx>>>,
1230        >,
1231        fn_traits: &mut FxIndexMap<
1232            (ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>>, bool),
1233            OpaqueFnEntry<'tcx>,
1234        >,
1235    ) {
1236        let tcx = self.tcx();
1237        let trait_def_id = trait_pred.def_id();
1238
1239        let fn_trait_and_async = if let Some(kind) = tcx.fn_trait_kind_from_def_id(trait_def_id) {
1240            Some((kind, false))
1241        } else if let Some(kind) = tcx.async_fn_trait_kind_from_def_id(trait_def_id) {
1242            Some((kind, true))
1243        } else {
1244            None
1245        };
1246
1247        if trait_pred.polarity() == ty::PredicatePolarity::Positive
1248            && let Some((kind, is_async)) = fn_trait_and_async
1249            && let ty::Tuple(types) = *trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
1250        {
1251            let entry = fn_traits
1252                .entry((trait_pred.rebind(types), is_async))
1253                .or_insert_with(|| OpaqueFnEntry { kind, return_ty: None });
1254            if kind.extends(entry.kind) {
1255                entry.kind = kind;
1256            }
1257            if let Some((proj_def_id, proj_ty)) = proj_ty
1258                && tcx.item_name(proj_def_id) == sym::Output
1259            {
1260                entry.return_ty = Some(proj_ty);
1261            }
1262            return;
1263        }
1264
1265        // Otherwise, just group our traits and projection types.
1266        traits.entry(trait_pred).or_default().extend(proj_ty);
1267    }
1268
1269    fn pretty_print_inherent_projection(
1270        &mut self,
1271        alias_ty: ty::AliasTerm<'tcx>,
1272    ) -> Result<(), PrintError> {
1273        let def_key = self.tcx().def_key(alias_ty.def_id);
1274        self.path_generic_args(
1275            |cx| {
1276                cx.path_append(
1277                    |cx| cx.path_qualified(alias_ty.self_ty(), None),
1278                    &def_key.disambiguated_data,
1279                )
1280            },
1281            &alias_ty.args[1..],
1282        )
1283    }
1284
1285    fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
1286        None
1287    }
1288
1289    fn const_infer_name(&self, _: ty::ConstVid) -> Option<Symbol> {
1290        None
1291    }
1292
1293    fn pretty_print_dyn_existential(
1294        &mut self,
1295        predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
1296    ) -> Result<(), PrintError> {
1297        // Generate the main trait ref, including associated types.
1298        let mut first = true;
1299
1300        if let Some(bound_principal) = predicates.principal() {
1301            self.wrap_binder(&bound_principal, |principal, cx| {
1302                define_scoped_cx!(cx);
1303                p!(print_def_path(principal.def_id, &[]));
1304
1305                let mut resugared = false;
1306
1307                // Special-case `Fn(...) -> ...` and re-sugar it.
1308                let fn_trait_kind = cx.tcx().fn_trait_kind_from_def_id(principal.def_id);
1309                if !cx.should_print_verbose() && fn_trait_kind.is_some() {
1310                    if let ty::Tuple(tys) = principal.args.type_at(0).kind() {
1311                        let mut projections = predicates.projection_bounds();
1312                        if let (Some(proj), None) = (projections.next(), projections.next()) {
1313                            p!(pretty_fn_sig(
1314                                tys,
1315                                false,
1316                                proj.skip_binder().term.as_type().expect("Return type was a const")
1317                            ));
1318                            resugared = true;
1319                        }
1320                    }
1321                }
1322
1323                // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
1324                // in order to place the projections inside the `<...>`.
1325                if !resugared {
1326                    let principal_with_self =
1327                        principal.with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self);
1328
1329                    let args = cx
1330                        .tcx()
1331                        .generics_of(principal_with_self.def_id)
1332                        .own_args_no_defaults(cx.tcx(), principal_with_self.args);
1333
1334                    let bound_principal_with_self = bound_principal
1335                        .with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self);
1336
1337                    let clause: ty::Clause<'tcx> = bound_principal_with_self.upcast(cx.tcx());
1338                    let super_projections: Vec<_> = elaborate::elaborate(cx.tcx(), [clause])
1339                        .filter_only_self()
1340                        .filter_map(|clause| clause.as_projection_clause())
1341                        .collect();
1342
1343                    let mut projections: Vec<_> = predicates
1344                        .projection_bounds()
1345                        .filter(|&proj| {
1346                            // Filter out projections that are implied by the super predicates.
1347                            let proj_is_implied = super_projections.iter().any(|&super_proj| {
1348                                let super_proj = super_proj.map_bound(|super_proj| {
1349                                    ty::ExistentialProjection::erase_self_ty(cx.tcx(), super_proj)
1350                                });
1351
1352                                // This function is sometimes called on types with erased and
1353                                // anonymized regions, but the super projections can still
1354                                // contain named regions. So we erase and anonymize everything
1355                                // here to compare the types modulo regions below.
1356                                let proj = cx.tcx().erase_regions(proj);
1357                                let proj = cx.tcx().anonymize_bound_vars(proj);
1358                                let super_proj = cx.tcx().erase_regions(super_proj);
1359                                let super_proj = cx.tcx().anonymize_bound_vars(super_proj);
1360
1361                                proj == super_proj
1362                            });
1363                            !proj_is_implied
1364                        })
1365                        .map(|proj| {
1366                            // Skip the binder, because we don't want to print the binder in
1367                            // front of the associated item.
1368                            proj.skip_binder()
1369                        })
1370                        .collect();
1371
1372                    projections
1373                        .sort_by_cached_key(|proj| cx.tcx().item_name(proj.def_id).to_string());
1374
1375                    if !args.is_empty() || !projections.is_empty() {
1376                        p!(generic_delimiters(|cx| {
1377                            cx.comma_sep(args.iter().copied())?;
1378                            if !args.is_empty() && !projections.is_empty() {
1379                                write!(cx, ", ")?;
1380                            }
1381                            cx.comma_sep(projections.iter().copied())
1382                        }));
1383                    }
1384                }
1385                Ok(())
1386            })?;
1387
1388            first = false;
1389        }
1390
1391        define_scoped_cx!(self);
1392
1393        // Builtin bounds.
1394        // FIXME(eddyb) avoid printing twice (needed to ensure
1395        // that the auto traits are sorted *and* printed via cx).
1396        let mut auto_traits: Vec<_> = predicates.auto_traits().collect();
1397
1398        // The auto traits come ordered by `DefPathHash`. While
1399        // `DefPathHash` is *stable* in the sense that it depends on
1400        // neither the host nor the phase of the moon, it depends
1401        // "pseudorandomly" on the compiler version and the target.
1402        //
1403        // To avoid causing instabilities in compiletest
1404        // output, sort the auto-traits alphabetically.
1405        auto_traits.sort_by_cached_key(|did| with_no_trimmed_paths!(self.tcx().def_path_str(*did)));
1406
1407        for def_id in auto_traits {
1408            if !first {
1409                p!(" + ");
1410            }
1411            first = false;
1412
1413            p!(print_def_path(def_id, &[]));
1414        }
1415
1416        Ok(())
1417    }
1418
1419    fn pretty_fn_sig(
1420        &mut self,
1421        inputs: &[Ty<'tcx>],
1422        c_variadic: bool,
1423        output: Ty<'tcx>,
1424    ) -> Result<(), PrintError> {
1425        define_scoped_cx!(self);
1426
1427        p!("(", comma_sep(inputs.iter().copied()));
1428        if c_variadic {
1429            if !inputs.is_empty() {
1430                p!(", ");
1431            }
1432            p!("...");
1433        }
1434        p!(")");
1435        if !output.is_unit() {
1436            p!(" -> ", print(output));
1437        }
1438
1439        Ok(())
1440    }
1441
1442    fn pretty_print_const(
1443        &mut self,
1444        ct: ty::Const<'tcx>,
1445        print_ty: bool,
1446    ) -> Result<(), PrintError> {
1447        define_scoped_cx!(self);
1448
1449        if self.should_print_verbose() {
1450            p!(write("{:?}", ct));
1451            return Ok(());
1452        }
1453
1454        match ct.kind() {
1455            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
1456                match self.tcx().def_kind(def) {
1457                    DefKind::Const | DefKind::AssocConst => {
1458                        p!(print_value_path(def, args))
1459                    }
1460                    DefKind::AnonConst => {
1461                        if def.is_local()
1462                            && let span = self.tcx().def_span(def)
1463                            && let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
1464                        {
1465                            p!(write("{}", snip))
1466                        } else {
1467                            // Do not call `print_value_path` as if a parent of this anon const is an impl it will
1468                            // attempt to print out the impl trait ref i.e. `<T as Trait>::{constant#0}`. This would
1469                            // cause printing to enter an infinite recursion if the anon const is in the self type i.e.
1470                            // `impl<T: Default> Default for [T; 32 - 1 - 1 - 1] {`
1471                            // where we would try to print `<[T; /* print `constant#0` again */] as Default>::{constant#0}`
1472                            p!(write(
1473                                "{}::{}",
1474                                self.tcx().crate_name(def.krate),
1475                                self.tcx().def_path(def).to_string_no_crate_verbose()
1476                            ))
1477                        }
1478                    }
1479                    defkind => bug!("`{:?}` has unexpected defkind {:?}", ct, defkind),
1480                }
1481            }
1482            ty::ConstKind::Infer(infer_ct) => match infer_ct {
1483                ty::InferConst::Var(ct_vid) if let Some(name) = self.const_infer_name(ct_vid) => {
1484                    p!(write("{}", name))
1485                }
1486                _ => write!(self, "_")?,
1487            },
1488            ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
1489            ty::ConstKind::Value(cv) => {
1490                return self.pretty_print_const_valtree(cv, print_ty);
1491            }
1492
1493            ty::ConstKind::Bound(debruijn, bound_var) => {
1494                rustc_type_ir::debug_bound_var(self, debruijn, bound_var)?
1495            }
1496            ty::ConstKind::Placeholder(placeholder) => p!(write("{placeholder:?}")),
1497            // FIXME(generic_const_exprs):
1498            // write out some legible representation of an abstract const?
1499            ty::ConstKind::Expr(expr) => self.pretty_print_const_expr(expr, print_ty)?,
1500            ty::ConstKind::Error(_) => p!("{{const error}}"),
1501        };
1502        Ok(())
1503    }
1504
1505    fn pretty_print_const_expr(
1506        &mut self,
1507        expr: Expr<'tcx>,
1508        print_ty: bool,
1509    ) -> Result<(), PrintError> {
1510        define_scoped_cx!(self);
1511        match expr.kind {
1512            ty::ExprKind::Binop(op) => {
1513                let (_, _, c1, c2) = expr.binop_args();
1514
1515                let precedence = |binop: crate::mir::BinOp| {
1516                    use rustc_ast::util::parser::AssocOp;
1517                    AssocOp::from_ast_binop(binop.to_hir_binop()).precedence()
1518                };
1519                let op_precedence = precedence(op);
1520                let formatted_op = op.to_hir_binop().as_str();
1521                let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) {
1522                    (
1523                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }),
1524                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }),
1525                    ) => (precedence(lhs_op) < op_precedence, precedence(rhs_op) < op_precedence),
1526                    (
1527                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }),
1528                        ty::ConstKind::Expr(_),
1529                    ) => (precedence(lhs_op) < op_precedence, true),
1530                    (
1531                        ty::ConstKind::Expr(_),
1532                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }),
1533                    ) => (true, precedence(rhs_op) < op_precedence),
1534                    (ty::ConstKind::Expr(_), ty::ConstKind::Expr(_)) => (true, true),
1535                    (
1536                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }),
1537                        _,
1538                    ) => (precedence(lhs_op) < op_precedence, false),
1539                    (
1540                        _,
1541                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }),
1542                    ) => (false, precedence(rhs_op) < op_precedence),
1543                    (ty::ConstKind::Expr(_), _) => (true, false),
1544                    (_, ty::ConstKind::Expr(_)) => (false, true),
1545                    _ => (false, false),
1546                };
1547
1548                self.maybe_parenthesized(
1549                    |this| this.pretty_print_const(c1, print_ty),
1550                    lhs_parenthesized,
1551                )?;
1552                p!(write(" {formatted_op} "));
1553                self.maybe_parenthesized(
1554                    |this| this.pretty_print_const(c2, print_ty),
1555                    rhs_parenthesized,
1556                )?;
1557            }
1558            ty::ExprKind::UnOp(op) => {
1559                let (_, ct) = expr.unop_args();
1560
1561                use crate::mir::UnOp;
1562                let formatted_op = match op {
1563                    UnOp::Not => "!",
1564                    UnOp::Neg => "-",
1565                    UnOp::PtrMetadata => "PtrMetadata",
1566                };
1567                let parenthesized = match ct.kind() {
1568                    _ if op == UnOp::PtrMetadata => true,
1569                    ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::UnOp(c_op), .. }) => {
1570                        c_op != op
1571                    }
1572                    ty::ConstKind::Expr(_) => true,
1573                    _ => false,
1574                };
1575                p!(write("{formatted_op}"));
1576                self.maybe_parenthesized(
1577                    |this| this.pretty_print_const(ct, print_ty),
1578                    parenthesized,
1579                )?
1580            }
1581            ty::ExprKind::FunctionCall => {
1582                let (_, fn_def, fn_args) = expr.call_args();
1583
1584                write!(self, "(")?;
1585                self.pretty_print_const(fn_def, print_ty)?;
1586                p!(")(", comma_sep(fn_args), ")");
1587            }
1588            ty::ExprKind::Cast(kind) => {
1589                let (_, value, to_ty) = expr.cast_args();
1590
1591                use ty::abstract_const::CastKind;
1592                if kind == CastKind::As || (kind == CastKind::Use && self.should_print_verbose()) {
1593                    let parenthesized = match value.kind() {
1594                        ty::ConstKind::Expr(ty::Expr {
1595                            kind: ty::ExprKind::Cast { .. }, ..
1596                        }) => false,
1597                        ty::ConstKind::Expr(_) => true,
1598                        _ => false,
1599                    };
1600                    self.maybe_parenthesized(
1601                        |this| {
1602                            this.typed_value(
1603                                |this| this.pretty_print_const(value, print_ty),
1604                                |this| this.pretty_print_type(to_ty),
1605                                " as ",
1606                            )
1607                        },
1608                        parenthesized,
1609                    )?;
1610                } else {
1611                    self.pretty_print_const(value, print_ty)?
1612                }
1613            }
1614        }
1615        Ok(())
1616    }
1617
1618    fn pretty_print_const_scalar(
1619        &mut self,
1620        scalar: Scalar,
1621        ty: Ty<'tcx>,
1622    ) -> Result<(), PrintError> {
1623        match scalar {
1624            Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty),
1625            Scalar::Int(int) => {
1626                self.pretty_print_const_scalar_int(int, ty, /* print_ty */ true)
1627            }
1628        }
1629    }
1630
1631    fn pretty_print_const_scalar_ptr(
1632        &mut self,
1633        ptr: Pointer,
1634        ty: Ty<'tcx>,
1635    ) -> Result<(), PrintError> {
1636        define_scoped_cx!(self);
1637
1638        let (prov, offset) = ptr.into_parts();
1639        match ty.kind() {
1640            // Byte strings (&[u8; N])
1641            ty::Ref(_, inner, _) => {
1642                if let ty::Array(elem, ct_len) = inner.kind()
1643                    && let ty::Uint(ty::UintTy::U8) = elem.kind()
1644                    && let Some(len) = ct_len.try_to_target_usize(self.tcx())
1645                {
1646                    match self.tcx().try_get_global_alloc(prov.alloc_id()) {
1647                        Some(GlobalAlloc::Memory(alloc)) => {
1648                            let range = AllocRange { start: offset, size: Size::from_bytes(len) };
1649                            if let Ok(byte_str) =
1650                                alloc.inner().get_bytes_strip_provenance(&self.tcx(), range)
1651                            {
1652                                p!(pretty_print_byte_str(byte_str))
1653                            } else {
1654                                p!("<too short allocation>")
1655                            }
1656                        }
1657                        // FIXME: for statics, vtables, and functions, we could in principle print more detail.
1658                        Some(GlobalAlloc::Static(def_id)) => {
1659                            p!(write("<static({:?})>", def_id))
1660                        }
1661                        Some(GlobalAlloc::Function { .. }) => p!("<function>"),
1662                        Some(GlobalAlloc::VTable(..)) => p!("<vtable>"),
1663                        None => p!("<dangling pointer>"),
1664                    }
1665                    return Ok(());
1666                }
1667            }
1668            ty::FnPtr(..) => {
1669                // FIXME: We should probably have a helper method to share code with the "Byte strings"
1670                // printing above (which also has to handle pointers to all sorts of things).
1671                if let Some(GlobalAlloc::Function { instance, .. }) =
1672                    self.tcx().try_get_global_alloc(prov.alloc_id())
1673                {
1674                    self.typed_value(
1675                        |this| this.print_value_path(instance.def_id(), instance.args),
1676                        |this| this.print_type(ty),
1677                        " as ",
1678                    )?;
1679                    return Ok(());
1680                }
1681            }
1682            _ => {}
1683        }
1684        // Any pointer values not covered by a branch above
1685        self.pretty_print_const_pointer(ptr, ty)?;
1686        Ok(())
1687    }
1688
1689    fn pretty_print_const_scalar_int(
1690        &mut self,
1691        int: ScalarInt,
1692        ty: Ty<'tcx>,
1693        print_ty: bool,
1694    ) -> Result<(), PrintError> {
1695        define_scoped_cx!(self);
1696
1697        match ty.kind() {
1698            // Bool
1699            ty::Bool if int == ScalarInt::FALSE => p!("false"),
1700            ty::Bool if int == ScalarInt::TRUE => p!("true"),
1701            // Float
1702            ty::Float(fty) => match fty {
1703                ty::FloatTy::F16 => {
1704                    let val = Half::try_from(int).unwrap();
1705                    p!(write("{}{}f16", val, if val.is_finite() { "" } else { "_" }))
1706                }
1707                ty::FloatTy::F32 => {
1708                    let val = Single::try_from(int).unwrap();
1709                    p!(write("{}{}f32", val, if val.is_finite() { "" } else { "_" }))
1710                }
1711                ty::FloatTy::F64 => {
1712                    let val = Double::try_from(int).unwrap();
1713                    p!(write("{}{}f64", val, if val.is_finite() { "" } else { "_" }))
1714                }
1715                ty::FloatTy::F128 => {
1716                    let val = Quad::try_from(int).unwrap();
1717                    p!(write("{}{}f128", val, if val.is_finite() { "" } else { "_" }))
1718                }
1719            },
1720            // Int
1721            ty::Uint(_) | ty::Int(_) => {
1722                let int =
1723                    ConstInt::new(int, matches!(ty.kind(), ty::Int(_)), ty.is_ptr_sized_integral());
1724                if print_ty { p!(write("{:#?}", int)) } else { p!(write("{:?}", int)) }
1725            }
1726            // Char
1727            ty::Char if char::try_from(int).is_ok() => {
1728                p!(write("{:?}", char::try_from(int).unwrap()))
1729            }
1730            // Pointer types
1731            ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(..) => {
1732                let data = int.to_bits(self.tcx().data_layout.pointer_size);
1733                self.typed_value(
1734                    |this| {
1735                        write!(this, "0x{data:x}")?;
1736                        Ok(())
1737                    },
1738                    |this| this.print_type(ty),
1739                    " as ",
1740                )?;
1741            }
1742            ty::Pat(base_ty, pat) if self.tcx().validate_scalar_in_layout(int, ty) => {
1743                self.pretty_print_const_scalar_int(int, *base_ty, print_ty)?;
1744                p!(write(" is {pat:?}"));
1745            }
1746            // Nontrivial types with scalar bit representation
1747            _ => {
1748                let print = |this: &mut Self| {
1749                    if int.size() == Size::ZERO {
1750                        write!(this, "transmute(())")?;
1751                    } else {
1752                        write!(this, "transmute(0x{int:x})")?;
1753                    }
1754                    Ok(())
1755                };
1756                if print_ty {
1757                    self.typed_value(print, |this| this.print_type(ty), ": ")?
1758                } else {
1759                    print(self)?
1760                };
1761            }
1762        }
1763        Ok(())
1764    }
1765
1766    /// This is overridden for MIR printing because we only want to hide alloc ids from users, not
1767    /// from MIR where it is actually useful.
1768    fn pretty_print_const_pointer<Prov: Provenance>(
1769        &mut self,
1770        _: Pointer<Prov>,
1771        ty: Ty<'tcx>,
1772    ) -> Result<(), PrintError> {
1773        self.typed_value(
1774            |this| {
1775                this.write_str("&_")?;
1776                Ok(())
1777            },
1778            |this| this.print_type(ty),
1779            ": ",
1780        )
1781    }
1782
1783    fn pretty_print_byte_str(&mut self, byte_str: &'tcx [u8]) -> Result<(), PrintError> {
1784        write!(self, "b\"{}\"", byte_str.escape_ascii())?;
1785        Ok(())
1786    }
1787
1788    fn pretty_print_const_valtree(
1789        &mut self,
1790        cv: ty::Value<'tcx>,
1791        print_ty: bool,
1792    ) -> Result<(), PrintError> {
1793        define_scoped_cx!(self);
1794
1795        if self.should_print_verbose() {
1796            p!(write("ValTree({:?}: ", cv.valtree), print(cv.ty), ")");
1797            return Ok(());
1798        }
1799
1800        let u8_type = self.tcx().types.u8;
1801        match (*cv.valtree, *cv.ty.kind()) {
1802            (ty::ValTreeKind::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
1803                ty::Slice(t) if *t == u8_type => {
1804                    let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
1805                        bug!(
1806                            "expected to convert valtree {:?} to raw bytes for type {:?}",
1807                            cv.valtree,
1808                            t
1809                        )
1810                    });
1811                    return self.pretty_print_byte_str(bytes);
1812                }
1813                ty::Str => {
1814                    let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
1815                        bug!("expected to convert valtree to raw bytes for type {:?}", cv.ty)
1816                    });
1817                    p!(write("{:?}", String::from_utf8_lossy(bytes)));
1818                    return Ok(());
1819                }
1820                _ => {
1821                    let cv = ty::Value { valtree: cv.valtree, ty: inner_ty };
1822                    p!("&");
1823                    p!(pretty_print_const_valtree(cv, print_ty));
1824                    return Ok(());
1825                }
1826            },
1827            (ty::ValTreeKind::Branch(_), ty::Array(t, _)) if t == u8_type => {
1828                let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
1829                    bug!("expected to convert valtree to raw bytes for type {:?}", t)
1830                });
1831                p!("*");
1832                p!(pretty_print_byte_str(bytes));
1833                return Ok(());
1834            }
1835            // Aggregates, printed as array/tuple/struct/variant construction syntax.
1836            (ty::ValTreeKind::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
1837                let contents = self.tcx().destructure_const(ty::Const::new_value(
1838                    self.tcx(),
1839                    cv.valtree,
1840                    cv.ty,
1841                ));
1842                let fields = contents.fields.iter().copied();
1843                match *cv.ty.kind() {
1844                    ty::Array(..) => {
1845                        p!("[", comma_sep(fields), "]");
1846                    }
1847                    ty::Tuple(..) => {
1848                        p!("(", comma_sep(fields));
1849                        if contents.fields.len() == 1 {
1850                            p!(",");
1851                        }
1852                        p!(")");
1853                    }
1854                    ty::Adt(def, _) if def.variants().is_empty() => {
1855                        self.typed_value(
1856                            |this| {
1857                                write!(this, "unreachable()")?;
1858                                Ok(())
1859                            },
1860                            |this| this.print_type(cv.ty),
1861                            ": ",
1862                        )?;
1863                    }
1864                    ty::Adt(def, args) => {
1865                        let variant_idx =
1866                            contents.variant.expect("destructed const of adt without variant idx");
1867                        let variant_def = &def.variant(variant_idx);
1868                        p!(print_value_path(variant_def.def_id, args));
1869                        match variant_def.ctor_kind() {
1870                            Some(CtorKind::Const) => {}
1871                            Some(CtorKind::Fn) => {
1872                                p!("(", comma_sep(fields), ")");
1873                            }
1874                            None => {
1875                                p!(" {{ ");
1876                                let mut first = true;
1877                                for (field_def, field) in iter::zip(&variant_def.fields, fields) {
1878                                    if !first {
1879                                        p!(", ");
1880                                    }
1881                                    p!(write("{}: ", field_def.name), print(field));
1882                                    first = false;
1883                                }
1884                                p!(" }}");
1885                            }
1886                        }
1887                    }
1888                    _ => unreachable!(),
1889                }
1890                return Ok(());
1891            }
1892            (ty::ValTreeKind::Leaf(leaf), ty::Ref(_, inner_ty, _)) => {
1893                p!(write("&"));
1894                return self.pretty_print_const_scalar_int(*leaf, inner_ty, print_ty);
1895            }
1896            (ty::ValTreeKind::Leaf(leaf), _) => {
1897                return self.pretty_print_const_scalar_int(*leaf, cv.ty, print_ty);
1898            }
1899            (_, ty::FnDef(def_id, args)) => {
1900                // Never allowed today, but we still encounter them in invalid const args.
1901                p!(print_value_path(def_id, args));
1902                return Ok(());
1903            }
1904            // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
1905            // their fields instead of just dumping the memory.
1906            _ => {}
1907        }
1908
1909        // fallback
1910        if cv.valtree.is_zst() {
1911            p!(write("<ZST>"));
1912        } else {
1913            p!(write("{:?}", cv.valtree));
1914        }
1915        if print_ty {
1916            p!(": ", print(cv.ty));
1917        }
1918        Ok(())
1919    }
1920
1921    fn pretty_closure_as_impl(
1922        &mut self,
1923        closure: ty::ClosureArgs<TyCtxt<'tcx>>,
1924    ) -> Result<(), PrintError> {
1925        let sig = closure.sig();
1926        let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn);
1927
1928        write!(self, "impl ")?;
1929        self.wrap_binder(&sig, |sig, cx| {
1930            define_scoped_cx!(cx);
1931
1932            p!(write("{kind}("));
1933            for (i, arg) in sig.inputs()[0].tuple_fields().iter().enumerate() {
1934                if i > 0 {
1935                    p!(", ");
1936                }
1937                p!(print(arg));
1938            }
1939            p!(")");
1940
1941            if !sig.output().is_unit() {
1942                p!(" -> ", print(sig.output()));
1943            }
1944
1945            Ok(())
1946        })
1947    }
1948
1949    fn pretty_print_bound_constness(
1950        &mut self,
1951        constness: ty::BoundConstness,
1952    ) -> Result<(), PrintError> {
1953        define_scoped_cx!(self);
1954
1955        match constness {
1956            ty::BoundConstness::Const => {
1957                p!("const ");
1958            }
1959            ty::BoundConstness::Maybe => {
1960                p!("~const ");
1961            }
1962        }
1963        Ok(())
1964    }
1965
1966    fn should_print_verbose(&self) -> bool {
1967        self.tcx().sess.verbose_internals()
1968    }
1969}
1970
1971pub(crate) fn pretty_print_const<'tcx>(
1972    c: ty::Const<'tcx>,
1973    fmt: &mut fmt::Formatter<'_>,
1974    print_types: bool,
1975) -> fmt::Result {
1976    ty::tls::with(|tcx| {
1977        let literal = tcx.lift(c).unwrap();
1978        let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
1979        cx.print_alloc_ids = true;
1980        cx.pretty_print_const(literal, print_types)?;
1981        fmt.write_str(&cx.into_buffer())?;
1982        Ok(())
1983    })
1984}
1985
1986// HACK(eddyb) boxed to avoid moving around a large struct by-value.
1987pub struct FmtPrinter<'a, 'tcx>(Box<FmtPrinterData<'a, 'tcx>>);
1988
1989pub struct FmtPrinterData<'a, 'tcx> {
1990    tcx: TyCtxt<'tcx>,
1991    fmt: String,
1992
1993    empty_path: bool,
1994    in_value: bool,
1995    pub print_alloc_ids: bool,
1996
1997    // set of all named (non-anonymous) region names
1998    used_region_names: FxHashSet<Symbol>,
1999
2000    region_index: usize,
2001    binder_depth: usize,
2002    printed_type_count: usize,
2003    type_length_limit: Limit,
2004
2005    pub region_highlight_mode: RegionHighlightMode<'tcx>,
2006
2007    pub ty_infer_name_resolver: Option<Box<dyn Fn(ty::TyVid) -> Option<Symbol> + 'a>>,
2008    pub const_infer_name_resolver: Option<Box<dyn Fn(ty::ConstVid) -> Option<Symbol> + 'a>>,
2009}
2010
2011impl<'a, 'tcx> Deref for FmtPrinter<'a, 'tcx> {
2012    type Target = FmtPrinterData<'a, 'tcx>;
2013    fn deref(&self) -> &Self::Target {
2014        &self.0
2015    }
2016}
2017
2018impl DerefMut for FmtPrinter<'_, '_> {
2019    fn deref_mut(&mut self) -> &mut Self::Target {
2020        &mut self.0
2021    }
2022}
2023
2024impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
2025    pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self {
2026        let limit =
2027            if with_reduced_queries() { Limit::new(1048576) } else { tcx.type_length_limit() };
2028        Self::new_with_limit(tcx, ns, limit)
2029    }
2030
2031    pub fn print_string(
2032        tcx: TyCtxt<'tcx>,
2033        ns: Namespace,
2034        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
2035    ) -> Result<String, PrintError> {
2036        let mut c = FmtPrinter::new(tcx, ns);
2037        f(&mut c)?;
2038        Ok(c.into_buffer())
2039    }
2040
2041    pub fn new_with_limit(tcx: TyCtxt<'tcx>, ns: Namespace, type_length_limit: Limit) -> Self {
2042        FmtPrinter(Box::new(FmtPrinterData {
2043            tcx,
2044            // Estimated reasonable capacity to allocate upfront based on a few
2045            // benchmarks.
2046            fmt: String::with_capacity(64),
2047            empty_path: false,
2048            in_value: ns == Namespace::ValueNS,
2049            print_alloc_ids: false,
2050            used_region_names: Default::default(),
2051            region_index: 0,
2052            binder_depth: 0,
2053            printed_type_count: 0,
2054            type_length_limit,
2055            region_highlight_mode: RegionHighlightMode::default(),
2056            ty_infer_name_resolver: None,
2057            const_infer_name_resolver: None,
2058        }))
2059    }
2060
2061    pub fn into_buffer(self) -> String {
2062        self.0.fmt
2063    }
2064}
2065
2066// HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
2067// (but also some things just print a `DefId` generally so maybe we need this?)
2068fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
2069    match tcx.def_key(def_id).disambiguated_data.data {
2070        DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::OpaqueTy => {
2071            Namespace::TypeNS
2072        }
2073
2074        DefPathData::ValueNs(..)
2075        | DefPathData::AnonConst
2076        | DefPathData::Closure
2077        | DefPathData::Ctor => Namespace::ValueNS,
2078
2079        DefPathData::MacroNs(..) => Namespace::MacroNS,
2080
2081        _ => Namespace::TypeNS,
2082    }
2083}
2084
2085impl<'t> TyCtxt<'t> {
2086    /// Returns a string identifying this `DefId`. This string is
2087    /// suitable for user output.
2088    pub fn def_path_str(self, def_id: impl IntoQueryParam<DefId>) -> String {
2089        self.def_path_str_with_args(def_id, &[])
2090    }
2091
2092    pub fn def_path_str_with_args(
2093        self,
2094        def_id: impl IntoQueryParam<DefId>,
2095        args: &'t [GenericArg<'t>],
2096    ) -> String {
2097        let def_id = def_id.into_query_param();
2098        let ns = guess_def_namespace(self, def_id);
2099        debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
2100
2101        FmtPrinter::print_string(self, ns, |cx| cx.print_def_path(def_id, args)).unwrap()
2102    }
2103
2104    pub fn value_path_str_with_args(
2105        self,
2106        def_id: impl IntoQueryParam<DefId>,
2107        args: &'t [GenericArg<'t>],
2108    ) -> String {
2109        let def_id = def_id.into_query_param();
2110        let ns = guess_def_namespace(self, def_id);
2111        debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns);
2112
2113        FmtPrinter::print_string(self, ns, |cx| cx.print_value_path(def_id, args)).unwrap()
2114    }
2115}
2116
2117impl fmt::Write for FmtPrinter<'_, '_> {
2118    fn write_str(&mut self, s: &str) -> fmt::Result {
2119        self.fmt.push_str(s);
2120        Ok(())
2121    }
2122}
2123
2124impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
2125    fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
2126        self.tcx
2127    }
2128
2129    fn print_def_path(
2130        &mut self,
2131        def_id: DefId,
2132        args: &'tcx [GenericArg<'tcx>],
2133    ) -> Result<(), PrintError> {
2134        if args.is_empty() {
2135            match self.try_print_trimmed_def_path(def_id)? {
2136                true => return Ok(()),
2137                false => {}
2138            }
2139
2140            match self.try_print_visible_def_path(def_id)? {
2141                true => return Ok(()),
2142                false => {}
2143            }
2144        }
2145
2146        let key = self.tcx.def_key(def_id);
2147        if let DefPathData::Impl = key.disambiguated_data.data {
2148            // Always use types for non-local impls, where types are always
2149            // available, and filename/line-number is mostly uninteresting.
2150            let use_types = !def_id.is_local() || {
2151                // Otherwise, use filename/line-number if forced.
2152                let force_no_types = with_forced_impl_filename_line();
2153                !force_no_types
2154            };
2155
2156            if !use_types {
2157                // If no type info is available, fall back to
2158                // pretty printing some span information. This should
2159                // only occur very early in the compiler pipeline.
2160                let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
2161                let span = self.tcx.def_span(def_id);
2162
2163                self.print_def_path(parent_def_id, &[])?;
2164
2165                // HACK(eddyb) copy of `path_append` to avoid
2166                // constructing a `DisambiguatedDefPathData`.
2167                if !self.empty_path {
2168                    write!(self, "::")?;
2169                }
2170                write!(
2171                    self,
2172                    "<impl at {}>",
2173                    // This may end up in stderr diagnostics but it may also be emitted
2174                    // into MIR. Hence we use the remapped path if available
2175                    self.tcx.sess.source_map().span_to_embeddable_string(span)
2176                )?;
2177                self.empty_path = false;
2178
2179                return Ok(());
2180            }
2181        }
2182
2183        self.default_print_def_path(def_id, args)
2184    }
2185
2186    fn print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), PrintError> {
2187        self.pretty_print_region(region)
2188    }
2189
2190    fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
2191        match ty.kind() {
2192            ty::Tuple(tys) if tys.len() == 0 && self.should_truncate() => {
2193                // Don't truncate `()`.
2194                self.printed_type_count += 1;
2195                self.pretty_print_type(ty)
2196            }
2197            ty::Adt(..)
2198            | ty::Foreign(_)
2199            | ty::Pat(..)
2200            | ty::RawPtr(..)
2201            | ty::Ref(..)
2202            | ty::FnDef(..)
2203            | ty::FnPtr(..)
2204            | ty::UnsafeBinder(..)
2205            | ty::Dynamic(..)
2206            | ty::Closure(..)
2207            | ty::CoroutineClosure(..)
2208            | ty::Coroutine(..)
2209            | ty::CoroutineWitness(..)
2210            | ty::Tuple(_)
2211            | ty::Alias(..)
2212            | ty::Param(_)
2213            | ty::Bound(..)
2214            | ty::Placeholder(_)
2215            | ty::Error(_)
2216                if self.should_truncate() =>
2217            {
2218                // We only truncate types that we know are likely to be much longer than 3 chars.
2219                // There's no point in replacing `i32` or `!`.
2220                write!(self, "...")?;
2221                Ok(())
2222            }
2223            _ => {
2224                self.printed_type_count += 1;
2225                self.pretty_print_type(ty)
2226            }
2227        }
2228    }
2229
2230    fn should_truncate(&mut self) -> bool {
2231        !self.type_length_limit.value_within_limit(self.printed_type_count)
2232    }
2233
2234    fn print_dyn_existential(
2235        &mut self,
2236        predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
2237    ) -> Result<(), PrintError> {
2238        self.pretty_print_dyn_existential(predicates)
2239    }
2240
2241    fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
2242        self.pretty_print_const(ct, false)
2243    }
2244
2245    fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
2246        self.empty_path = true;
2247        if cnum == LOCAL_CRATE {
2248            if self.tcx.sess.at_least_rust_2018() {
2249                // We add the `crate::` keyword on Rust 2018, only when desired.
2250                if with_crate_prefix() {
2251                    write!(self, "{}", kw::Crate)?;
2252                    self.empty_path = false;
2253                }
2254            }
2255        } else {
2256            write!(self, "{}", self.tcx.crate_name(cnum))?;
2257            self.empty_path = false;
2258        }
2259        Ok(())
2260    }
2261
2262    fn path_qualified(
2263        &mut self,
2264        self_ty: Ty<'tcx>,
2265        trait_ref: Option<ty::TraitRef<'tcx>>,
2266    ) -> Result<(), PrintError> {
2267        self.pretty_path_qualified(self_ty, trait_ref)?;
2268        self.empty_path = false;
2269        Ok(())
2270    }
2271
2272    fn path_append_impl(
2273        &mut self,
2274        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
2275        _disambiguated_data: &DisambiguatedDefPathData,
2276        self_ty: Ty<'tcx>,
2277        trait_ref: Option<ty::TraitRef<'tcx>>,
2278    ) -> Result<(), PrintError> {
2279        self.pretty_path_append_impl(
2280            |cx| {
2281                print_prefix(cx)?;
2282                if !cx.empty_path {
2283                    write!(cx, "::")?;
2284                }
2285
2286                Ok(())
2287            },
2288            self_ty,
2289            trait_ref,
2290        )?;
2291        self.empty_path = false;
2292        Ok(())
2293    }
2294
2295    fn path_append(
2296        &mut self,
2297        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
2298        disambiguated_data: &DisambiguatedDefPathData,
2299    ) -> Result<(), PrintError> {
2300        print_prefix(self)?;
2301
2302        // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
2303        if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data {
2304            return Ok(());
2305        }
2306
2307        let name = disambiguated_data.data.name();
2308        if !self.empty_path {
2309            write!(self, "::")?;
2310        }
2311
2312        if let DefPathDataName::Named(name) = name {
2313            if Ident::with_dummy_span(name).is_raw_guess() {
2314                write!(self, "r#")?;
2315            }
2316        }
2317
2318        let verbose = self.should_print_verbose();
2319        disambiguated_data.fmt_maybe_verbose(self, verbose)?;
2320
2321        self.empty_path = false;
2322
2323        Ok(())
2324    }
2325
2326    fn path_generic_args(
2327        &mut self,
2328        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
2329        args: &[GenericArg<'tcx>],
2330    ) -> Result<(), PrintError> {
2331        print_prefix(self)?;
2332
2333        if !args.is_empty() {
2334            if self.in_value {
2335                write!(self, "::")?;
2336            }
2337            self.generic_delimiters(|cx| cx.comma_sep(args.iter().copied()))
2338        } else {
2339            Ok(())
2340        }
2341    }
2342}
2343
2344impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
2345    fn ty_infer_name(&self, id: ty::TyVid) -> Option<Symbol> {
2346        self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id))
2347    }
2348
2349    fn reset_type_limit(&mut self) {
2350        self.printed_type_count = 0;
2351    }
2352
2353    fn const_infer_name(&self, id: ty::ConstVid) -> Option<Symbol> {
2354        self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id))
2355    }
2356
2357    fn print_value_path(
2358        &mut self,
2359        def_id: DefId,
2360        args: &'tcx [GenericArg<'tcx>],
2361    ) -> Result<(), PrintError> {
2362        let was_in_value = std::mem::replace(&mut self.in_value, true);
2363        self.print_def_path(def_id, args)?;
2364        self.in_value = was_in_value;
2365
2366        Ok(())
2367    }
2368
2369    fn in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
2370    where
2371        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
2372    {
2373        self.pretty_in_binder(value)
2374    }
2375
2376    fn wrap_binder<T, C: FnOnce(&T, &mut Self) -> Result<(), PrintError>>(
2377        &mut self,
2378        value: &ty::Binder<'tcx, T>,
2379        f: C,
2380    ) -> Result<(), PrintError>
2381    where
2382        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
2383    {
2384        self.pretty_wrap_binder(value, f)
2385    }
2386
2387    fn typed_value(
2388        &mut self,
2389        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
2390        t: impl FnOnce(&mut Self) -> Result<(), PrintError>,
2391        conversion: &str,
2392    ) -> Result<(), PrintError> {
2393        self.write_str("{")?;
2394        f(self)?;
2395        self.write_str(conversion)?;
2396        let was_in_value = std::mem::replace(&mut self.in_value, false);
2397        t(self)?;
2398        self.in_value = was_in_value;
2399        self.write_str("}")?;
2400        Ok(())
2401    }
2402
2403    fn generic_delimiters(
2404        &mut self,
2405        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
2406    ) -> Result<(), PrintError> {
2407        write!(self, "<")?;
2408
2409        let was_in_value = std::mem::replace(&mut self.in_value, false);
2410        f(self)?;
2411        self.in_value = was_in_value;
2412
2413        write!(self, ">")?;
2414        Ok(())
2415    }
2416
2417    fn should_print_region(&self, region: ty::Region<'tcx>) -> bool {
2418        let highlight = self.region_highlight_mode;
2419        if highlight.region_highlighted(region).is_some() {
2420            return true;
2421        }
2422
2423        if self.should_print_verbose() {
2424            return true;
2425        }
2426
2427        if with_forced_trimmed_paths() {
2428            return false;
2429        }
2430
2431        let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
2432
2433        match *region {
2434            ty::ReEarlyParam(ref data) => data.has_name(),
2435
2436            ty::ReLateParam(ty::LateParamRegion { kind, .. }) => kind.is_named(),
2437            ty::ReBound(_, ty::BoundRegion { kind: br, .. })
2438            | ty::RePlaceholder(ty::Placeholder {
2439                bound: ty::BoundRegion { kind: br, .. }, ..
2440            }) => {
2441                if br.is_named() {
2442                    return true;
2443                }
2444
2445                if let Some((region, _)) = highlight.highlight_bound_region {
2446                    if br == region {
2447                        return true;
2448                    }
2449                }
2450
2451                false
2452            }
2453
2454            ty::ReVar(_) if identify_regions => true,
2455
2456            ty::ReVar(_) | ty::ReErased | ty::ReError(_) => false,
2457
2458            ty::ReStatic => true,
2459        }
2460    }
2461
2462    fn pretty_print_const_pointer<Prov: Provenance>(
2463        &mut self,
2464        p: Pointer<Prov>,
2465        ty: Ty<'tcx>,
2466    ) -> Result<(), PrintError> {
2467        let print = |this: &mut Self| {
2468            define_scoped_cx!(this);
2469            if this.print_alloc_ids {
2470                p!(write("{:?}", p));
2471            } else {
2472                p!("&_");
2473            }
2474            Ok(())
2475        };
2476        self.typed_value(print, |this| this.print_type(ty), ": ")
2477    }
2478}
2479
2480// HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
2481impl<'tcx> FmtPrinter<'_, 'tcx> {
2482    pub fn pretty_print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), fmt::Error> {
2483        define_scoped_cx!(self);
2484
2485        // Watch out for region highlights.
2486        let highlight = self.region_highlight_mode;
2487        if let Some(n) = highlight.region_highlighted(region) {
2488            p!(write("'{}", n));
2489            return Ok(());
2490        }
2491
2492        if self.should_print_verbose() {
2493            p!(write("{:?}", region));
2494            return Ok(());
2495        }
2496
2497        let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
2498
2499        // These printouts are concise. They do not contain all the information
2500        // the user might want to diagnose an error, but there is basically no way
2501        // to fit that into a short string. Hence the recommendation to use
2502        // `explain_region()` or `note_and_explain_region()`.
2503        match *region {
2504            ty::ReEarlyParam(ref data) => {
2505                if data.name != kw::Empty {
2506                    p!(write("{}", data.name));
2507                    return Ok(());
2508                }
2509            }
2510            ty::ReLateParam(ty::LateParamRegion { kind, .. }) => {
2511                if let Some(name) = kind.get_name() {
2512                    p!(write("{}", name));
2513                    return Ok(());
2514                }
2515            }
2516            ty::ReBound(_, ty::BoundRegion { kind: br, .. })
2517            | ty::RePlaceholder(ty::Placeholder {
2518                bound: ty::BoundRegion { kind: br, .. }, ..
2519            }) => {
2520                if let ty::BoundRegionKind::Named(_, name) = br
2521                    && br.is_named()
2522                {
2523                    p!(write("{}", name));
2524                    return Ok(());
2525                }
2526
2527                if let Some((region, counter)) = highlight.highlight_bound_region {
2528                    if br == region {
2529                        p!(write("'{}", counter));
2530                        return Ok(());
2531                    }
2532                }
2533            }
2534            ty::ReVar(region_vid) if identify_regions => {
2535                p!(write("{:?}", region_vid));
2536                return Ok(());
2537            }
2538            ty::ReVar(_) => {}
2539            ty::ReErased => {}
2540            ty::ReError(_) => {}
2541            ty::ReStatic => {
2542                p!("'static");
2543                return Ok(());
2544            }
2545        }
2546
2547        p!("'_");
2548
2549        Ok(())
2550    }
2551}
2552
2553/// Folds through bound vars and placeholders, naming them
2554struct RegionFolder<'a, 'tcx> {
2555    tcx: TyCtxt<'tcx>,
2556    current_index: ty::DebruijnIndex,
2557    region_map: UnordMap<ty::BoundRegion, ty::Region<'tcx>>,
2558    name: &'a mut (
2559                dyn FnMut(
2560        Option<ty::DebruijnIndex>, // Debruijn index of the folded late-bound region
2561        ty::DebruijnIndex,         // Index corresponding to binder level
2562        ty::BoundRegion,
2563    ) -> ty::Region<'tcx>
2564                    + 'a
2565            ),
2566}
2567
2568impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
2569    fn cx(&self) -> TyCtxt<'tcx> {
2570        self.tcx
2571    }
2572
2573    fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
2574        &mut self,
2575        t: ty::Binder<'tcx, T>,
2576    ) -> ty::Binder<'tcx, T> {
2577        self.current_index.shift_in(1);
2578        let t = t.super_fold_with(self);
2579        self.current_index.shift_out(1);
2580        t
2581    }
2582
2583    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
2584        match *t.kind() {
2585            _ if t.has_vars_bound_at_or_above(self.current_index) || t.has_placeholders() => {
2586                return t.super_fold_with(self);
2587            }
2588            _ => {}
2589        }
2590        t
2591    }
2592
2593    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
2594        let name = &mut self.name;
2595        let region = match *r {
2596            ty::ReBound(db, br) if db >= self.current_index => {
2597                *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br))
2598            }
2599            ty::RePlaceholder(ty::PlaceholderRegion {
2600                bound: ty::BoundRegion { kind, .. },
2601                ..
2602            }) => {
2603                // If this is an anonymous placeholder, don't rename. Otherwise, in some
2604                // async fns, we get a `for<'r> Send` bound
2605                match kind {
2606                    ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => r,
2607                    _ => {
2608                        // Index doesn't matter, since this is just for naming and these never get bound
2609                        let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind };
2610                        *self
2611                            .region_map
2612                            .entry(br)
2613                            .or_insert_with(|| name(None, self.current_index, br))
2614                    }
2615                }
2616            }
2617            _ => return r,
2618        };
2619        if let ty::ReBound(debruijn1, br) = *region {
2620            assert_eq!(debruijn1, ty::INNERMOST);
2621            ty::Region::new_bound(self.tcx, self.current_index, br)
2622        } else {
2623            region
2624        }
2625    }
2626}
2627
2628// HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
2629// `region_index` and `used_region_names`.
2630impl<'tcx> FmtPrinter<'_, 'tcx> {
2631    pub fn name_all_regions<T>(
2632        &mut self,
2633        value: &ty::Binder<'tcx, T>,
2634    ) -> Result<(T, UnordMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
2635    where
2636        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
2637    {
2638        fn name_by_region_index(
2639            index: usize,
2640            available_names: &mut Vec<Symbol>,
2641            num_available: usize,
2642        ) -> Symbol {
2643            if let Some(name) = available_names.pop() {
2644                name
2645            } else {
2646                Symbol::intern(&format!("'z{}", index - num_available))
2647            }
2648        }
2649
2650        debug!("name_all_regions");
2651
2652        // Replace any anonymous late-bound regions with named
2653        // variants, using new unique identifiers, so that we can
2654        // clearly differentiate between named and unnamed regions in
2655        // the output. We'll probably want to tweak this over time to
2656        // decide just how much information to give.
2657        if self.binder_depth == 0 {
2658            self.prepare_region_info(value);
2659        }
2660
2661        debug!("self.used_region_names: {:?}", self.used_region_names);
2662
2663        let mut empty = true;
2664        let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
2665            let w = if empty {
2666                empty = false;
2667                start
2668            } else {
2669                cont
2670            };
2671            let _ = write!(cx, "{w}");
2672        };
2673        let do_continue = |cx: &mut Self, cont: Symbol| {
2674            let _ = write!(cx, "{cont}");
2675        };
2676
2677        let possible_names = ('a'..='z').rev().map(|s| Symbol::intern(&format!("'{s}")));
2678
2679        let mut available_names = possible_names
2680            .filter(|name| !self.used_region_names.contains(name))
2681            .collect::<Vec<_>>();
2682        debug!(?available_names);
2683        let num_available = available_names.len();
2684
2685        let mut region_index = self.region_index;
2686        let mut next_name = |this: &Self| {
2687            let mut name;
2688
2689            loop {
2690                name = name_by_region_index(region_index, &mut available_names, num_available);
2691                region_index += 1;
2692
2693                if !this.used_region_names.contains(&name) {
2694                    break;
2695                }
2696            }
2697
2698            name
2699        };
2700
2701        // If we want to print verbosely, then print *all* binders, even if they
2702        // aren't named. Eventually, we might just want this as the default, but
2703        // this is not *quite* right and changes the ordering of some output
2704        // anyways.
2705        let (new_value, map) = if self.should_print_verbose() {
2706            for var in value.bound_vars().iter() {
2707                start_or_continue(self, "for<", ", ");
2708                write!(self, "{var:?}")?;
2709            }
2710            start_or_continue(self, "", "> ");
2711            (value.clone().skip_binder(), UnordMap::default())
2712        } else {
2713            let tcx = self.tcx;
2714
2715            let trim_path = with_forced_trimmed_paths();
2716            // Closure used in `RegionFolder` to create names for anonymous late-bound
2717            // regions. We use two `DebruijnIndex`es (one for the currently folded
2718            // late-bound region and the other for the binder level) to determine
2719            // whether a name has already been created for the currently folded region,
2720            // see issue #102392.
2721            let mut name = |lifetime_idx: Option<ty::DebruijnIndex>,
2722                            binder_level_idx: ty::DebruijnIndex,
2723                            br: ty::BoundRegion| {
2724                let (name, kind) = match br.kind {
2725                    ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
2726                        let name = next_name(self);
2727
2728                        if let Some(lt_idx) = lifetime_idx {
2729                            if lt_idx > binder_level_idx {
2730                                let kind =
2731                                    ty::BoundRegionKind::Named(CRATE_DEF_ID.to_def_id(), name);
2732                                return ty::Region::new_bound(
2733                                    tcx,
2734                                    ty::INNERMOST,
2735                                    ty::BoundRegion { var: br.var, kind },
2736                                );
2737                            }
2738                        }
2739
2740                        (name, ty::BoundRegionKind::Named(CRATE_DEF_ID.to_def_id(), name))
2741                    }
2742                    ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime | kw::Empty) => {
2743                        let name = next_name(self);
2744
2745                        if let Some(lt_idx) = lifetime_idx {
2746                            if lt_idx > binder_level_idx {
2747                                let kind = ty::BoundRegionKind::Named(def_id, name);
2748                                return ty::Region::new_bound(
2749                                    tcx,
2750                                    ty::INNERMOST,
2751                                    ty::BoundRegion { var: br.var, kind },
2752                                );
2753                            }
2754                        }
2755
2756                        (name, ty::BoundRegionKind::Named(def_id, name))
2757                    }
2758                    ty::BoundRegionKind::Named(_, name) => {
2759                        if let Some(lt_idx) = lifetime_idx {
2760                            if lt_idx > binder_level_idx {
2761                                let kind = br.kind;
2762                                return ty::Region::new_bound(
2763                                    tcx,
2764                                    ty::INNERMOST,
2765                                    ty::BoundRegion { var: br.var, kind },
2766                                );
2767                            }
2768                        }
2769
2770                        (name, br.kind)
2771                    }
2772                };
2773
2774                if !trim_path {
2775                    start_or_continue(self, "for<", ", ");
2776                    do_continue(self, name);
2777                }
2778                ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
2779            };
2780            let mut folder = RegionFolder {
2781                tcx,
2782                current_index: ty::INNERMOST,
2783                name: &mut name,
2784                region_map: UnordMap::default(),
2785            };
2786            let new_value = value.clone().skip_binder().fold_with(&mut folder);
2787            let region_map = folder.region_map;
2788            if !trim_path {
2789                start_or_continue(self, "", "> ");
2790            }
2791            (new_value, region_map)
2792        };
2793
2794        self.binder_depth += 1;
2795        self.region_index = region_index;
2796        Ok((new_value, map))
2797    }
2798
2799    pub fn pretty_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), fmt::Error>
2800    where
2801        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
2802    {
2803        let old_region_index = self.region_index;
2804        let (new_value, _) = self.name_all_regions(value)?;
2805        new_value.print(self)?;
2806        self.region_index = old_region_index;
2807        self.binder_depth -= 1;
2808        Ok(())
2809    }
2810
2811    pub fn pretty_wrap_binder<T, C: FnOnce(&T, &mut Self) -> Result<(), fmt::Error>>(
2812        &mut self,
2813        value: &ty::Binder<'tcx, T>,
2814        f: C,
2815    ) -> Result<(), fmt::Error>
2816    where
2817        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
2818    {
2819        let old_region_index = self.region_index;
2820        let (new_value, _) = self.name_all_regions(value)?;
2821        f(&new_value, self)?;
2822        self.region_index = old_region_index;
2823        self.binder_depth -= 1;
2824        Ok(())
2825    }
2826
2827    fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
2828    where
2829        T: TypeVisitable<TyCtxt<'tcx>>,
2830    {
2831        struct RegionNameCollector<'tcx> {
2832            used_region_names: FxHashSet<Symbol>,
2833            type_collector: SsoHashSet<Ty<'tcx>>,
2834        }
2835
2836        impl<'tcx> RegionNameCollector<'tcx> {
2837            fn new() -> Self {
2838                RegionNameCollector {
2839                    used_region_names: Default::default(),
2840                    type_collector: SsoHashSet::new(),
2841                }
2842            }
2843        }
2844
2845        impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for RegionNameCollector<'tcx> {
2846            fn visit_region(&mut self, r: ty::Region<'tcx>) {
2847                trace!("address: {:p}", r.0.0);
2848
2849                // Collect all named lifetimes. These allow us to prevent duplication
2850                // of already existing lifetime names when introducing names for
2851                // anonymous late-bound regions.
2852                if let Some(name) = r.get_name() {
2853                    self.used_region_names.insert(name);
2854                }
2855            }
2856
2857            // We collect types in order to prevent really large types from compiling for
2858            // a really long time. See issue #83150 for why this is necessary.
2859            fn visit_ty(&mut self, ty: Ty<'tcx>) {
2860                let not_previously_inserted = self.type_collector.insert(ty);
2861                if not_previously_inserted {
2862                    ty.super_visit_with(self)
2863                }
2864            }
2865        }
2866
2867        let mut collector = RegionNameCollector::new();
2868        value.visit_with(&mut collector);
2869        self.used_region_names = collector.used_region_names;
2870        self.region_index = 0;
2871    }
2872}
2873
2874impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T>
2875where
2876    T: Print<'tcx, P> + TypeFoldable<TyCtxt<'tcx>>,
2877{
2878    fn print(&self, cx: &mut P) -> Result<(), PrintError> {
2879        cx.in_binder(self)
2880    }
2881}
2882
2883impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate<'tcx, T>
2884where
2885    T: Print<'tcx, P>,
2886{
2887    fn print(&self, cx: &mut P) -> Result<(), PrintError> {
2888        define_scoped_cx!(cx);
2889        p!(print(self.0), ": ", print(self.1));
2890        Ok(())
2891    }
2892}
2893
2894/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
2895/// the trait path. That is, it will print `Trait<U>` instead of
2896/// `<T as Trait<U>>`.
2897#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
2898pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
2899
2900impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintOnlyTraitPath<'tcx> {
2901    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
2902        self.to_string().into_diag_arg()
2903    }
2904}
2905
2906impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
2907    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2908        fmt::Display::fmt(self, f)
2909    }
2910}
2911
2912/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
2913/// the trait path, and additionally tries to "sugar" `Fn(...)` trait bounds.
2914#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
2915pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>);
2916
2917impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintSugared<'tcx> {
2918    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
2919        self.to_string().into_diag_arg()
2920    }
2921}
2922
2923impl<'tcx> fmt::Debug for TraitRefPrintSugared<'tcx> {
2924    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2925        fmt::Display::fmt(self, f)
2926    }
2927}
2928
2929/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
2930/// the trait name. That is, it will print `Trait` instead of
2931/// `<T as Trait<U>>`.
2932#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
2933pub struct TraitRefPrintOnlyTraitName<'tcx>(ty::TraitRef<'tcx>);
2934
2935impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> {
2936    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2937        fmt::Display::fmt(self, f)
2938    }
2939}
2940
2941#[extension(pub trait PrintTraitRefExt<'tcx>)]
2942impl<'tcx> ty::TraitRef<'tcx> {
2943    fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
2944        TraitRefPrintOnlyTraitPath(self)
2945    }
2946
2947    fn print_trait_sugared(self) -> TraitRefPrintSugared<'tcx> {
2948        TraitRefPrintSugared(self)
2949    }
2950
2951    fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> {
2952        TraitRefPrintOnlyTraitName(self)
2953    }
2954}
2955
2956#[extension(pub trait PrintPolyTraitRefExt<'tcx>)]
2957impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> {
2958    fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> {
2959        self.map_bound(|tr| tr.print_only_trait_path())
2960    }
2961
2962    fn print_trait_sugared(self) -> ty::Binder<'tcx, TraitRefPrintSugared<'tcx>> {
2963        self.map_bound(|tr| tr.print_trait_sugared())
2964    }
2965}
2966
2967#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
2968pub struct TraitPredPrintModifiersAndPath<'tcx>(ty::TraitPredicate<'tcx>);
2969
2970impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> {
2971    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2972        fmt::Display::fmt(self, f)
2973    }
2974}
2975
2976#[extension(pub trait PrintTraitPredicateExt<'tcx>)]
2977impl<'tcx> ty::TraitPredicate<'tcx> {
2978    fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> {
2979        TraitPredPrintModifiersAndPath(self)
2980    }
2981}
2982
2983#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)]
2984pub struct TraitPredPrintWithBoundConstness<'tcx>(
2985    ty::TraitPredicate<'tcx>,
2986    Option<ty::BoundConstness>,
2987);
2988
2989impl<'tcx> fmt::Debug for TraitPredPrintWithBoundConstness<'tcx> {
2990    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2991        fmt::Display::fmt(self, f)
2992    }
2993}
2994
2995#[extension(pub trait PrintPolyTraitPredicateExt<'tcx>)]
2996impl<'tcx> ty::PolyTraitPredicate<'tcx> {
2997    fn print_modifiers_and_trait_path(
2998        self,
2999    ) -> ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>> {
3000        self.map_bound(TraitPredPrintModifiersAndPath)
3001    }
3002
3003    fn print_with_bound_constness(
3004        self,
3005        constness: Option<ty::BoundConstness>,
3006    ) -> ty::Binder<'tcx, TraitPredPrintWithBoundConstness<'tcx>> {
3007        self.map_bound(|trait_pred| TraitPredPrintWithBoundConstness(trait_pred, constness))
3008    }
3009}
3010
3011#[derive(Debug, Copy, Clone, Lift)]
3012pub struct PrintClosureAsImpl<'tcx> {
3013    pub closure: ty::ClosureArgs<TyCtxt<'tcx>>,
3014}
3015
3016macro_rules! forward_display_to_print {
3017    ($($ty:ty),+) => {
3018        // Some of the $ty arguments may not actually use 'tcx
3019        $(#[allow(unused_lifetimes)] impl<'tcx> fmt::Display for $ty {
3020            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3021                ty::tls::with(|tcx| {
3022                    let mut cx = FmtPrinter::new(tcx, Namespace::TypeNS);
3023                    tcx.lift(*self)
3024                        .expect("could not lift for printing")
3025                        .print(&mut cx)?;
3026                    f.write_str(&cx.into_buffer())?;
3027                    Ok(())
3028                })
3029            }
3030        })+
3031    };
3032}
3033
3034macro_rules! define_print {
3035    (($self:ident, $cx:ident): $($ty:ty $print:block)+) => {
3036        $(impl<'tcx, P: PrettyPrinter<'tcx>> Print<'tcx, P> for $ty {
3037            fn print(&$self, $cx: &mut P) -> Result<(), PrintError> {
3038                define_scoped_cx!($cx);
3039                let _: () = $print;
3040                Ok(())
3041            }
3042        })+
3043    };
3044}
3045
3046macro_rules! define_print_and_forward_display {
3047    (($self:ident, $cx:ident): $($ty:ty $print:block)+) => {
3048        define_print!(($self, $cx): $($ty $print)*);
3049        forward_display_to_print!($($ty),+);
3050    };
3051}
3052
3053forward_display_to_print! {
3054    ty::Region<'tcx>,
3055    Ty<'tcx>,
3056    &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
3057    ty::Const<'tcx>
3058}
3059
3060define_print! {
3061    (self, cx):
3062
3063    ty::FnSig<'tcx> {
3064        p!(write("{}", self.safety.prefix_str()));
3065
3066        if self.abi != ExternAbi::Rust {
3067            p!(write("extern {} ", self.abi));
3068        }
3069
3070        p!("fn", pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
3071    }
3072
3073    ty::TraitRef<'tcx> {
3074        p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
3075    }
3076
3077    ty::AliasTy<'tcx> {
3078        let alias_term: ty::AliasTerm<'tcx> = (*self).into();
3079        p!(print(alias_term))
3080    }
3081
3082    ty::AliasTerm<'tcx> {
3083        match self.kind(cx.tcx()) {
3084            ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
3085            ty::AliasTermKind::ProjectionTy
3086            | ty::AliasTermKind::WeakTy
3087            | ty::AliasTermKind::OpaqueTy
3088            | ty::AliasTermKind::UnevaluatedConst
3089            | ty::AliasTermKind::ProjectionConst => {
3090                // If we're printing verbosely, or don't want to invoke queries
3091                // (`is_impl_trait_in_trait`), then fall back to printing the def path.
3092                // This is likely what you want if you're debugging the compiler anyways.
3093                if !(cx.should_print_verbose() || with_reduced_queries())
3094                    && cx.tcx().is_impl_trait_in_trait(self.def_id)
3095                {
3096                    return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
3097                } else {
3098                    p!(print_def_path(self.def_id, self.args));
3099                }
3100            }
3101        }
3102    }
3103
3104    ty::TraitPredicate<'tcx> {
3105        p!(print(self.trait_ref.self_ty()), ": ");
3106        if let ty::PredicatePolarity::Negative = self.polarity {
3107            p!("!");
3108        }
3109        p!(print(self.trait_ref.print_trait_sugared()))
3110    }
3111
3112    ty::HostEffectPredicate<'tcx> {
3113        let constness = match self.constness {
3114            ty::BoundConstness::Const => { "const" }
3115            ty::BoundConstness::Maybe => { "~const" }
3116        };
3117        p!(print(self.trait_ref.self_ty()), ": {constness} ");
3118        p!(print(self.trait_ref.print_trait_sugared()))
3119    }
3120
3121    ty::TypeAndMut<'tcx> {
3122        p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
3123    }
3124
3125    ty::ClauseKind<'tcx> {
3126        match *self {
3127            ty::ClauseKind::Trait(ref data) => {
3128                p!(print(data))
3129            }
3130            ty::ClauseKind::RegionOutlives(predicate) => p!(print(predicate)),
3131            ty::ClauseKind::TypeOutlives(predicate) => p!(print(predicate)),
3132            ty::ClauseKind::Projection(predicate) => p!(print(predicate)),
3133            ty::ClauseKind::HostEffect(predicate) => p!(print(predicate)),
3134            ty::ClauseKind::ConstArgHasType(ct, ty) => {
3135                p!("the constant `", print(ct), "` has type `", print(ty), "`")
3136            },
3137            ty::ClauseKind::WellFormed(arg) => p!(print(arg), " well-formed"),
3138            ty::ClauseKind::ConstEvaluatable(ct) => {
3139                p!("the constant `", print(ct), "` can be evaluated")
3140            }
3141        }
3142    }
3143
3144    ty::PredicateKind<'tcx> {
3145        match *self {
3146            ty::PredicateKind::Clause(data) => {
3147                p!(print(data))
3148            }
3149            ty::PredicateKind::Subtype(predicate) => p!(print(predicate)),
3150            ty::PredicateKind::Coerce(predicate) => p!(print(predicate)),
3151            ty::PredicateKind::DynCompatible(trait_def_id) => {
3152                p!("the trait `", print_def_path(trait_def_id, &[]), "` is dyn-compatible")
3153            }
3154            ty::PredicateKind::ConstEquate(c1, c2) => {
3155                p!("the constant `", print(c1), "` equals `", print(c2), "`")
3156            }
3157            ty::PredicateKind::Ambiguous => p!("ambiguous"),
3158            ty::PredicateKind::NormalizesTo(data) => p!(print(data)),
3159            ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
3160        }
3161    }
3162
3163    ty::ExistentialPredicate<'tcx> {
3164        match *self {
3165            ty::ExistentialPredicate::Trait(x) => p!(print(x)),
3166            ty::ExistentialPredicate::Projection(x) => p!(print(x)),
3167            ty::ExistentialPredicate::AutoTrait(def_id) => {
3168                p!(print_def_path(def_id, &[]));
3169            }
3170        }
3171    }
3172
3173    ty::ExistentialTraitRef<'tcx> {
3174        // Use a type that can't appear in defaults of type parameters.
3175        let dummy_self = Ty::new_fresh(cx.tcx(), 0);
3176        let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
3177        p!(print(trait_ref.print_only_trait_path()))
3178    }
3179
3180    ty::ExistentialProjection<'tcx> {
3181        let name = cx.tcx().associated_item(self.def_id).name;
3182        // The args don't contain the self ty (as it has been erased) but the corresp.
3183        // generics do as the trait always has a self ty param. We need to offset.
3184        let args = &self.args[cx.tcx().generics_of(self.def_id).parent_count - 1..];
3185        p!(path_generic_args(|cx| write!(cx, "{name}"), args), " = ", print(self.term))
3186    }
3187
3188    ty::ProjectionPredicate<'tcx> {
3189        p!(print(self.projection_term), " == ");
3190        cx.reset_type_limit();
3191        p!(print(self.term))
3192    }
3193
3194    ty::SubtypePredicate<'tcx> {
3195        p!(print(self.a), " <: ");
3196        cx.reset_type_limit();
3197        p!(print(self.b))
3198    }
3199
3200    ty::CoercePredicate<'tcx> {
3201        p!(print(self.a), " -> ");
3202        cx.reset_type_limit();
3203        p!(print(self.b))
3204    }
3205
3206    ty::NormalizesTo<'tcx> {
3207        p!(print(self.alias), " normalizes-to ");
3208        cx.reset_type_limit();
3209        p!(print(self.term))
3210    }
3211}
3212
3213define_print_and_forward_display! {
3214    (self, cx):
3215
3216    &'tcx ty::List<Ty<'tcx>> {
3217        p!("{{", comma_sep(self.iter()), "}}")
3218    }
3219
3220    TraitRefPrintOnlyTraitPath<'tcx> {
3221        p!(print_def_path(self.0.def_id, self.0.args));
3222    }
3223
3224    TraitRefPrintSugared<'tcx> {
3225        if !with_reduced_queries()
3226            && cx.tcx().trait_def(self.0.def_id).paren_sugar
3227            && let ty::Tuple(args) = self.0.args.type_at(1).kind()
3228        {
3229            p!(write("{}", cx.tcx().item_name(self.0.def_id)), "(");
3230            for (i, arg) in args.iter().enumerate() {
3231                if i > 0 {
3232                    p!(", ");
3233                }
3234                p!(print(arg));
3235            }
3236            p!(")");
3237        } else {
3238            p!(print_def_path(self.0.def_id, self.0.args));
3239        }
3240    }
3241
3242    TraitRefPrintOnlyTraitName<'tcx> {
3243        p!(print_def_path(self.0.def_id, &[]));
3244    }
3245
3246    TraitPredPrintModifiersAndPath<'tcx> {
3247        if let ty::PredicatePolarity::Negative = self.0.polarity {
3248            p!("!")
3249        }
3250        p!(print(self.0.trait_ref.print_trait_sugared()));
3251    }
3252
3253    TraitPredPrintWithBoundConstness<'tcx> {
3254        p!(print(self.0.trait_ref.self_ty()), ": ");
3255        if let Some(constness) = self.1 {
3256            p!(pretty_print_bound_constness(constness));
3257        }
3258        if let ty::PredicatePolarity::Negative = self.0.polarity {
3259            p!("!");
3260        }
3261        p!(print(self.0.trait_ref.print_trait_sugared()))
3262    }
3263
3264    PrintClosureAsImpl<'tcx> {
3265        p!(pretty_closure_as_impl(self.closure))
3266    }
3267
3268    ty::ParamTy {
3269        p!(write("{}", self.name))
3270    }
3271
3272    ty::ParamConst {
3273        p!(write("{}", self.name))
3274    }
3275
3276    ty::Term<'tcx> {
3277      match self.unpack() {
3278        ty::TermKind::Ty(ty) => p!(print(ty)),
3279        ty::TermKind::Const(c) => p!(print(c)),
3280      }
3281    }
3282
3283    ty::Predicate<'tcx> {
3284        p!(print(self.kind()))
3285    }
3286
3287    ty::Clause<'tcx> {
3288        p!(print(self.kind()))
3289    }
3290
3291    GenericArg<'tcx> {
3292        match self.unpack() {
3293            GenericArgKind::Lifetime(lt) => p!(print(lt)),
3294            GenericArgKind::Type(ty) => p!(print(ty)),
3295            GenericArgKind::Const(ct) => p!(print(ct)),
3296        }
3297    }
3298}
3299
3300fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) {
3301    // Iterate all local crate items no matter where they are defined.
3302    let hir = tcx.hir();
3303    for id in hir.items() {
3304        if matches!(tcx.def_kind(id.owner_id), DefKind::Use) {
3305            continue;
3306        }
3307
3308        let item = hir.item(id);
3309        if item.ident.name == kw::Empty {
3310            continue;
3311        }
3312
3313        let def_id = item.owner_id.to_def_id();
3314        let ns = tcx.def_kind(def_id).ns().unwrap_or(Namespace::TypeNS);
3315        collect_fn(&item.ident, ns, def_id);
3316    }
3317
3318    // Now take care of extern crate items.
3319    let queue = &mut Vec::new();
3320    let mut seen_defs: DefIdSet = Default::default();
3321
3322    for &cnum in tcx.crates(()).iter() {
3323        // Ignore crates that are not direct dependencies.
3324        match tcx.extern_crate(cnum) {
3325            None => continue,
3326            Some(extern_crate) => {
3327                if !extern_crate.is_direct() {
3328                    continue;
3329                }
3330            }
3331        }
3332
3333        queue.push(cnum.as_def_id());
3334    }
3335
3336    // Iterate external crate defs but be mindful about visibility
3337    while let Some(def) = queue.pop() {
3338        for child in tcx.module_children(def).iter() {
3339            if !child.vis.is_public() {
3340                continue;
3341            }
3342
3343            match child.res {
3344                def::Res::Def(DefKind::AssocTy, _) => {}
3345                def::Res::Def(DefKind::TyAlias, _) => {}
3346                def::Res::Def(defkind, def_id) => {
3347                    if let Some(ns) = defkind.ns() {
3348                        collect_fn(&child.ident, ns, def_id);
3349                    }
3350
3351                    if matches!(defkind, DefKind::Mod | DefKind::Enum | DefKind::Trait)
3352                        && seen_defs.insert(def_id)
3353                    {
3354                        queue.push(def_id);
3355                    }
3356                }
3357                _ => {}
3358            }
3359        }
3360    }
3361}
3362
3363/// The purpose of this function is to collect public symbols names that are unique across all
3364/// crates in the build. Later, when printing about types we can use those names instead of the
3365/// full exported path to them.
3366///
3367/// So essentially, if a symbol name can only be imported from one place for a type, and as
3368/// long as it was not glob-imported anywhere in the current crate, we can trim its printed
3369/// path and print only the name.
3370///
3371/// This has wide implications on error messages with types, for example, shortening
3372/// `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable anywhere.
3373///
3374/// The implementation uses similar import discovery logic to that of 'use' suggestions.
3375///
3376/// See also [`with_no_trimmed_paths!`].
3377// this is pub to be able to intra-doc-link it
3378pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
3379    // Trimming paths is expensive and not optimized, since we expect it to only be used for error
3380    // reporting. Record the fact that we did it, so we can abort if we later found it was
3381    // unnecessary.
3382    //
3383    // The `rustc_middle::ty::print::with_no_trimmed_paths` wrapper can be used to suppress this
3384    // checking, in exchange for full paths being formatted.
3385    tcx.sess.record_trimmed_def_paths();
3386
3387    // Once constructed, unique namespace+symbol pairs will have a `Some(_)` entry, while
3388    // non-unique pairs will have a `None` entry.
3389    let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
3390        &mut FxHashMap::default();
3391
3392    for symbol_set in tcx.resolutions(()).glob_map.values() {
3393        for symbol in symbol_set {
3394            unique_symbols_rev.insert((Namespace::TypeNS, *symbol), None);
3395            unique_symbols_rev.insert((Namespace::ValueNS, *symbol), None);
3396            unique_symbols_rev.insert((Namespace::MacroNS, *symbol), None);
3397        }
3398    }
3399
3400    for_each_def(tcx, |ident, ns, def_id| {
3401        use std::collections::hash_map::Entry::{Occupied, Vacant};
3402
3403        match unique_symbols_rev.entry((ns, ident.name)) {
3404            Occupied(mut v) => match v.get() {
3405                None => {}
3406                Some(existing) => {
3407                    if *existing != def_id {
3408                        v.insert(None);
3409                    }
3410                }
3411            },
3412            Vacant(v) => {
3413                v.insert(Some(def_id));
3414            }
3415        }
3416    });
3417
3418    // Put the symbol from all the unique namespace+symbol pairs into `map`.
3419    let mut map: DefIdMap<Symbol> = Default::default();
3420    for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() {
3421        use std::collections::hash_map::Entry::{Occupied, Vacant};
3422
3423        if let Some(def_id) = opt_def_id {
3424            match map.entry(def_id) {
3425                Occupied(mut v) => {
3426                    // A single DefId can be known under multiple names (e.g.,
3427                    // with a `pub use ... as ...;`). We need to ensure that the
3428                    // name placed in this map is chosen deterministically, so
3429                    // if we find multiple names (`symbol`) resolving to the
3430                    // same `def_id`, we prefer the lexicographically smallest
3431                    // name.
3432                    //
3433                    // Any stable ordering would be fine here though.
3434                    if *v.get() != symbol && v.get().as_str() > symbol.as_str() {
3435                        v.insert(symbol);
3436                    }
3437                }
3438                Vacant(v) => {
3439                    v.insert(symbol);
3440                }
3441            }
3442        }
3443    }
3444
3445    map
3446}
3447
3448pub fn provide(providers: &mut Providers) {
3449    *providers = Providers { trimmed_def_paths, ..*providers };
3450}
3451
3452pub struct OpaqueFnEntry<'tcx> {
3453    kind: ty::ClosureKind,
3454    return_ty: Option<ty::Binder<'tcx, Term<'tcx>>>,
3455}