]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/print/pretty.rs
Auto merge of #85178 - cjgillot:local-crate, r=oli-obk
[rust.git] / compiler / rustc_middle / src / ty / print / pretty.rs
1 use crate::middle::cstore::{ExternCrate, ExternCrateSource};
2 use crate::mir::interpret::{AllocId, ConstValue, GlobalAlloc, Pointer, Scalar};
3 use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
4 use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable};
5 use rustc_apfloat::ieee::{Double, Single};
6 use rustc_data_structures::fx::FxHashMap;
7 use rustc_data_structures::sso::SsoHashSet;
8 use rustc_hir as hir;
9 use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
10 use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
11 use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
12 use rustc_hir::ItemKind;
13 use rustc_session::config::TrimmedDefPaths;
14 use rustc_span::symbol::{kw, Ident, Symbol};
15 use rustc_target::abi::Size;
16 use rustc_target::spec::abi::Abi;
17
18 use std::cell::Cell;
19 use std::char;
20 use std::collections::BTreeMap;
21 use std::convert::TryFrom;
22 use std::fmt::{self, Write as _};
23 use std::iter;
24 use std::ops::{ControlFlow, Deref, DerefMut};
25
26 // `pretty` is a separate module only for organization.
27 use super::*;
28
29 macro_rules! p {
30     (@$lit:literal) => {
31         write!(scoped_cx!(), $lit)?
32     };
33     (@write($($data:expr),+)) => {
34         write!(scoped_cx!(), $($data),+)?
35     };
36     (@print($x:expr)) => {
37         scoped_cx!() = $x.print(scoped_cx!())?
38     };
39     (@$method:ident($($arg:expr),*)) => {
40         scoped_cx!() = scoped_cx!().$method($($arg),*)?
41     };
42     ($($elem:tt $(($($args:tt)*))?),+) => {{
43         $(p!(@ $elem $(($($args)*))?);)+
44     }};
45 }
46 macro_rules! define_scoped_cx {
47     ($cx:ident) => {
48         #[allow(unused_macros)]
49         macro_rules! scoped_cx {
50             () => {
51                 $cx
52             };
53         }
54     };
55 }
56
57 thread_local! {
58     static FORCE_IMPL_FILENAME_LINE: Cell<bool> = const { Cell::new(false) };
59     static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
60     static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
61     static NO_QUERIES: Cell<bool> = const { Cell::new(false) };
62 }
63
64 /// Avoids running any queries during any prints that occur
65 /// during the closure. This may alter the appearance of some
66 /// types (e.g. forcing verbose printing for opaque types).
67 /// This method is used during some queries (e.g. `explicit_item_bounds`
68 /// for opaque types), to ensure that any debug printing that
69 /// occurs during the query computation does not end up recursively
70 /// calling the same query.
71 pub fn with_no_queries<F: FnOnce() -> R, R>(f: F) -> R {
72     NO_QUERIES.with(|no_queries| {
73         let old = no_queries.replace(true);
74         let result = f();
75         no_queries.set(old);
76         result
77     })
78 }
79
80 /// Force us to name impls with just the filename/line number. We
81 /// normally try to use types. But at some points, notably while printing
82 /// cycle errors, this can result in extra or suboptimal error output,
83 /// so this variable disables that check.
84 pub fn with_forced_impl_filename_line<F: FnOnce() -> R, R>(f: F) -> R {
85     FORCE_IMPL_FILENAME_LINE.with(|force| {
86         let old = force.replace(true);
87         let result = f();
88         force.set(old);
89         result
90     })
91 }
92
93 /// Adds the `crate::` prefix to paths where appropriate.
94 pub fn with_crate_prefix<F: FnOnce() -> R, R>(f: F) -> R {
95     SHOULD_PREFIX_WITH_CRATE.with(|flag| {
96         let old = flag.replace(true);
97         let result = f();
98         flag.set(old);
99         result
100     })
101 }
102
103 /// Prevent path trimming if it is turned on. Path trimming affects `Display` impl
104 /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
105 /// if no other `Vec` is found.
106 pub fn with_no_trimmed_paths<F: FnOnce() -> R, R>(f: F) -> R {
107     NO_TRIMMED_PATH.with(|flag| {
108         let old = flag.replace(true);
109         let result = f();
110         flag.set(old);
111         result
112     })
113 }
114
115 /// The "region highlights" are used to control region printing during
116 /// specific error messages. When a "region highlight" is enabled, it
117 /// gives an alternate way to print specific regions. For now, we
118 /// always print those regions using a number, so something like "`'0`".
119 ///
120 /// Regions not selected by the region highlight mode are presently
121 /// unaffected.
122 #[derive(Copy, Clone, Default)]
123 pub struct RegionHighlightMode {
124     /// If enabled, when we see the selected region, use "`'N`"
125     /// instead of the ordinary behavior.
126     highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
127
128     /// If enabled, when printing a "free region" that originated from
129     /// the given `ty::BoundRegionKind`, print it as "`'1`". Free regions that would ordinarily
130     /// have names print as normal.
131     ///
132     /// This is used when you have a signature like `fn foo(x: &u32,
133     /// y: &'a u32)` and we want to give a name to the region of the
134     /// reference `x`.
135     highlight_bound_region: Option<(ty::BoundRegionKind, usize)>,
136 }
137
138 impl RegionHighlightMode {
139     /// If `region` and `number` are both `Some`, invokes
140     /// `highlighting_region`.
141     pub fn maybe_highlighting_region(
142         &mut self,
143         region: Option<ty::Region<'_>>,
144         number: Option<usize>,
145     ) {
146         if let Some(k) = region {
147             if let Some(n) = number {
148                 self.highlighting_region(k, n);
149             }
150         }
151     }
152
153     /// Highlights the region inference variable `vid` as `'N`.
154     pub fn highlighting_region(&mut self, region: ty::Region<'_>, number: usize) {
155         let num_slots = self.highlight_regions.len();
156         let first_avail_slot =
157             self.highlight_regions.iter_mut().find(|s| s.is_none()).unwrap_or_else(|| {
158                 bug!("can only highlight {} placeholders at a time", num_slots,)
159             });
160         *first_avail_slot = Some((*region, number));
161     }
162
163     /// Convenience wrapper for `highlighting_region`.
164     pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) {
165         self.highlighting_region(&ty::ReVar(vid), number)
166     }
167
168     /// Returns `Some(n)` with the number to use for the given region, if any.
169     fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
170         self.highlight_regions.iter().find_map(|h| match h {
171             Some((r, n)) if r == region => Some(*n),
172             _ => None,
173         })
174     }
175
176     /// Highlight the given bound region.
177     /// We can only highlight one bound region at a time. See
178     /// the field `highlight_bound_region` for more detailed notes.
179     pub fn highlighting_bound_region(&mut self, br: ty::BoundRegionKind, number: usize) {
180         assert!(self.highlight_bound_region.is_none());
181         self.highlight_bound_region = Some((br, number));
182     }
183 }
184
185 /// Trait for printers that pretty-print using `fmt::Write` to the printer.
186 pub trait PrettyPrinter<'tcx>:
187     Printer<
188         'tcx,
189         Error = fmt::Error,
190         Path = Self,
191         Region = Self,
192         Type = Self,
193         DynExistential = Self,
194         Const = Self,
195     > + fmt::Write
196 {
197     /// Like `print_def_path` but for value paths.
198     fn print_value_path(
199         self,
200         def_id: DefId,
201         substs: &'tcx [GenericArg<'tcx>],
202     ) -> Result<Self::Path, Self::Error> {
203         self.print_def_path(def_id, substs)
204     }
205
206     fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
207     where
208         T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
209     {
210         value.as_ref().skip_binder().print(self)
211     }
212
213     fn wrap_binder<T, F: Fn(&T, Self) -> Result<Self, fmt::Error>>(
214         self,
215         value: &ty::Binder<'tcx, T>,
216         f: F,
217     ) -> Result<Self, Self::Error>
218     where
219         T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
220     {
221         f(value.as_ref().skip_binder(), self)
222     }
223
224     /// Prints comma-separated elements.
225     fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
226     where
227         T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
228     {
229         if let Some(first) = elems.next() {
230             self = first.print(self)?;
231             for elem in elems {
232                 self.write_str(", ")?;
233                 self = elem.print(self)?;
234             }
235         }
236         Ok(self)
237     }
238
239     /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument
240     fn typed_value(
241         mut self,
242         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
243         t: impl FnOnce(Self) -> Result<Self, Self::Error>,
244         conversion: &str,
245     ) -> Result<Self::Const, Self::Error> {
246         self.write_str("{")?;
247         self = f(self)?;
248         self.write_str(conversion)?;
249         self = t(self)?;
250         self.write_str("}")?;
251         Ok(self)
252     }
253
254     /// Prints `<...>` around what `f` prints.
255     fn generic_delimiters(
256         self,
257         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
258     ) -> Result<Self, Self::Error>;
259
260     /// Returns `true` if the region should be printed in
261     /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`.
262     /// This is typically the case for all non-`'_` regions.
263     fn region_should_not_be_omitted(&self, region: ty::Region<'_>) -> bool;
264
265     // Defaults (should not be overridden):
266
267     /// If possible, this returns a global path resolving to `def_id` that is visible
268     /// from at least one local module, and returns `true`. If the crate defining `def_id` is
269     /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
270     fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), Self::Error> {
271         let mut callers = Vec::new();
272         self.try_print_visible_def_path_recur(def_id, &mut callers)
273     }
274
275     /// Try to see if this path can be trimmed to a unique symbol name.
276     fn try_print_trimmed_def_path(
277         mut self,
278         def_id: DefId,
279     ) -> Result<(Self::Path, bool), Self::Error> {
280         if !self.tcx().sess.opts.debugging_opts.trim_diagnostic_paths
281             || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never)
282             || NO_TRIMMED_PATH.with(|flag| flag.get())
283             || SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get())
284         {
285             return Ok((self, false));
286         }
287
288         match self.tcx().trimmed_def_paths(()).get(&def_id) {
289             None => Ok((self, false)),
290             Some(symbol) => {
291                 self.write_str(&symbol.as_str())?;
292                 Ok((self, true))
293             }
294         }
295     }
296
297     /// Does the work of `try_print_visible_def_path`, building the
298     /// full definition path recursively before attempting to
299     /// post-process it into the valid and visible version that
300     /// accounts for re-exports.
301     ///
302     /// This method should only be called by itself or
303     /// `try_print_visible_def_path`.
304     ///
305     /// `callers` is a chain of visible_parent's leading to `def_id`,
306     /// to support cycle detection during recursion.
307     fn try_print_visible_def_path_recur(
308         mut self,
309         def_id: DefId,
310         callers: &mut Vec<DefId>,
311     ) -> Result<(Self, bool), Self::Error> {
312         define_scoped_cx!(self);
313
314         debug!("try_print_visible_def_path: def_id={:?}", def_id);
315
316         // If `def_id` is a direct or injected extern crate, return the
317         // path to the crate followed by the path to the item within the crate.
318         if def_id.index == CRATE_DEF_INDEX {
319             let cnum = def_id.krate;
320
321             if cnum == LOCAL_CRATE {
322                 return Ok((self.path_crate(cnum)?, true));
323             }
324
325             // In local mode, when we encounter a crate other than
326             // LOCAL_CRATE, execution proceeds in one of two ways:
327             //
328             // 1. For a direct dependency, where user added an
329             //    `extern crate` manually, we put the `extern
330             //    crate` as the parent. So you wind up with
331             //    something relative to the current crate.
332             // 2. For an extern inferred from a path or an indirect crate,
333             //    where there is no explicit `extern crate`, we just prepend
334             //    the crate name.
335             match self.tcx().extern_crate(def_id) {
336                 Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) {
337                     (ExternCrateSource::Extern(def_id), LOCAL_CRATE) => {
338                         debug!("try_print_visible_def_path: def_id={:?}", def_id);
339                         return Ok((
340                             if !span.is_dummy() {
341                                 self.print_def_path(def_id, &[])?
342                             } else {
343                                 self.path_crate(cnum)?
344                             },
345                             true,
346                         ));
347                     }
348                     (ExternCrateSource::Path, LOCAL_CRATE) => {
349                         debug!("try_print_visible_def_path: def_id={:?}", def_id);
350                         return Ok((self.path_crate(cnum)?, true));
351                     }
352                     _ => {}
353                 },
354                 None => {
355                     return Ok((self.path_crate(cnum)?, true));
356                 }
357             }
358         }
359
360         if def_id.is_local() {
361             return Ok((self, false));
362         }
363
364         let visible_parent_map = self.tcx().visible_parent_map(());
365
366         let mut cur_def_key = self.tcx().def_key(def_id);
367         debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
368
369         // For a constructor, we want the name of its parent rather than <unnamed>.
370         if let DefPathData::Ctor = cur_def_key.disambiguated_data.data {
371             let parent = DefId {
372                 krate: def_id.krate,
373                 index: cur_def_key
374                     .parent
375                     .expect("`DefPathData::Ctor` / `VariantData` missing a parent"),
376             };
377
378             cur_def_key = self.tcx().def_key(parent);
379         }
380
381         let visible_parent = match visible_parent_map.get(&def_id).cloned() {
382             Some(parent) => parent,
383             None => return Ok((self, false)),
384         };
385         if callers.contains(&visible_parent) {
386             return Ok((self, false));
387         }
388         callers.push(visible_parent);
389         // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid
390         // knowing ahead of time whether the entire path will succeed or not.
391         // To support printers that do not implement `PrettyPrinter`, a `Vec` or
392         // linked list on the stack would need to be built, before any printing.
393         match self.try_print_visible_def_path_recur(visible_parent, callers)? {
394             (cx, false) => return Ok((cx, false)),
395             (cx, true) => self = cx,
396         }
397         callers.pop();
398         let actual_parent = self.tcx().parent(def_id);
399         debug!(
400             "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}",
401             visible_parent, actual_parent,
402         );
403
404         let mut data = cur_def_key.disambiguated_data.data;
405         debug!(
406             "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
407             data, visible_parent, actual_parent,
408         );
409
410         match data {
411             // In order to output a path that could actually be imported (valid and visible),
412             // we need to handle re-exports correctly.
413             //
414             // For example, take `std::os::unix::process::CommandExt`, this trait is actually
415             // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
416             //
417             // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is
418             // private so the "true" path to `CommandExt` isn't accessible.
419             //
420             // In this case, the `visible_parent_map` will look something like this:
421             //
422             // (child) -> (parent)
423             // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
424             // `std::sys::unix::ext::process` -> `std::sys::unix::ext`
425             // `std::sys::unix::ext` -> `std::os`
426             //
427             // This is correct, as the visible parent of `std::sys::unix::ext` is in fact
428             // `std::os`.
429             //
430             // When printing the path to `CommandExt` and looking at the `cur_def_key` that
431             // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
432             // to the parent - resulting in a mangled path like
433             // `std::os::ext::process::CommandExt`.
434             //
435             // Instead, we must detect that there was a re-export and instead print `unix`
436             // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
437             // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
438             // the visible parent (`std::os`). If these do not match, then we iterate over
439             // the children of the visible parent (as was done when computing
440             // `visible_parent_map`), looking for the specific child we currently have and then
441             // have access to the re-exported name.
442             DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => {
443                 let reexport = self
444                     .tcx()
445                     .item_children(visible_parent)
446                     .iter()
447                     .find(|child| child.res.opt_def_id() == Some(def_id))
448                     .map(|child| child.ident.name);
449                 if let Some(reexport) = reexport {
450                     *name = reexport;
451                 }
452             }
453             // Re-exported `extern crate` (#43189).
454             DefPathData::CrateRoot => {
455                 data = DefPathData::TypeNs(self.tcx().original_crate_name(def_id.krate));
456             }
457             _ => {}
458         }
459         debug!("try_print_visible_def_path: data={:?}", data);
460
461         Ok((self.path_append(Ok, &DisambiguatedDefPathData { data, disambiguator: 0 })?, true))
462     }
463
464     fn pretty_path_qualified(
465         self,
466         self_ty: Ty<'tcx>,
467         trait_ref: Option<ty::TraitRef<'tcx>>,
468     ) -> Result<Self::Path, Self::Error> {
469         if trait_ref.is_none() {
470             // Inherent impls. Try to print `Foo::bar` for an inherent
471             // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
472             // anything other than a simple path.
473             match self_ty.kind() {
474                 ty::Adt(..)
475                 | ty::Foreign(_)
476                 | ty::Bool
477                 | ty::Char
478                 | ty::Str
479                 | ty::Int(_)
480                 | ty::Uint(_)
481                 | ty::Float(_) => {
482                     return self_ty.print(self);
483                 }
484
485                 _ => {}
486             }
487         }
488
489         self.generic_delimiters(|mut cx| {
490             define_scoped_cx!(cx);
491
492             p!(print(self_ty));
493             if let Some(trait_ref) = trait_ref {
494                 p!(" as ", print(trait_ref.print_only_trait_path()));
495             }
496             Ok(cx)
497         })
498     }
499
500     fn pretty_path_append_impl(
501         mut self,
502         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
503         self_ty: Ty<'tcx>,
504         trait_ref: Option<ty::TraitRef<'tcx>>,
505     ) -> Result<Self::Path, Self::Error> {
506         self = print_prefix(self)?;
507
508         self.generic_delimiters(|mut cx| {
509             define_scoped_cx!(cx);
510
511             p!("impl ");
512             if let Some(trait_ref) = trait_ref {
513                 p!(print(trait_ref.print_only_trait_path()), " for ");
514             }
515             p!(print(self_ty));
516
517             Ok(cx)
518         })
519     }
520
521     fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
522         define_scoped_cx!(self);
523
524         match *ty.kind() {
525             ty::Bool => p!("bool"),
526             ty::Char => p!("char"),
527             ty::Int(t) => p!(write("{}", t.name_str())),
528             ty::Uint(t) => p!(write("{}", t.name_str())),
529             ty::Float(t) => p!(write("{}", t.name_str())),
530             ty::RawPtr(ref tm) => {
531                 p!(write(
532                     "*{} ",
533                     match tm.mutbl {
534                         hir::Mutability::Mut => "mut",
535                         hir::Mutability::Not => "const",
536                     }
537                 ));
538                 p!(print(tm.ty))
539             }
540             ty::Ref(r, ty, mutbl) => {
541                 p!("&");
542                 if self.region_should_not_be_omitted(r) {
543                     p!(print(r), " ");
544                 }
545                 p!(print(ty::TypeAndMut { ty, mutbl }))
546             }
547             ty::Never => p!("!"),
548             ty::Tuple(ref tys) => {
549                 p!("(", comma_sep(tys.iter()));
550                 if tys.len() == 1 {
551                     p!(",");
552                 }
553                 p!(")")
554             }
555             ty::FnDef(def_id, substs) => {
556                 let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
557                 p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
558             }
559             ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
560             ty::Infer(infer_ty) => {
561                 let verbose = self.tcx().sess.verbose();
562                 if let ty::TyVar(ty_vid) = infer_ty {
563                     if let Some(name) = self.infer_ty_name(ty_vid) {
564                         p!(write("{}", name))
565                     } else {
566                         if verbose {
567                             p!(write("{:?}", infer_ty))
568                         } else {
569                             p!(write("{}", infer_ty))
570                         }
571                     }
572                 } else {
573                     if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) }
574                 }
575             }
576             ty::Error(_) => p!("[type error]"),
577             ty::Param(ref param_ty) => p!(write("{}", param_ty)),
578             ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
579                 ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
580                 ty::BoundTyKind::Param(p) => p!(write("{}", p)),
581             },
582             ty::Adt(def, substs) => {
583                 p!(print_def_path(def.did, substs));
584             }
585             ty::Dynamic(data, r) => {
586                 let print_r = self.region_should_not_be_omitted(r);
587                 if print_r {
588                     p!("(");
589                 }
590                 p!("dyn ", print(data));
591                 if print_r {
592                     p!(" + ", print(r), ")");
593                 }
594             }
595             ty::Foreign(def_id) => {
596                 p!(print_def_path(def_id, &[]));
597             }
598             ty::Projection(ref data) => p!(print(data)),
599             ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
600             ty::Opaque(def_id, substs) => {
601                 // FIXME(eddyb) print this with `print_def_path`.
602                 // We use verbose printing in 'NO_QUERIES' mode, to
603                 // avoid needing to call `predicates_of`. This should
604                 // only affect certain debug messages (e.g. messages printed
605                 // from `rustc_middle::ty` during the computation of `tcx.predicates_of`),
606                 // and should have no effect on any compiler output.
607                 if self.tcx().sess.verbose() || NO_QUERIES.with(|q| q.get()) {
608                     p!(write("Opaque({:?}, {:?})", def_id, substs));
609                     return Ok(self);
610                 }
611
612                 return with_no_queries(|| {
613                     let def_key = self.tcx().def_key(def_id);
614                     if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
615                         p!(write("{}", name));
616                         // FIXME(eddyb) print this with `print_def_path`.
617                         if !substs.is_empty() {
618                             p!("::");
619                             p!(generic_delimiters(|cx| cx.comma_sep(substs.iter())));
620                         }
621                         return Ok(self);
622                     }
623                     // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
624                     // by looking up the projections associated with the def_id.
625                     let bounds = self.tcx().explicit_item_bounds(def_id);
626
627                     let mut first = true;
628                     let mut is_sized = false;
629                     p!("impl");
630                     for (predicate, _) in bounds {
631                         let predicate = predicate.subst(self.tcx(), substs);
632                         let bound_predicate = predicate.kind();
633                         if let ty::PredicateKind::Trait(pred, _) = bound_predicate.skip_binder() {
634                             let trait_ref = bound_predicate.rebind(pred.trait_ref);
635                             // Don't print +Sized, but rather +?Sized if absent.
636                             if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
637                                 is_sized = true;
638                                 continue;
639                             }
640
641                             p!(
642                                 write("{}", if first { " " } else { "+" }),
643                                 print(trait_ref.print_only_trait_path())
644                             );
645                             first = false;
646                         }
647                     }
648                     if !is_sized {
649                         p!(write("{}?Sized", if first { " " } else { "+" }));
650                     } else if first {
651                         p!(" Sized");
652                     }
653                     Ok(self)
654                 });
655             }
656             ty::Str => p!("str"),
657             ty::Generator(did, substs, movability) => {
658                 p!(write("["));
659                 match movability {
660                     hir::Movability::Movable => {}
661                     hir::Movability::Static => p!("static "),
662                 }
663
664                 if !self.tcx().sess.verbose() {
665                     p!("generator");
666                     // FIXME(eddyb) should use `def_span`.
667                     if let Some(did) = did.as_local() {
668                         let hir_id = self.tcx().hir().local_def_id_to_hir_id(did);
669                         let span = self.tcx().hir().span(hir_id);
670                         p!(write(
671                             "@{}",
672                             // This may end up in stderr diagnostics but it may also be emitted
673                             // into MIR. Hence we use the remapped path if available
674                             self.tcx().sess.source_map().span_to_embeddable_string(span)
675                         ));
676                     } else {
677                         p!(write("@"), print_def_path(did, substs));
678                     }
679                 } else {
680                     p!(print_def_path(did, substs));
681                     p!(" upvar_tys=(");
682                     if !substs.as_generator().is_valid() {
683                         p!("unavailable");
684                     } else {
685                         self = self.comma_sep(substs.as_generator().upvar_tys())?;
686                     }
687                     p!(")");
688                 }
689
690                 if substs.as_generator().is_valid() {
691                     p!(" ", print(substs.as_generator().witness()));
692                 }
693
694                 p!("]")
695             }
696             ty::GeneratorWitness(types) => {
697                 p!(in_binder(&types));
698             }
699             ty::Closure(did, substs) => {
700                 p!(write("["));
701                 if !self.tcx().sess.verbose() {
702                     p!(write("closure"));
703                     // FIXME(eddyb) should use `def_span`.
704                     if let Some(did) = did.as_local() {
705                         let hir_id = self.tcx().hir().local_def_id_to_hir_id(did);
706                         if self.tcx().sess.opts.debugging_opts.span_free_formats {
707                             p!("@", print_def_path(did.to_def_id(), substs));
708                         } else {
709                             let span = self.tcx().hir().span(hir_id);
710                             p!(write(
711                                 "@{}",
712                                 // This may end up in stderr diagnostics but it may also be emitted
713                                 // into MIR. Hence we use the remapped path if available
714                                 self.tcx().sess.source_map().span_to_embeddable_string(span)
715                             ));
716                         }
717                     } else {
718                         p!(write("@"), print_def_path(did, substs));
719                     }
720                 } else {
721                     p!(print_def_path(did, substs));
722                     if !substs.as_closure().is_valid() {
723                         p!(" closure_substs=(unavailable)");
724                     } else {
725                         p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
726                         p!(
727                             " closure_sig_as_fn_ptr_ty=",
728                             print(substs.as_closure().sig_as_fn_ptr_ty())
729                         );
730                         p!(" upvar_tys=(");
731                         self = self.comma_sep(substs.as_closure().upvar_tys())?;
732                         p!(")");
733                     }
734                 }
735                 p!("]");
736             }
737             ty::Array(ty, sz) => {
738                 p!("[", print(ty), "; ");
739                 if self.tcx().sess.verbose() {
740                     p!(write("{:?}", sz));
741                 } else if let ty::ConstKind::Unevaluated(..) = sz.val {
742                     // Do not try to evaluate unevaluated constants. If we are const evaluating an
743                     // array length anon const, rustc will (with debug assertions) print the
744                     // constant's path. Which will end up here again.
745                     p!("_");
746                 } else if let Some(n) = sz.val.try_to_bits(self.tcx().data_layout.pointer_size) {
747                     p!(write("{}", n));
748                 } else if let ty::ConstKind::Param(param) = sz.val {
749                     p!(write("{}", param));
750                 } else {
751                     p!("_");
752                 }
753                 p!("]")
754             }
755             ty::Slice(ty) => p!("[", print(ty), "]"),
756         }
757
758         Ok(self)
759     }
760
761     fn pretty_print_bound_var(
762         &mut self,
763         debruijn: ty::DebruijnIndex,
764         var: ty::BoundVar,
765     ) -> Result<(), Self::Error> {
766         if debruijn == ty::INNERMOST {
767             write!(self, "^{}", var.index())
768         } else {
769             write!(self, "^{}_{}", debruijn.index(), var.index())
770         }
771     }
772
773     fn infer_ty_name(&self, _: ty::TyVid) -> Option<String> {
774         None
775     }
776
777     fn pretty_print_dyn_existential(
778         mut self,
779         predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
780     ) -> Result<Self::DynExistential, Self::Error> {
781         // Generate the main trait ref, including associated types.
782         let mut first = true;
783
784         if let Some(principal) = predicates.principal() {
785             self = self.wrap_binder(&principal, |principal, mut cx| {
786                 define_scoped_cx!(cx);
787                 p!(print_def_path(principal.def_id, &[]));
788
789                 let mut resugared = false;
790
791                 // Special-case `Fn(...) -> ...` and resugar it.
792                 let fn_trait_kind = cx.tcx().fn_trait_kind_from_lang_item(principal.def_id);
793                 if !cx.tcx().sess.verbose() && fn_trait_kind.is_some() {
794                     if let ty::Tuple(ref args) = principal.substs.type_at(0).kind() {
795                         let mut projections = predicates.projection_bounds();
796                         if let (Some(proj), None) = (projections.next(), projections.next()) {
797                             let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect();
798                             p!(pretty_fn_sig(&tys, false, proj.skip_binder().ty));
799                             resugared = true;
800                         }
801                     }
802                 }
803
804                 // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
805                 // in order to place the projections inside the `<...>`.
806                 if !resugared {
807                     // Use a type that can't appear in defaults of type parameters.
808                     let dummy_cx = cx.tcx().mk_ty_infer(ty::FreshTy(0));
809                     let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
810
811                     let args = cx.generic_args_to_print(
812                         cx.tcx().generics_of(principal.def_id),
813                         principal.substs,
814                     );
815
816                     // Don't print `'_` if there's no unerased regions.
817                     let print_regions = args.iter().any(|arg| match arg.unpack() {
818                         GenericArgKind::Lifetime(r) => *r != ty::ReErased,
819                         _ => false,
820                     });
821                     let mut args = args.iter().cloned().filter(|arg| match arg.unpack() {
822                         GenericArgKind::Lifetime(_) => print_regions,
823                         _ => true,
824                     });
825                     let mut projections = predicates.projection_bounds();
826
827                     let arg0 = args.next();
828                     let projection0 = projections.next();
829                     if arg0.is_some() || projection0.is_some() {
830                         let args = arg0.into_iter().chain(args);
831                         let projections = projection0.into_iter().chain(projections);
832
833                         p!(generic_delimiters(|mut cx| {
834                             cx = cx.comma_sep(args)?;
835                             if arg0.is_some() && projection0.is_some() {
836                                 write!(cx, ", ")?;
837                             }
838                             cx.comma_sep(projections)
839                         }));
840                     }
841                 }
842                 Ok(cx)
843             })?;
844
845             first = false;
846         }
847
848         define_scoped_cx!(self);
849
850         // Builtin bounds.
851         // FIXME(eddyb) avoid printing twice (needed to ensure
852         // that the auto traits are sorted *and* printed via cx).
853         let mut auto_traits: Vec<_> =
854             predicates.auto_traits().map(|did| (self.tcx().def_path_str(did), did)).collect();
855
856         // The auto traits come ordered by `DefPathHash`. While
857         // `DefPathHash` is *stable* in the sense that it depends on
858         // neither the host nor the phase of the moon, it depends
859         // "pseudorandomly" on the compiler version and the target.
860         //
861         // To avoid that causing instabilities in compiletest
862         // output, sort the auto-traits alphabetically.
863         auto_traits.sort();
864
865         for (_, def_id) in auto_traits {
866             if !first {
867                 p!(" + ");
868             }
869             first = false;
870
871             p!(print_def_path(def_id, &[]));
872         }
873
874         Ok(self)
875     }
876
877     fn pretty_fn_sig(
878         mut self,
879         inputs: &[Ty<'tcx>],
880         c_variadic: bool,
881         output: Ty<'tcx>,
882     ) -> Result<Self, Self::Error> {
883         define_scoped_cx!(self);
884
885         p!("(", comma_sep(inputs.iter().copied()));
886         if c_variadic {
887             if !inputs.is_empty() {
888                 p!(", ");
889             }
890             p!("...");
891         }
892         p!(")");
893         if !output.is_unit() {
894             p!(" -> ", print(output));
895         }
896
897         Ok(self)
898     }
899
900     fn pretty_print_const(
901         mut self,
902         ct: &'tcx ty::Const<'tcx>,
903         print_ty: bool,
904     ) -> Result<Self::Const, Self::Error> {
905         define_scoped_cx!(self);
906
907         if self.tcx().sess.verbose() {
908             p!(write("Const({:?}: {:?})", ct.val, ct.ty));
909             return Ok(self);
910         }
911
912         macro_rules! print_underscore {
913             () => {{
914                 if print_ty {
915                     self = self.typed_value(
916                         |mut this| {
917                             write!(this, "_")?;
918                             Ok(this)
919                         },
920                         |this| this.print_type(ct.ty),
921                         ": ",
922                     )?;
923                 } else {
924                     write!(self, "_")?;
925                 }
926             }};
927         }
928
929         match ct.val {
930             ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
931                 if let Some(promoted) = promoted {
932                     p!(print_value_path(def.did, substs));
933                     p!(write("::{:?}", promoted));
934                 } else {
935                     match self.tcx().def_kind(def.did) {
936                         DefKind::Static | DefKind::Const | DefKind::AssocConst => {
937                             p!(print_value_path(def.did, substs))
938                         }
939                         _ => {
940                             if def.is_local() {
941                                 let span = self.tcx().def_span(def.did);
942                                 if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
943                                 {
944                                     p!(write("{}", snip))
945                                 } else {
946                                     print_underscore!()
947                                 }
948                             } else {
949                                 print_underscore!()
950                             }
951                         }
952                     }
953                 }
954             }
955             ty::ConstKind::Infer(..) => print_underscore!(),
956             ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
957             ty::ConstKind::Value(value) => {
958                 return self.pretty_print_const_value(value, ct.ty, print_ty);
959             }
960
961             ty::ConstKind::Bound(debruijn, bound_var) => {
962                 self.pretty_print_bound_var(debruijn, bound_var)?
963             }
964             ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
965             ty::ConstKind::Error(_) => p!("[const error]"),
966         };
967         Ok(self)
968     }
969
970     fn pretty_print_const_scalar(
971         self,
972         scalar: Scalar,
973         ty: Ty<'tcx>,
974         print_ty: bool,
975     ) -> Result<Self::Const, Self::Error> {
976         match scalar {
977             Scalar::Ptr(ptr) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty),
978             Scalar::Int(int) => self.pretty_print_const_scalar_int(int, ty, print_ty),
979         }
980     }
981
982     fn pretty_print_const_scalar_ptr(
983         mut self,
984         ptr: Pointer,
985         ty: Ty<'tcx>,
986         print_ty: bool,
987     ) -> Result<Self::Const, Self::Error> {
988         define_scoped_cx!(self);
989
990         match ty.kind() {
991             // Byte strings (&[u8; N])
992             ty::Ref(
993                 _,
994                 ty::TyS {
995                     kind:
996                         ty::Array(
997                             ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. },
998                             ty::Const {
999                                 val: ty::ConstKind::Value(ConstValue::Scalar(int)), ..
1000                             },
1001                         ),
1002                     ..
1003                 },
1004                 _,
1005             ) => match self.tcx().get_global_alloc(ptr.alloc_id) {
1006                 Some(GlobalAlloc::Memory(alloc)) => {
1007                     let bytes = int.assert_bits(self.tcx().data_layout.pointer_size);
1008                     let size = Size::from_bytes(bytes);
1009                     if let Ok(byte_str) = alloc.get_bytes(&self.tcx(), ptr, size) {
1010                         p!(pretty_print_byte_str(byte_str))
1011                     } else {
1012                         p!("<too short allocation>")
1013                     }
1014                 }
1015                 // FIXME: for statics and functions, we could in principle print more detail.
1016                 Some(GlobalAlloc::Static(def_id)) => p!(write("<static({:?})>", def_id)),
1017                 Some(GlobalAlloc::Function(_)) => p!("<function>"),
1018                 None => p!("<dangling pointer>"),
1019             },
1020             ty::FnPtr(_) => {
1021                 // FIXME: We should probably have a helper method to share code with the "Byte strings"
1022                 // printing above (which also has to handle pointers to all sorts of things).
1023                 match self.tcx().get_global_alloc(ptr.alloc_id) {
1024                     Some(GlobalAlloc::Function(instance)) => {
1025                         self = self.typed_value(
1026                             |this| this.print_value_path(instance.def_id(), instance.substs),
1027                             |this| this.print_type(ty),
1028                             " as ",
1029                         )?;
1030                     }
1031                     _ => self = self.pretty_print_const_pointer(ptr, ty, print_ty)?,
1032                 }
1033             }
1034             // Any pointer values not covered by a branch above
1035             _ => {
1036                 self = self.pretty_print_const_pointer(ptr, ty, print_ty)?;
1037             }
1038         }
1039         Ok(self)
1040     }
1041
1042     fn pretty_print_const_scalar_int(
1043         mut self,
1044         int: ScalarInt,
1045         ty: Ty<'tcx>,
1046         print_ty: bool,
1047     ) -> Result<Self::Const, Self::Error> {
1048         define_scoped_cx!(self);
1049
1050         match ty.kind() {
1051             // Bool
1052             ty::Bool if int == ScalarInt::FALSE => p!("false"),
1053             ty::Bool if int == ScalarInt::TRUE => p!("true"),
1054             // Float
1055             ty::Float(ty::FloatTy::F32) => {
1056                 p!(write("{}f32", Single::try_from(int).unwrap()))
1057             }
1058             ty::Float(ty::FloatTy::F64) => {
1059                 p!(write("{}f64", Double::try_from(int).unwrap()))
1060             }
1061             // Int
1062             ty::Uint(_) | ty::Int(_) => {
1063                 let int =
1064                     ConstInt::new(int, matches!(ty.kind(), ty::Int(_)), ty.is_ptr_sized_integral());
1065                 if print_ty { p!(write("{:#?}", int)) } else { p!(write("{:?}", int)) }
1066             }
1067             // Char
1068             ty::Char if char::try_from(int).is_ok() => {
1069                 p!(write("{:?}", char::try_from(int).unwrap()))
1070             }
1071             // Raw pointers
1072             ty::RawPtr(_) | ty::FnPtr(_) => {
1073                 let data = int.assert_bits(self.tcx().data_layout.pointer_size);
1074                 self = self.typed_value(
1075                     |mut this| {
1076                         write!(this, "0x{:x}", data)?;
1077                         Ok(this)
1078                     },
1079                     |this| this.print_type(ty),
1080                     " as ",
1081                 )?;
1082             }
1083             // For function type zsts just printing the path is enough
1084             ty::FnDef(d, s) if int == ScalarInt::ZST => {
1085                 p!(print_value_path(*d, s))
1086             }
1087             // Nontrivial types with scalar bit representation
1088             _ => {
1089                 let print = |mut this: Self| {
1090                     if int.size() == Size::ZERO {
1091                         write!(this, "transmute(())")?;
1092                     } else {
1093                         write!(this, "transmute(0x{:x})", int)?;
1094                     }
1095                     Ok(this)
1096                 };
1097                 self = if print_ty {
1098                     self.typed_value(print, |this| this.print_type(ty), ": ")?
1099                 } else {
1100                     print(self)?
1101                 };
1102             }
1103         }
1104         Ok(self)
1105     }
1106
1107     /// This is overridden for MIR printing because we only want to hide alloc ids from users, not
1108     /// from MIR where it is actually useful.
1109     fn pretty_print_const_pointer(
1110         mut self,
1111         _: Pointer,
1112         ty: Ty<'tcx>,
1113         print_ty: bool,
1114     ) -> Result<Self::Const, Self::Error> {
1115         if print_ty {
1116             self.typed_value(
1117                 |mut this| {
1118                     this.write_str("&_")?;
1119                     Ok(this)
1120                 },
1121                 |this| this.print_type(ty),
1122                 ": ",
1123             )
1124         } else {
1125             self.write_str("&_")?;
1126             Ok(self)
1127         }
1128     }
1129
1130     fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> {
1131         define_scoped_cx!(self);
1132         p!("b\"");
1133         for &c in byte_str {
1134             for e in std::ascii::escape_default(c) {
1135                 self.write_char(e as char)?;
1136             }
1137         }
1138         p!("\"");
1139         Ok(self)
1140     }
1141
1142     fn pretty_print_const_value(
1143         mut self,
1144         ct: ConstValue<'tcx>,
1145         ty: Ty<'tcx>,
1146         print_ty: bool,
1147     ) -> Result<Self::Const, Self::Error> {
1148         define_scoped_cx!(self);
1149
1150         if self.tcx().sess.verbose() {
1151             p!(write("ConstValue({:?}: ", ct), print(ty), ")");
1152             return Ok(self);
1153         }
1154
1155         let u8_type = self.tcx().types.u8;
1156
1157         match (ct, ty.kind()) {
1158             // Byte/string slices, printed as (byte) string literals.
1159             (
1160                 ConstValue::Slice { data, start, end },
1161                 ty::Ref(_, ty::TyS { kind: ty::Slice(t), .. }, _),
1162             ) if *t == u8_type => {
1163                 // The `inspect` here is okay since we checked the bounds, and there are
1164                 // no relocations (we have an active slice reference here). We don't use
1165                 // this result to affect interpreter execution.
1166                 let byte_str = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
1167                 self.pretty_print_byte_str(byte_str)
1168             }
1169             (
1170                 ConstValue::Slice { data, start, end },
1171                 ty::Ref(_, ty::TyS { kind: ty::Str, .. }, _),
1172             ) => {
1173                 // The `inspect` here is okay since we checked the bounds, and there are no
1174                 // relocations (we have an active `str` reference here). We don't use this
1175                 // result to affect interpreter execution.
1176                 let slice = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
1177                 let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
1178                 p!(write("{:?}", s));
1179                 Ok(self)
1180             }
1181             (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
1182                 let n = n.val.try_to_bits(self.tcx().data_layout.pointer_size).unwrap();
1183                 // cast is ok because we already checked for pointer size (32 or 64 bit) above
1184                 let n = Size::from_bytes(n);
1185                 let ptr = Pointer::new(AllocId(0), offset);
1186
1187                 let byte_str = alloc.get_bytes(&self.tcx(), ptr, n).unwrap();
1188                 p!("*");
1189                 p!(pretty_print_byte_str(byte_str));
1190                 Ok(self)
1191             }
1192
1193             // Aggregates, printed as array/tuple/struct/variant construction syntax.
1194             //
1195             // NB: the `has_param_types_or_consts` check ensures that we can use
1196             // the `destructure_const` query with an empty `ty::ParamEnv` without
1197             // introducing ICEs (e.g. via `layout_of`) from missing bounds.
1198             // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
1199             // to be able to destructure the tuple into `(0u8, *mut T)
1200             //
1201             // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
1202             // correct `ty::ParamEnv` to allow printing *all* constant values.
1203             (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
1204                 let contents = self.tcx().destructure_const(
1205                     ty::ParamEnv::reveal_all()
1206                         .and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })),
1207                 );
1208                 let fields = contents.fields.iter().copied();
1209
1210                 match *ty.kind() {
1211                     ty::Array(..) => {
1212                         p!("[", comma_sep(fields), "]");
1213                     }
1214                     ty::Tuple(..) => {
1215                         p!("(", comma_sep(fields));
1216                         if contents.fields.len() == 1 {
1217                             p!(",");
1218                         }
1219                         p!(")");
1220                     }
1221                     ty::Adt(def, substs) if def.variants.is_empty() => {
1222                         p!(print_value_path(def.did, substs));
1223                     }
1224                     ty::Adt(def, substs) => {
1225                         let variant_id =
1226                             contents.variant.expect("destructed const of adt without variant id");
1227                         let variant_def = &def.variants[variant_id];
1228                         p!(print_value_path(variant_def.def_id, substs));
1229
1230                         match variant_def.ctor_kind {
1231                             CtorKind::Const => {}
1232                             CtorKind::Fn => {
1233                                 p!("(", comma_sep(fields), ")");
1234                             }
1235                             CtorKind::Fictive => {
1236                                 p!(" {{ ");
1237                                 let mut first = true;
1238                                 for (field_def, field) in iter::zip(&variant_def.fields, fields) {
1239                                     if !first {
1240                                         p!(", ");
1241                                     }
1242                                     p!(write("{}: ", field_def.ident), print(field));
1243                                     first = false;
1244                                 }
1245                                 p!(" }}");
1246                             }
1247                         }
1248                     }
1249                     _ => unreachable!(),
1250                 }
1251
1252                 Ok(self)
1253             }
1254
1255             (ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty),
1256
1257             // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
1258             // their fields instead of just dumping the memory.
1259             _ => {
1260                 // fallback
1261                 p!(write("{:?}", ct));
1262                 if print_ty {
1263                     p!(": ", print(ty));
1264                 }
1265                 Ok(self)
1266             }
1267         }
1268     }
1269 }
1270
1271 // HACK(eddyb) boxed to avoid moving around a large struct by-value.
1272 pub struct FmtPrinter<'a, 'tcx, F>(Box<FmtPrinterData<'a, 'tcx, F>>);
1273
1274 pub struct FmtPrinterData<'a, 'tcx, F> {
1275     tcx: TyCtxt<'tcx>,
1276     fmt: F,
1277
1278     empty_path: bool,
1279     in_value: bool,
1280     pub print_alloc_ids: bool,
1281
1282     used_region_names: FxHashSet<Symbol>,
1283     region_index: usize,
1284     binder_depth: usize,
1285     printed_type_count: usize,
1286
1287     pub region_highlight_mode: RegionHighlightMode,
1288
1289     pub name_resolver: Option<Box<&'a dyn Fn(ty::TyVid) -> Option<String>>>,
1290 }
1291
1292 impl<F> Deref for FmtPrinter<'a, 'tcx, F> {
1293     type Target = FmtPrinterData<'a, 'tcx, F>;
1294     fn deref(&self) -> &Self::Target {
1295         &self.0
1296     }
1297 }
1298
1299 impl<F> DerefMut for FmtPrinter<'_, '_, F> {
1300     fn deref_mut(&mut self) -> &mut Self::Target {
1301         &mut self.0
1302     }
1303 }
1304
1305 impl<F> FmtPrinter<'a, 'tcx, F> {
1306     pub fn new(tcx: TyCtxt<'tcx>, fmt: F, ns: Namespace) -> Self {
1307         FmtPrinter(Box::new(FmtPrinterData {
1308             tcx,
1309             fmt,
1310             empty_path: false,
1311             in_value: ns == Namespace::ValueNS,
1312             print_alloc_ids: false,
1313             used_region_names: Default::default(),
1314             region_index: 0,
1315             binder_depth: 0,
1316             printed_type_count: 0,
1317             region_highlight_mode: RegionHighlightMode::default(),
1318             name_resolver: None,
1319         }))
1320     }
1321 }
1322
1323 // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
1324 // (but also some things just print a `DefId` generally so maybe we need this?)
1325 fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
1326     match tcx.def_key(def_id).disambiguated_data.data {
1327         DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => {
1328             Namespace::TypeNS
1329         }
1330
1331         DefPathData::ValueNs(..)
1332         | DefPathData::AnonConst
1333         | DefPathData::ClosureExpr
1334         | DefPathData::Ctor => Namespace::ValueNS,
1335
1336         DefPathData::MacroNs(..) => Namespace::MacroNS,
1337
1338         _ => Namespace::TypeNS,
1339     }
1340 }
1341
1342 impl TyCtxt<'t> {
1343     /// Returns a string identifying this `DefId`. This string is
1344     /// suitable for user output.
1345     pub fn def_path_str(self, def_id: DefId) -> String {
1346         self.def_path_str_with_substs(def_id, &[])
1347     }
1348
1349     pub fn def_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String {
1350         let ns = guess_def_namespace(self, def_id);
1351         debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
1352         let mut s = String::new();
1353         let _ = FmtPrinter::new(self, &mut s, ns).print_def_path(def_id, substs);
1354         s
1355     }
1356 }
1357
1358 impl<F: fmt::Write> fmt::Write for FmtPrinter<'_, '_, F> {
1359     fn write_str(&mut self, s: &str) -> fmt::Result {
1360         self.fmt.write_str(s)
1361     }
1362 }
1363
1364 impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
1365     type Error = fmt::Error;
1366
1367     type Path = Self;
1368     type Region = Self;
1369     type Type = Self;
1370     type DynExistential = Self;
1371     type Const = Self;
1372
1373     fn tcx(&'a self) -> TyCtxt<'tcx> {
1374         self.tcx
1375     }
1376
1377     fn print_def_path(
1378         mut self,
1379         def_id: DefId,
1380         substs: &'tcx [GenericArg<'tcx>],
1381     ) -> Result<Self::Path, Self::Error> {
1382         define_scoped_cx!(self);
1383
1384         if substs.is_empty() {
1385             match self.try_print_trimmed_def_path(def_id)? {
1386                 (cx, true) => return Ok(cx),
1387                 (cx, false) => self = cx,
1388             }
1389
1390             match self.try_print_visible_def_path(def_id)? {
1391                 (cx, true) => return Ok(cx),
1392                 (cx, false) => self = cx,
1393             }
1394         }
1395
1396         let key = self.tcx.def_key(def_id);
1397         if let DefPathData::Impl = key.disambiguated_data.data {
1398             // Always use types for non-local impls, where types are always
1399             // available, and filename/line-number is mostly uninteresting.
1400             let use_types = !def_id.is_local() || {
1401                 // Otherwise, use filename/line-number if forced.
1402                 let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
1403                 !force_no_types
1404             };
1405
1406             if !use_types {
1407                 // If no type info is available, fall back to
1408                 // pretty printing some span information. This should
1409                 // only occur very early in the compiler pipeline.
1410                 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
1411                 let span = self.tcx.def_span(def_id);
1412
1413                 self = self.print_def_path(parent_def_id, &[])?;
1414
1415                 // HACK(eddyb) copy of `path_append` to avoid
1416                 // constructing a `DisambiguatedDefPathData`.
1417                 if !self.empty_path {
1418                     write!(self, "::")?;
1419                 }
1420                 write!(
1421                     self,
1422                     "<impl at {}>",
1423                     // This may end up in stderr diagnostics but it may also be emitted
1424                     // into MIR. Hence we use the remapped path if available
1425                     self.tcx.sess.source_map().span_to_embeddable_string(span)
1426                 )?;
1427                 self.empty_path = false;
1428
1429                 return Ok(self);
1430             }
1431         }
1432
1433         self.default_print_def_path(def_id, substs)
1434     }
1435
1436     fn print_region(self, region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
1437         self.pretty_print_region(region)
1438     }
1439
1440     fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
1441         let type_length_limit = self.tcx.sess.type_length_limit();
1442         if type_length_limit.value_within_limit(self.printed_type_count) {
1443             self.printed_type_count += 1;
1444             self.pretty_print_type(ty)
1445         } else {
1446             write!(self, "...")?;
1447             Ok(self)
1448         }
1449     }
1450
1451     fn print_dyn_existential(
1452         self,
1453         predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
1454     ) -> Result<Self::DynExistential, Self::Error> {
1455         self.pretty_print_dyn_existential(predicates)
1456     }
1457
1458     fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
1459         self.pretty_print_const(ct, true)
1460     }
1461
1462     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
1463         self.empty_path = true;
1464         if cnum == LOCAL_CRATE {
1465             if self.tcx.sess.rust_2018() {
1466                 // We add the `crate::` keyword on Rust 2018, only when desired.
1467                 if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
1468                     write!(self, "{}", kw::Crate)?;
1469                     self.empty_path = false;
1470                 }
1471             }
1472         } else {
1473             write!(self, "{}", self.tcx.crate_name(cnum))?;
1474             self.empty_path = false;
1475         }
1476         Ok(self)
1477     }
1478
1479     fn path_qualified(
1480         mut self,
1481         self_ty: Ty<'tcx>,
1482         trait_ref: Option<ty::TraitRef<'tcx>>,
1483     ) -> Result<Self::Path, Self::Error> {
1484         self = self.pretty_path_qualified(self_ty, trait_ref)?;
1485         self.empty_path = false;
1486         Ok(self)
1487     }
1488
1489     fn path_append_impl(
1490         mut self,
1491         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
1492         _disambiguated_data: &DisambiguatedDefPathData,
1493         self_ty: Ty<'tcx>,
1494         trait_ref: Option<ty::TraitRef<'tcx>>,
1495     ) -> Result<Self::Path, Self::Error> {
1496         self = self.pretty_path_append_impl(
1497             |mut cx| {
1498                 cx = print_prefix(cx)?;
1499                 if !cx.empty_path {
1500                     write!(cx, "::")?;
1501                 }
1502
1503                 Ok(cx)
1504             },
1505             self_ty,
1506             trait_ref,
1507         )?;
1508         self.empty_path = false;
1509         Ok(self)
1510     }
1511
1512     fn path_append(
1513         mut self,
1514         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
1515         disambiguated_data: &DisambiguatedDefPathData,
1516     ) -> Result<Self::Path, Self::Error> {
1517         self = print_prefix(self)?;
1518
1519         // Skip `::{{constructor}}` on tuple/unit structs.
1520         if let DefPathData::Ctor = disambiguated_data.data {
1521             return Ok(self);
1522         }
1523
1524         // FIXME(eddyb) `name` should never be empty, but it
1525         // currently is for `extern { ... }` "foreign modules".
1526         let name = disambiguated_data.data.name();
1527         if name != DefPathDataName::Named(kw::Empty) {
1528             if !self.empty_path {
1529                 write!(self, "::")?;
1530             }
1531
1532             if let DefPathDataName::Named(name) = name {
1533                 if Ident::with_dummy_span(name).is_raw_guess() {
1534                     write!(self, "r#")?;
1535                 }
1536             }
1537
1538             let verbose = self.tcx.sess.verbose();
1539             disambiguated_data.fmt_maybe_verbose(&mut self, verbose)?;
1540
1541             self.empty_path = false;
1542         }
1543
1544         Ok(self)
1545     }
1546
1547     fn path_generic_args(
1548         mut self,
1549         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
1550         args: &[GenericArg<'tcx>],
1551     ) -> Result<Self::Path, Self::Error> {
1552         self = print_prefix(self)?;
1553
1554         // Don't print `'_` if there's no unerased regions.
1555         let print_regions = args.iter().any(|arg| match arg.unpack() {
1556             GenericArgKind::Lifetime(r) => *r != ty::ReErased,
1557             _ => false,
1558         });
1559         let args = args.iter().cloned().filter(|arg| match arg.unpack() {
1560             GenericArgKind::Lifetime(_) => print_regions,
1561             _ => true,
1562         });
1563
1564         if args.clone().next().is_some() {
1565             if self.in_value {
1566                 write!(self, "::")?;
1567             }
1568             self.generic_delimiters(|cx| cx.comma_sep(args))
1569         } else {
1570             Ok(self)
1571         }
1572     }
1573 }
1574
1575 impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
1576     fn infer_ty_name(&self, id: ty::TyVid) -> Option<String> {
1577         self.0.name_resolver.as_ref().and_then(|func| func(id))
1578     }
1579
1580     fn print_value_path(
1581         mut self,
1582         def_id: DefId,
1583         substs: &'tcx [GenericArg<'tcx>],
1584     ) -> Result<Self::Path, Self::Error> {
1585         let was_in_value = std::mem::replace(&mut self.in_value, true);
1586         self = self.print_def_path(def_id, substs)?;
1587         self.in_value = was_in_value;
1588
1589         Ok(self)
1590     }
1591
1592     fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
1593     where
1594         T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
1595     {
1596         self.pretty_in_binder(value)
1597     }
1598
1599     fn wrap_binder<T, C: Fn(&T, Self) -> Result<Self, Self::Error>>(
1600         self,
1601         value: &ty::Binder<'tcx, T>,
1602         f: C,
1603     ) -> Result<Self, Self::Error>
1604     where
1605         T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
1606     {
1607         self.pretty_wrap_binder(value, f)
1608     }
1609
1610     fn typed_value(
1611         mut self,
1612         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
1613         t: impl FnOnce(Self) -> Result<Self, Self::Error>,
1614         conversion: &str,
1615     ) -> Result<Self::Const, Self::Error> {
1616         self.write_str("{")?;
1617         self = f(self)?;
1618         self.write_str(conversion)?;
1619         let was_in_value = std::mem::replace(&mut self.in_value, false);
1620         self = t(self)?;
1621         self.in_value = was_in_value;
1622         self.write_str("}")?;
1623         Ok(self)
1624     }
1625
1626     fn generic_delimiters(
1627         mut self,
1628         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
1629     ) -> Result<Self, Self::Error> {
1630         write!(self, "<")?;
1631
1632         let was_in_value = std::mem::replace(&mut self.in_value, false);
1633         let mut inner = f(self)?;
1634         inner.in_value = was_in_value;
1635
1636         write!(inner, ">")?;
1637         Ok(inner)
1638     }
1639
1640     fn region_should_not_be_omitted(&self, region: ty::Region<'_>) -> bool {
1641         let highlight = self.region_highlight_mode;
1642         if highlight.region_highlighted(region).is_some() {
1643             return true;
1644         }
1645
1646         if self.tcx.sess.verbose() {
1647             return true;
1648         }
1649
1650         let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions;
1651
1652         match *region {
1653             ty::ReEarlyBound(ref data) => {
1654                 data.name != kw::Empty && data.name != kw::UnderscoreLifetime
1655             }
1656
1657             ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
1658             | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
1659             | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
1660                 if let ty::BrNamed(_, name) = br {
1661                     if name != kw::Empty && name != kw::UnderscoreLifetime {
1662                         return true;
1663                     }
1664                 }
1665
1666                 if let Some((region, _)) = highlight.highlight_bound_region {
1667                     if br == region {
1668                         return true;
1669                     }
1670                 }
1671
1672                 false
1673             }
1674
1675             ty::ReVar(_) if identify_regions => true,
1676
1677             ty::ReVar(_) | ty::ReErased => false,
1678
1679             ty::ReStatic | ty::ReEmpty(_) => true,
1680         }
1681     }
1682
1683     fn pretty_print_const_pointer(
1684         self,
1685         p: Pointer,
1686         ty: Ty<'tcx>,
1687         print_ty: bool,
1688     ) -> Result<Self::Const, Self::Error> {
1689         let print = |mut this: Self| {
1690             define_scoped_cx!(this);
1691             if this.print_alloc_ids {
1692                 p!(write("{:?}", p));
1693             } else {
1694                 p!("&_");
1695             }
1696             Ok(this)
1697         };
1698         if print_ty {
1699             self.typed_value(print, |this| this.print_type(ty), ": ")
1700         } else {
1701             print(self)
1702         }
1703     }
1704 }
1705
1706 // HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
1707 impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
1708     pub fn pretty_print_region(mut self, region: ty::Region<'_>) -> Result<Self, fmt::Error> {
1709         define_scoped_cx!(self);
1710
1711         // Watch out for region highlights.
1712         let highlight = self.region_highlight_mode;
1713         if let Some(n) = highlight.region_highlighted(region) {
1714             p!(write("'{}", n));
1715             return Ok(self);
1716         }
1717
1718         if self.tcx.sess.verbose() {
1719             p!(write("{:?}", region));
1720             return Ok(self);
1721         }
1722
1723         let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions;
1724
1725         // These printouts are concise.  They do not contain all the information
1726         // the user might want to diagnose an error, but there is basically no way
1727         // to fit that into a short string.  Hence the recommendation to use
1728         // `explain_region()` or `note_and_explain_region()`.
1729         match *region {
1730             ty::ReEarlyBound(ref data) => {
1731                 if data.name != kw::Empty {
1732                     p!(write("{}", data.name));
1733                     return Ok(self);
1734                 }
1735             }
1736             ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
1737             | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
1738             | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
1739                 if let ty::BrNamed(_, name) = br {
1740                     if name != kw::Empty && name != kw::UnderscoreLifetime {
1741                         p!(write("{}", name));
1742                         return Ok(self);
1743                     }
1744                 }
1745
1746                 if let Some((region, counter)) = highlight.highlight_bound_region {
1747                     if br == region {
1748                         p!(write("'{}", counter));
1749                         return Ok(self);
1750                     }
1751                 }
1752             }
1753             ty::ReVar(region_vid) if identify_regions => {
1754                 p!(write("{:?}", region_vid));
1755                 return Ok(self);
1756             }
1757             ty::ReVar(_) => {}
1758             ty::ReErased => {}
1759             ty::ReStatic => {
1760                 p!("'static");
1761                 return Ok(self);
1762             }
1763             ty::ReEmpty(ty::UniverseIndex::ROOT) => {
1764                 p!("'<empty>");
1765                 return Ok(self);
1766             }
1767             ty::ReEmpty(ui) => {
1768                 p!(write("'<empty:{:?}>", ui));
1769                 return Ok(self);
1770             }
1771         }
1772
1773         p!("'_");
1774
1775         Ok(self)
1776     }
1777 }
1778
1779 // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
1780 // `region_index` and `used_region_names`.
1781 impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
1782     pub fn name_all_regions<T>(
1783         mut self,
1784         value: &ty::Binder<'tcx, T>,
1785     ) -> Result<(Self, (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)), fmt::Error>
1786     where
1787         T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
1788     {
1789         fn name_by_region_index(index: usize) -> Symbol {
1790             match index {
1791                 0 => Symbol::intern("'r"),
1792                 1 => Symbol::intern("'s"),
1793                 i => Symbol::intern(&format!("'t{}", i - 2)),
1794             }
1795         }
1796
1797         // Replace any anonymous late-bound regions with named
1798         // variants, using new unique identifiers, so that we can
1799         // clearly differentiate between named and unnamed regions in
1800         // the output. We'll probably want to tweak this over time to
1801         // decide just how much information to give.
1802         if self.binder_depth == 0 {
1803             self.prepare_late_bound_region_info(value);
1804         }
1805
1806         let mut empty = true;
1807         let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
1808             write!(
1809                 cx,
1810                 "{}",
1811                 if empty {
1812                     empty = false;
1813                     start
1814                 } else {
1815                     cont
1816                 }
1817             )
1818         };
1819
1820         define_scoped_cx!(self);
1821
1822         let mut region_index = self.region_index;
1823         // If we want to print verbosly, then print *all* binders, even if they
1824         // aren't named. Eventually, we might just want this as the default, but
1825         // this is not *quite* right and changes the ordering of some output
1826         // anyways.
1827         let new_value = if self.tcx().sess.verbose() {
1828             // anon index + 1 (BrEnv takes 0) -> name
1829             let mut region_map: BTreeMap<u32, Symbol> = BTreeMap::default();
1830             let bound_vars = value.bound_vars();
1831             for var in bound_vars {
1832                 match var {
1833                     ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => {
1834                         let _ = start_or_continue(&mut self, "for<", ", ");
1835                         let _ = write!(self, "{}", name);
1836                     }
1837                     ty::BoundVariableKind::Region(ty::BrAnon(i)) => {
1838                         let _ = start_or_continue(&mut self, "for<", ", ");
1839                         let name = loop {
1840                             let name = name_by_region_index(region_index);
1841                             region_index += 1;
1842                             if !self.used_region_names.contains(&name) {
1843                                 break name;
1844                             }
1845                         };
1846                         let _ = write!(self, "{}", name);
1847                         region_map.insert(i + 1, name);
1848                     }
1849                     ty::BoundVariableKind::Region(ty::BrEnv) => {
1850                         let _ = start_or_continue(&mut self, "for<", ", ");
1851                         let name = loop {
1852                             let name = name_by_region_index(region_index);
1853                             region_index += 1;
1854                             if !self.used_region_names.contains(&name) {
1855                                 break name;
1856                             }
1857                         };
1858                         let _ = write!(self, "{}", name);
1859                         region_map.insert(0, name);
1860                     }
1861                     _ => continue,
1862                 }
1863             }
1864             start_or_continue(&mut self, "", "> ")?;
1865
1866             self.tcx.replace_late_bound_regions(value.clone(), |br| {
1867                 let kind = match br.kind {
1868                     ty::BrNamed(_, _) => br.kind,
1869                     ty::BrAnon(i) => {
1870                         let name = region_map[&(i + 1)];
1871                         ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
1872                     }
1873                     ty::BrEnv => {
1874                         let name = region_map[&0];
1875                         ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
1876                     }
1877                 };
1878                 self.tcx.mk_region(ty::ReLateBound(
1879                     ty::INNERMOST,
1880                     ty::BoundRegion { var: br.var, kind },
1881                 ))
1882             })
1883         } else {
1884             let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| {
1885                 let _ = start_or_continue(&mut self, "for<", ", ");
1886                 let kind = match br.kind {
1887                     ty::BrNamed(_, name) => {
1888                         let _ = write!(self, "{}", name);
1889                         br.kind
1890                     }
1891                     ty::BrAnon(_) | ty::BrEnv => {
1892                         let name = loop {
1893                             let name = name_by_region_index(region_index);
1894                             region_index += 1;
1895                             if !self.used_region_names.contains(&name) {
1896                                 break name;
1897                             }
1898                         };
1899                         let _ = write!(self, "{}", name);
1900                         ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
1901                     }
1902                 };
1903                 self.tcx.mk_region(ty::ReLateBound(
1904                     ty::INNERMOST,
1905                     ty::BoundRegion { var: br.var, kind },
1906                 ))
1907             });
1908             start_or_continue(&mut self, "", "> ")?;
1909             new_value
1910         };
1911
1912         self.binder_depth += 1;
1913         self.region_index = region_index;
1914         Ok((self, new_value))
1915     }
1916
1917     pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fmt::Error>
1918     where
1919         T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
1920     {
1921         let old_region_index = self.region_index;
1922         let (new, new_value) = self.name_all_regions(value)?;
1923         let mut inner = new_value.0.print(new)?;
1924         inner.region_index = old_region_index;
1925         inner.binder_depth -= 1;
1926         Ok(inner)
1927     }
1928
1929     pub fn pretty_wrap_binder<T, C: Fn(&T, Self) -> Result<Self, fmt::Error>>(
1930         self,
1931         value: &ty::Binder<'tcx, T>,
1932         f: C,
1933     ) -> Result<Self, fmt::Error>
1934     where
1935         T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
1936     {
1937         let old_region_index = self.region_index;
1938         let (new, new_value) = self.name_all_regions(value)?;
1939         let mut inner = f(&new_value.0, new)?;
1940         inner.region_index = old_region_index;
1941         inner.binder_depth -= 1;
1942         Ok(inner)
1943     }
1944
1945     fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
1946     where
1947         T: TypeFoldable<'tcx>,
1948     {
1949         debug!("prepare_late_bound_region_info(value: {:?})", value);
1950
1951         struct LateBoundRegionNameCollector<'a, 'tcx> {
1952             used_region_names: &'a mut FxHashSet<Symbol>,
1953             type_collector: SsoHashSet<Ty<'tcx>>,
1954         }
1955
1956         impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
1957             type BreakTy = ();
1958
1959             fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
1960                 debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r);
1961                 if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
1962                     self.used_region_names.insert(name);
1963                 }
1964                 r.super_visit_with(self)
1965             }
1966
1967             // We collect types in order to prevent really large types from compiling for
1968             // a really long time. See issue #83150 for why this is necessary.
1969             fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1970                 debug!("LateBoundRegionNameCollector::visit_ty(ty: {:?}", ty);
1971                 let not_previously_inserted = self.type_collector.insert(ty);
1972                 if not_previously_inserted {
1973                     ty.super_visit_with(self)
1974                 } else {
1975                     ControlFlow::CONTINUE
1976                 }
1977             }
1978         }
1979
1980         self.used_region_names.clear();
1981         let mut collector = LateBoundRegionNameCollector {
1982             used_region_names: &mut self.used_region_names,
1983             type_collector: SsoHashSet::new(),
1984         };
1985         value.visit_with(&mut collector);
1986         self.region_index = 0;
1987     }
1988 }
1989
1990 impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T>
1991 where
1992     T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx>,
1993 {
1994     type Output = P;
1995     type Error = P::Error;
1996     fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
1997         cx.in_binder(self)
1998     }
1999 }
2000
2001 impl<'tcx, T, U, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate<T, U>
2002 where
2003     T: Print<'tcx, P, Output = P, Error = P::Error>,
2004     U: Print<'tcx, P, Output = P, Error = P::Error>,
2005 {
2006     type Output = P;
2007     type Error = P::Error;
2008     fn print(&self, mut cx: P) -> Result<Self::Output, Self::Error> {
2009         define_scoped_cx!(cx);
2010         p!(print(self.0), ": ", print(self.1));
2011         Ok(cx)
2012     }
2013 }
2014
2015 macro_rules! forward_display_to_print {
2016     ($($ty:ty),+) => {
2017         $(impl fmt::Display for $ty {
2018             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2019                 ty::tls::with(|tcx| {
2020                     tcx.lift(*self)
2021                         .expect("could not lift for printing")
2022                         .print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?;
2023                     Ok(())
2024                 })
2025             }
2026         })+
2027     };
2028 }
2029
2030 macro_rules! define_print_and_forward_display {
2031     (($self:ident, $cx:ident): $($ty:ty $print:block)+) => {
2032         $(impl<'tcx, P: PrettyPrinter<'tcx>> Print<'tcx, P> for $ty {
2033             type Output = P;
2034             type Error = fmt::Error;
2035             fn print(&$self, $cx: P) -> Result<Self::Output, Self::Error> {
2036                 #[allow(unused_mut)]
2037                 let mut $cx = $cx;
2038                 define_scoped_cx!($cx);
2039                 let _: () = $print;
2040                 #[allow(unreachable_code)]
2041                 Ok($cx)
2042             }
2043         })+
2044
2045         forward_display_to_print!($($ty),+);
2046     };
2047 }
2048
2049 // HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting.
2050 impl fmt::Display for ty::RegionKind {
2051     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2052         ty::tls::with(|tcx| {
2053             self.print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?;
2054             Ok(())
2055         })
2056     }
2057 }
2058
2059 /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
2060 /// the trait path. That is, it will print `Trait<U>` instead of
2061 /// `<T as Trait<U>>`.
2062 #[derive(Copy, Clone, TypeFoldable, Lift)]
2063 pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
2064
2065 impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
2066     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2067         fmt::Display::fmt(self, f)
2068     }
2069 }
2070
2071 impl ty::TraitRef<'tcx> {
2072     pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
2073         TraitRefPrintOnlyTraitPath(self)
2074     }
2075 }
2076
2077 impl ty::Binder<'tcx, ty::TraitRef<'tcx>> {
2078     pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> {
2079         self.map_bound(|tr| tr.print_only_trait_path())
2080     }
2081 }
2082
2083 forward_display_to_print! {
2084     Ty<'tcx>,
2085     &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
2086     &'tcx ty::Const<'tcx>,
2087
2088     // HACK(eddyb) these are exhaustive instead of generic,
2089     // because `for<'tcx>` isn't possible yet.
2090     ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>,
2091     ty::Binder<'tcx, ty::TraitRef<'tcx>>,
2092     ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
2093     ty::Binder<'tcx, ty::FnSig<'tcx>>,
2094     ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
2095     ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>,
2096     ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
2097     ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
2098     ty::Binder<'tcx, ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>,
2099
2100     ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
2101     ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
2102 }
2103
2104 define_print_and_forward_display! {
2105     (self, cx):
2106
2107     &'tcx ty::List<Ty<'tcx>> {
2108         p!("{{", comma_sep(self.iter()), "}}")
2109     }
2110
2111     ty::TypeAndMut<'tcx> {
2112         p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
2113     }
2114
2115     ty::ExistentialTraitRef<'tcx> {
2116         // Use a type that can't appear in defaults of type parameters.
2117         let dummy_self = cx.tcx().mk_ty_infer(ty::FreshTy(0));
2118         let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
2119         p!(print(trait_ref.print_only_trait_path()))
2120     }
2121
2122     ty::ExistentialProjection<'tcx> {
2123         let name = cx.tcx().associated_item(self.item_def_id).ident;
2124         p!(write("{} = ", name), print(self.ty))
2125     }
2126
2127     ty::ExistentialPredicate<'tcx> {
2128         match *self {
2129             ty::ExistentialPredicate::Trait(x) => p!(print(x)),
2130             ty::ExistentialPredicate::Projection(x) => p!(print(x)),
2131             ty::ExistentialPredicate::AutoTrait(def_id) => {
2132                 p!(print_def_path(def_id, &[]));
2133             }
2134         }
2135     }
2136
2137     ty::FnSig<'tcx> {
2138         p!(write("{}", self.unsafety.prefix_str()));
2139
2140         if self.abi != Abi::Rust {
2141             p!(write("extern {} ", self.abi));
2142         }
2143
2144         p!("fn", pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
2145     }
2146
2147     ty::TraitRef<'tcx> {
2148         p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
2149     }
2150
2151     TraitRefPrintOnlyTraitPath<'tcx> {
2152         p!(print_def_path(self.0.def_id, self.0.substs));
2153     }
2154
2155     ty::ParamTy {
2156         p!(write("{}", self.name))
2157     }
2158
2159     ty::ParamConst {
2160         p!(write("{}", self.name))
2161     }
2162
2163     ty::SubtypePredicate<'tcx> {
2164         p!(print(self.a), " <: ", print(self.b))
2165     }
2166
2167     ty::TraitPredicate<'tcx> {
2168         p!(print(self.trait_ref.self_ty()), ": ",
2169            print(self.trait_ref.print_only_trait_path()))
2170     }
2171
2172     ty::ProjectionPredicate<'tcx> {
2173         p!(print(self.projection_ty), " == ", print(self.ty))
2174     }
2175
2176     ty::ProjectionTy<'tcx> {
2177         p!(print_def_path(self.item_def_id, self.substs));
2178     }
2179
2180     ty::ClosureKind {
2181         match *self {
2182             ty::ClosureKind::Fn => p!("Fn"),
2183             ty::ClosureKind::FnMut => p!("FnMut"),
2184             ty::ClosureKind::FnOnce => p!("FnOnce"),
2185         }
2186     }
2187
2188     ty::Predicate<'tcx> {
2189         let binder = self.kind();
2190         p!(print(binder))
2191     }
2192
2193     ty::PredicateKind<'tcx> {
2194         match *self {
2195             ty::PredicateKind::Trait(ref data, constness) => {
2196                 if let hir::Constness::Const = constness {
2197                     p!("const ");
2198                 }
2199                 p!(print(data))
2200             }
2201             ty::PredicateKind::Subtype(predicate) => p!(print(predicate)),
2202             ty::PredicateKind::RegionOutlives(predicate) => p!(print(predicate)),
2203             ty::PredicateKind::TypeOutlives(predicate) => p!(print(predicate)),
2204             ty::PredicateKind::Projection(predicate) => p!(print(predicate)),
2205             ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"),
2206             ty::PredicateKind::ObjectSafe(trait_def_id) => {
2207                 p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
2208             }
2209             ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => {
2210                 p!("the closure `",
2211                 print_value_path(closure_def_id, &[]),
2212                 write("` implements the trait `{}`", kind))
2213             }
2214             ty::PredicateKind::ConstEvaluatable(def, substs) => {
2215                 p!("the constant `", print_value_path(def.did, substs), "` can be evaluated")
2216             }
2217             ty::PredicateKind::ConstEquate(c1, c2) => {
2218                 p!("the constant `", print(c1), "` equals `", print(c2), "`")
2219             }
2220             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
2221                 p!("the type `", print(ty), "` is found in the environment")
2222             }
2223         }
2224     }
2225
2226     GenericArg<'tcx> {
2227         match self.unpack() {
2228             GenericArgKind::Lifetime(lt) => p!(print(lt)),
2229             GenericArgKind::Type(ty) => p!(print(ty)),
2230             GenericArgKind::Const(ct) => p!(print(ct)),
2231         }
2232     }
2233 }
2234
2235 fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) {
2236     // Iterate all local crate items no matter where they are defined.
2237     let hir = tcx.hir();
2238     for item in hir.krate().items.values() {
2239         if item.ident.name.as_str().is_empty() || matches!(item.kind, ItemKind::Use(_, _)) {
2240             continue;
2241         }
2242
2243         let def_id = item.def_id.to_def_id();
2244         let ns = tcx.def_kind(def_id).ns().unwrap_or(Namespace::TypeNS);
2245         collect_fn(&item.ident, ns, def_id);
2246     }
2247
2248     // Now take care of extern crate items.
2249     let queue = &mut Vec::new();
2250     let mut seen_defs: DefIdSet = Default::default();
2251
2252     for &cnum in tcx.crates().iter() {
2253         let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
2254
2255         // Ignore crates that are not direct dependencies.
2256         match tcx.extern_crate(def_id) {
2257             None => continue,
2258             Some(extern_crate) => {
2259                 if !extern_crate.is_direct() {
2260                     continue;
2261                 }
2262             }
2263         }
2264
2265         queue.push(def_id);
2266     }
2267
2268     // Iterate external crate defs but be mindful about visibility
2269     while let Some(def) = queue.pop() {
2270         for child in tcx.item_children(def).iter() {
2271             if child.vis != ty::Visibility::Public {
2272                 continue;
2273             }
2274
2275             match child.res {
2276                 def::Res::Def(DefKind::AssocTy, _) => {}
2277                 def::Res::Def(DefKind::TyAlias, _) => {}
2278                 def::Res::Def(defkind, def_id) => {
2279                     if let Some(ns) = defkind.ns() {
2280                         collect_fn(&child.ident, ns, def_id);
2281                     }
2282
2283                     if seen_defs.insert(def_id) {
2284                         queue.push(def_id);
2285                     }
2286                 }
2287                 _ => {}
2288             }
2289         }
2290     }
2291 }
2292
2293 /// The purpose of this function is to collect public symbols names that are unique across all
2294 /// crates in the build. Later, when printing about types we can use those names instead of the
2295 /// full exported path to them.
2296 ///
2297 /// So essentially, if a symbol name can only be imported from one place for a type, and as
2298 /// long as it was not glob-imported anywhere in the current crate, we can trim its printed
2299 /// path and print only the name.
2300 ///
2301 /// This has wide implications on error messages with types, for example, shortening
2302 /// `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable anywhere.
2303 ///
2304 /// The implementation uses similar import discovery logic to that of 'use' suggestions.
2305 fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
2306     let mut map = FxHashMap::default();
2307
2308     if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths {
2309         // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
2310         // wrapper can be used to suppress this query, in exchange for full paths being formatted.
2311         tcx.sess.delay_good_path_bug("trimmed_def_paths constructed");
2312     }
2313
2314     let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
2315         &mut FxHashMap::default();
2316
2317     for symbol_set in tcx.glob_map.values() {
2318         for symbol in symbol_set {
2319             unique_symbols_rev.insert((Namespace::TypeNS, *symbol), None);
2320             unique_symbols_rev.insert((Namespace::ValueNS, *symbol), None);
2321             unique_symbols_rev.insert((Namespace::MacroNS, *symbol), None);
2322         }
2323     }
2324
2325     for_each_def(tcx, |ident, ns, def_id| {
2326         use std::collections::hash_map::Entry::{Occupied, Vacant};
2327
2328         match unique_symbols_rev.entry((ns, ident.name)) {
2329             Occupied(mut v) => match v.get() {
2330                 None => {}
2331                 Some(existing) => {
2332                     if *existing != def_id {
2333                         v.insert(None);
2334                     }
2335                 }
2336             },
2337             Vacant(v) => {
2338                 v.insert(Some(def_id));
2339             }
2340         }
2341     });
2342
2343     for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() {
2344         if let Some(def_id) = opt_def_id {
2345             map.insert(def_id, symbol);
2346         }
2347     }
2348
2349     map
2350 }
2351
2352 pub fn provide(providers: &mut ty::query::Providers) {
2353     *providers = ty::query::Providers { trimmed_def_paths, ..*providers };
2354 }