]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/print/pretty.rs
Rollup merge of #61107 - blkerby:docs_typos, r=Centril
[rust.git] / src / librustc / ty / print / pretty.rs
1 use crate::hir;
2 use crate::hir::def::Namespace;
3 use crate::hir::map::{DefPathData, DisambiguatedDefPathData};
4 use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
5 use crate::middle::cstore::{ExternCrate, ExternCrateSource};
6 use crate::middle::region;
7 use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
8 use crate::ty::subst::{Kind, Subst, UnpackedKind};
9 use crate::mir::interpret::ConstValue;
10 use rustc_target::spec::abi::Abi;
11 use syntax::symbol::{kw, InternedString};
12
13 use std::cell::Cell;
14 use std::fmt::{self, Write as _};
15 use std::ops::{Deref, DerefMut};
16
17 // `pretty` is a separate module only for organization.
18 use super::*;
19
20 macro_rules! p {
21     (@write($($data:expr),+)) => {
22         write!(scoped_cx!(), $($data),+)?
23     };
24     (@print($x:expr)) => {
25         scoped_cx!() = $x.print(scoped_cx!())?
26     };
27     (@$method:ident($($arg:expr),*)) => {
28         scoped_cx!() = scoped_cx!().$method($($arg),*)?
29     };
30     ($($kind:ident $data:tt),+) => {{
31         $(p!(@$kind $data);)+
32     }};
33 }
34 macro_rules! define_scoped_cx {
35     ($cx:ident) => {
36         #[allow(unused_macros)]
37         macro_rules! scoped_cx {
38             () => ($cx)
39         }
40     };
41 }
42
43 thread_local! {
44     static FORCE_IMPL_FILENAME_LINE: Cell<bool> = Cell::new(false);
45     static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = Cell::new(false);
46 }
47
48 /// Force us to name impls with just the filename/line number. We
49 /// normally try to use types. But at some points, notably while printing
50 /// cycle errors, this can result in extra or suboptimal error output,
51 /// so this variable disables that check.
52 pub fn with_forced_impl_filename_line<F: FnOnce() -> R, R>(f: F) -> R {
53     FORCE_IMPL_FILENAME_LINE.with(|force| {
54         let old = force.get();
55         force.set(true);
56         let result = f();
57         force.set(old);
58         result
59     })
60 }
61
62 /// Adds the `crate::` prefix to paths where appropriate.
63 pub fn with_crate_prefix<F: FnOnce() -> R, R>(f: F) -> R {
64     SHOULD_PREFIX_WITH_CRATE.with(|flag| {
65         let old = flag.get();
66         flag.set(true);
67         let result = f();
68         flag.set(old);
69         result
70     })
71 }
72
73 /// The "region highlights" are used to control region printing during
74 /// specific error messages. When a "region highlight" is enabled, it
75 /// gives an alternate way to print specific regions. For now, we
76 /// always print those regions using a number, so something like "`'0`".
77 ///
78 /// Regions not selected by the region highlight mode are presently
79 /// unaffected.
80 #[derive(Copy, Clone, Default)]
81 pub struct RegionHighlightMode {
82     /// If enabled, when we see the selected region, use "`'N`"
83     /// instead of the ordinary behavior.
84     highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
85
86     /// If enabled, when printing a "free region" that originated from
87     /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
88     /// have names print as normal.
89     ///
90     /// This is used when you have a signature like `fn foo(x: &u32,
91     /// y: &'a u32)` and we want to give a name to the region of the
92     /// reference `x`.
93     highlight_bound_region: Option<(ty::BoundRegion, usize)>,
94 }
95
96 impl RegionHighlightMode {
97     /// If `region` and `number` are both `Some`, invokes
98     /// `highlighting_region`.
99     pub fn maybe_highlighting_region(
100         &mut self,
101         region: Option<ty::Region<'_>>,
102         number: Option<usize>,
103     ) {
104         if let Some(k) = region {
105             if let Some(n) = number {
106                 self.highlighting_region(k, n);
107             }
108         }
109     }
110
111     /// Highlights the region inference variable `vid` as `'N`.
112     pub fn highlighting_region(
113         &mut self,
114         region: ty::Region<'_>,
115         number: usize,
116     ) {
117         let num_slots = self.highlight_regions.len();
118         let first_avail_slot = self.highlight_regions.iter_mut()
119             .filter(|s| s.is_none())
120             .next()
121             .unwrap_or_else(|| {
122                 bug!(
123                     "can only highlight {} placeholders at a time",
124                     num_slots,
125                 )
126             });
127         *first_avail_slot = Some((*region, number));
128     }
129
130     /// Convenience wrapper for `highlighting_region`.
131     pub fn highlighting_region_vid(
132         &mut self,
133         vid: ty::RegionVid,
134         number: usize,
135     ) {
136         self.highlighting_region(&ty::ReVar(vid), number)
137     }
138
139     /// Returns `Some(n)` with the number to use for the given region, if any.
140     fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
141         self
142             .highlight_regions
143             .iter()
144             .filter_map(|h| match h {
145                 Some((r, n)) if r == region => Some(*n),
146                 _ => None,
147             })
148             .next()
149     }
150
151     /// Highlight the given bound region.
152     /// We can only highlight one bound region at a time. See
153     /// the field `highlight_bound_region` for more detailed notes.
154     pub fn highlighting_bound_region(
155         &mut self,
156         br: ty::BoundRegion,
157         number: usize,
158     ) {
159         assert!(self.highlight_bound_region.is_none());
160         self.highlight_bound_region = Some((br, number));
161     }
162 }
163
164 /// Trait for printers that pretty-print using `fmt::Write` to the printer.
165 pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
166     Printer<'gcx, 'tcx,
167         Error = fmt::Error,
168         Path = Self,
169         Region = Self,
170         Type = Self,
171         DynExistential = Self,
172     > +
173     fmt::Write
174 {
175     /// Like `print_def_path` but for value paths.
176     fn print_value_path(
177         self,
178         def_id: DefId,
179         substs: &'tcx [Kind<'tcx>],
180     ) -> Result<Self::Path, Self::Error> {
181         self.print_def_path(def_id, substs)
182     }
183
184     fn in_binder<T>(
185         self,
186         value: &ty::Binder<T>,
187     ) -> Result<Self, Self::Error>
188         where T: Print<'gcx, 'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>
189     {
190         value.skip_binder().print(self)
191     }
192
193     /// Print comma-separated elements.
194     fn comma_sep<T>(
195         mut self,
196         mut elems: impl Iterator<Item = T>,
197     ) -> Result<Self, Self::Error>
198         where T: Print<'gcx, 'tcx, Self, Output = Self, Error = Self::Error>
199     {
200         if let Some(first) = elems.next() {
201             self = first.print(self)?;
202             for elem in elems {
203                 self.write_str(", ")?;
204                 self = elem.print(self)?;
205             }
206         }
207         Ok(self)
208     }
209
210     /// Print `<...>` around what `f` prints.
211     fn generic_delimiters(
212         self,
213         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
214     ) -> Result<Self, Self::Error>;
215
216     /// Return `true` if the region should be printed in
217     /// optional positions, e.g. `&'a T` or `dyn Tr + 'b`.
218     /// This is typically the case for all non-`'_` regions.
219     fn region_should_not_be_omitted(
220         &self,
221         region: ty::Region<'_>,
222     ) -> bool;
223
224     // Defaults (should not be overriden):
225
226     /// If possible, this returns a global path resolving to `def_id` that is visible
227     /// from at least one local module and returns true. If the crate defining `def_id` is
228     /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
229     fn try_print_visible_def_path(
230         mut self,
231         def_id: DefId,
232     ) -> Result<(Self, bool), Self::Error> {
233         define_scoped_cx!(self);
234
235         debug!("try_print_visible_def_path: def_id={:?}", def_id);
236
237         // If `def_id` is a direct or injected extern crate, return the
238         // path to the crate followed by the path to the item within the crate.
239         if def_id.index == CRATE_DEF_INDEX {
240             let cnum = def_id.krate;
241
242             if cnum == LOCAL_CRATE {
243                 return Ok((self.path_crate(cnum)?, true));
244             }
245
246             // In local mode, when we encounter a crate other than
247             // LOCAL_CRATE, execution proceeds in one of two ways:
248             //
249             // 1. for a direct dependency, where user added an
250             //    `extern crate` manually, we put the `extern
251             //    crate` as the parent. So you wind up with
252             //    something relative to the current crate.
253             // 2. for an extern inferred from a path or an indirect crate,
254             //    where there is no explicit `extern crate`, we just prepend
255             //    the crate name.
256             match self.tcx().extern_crate(def_id) {
257                 Some(&ExternCrate {
258                     src: ExternCrateSource::Extern(def_id),
259                     direct: true,
260                     span,
261                     ..
262                 }) => {
263                     debug!("try_print_visible_def_path: def_id={:?}", def_id);
264                     return Ok((if !span.is_dummy() {
265                         self.print_def_path(def_id, &[])?
266                     } else {
267                         self.path_crate(cnum)?
268                     }, true));
269                 }
270                 None => {
271                     return Ok((self.path_crate(cnum)?, true));
272                 }
273                 _ => {},
274             }
275         }
276
277         if def_id.is_local() {
278             return Ok((self, false));
279         }
280
281         let visible_parent_map = self.tcx().visible_parent_map(LOCAL_CRATE);
282
283         let mut cur_def_key = self.tcx().def_key(def_id);
284         debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
285
286         // For a constructor we want the name of its parent rather than <unnamed>.
287         match cur_def_key.disambiguated_data.data {
288             DefPathData::Ctor => {
289                 let parent = DefId {
290                     krate: def_id.krate,
291                     index: cur_def_key.parent
292                         .expect("DefPathData::Ctor/VariantData missing a parent"),
293                 };
294
295                 cur_def_key = self.tcx().def_key(parent);
296             },
297             _ => {},
298         }
299
300         let visible_parent = match visible_parent_map.get(&def_id).cloned() {
301             Some(parent) => parent,
302             None => return Ok((self, false)),
303         };
304         // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid
305         // knowing ahead of time whether the entire path will succeed or not.
306         // To support printers that do not implement `PrettyPrinter`, a `Vec` or
307         // linked list on the stack would need to be built, before any printing.
308         match self.try_print_visible_def_path(visible_parent)? {
309             (cx, false) => return Ok((cx, false)),
310             (cx, true) => self = cx,
311         }
312         let actual_parent = self.tcx().parent(def_id);
313         debug!(
314             "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}",
315             visible_parent, actual_parent,
316         );
317
318         let mut data = cur_def_key.disambiguated_data.data;
319         debug!(
320             "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
321             data, visible_parent, actual_parent,
322         );
323
324         match data {
325             // In order to output a path that could actually be imported (valid and visible),
326             // we need to handle re-exports correctly.
327             //
328             // For example, take `std::os::unix::process::CommandExt`, this trait is actually
329             // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
330             //
331             // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is
332             // private so the "true" path to `CommandExt` isn't accessible.
333             //
334             // In this case, the `visible_parent_map` will look something like this:
335             //
336             // (child) -> (parent)
337             // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
338             // `std::sys::unix::ext::process` -> `std::sys::unix::ext`
339             // `std::sys::unix::ext` -> `std::os`
340             //
341             // This is correct, as the visible parent of `std::sys::unix::ext` is in fact
342             // `std::os`.
343             //
344             // When printing the path to `CommandExt` and looking at the `cur_def_key` that
345             // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
346             // to the parent - resulting in a mangled path like
347             // `std::os::ext::process::CommandExt`.
348             //
349             // Instead, we must detect that there was a re-export and instead print `unix`
350             // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
351             // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
352             // the visible parent (`std::os`). If these do not match, then we iterate over
353             // the children of the visible parent (as was done when computing
354             // `visible_parent_map`), looking for the specific child we currently have and then
355             // have access to the re-exported name.
356             DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => {
357                 let reexport = self.tcx().item_children(visible_parent)
358                     .iter()
359                     .find(|child| child.res.def_id() == def_id)
360                     .map(|child| child.ident.as_interned_str());
361                 if let Some(reexport) = reexport {
362                     *name = reexport;
363                 }
364             }
365             // Re-exported `extern crate` (#43189).
366             DefPathData::CrateRoot => {
367                 data = DefPathData::TypeNs(
368                     self.tcx().original_crate_name(def_id.krate).as_interned_str(),
369                 );
370             }
371             _ => {}
372         }
373         debug!("try_print_visible_def_path: data={:?}", data);
374
375         Ok((self.path_append(Ok, &DisambiguatedDefPathData {
376             data,
377             disambiguator: 0,
378         })?, true))
379     }
380
381     fn pretty_path_qualified(
382         self,
383         self_ty: Ty<'tcx>,
384         trait_ref: Option<ty::TraitRef<'tcx>>,
385     ) -> Result<Self::Path, Self::Error> {
386         if trait_ref.is_none() {
387             // Inherent impls. Try to print `Foo::bar` for an inherent
388             // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
389             // anything other than a simple path.
390             match self_ty.sty {
391                 ty::Adt(..) | ty::Foreign(_) |
392                 ty::Bool | ty::Char | ty::Str |
393                 ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
394                     return self_ty.print(self);
395                 }
396
397                 _ => {}
398             }
399         }
400
401         self.generic_delimiters(|mut cx| {
402             define_scoped_cx!(cx);
403
404             p!(print(self_ty));
405             if let Some(trait_ref) = trait_ref {
406                 p!(write(" as "), print(trait_ref));
407             }
408             Ok(cx)
409         })
410     }
411
412     fn pretty_path_append_impl(
413         mut self,
414         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
415         self_ty: Ty<'tcx>,
416         trait_ref: Option<ty::TraitRef<'tcx>>,
417     ) -> Result<Self::Path, Self::Error> {
418         self = print_prefix(self)?;
419
420         self.generic_delimiters(|mut cx| {
421             define_scoped_cx!(cx);
422
423             p!(write("impl "));
424             if let Some(trait_ref) = trait_ref {
425                 p!(print(trait_ref), write(" for "));
426             }
427             p!(print(self_ty));
428
429             Ok(cx)
430         })
431     }
432
433     fn pretty_print_type(
434         mut self,
435         ty: Ty<'tcx>,
436     ) -> Result<Self::Type, Self::Error> {
437         define_scoped_cx!(self);
438
439         match ty.sty {
440             ty::Bool => p!(write("bool")),
441             ty::Char => p!(write("char")),
442             ty::Int(t) => p!(write("{}", t.ty_to_string())),
443             ty::Uint(t) => p!(write("{}", t.ty_to_string())),
444             ty::Float(t) => p!(write("{}", t.ty_to_string())),
445             ty::RawPtr(ref tm) => {
446                 p!(write("*{} ", match tm.mutbl {
447                     hir::MutMutable => "mut",
448                     hir::MutImmutable => "const",
449                 }));
450                 p!(print(tm.ty))
451             }
452             ty::Ref(r, ty, mutbl) => {
453                 p!(write("&"));
454                 if self.region_should_not_be_omitted(r) {
455                     p!(print(r), write(" "));
456                 }
457                 p!(print(ty::TypeAndMut { ty, mutbl }))
458             }
459             ty::Never => p!(write("!")),
460             ty::Tuple(ref tys) => {
461                 p!(write("("));
462                 let mut tys = tys.iter();
463                 if let Some(&ty) = tys.next() {
464                     p!(print(ty), write(","));
465                     if let Some(&ty) = tys.next() {
466                         p!(write(" "), print(ty));
467                         for &ty in tys {
468                             p!(write(", "), print(ty));
469                         }
470                     }
471                 }
472                 p!(write(")"))
473             }
474             ty::FnDef(def_id, substs) => {
475                 let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
476                 p!(print(sig), write(" {{"), print_value_path(def_id, substs), write("}}"));
477             }
478             ty::FnPtr(ref bare_fn) => {
479                 p!(print(bare_fn))
480             }
481             ty::Infer(infer_ty) => p!(write("{}", infer_ty)),
482             ty::Error => p!(write("[type error]")),
483             ty::Param(ref param_ty) => p!(write("{}", param_ty)),
484             ty::Bound(debruijn, bound_ty) => {
485                 match bound_ty.kind {
486                     ty::BoundTyKind::Anon => {
487                         if debruijn == ty::INNERMOST {
488                             p!(write("^{}", bound_ty.var.index()))
489                         } else {
490                             p!(write("^{}_{}", debruijn.index(), bound_ty.var.index()))
491                         }
492                     }
493
494                     ty::BoundTyKind::Param(p) => p!(write("{}", p)),
495                 }
496             }
497             ty::Adt(def, substs) => {
498                 p!(print_def_path(def.did, substs));
499             }
500             ty::Dynamic(data, r) => {
501                 let print_r = self.region_should_not_be_omitted(r);
502                 if print_r {
503                     p!(write("("));
504                 }
505                 p!(write("dyn "), print(data));
506                 if print_r {
507                     p!(write(" + "), print(r), write(")"));
508                 }
509             }
510             ty::Foreign(def_id) => {
511                 p!(print_def_path(def_id, &[]));
512             }
513             ty::Projection(ref data) => p!(print(data)),
514             ty::UnnormalizedProjection(ref data) => {
515                 p!(write("Unnormalized("), print(data), write(")"))
516             }
517             ty::Placeholder(placeholder) => {
518                 p!(write("Placeholder({:?})", placeholder))
519             }
520             ty::Opaque(def_id, substs) => {
521                 // FIXME(eddyb) print this with `print_def_path`.
522                 if self.tcx().sess.verbose() {
523                     p!(write("Opaque({:?}, {:?})", def_id, substs));
524                     return Ok(self);
525                 }
526
527                 let def_key = self.tcx().def_key(def_id);
528                 if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
529                     p!(write("{}", name));
530                     let mut substs = substs.iter();
531                     // FIXME(eddyb) print this with `print_def_path`.
532                     if let Some(first) = substs.next() {
533                         p!(write("::<"));
534                         p!(print(first));
535                         for subst in substs {
536                             p!(write(", "), print(subst));
537                         }
538                         p!(write(">"));
539                     }
540                     return Ok(self);
541                 }
542                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
543                 // by looking up the projections associated with the def_id.
544                 let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
545
546                 let mut first = true;
547                 let mut is_sized = false;
548                 p!(write("impl"));
549                 for predicate in bounds.predicates {
550                     if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
551                         // Don't print +Sized, but rather +?Sized if absent.
552                         if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
553                             is_sized = true;
554                             continue;
555                         }
556
557                         p!(
558                                 write("{}", if first { " " } else { "+" }),
559                                 print(trait_ref));
560                         first = false;
561                     }
562                 }
563                 if !is_sized {
564                     p!(write("{}?Sized", if first { " " } else { "+" }));
565                 } else if first {
566                     p!(write(" Sized"));
567                 }
568             }
569             ty::Str => p!(write("str")),
570             ty::Generator(did, substs, movability) => {
571                 let upvar_tys = substs.upvar_tys(did, self.tcx());
572                 let witness = substs.witness(did, self.tcx());
573                 if movability == hir::GeneratorMovability::Movable {
574                     p!(write("[generator"));
575                 } else {
576                     p!(write("[static generator"));
577                 }
578
579                 // FIXME(eddyb) should use `def_span`.
580                 if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) {
581                     p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_id)));
582                     let mut sep = " ";
583                     for (upvar, upvar_ty) in self.tcx().upvars(did)
584                         .as_ref()
585                         .map_or(&[][..], |v| &v[..])
586                         .iter()
587                         .zip(upvar_tys)
588                     {
589                         p!(
590                             write("{}{}:",
591                                     sep,
592                                     self.tcx().hir().name_by_hir_id(upvar.var_id())),
593                             print(upvar_ty));
594                         sep = ", ";
595                     }
596                 } else {
597                     // cross-crate closure types should only be
598                     // visible in codegen bug reports, I imagine.
599                     p!(write("@{:?}", did));
600                     let mut sep = " ";
601                     for (index, upvar_ty) in upvar_tys.enumerate() {
602                         p!(
603                                 write("{}{}:", sep, index),
604                                 print(upvar_ty));
605                         sep = ", ";
606                     }
607                 }
608
609                 p!(write(" "), print(witness), write("]"))
610             },
611             ty::GeneratorWitness(types) => {
612                 p!(in_binder(&types));
613             }
614             ty::Closure(did, substs) => {
615                 let upvar_tys = substs.upvar_tys(did, self.tcx());
616                 p!(write("[closure"));
617
618                 // FIXME(eddyb) should use `def_span`.
619                 if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) {
620                     if self.tcx().sess.opts.debugging_opts.span_free_formats {
621                         p!(write("@{:?}", hir_id));
622                     } else {
623                         p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_id)));
624                     }
625                     let mut sep = " ";
626                     for (upvar, upvar_ty) in self.tcx().upvars(did)
627                         .as_ref()
628                         .map_or(&[][..], |v| &v[..])
629                         .iter()
630                         .zip(upvar_tys)
631                     {
632                         p!(
633                             write("{}{}:",
634                                     sep,
635                                     self.tcx().hir().name_by_hir_id(upvar.var_id())),
636                             print(upvar_ty));
637                         sep = ", ";
638                     }
639                 } else {
640                     // cross-crate closure types should only be
641                     // visible in codegen bug reports, I imagine.
642                     p!(write("@{:?}", did));
643                     let mut sep = " ";
644                     for (index, upvar_ty) in upvar_tys.enumerate() {
645                         p!(
646                                 write("{}{}:", sep, index),
647                                 print(upvar_ty));
648                         sep = ", ";
649                     }
650                 }
651
652                 if self.tcx().sess.verbose() {
653                     p!(write(
654                         " closure_kind_ty={:?} closure_sig_ty={:?}",
655                         substs.closure_kind_ty(did, self.tcx()),
656                         substs.closure_sig_ty(did, self.tcx())
657                     ));
658                 }
659
660                 p!(write("]"))
661             },
662             ty::Array(ty, sz) => {
663                 p!(write("["), print(ty), write("; "));
664                 match sz.val {
665                     ConstValue::Unevaluated(..) |
666                     ConstValue::Infer(..) => p!(write("_")),
667                     ConstValue::Param(ParamConst { name, .. }) =>
668                         p!(write("{}", name)),
669                     _ => p!(write("{}", sz.unwrap_usize(self.tcx()))),
670                 }
671                 p!(write("]"))
672             }
673             ty::Slice(ty) => {
674                 p!(write("["), print(ty), write("]"))
675             }
676         }
677
678         Ok(self)
679     }
680
681     fn pretty_print_dyn_existential(
682         mut self,
683         predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
684     ) -> Result<Self::DynExistential, Self::Error> {
685         define_scoped_cx!(self);
686
687         // Generate the main trait ref, including associated types.
688         let mut first = true;
689
690         if let Some(principal) = predicates.principal() {
691             p!(print_def_path(principal.def_id, &[]));
692
693             let mut resugared = false;
694
695             // Special-case `Fn(...) -> ...` and resugar it.
696             let fn_trait_kind = self.tcx().lang_items().fn_trait_kind(principal.def_id);
697             if !self.tcx().sess.verbose() && fn_trait_kind.is_some() {
698                 if let ty::Tuple(ref args) = principal.substs.type_at(0).sty {
699                     let mut projections = predicates.projection_bounds();
700                     if let (Some(proj), None) = (projections.next(), projections.next()) {
701                         let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect();
702                         p!(pretty_fn_sig(&tys, false, proj.ty));
703                         resugared = true;
704                     }
705                 }
706             }
707
708             // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
709             // in order to place the projections inside the `<...>`.
710             if !resugared {
711                 // Use a type that can't appear in defaults of type parameters.
712                 let dummy_self = self.tcx().mk_ty_infer(ty::FreshTy(0));
713                 let principal = principal.with_self_ty(self.tcx(), dummy_self);
714
715                 let args = self.generic_args_to_print(
716                     self.tcx().generics_of(principal.def_id),
717                     principal.substs,
718                 );
719
720                 // Don't print `'_` if there's no unerased regions.
721                 let print_regions = args.iter().any(|arg| {
722                     match arg.unpack() {
723                         UnpackedKind::Lifetime(r) => *r != ty::ReErased,
724                         _ => false,
725                     }
726                 });
727                 let mut args = args.iter().cloned().filter(|arg| {
728                     match arg.unpack() {
729                         UnpackedKind::Lifetime(_) => print_regions,
730                         _ => true,
731                     }
732                 });
733                 let mut projections = predicates.projection_bounds();
734
735                 let arg0 = args.next();
736                 let projection0 = projections.next();
737                 if arg0.is_some() || projection0.is_some() {
738                     let args = arg0.into_iter().chain(args);
739                     let projections = projection0.into_iter().chain(projections);
740
741                     p!(generic_delimiters(|mut cx| {
742                         cx = cx.comma_sep(args)?;
743                         if arg0.is_some() && projection0.is_some() {
744                             write!(cx, ", ")?;
745                         }
746                         cx.comma_sep(projections)
747                     }));
748                 }
749             }
750             first = false;
751         }
752
753         // Builtin bounds.
754         // FIXME(eddyb) avoid printing twice (needed to ensure
755         // that the auto traits are sorted *and* printed via cx).
756         let mut auto_traits: Vec<_> = predicates.auto_traits().map(|did| {
757             (self.tcx().def_path_str(did), did)
758         }).collect();
759
760         // The auto traits come ordered by `DefPathHash`. While
761         // `DefPathHash` is *stable* in the sense that it depends on
762         // neither the host nor the phase of the moon, it depends
763         // "pseudorandomly" on the compiler version and the target.
764         //
765         // To avoid that causing instabilities in compiletest
766         // output, sort the auto-traits alphabetically.
767         auto_traits.sort();
768
769         for (_, def_id) in auto_traits {
770             if !first {
771                 p!(write(" + "));
772             }
773             first = false;
774
775             p!(print_def_path(def_id, &[]));
776         }
777
778         Ok(self)
779     }
780
781     fn pretty_fn_sig(
782         mut self,
783         inputs: &[Ty<'tcx>],
784         c_variadic: bool,
785         output: Ty<'tcx>,
786     ) -> Result<Self, Self::Error> {
787         define_scoped_cx!(self);
788
789         p!(write("("));
790         let mut inputs = inputs.iter();
791         if let Some(&ty) = inputs.next() {
792             p!(print(ty));
793             for &ty in inputs {
794                 p!(write(", "), print(ty));
795             }
796             if c_variadic {
797                 p!(write(", ..."));
798             }
799         }
800         p!(write(")"));
801         if !output.is_unit() {
802             p!(write(" -> "), print(output));
803         }
804
805         Ok(self)
806     }
807 }
808
809 // HACK(eddyb) boxed to avoid moving around a large struct by-value.
810 pub struct FmtPrinter<'a, 'gcx, 'tcx, F>(Box<FmtPrinterData<'a, 'gcx, 'tcx, F>>);
811
812 pub struct FmtPrinterData<'a, 'gcx, 'tcx, F> {
813     tcx: TyCtxt<'a, 'gcx, 'tcx>,
814     fmt: F,
815
816     empty_path: bool,
817     in_value: bool,
818
819     used_region_names: FxHashSet<InternedString>,
820     region_index: usize,
821     binder_depth: usize,
822
823     pub region_highlight_mode: RegionHighlightMode,
824 }
825
826 impl<F> Deref for FmtPrinter<'a, 'gcx, 'tcx, F> {
827     type Target = FmtPrinterData<'a, 'gcx, 'tcx, F>;
828     fn deref(&self) -> &Self::Target {
829         &self.0
830     }
831 }
832
833 impl<F> DerefMut for FmtPrinter<'_, '_, '_, F> {
834     fn deref_mut(&mut self) -> &mut Self::Target {
835         &mut self.0
836     }
837 }
838
839 impl<F> FmtPrinter<'a, 'gcx, 'tcx, F> {
840     pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, fmt: F, ns: Namespace) -> Self {
841         FmtPrinter(Box::new(FmtPrinterData {
842             tcx,
843             fmt,
844             empty_path: false,
845             in_value: ns == Namespace::ValueNS,
846             used_region_names: Default::default(),
847             region_index: 0,
848             binder_depth: 0,
849             region_highlight_mode: RegionHighlightMode::default(),
850         }))
851     }
852 }
853
854 impl TyCtxt<'_, '_, '_> {
855     // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
856     // (but also some things just print a `DefId` generally so maybe we need this?)
857     fn guess_def_namespace(self, def_id: DefId) -> Namespace {
858         match self.def_key(def_id).disambiguated_data.data {
859             DefPathData::TypeNs(..)
860             | DefPathData::CrateRoot
861             | DefPathData::ImplTrait => Namespace::TypeNS,
862
863             DefPathData::ValueNs(..)
864             | DefPathData::AnonConst
865             | DefPathData::ClosureExpr
866             | DefPathData::Ctor => Namespace::ValueNS,
867
868             DefPathData::MacroNs(..) => Namespace::MacroNS,
869
870             _ => Namespace::TypeNS,
871         }
872     }
873
874     /// Returns a string identifying this `DefId`. This string is
875     /// suitable for user output.
876     pub fn def_path_str(self, def_id: DefId) -> String {
877         let ns = self.guess_def_namespace(def_id);
878         debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
879         let mut s = String::new();
880         let _ = FmtPrinter::new(self, &mut s, ns)
881             .print_def_path(def_id, &[]);
882         s
883     }
884 }
885
886 impl<F: fmt::Write> fmt::Write for FmtPrinter<'_, '_, '_, F> {
887     fn write_str(&mut self, s: &str) -> fmt::Result {
888         self.fmt.write_str(s)
889     }
890 }
891
892 impl<F: fmt::Write> Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
893     type Error = fmt::Error;
894
895     type Path = Self;
896     type Region = Self;
897     type Type = Self;
898     type DynExistential = Self;
899
900     fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
901         self.tcx
902     }
903
904     fn print_def_path(
905         mut self,
906         def_id: DefId,
907         substs: &'tcx [Kind<'tcx>],
908     ) -> Result<Self::Path, Self::Error> {
909         define_scoped_cx!(self);
910
911         if substs.is_empty() {
912             match self.try_print_visible_def_path(def_id)? {
913                 (cx, true) => return Ok(cx),
914                 (cx, false) => self = cx,
915             }
916         }
917
918         let key = self.tcx.def_key(def_id);
919         if let DefPathData::Impl = key.disambiguated_data.data {
920             // Always use types for non-local impls, where types are always
921             // available, and filename/line-number is mostly uninteresting.
922             let use_types =
923                 !def_id.is_local() || {
924                     // Otherwise, use filename/line-number if forced.
925                     let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
926                     !force_no_types
927                 };
928
929             if !use_types {
930                 // If no type info is available, fall back to
931                 // pretty printing some span information. This should
932                 // only occur very early in the compiler pipeline.
933                 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
934                 let span = self.tcx.def_span(def_id);
935
936                 self = self.print_def_path(parent_def_id, &[])?;
937
938                 // HACK(eddyb) copy of `path_append` to avoid
939                 // constructing a `DisambiguatedDefPathData`.
940                 if !self.empty_path {
941                     write!(self, "::")?;
942                 }
943                 write!(self, "<impl at {:?}>", span)?;
944                 self.empty_path = false;
945
946                 return Ok(self);
947             }
948         }
949
950         self.default_print_def_path(def_id, substs)
951     }
952
953     fn print_region(
954         self,
955         region: ty::Region<'_>,
956     ) -> Result<Self::Region, Self::Error> {
957         self.pretty_print_region(region)
958     }
959
960     fn print_type(
961         self,
962         ty: Ty<'tcx>,
963     ) -> Result<Self::Type, Self::Error> {
964         self.pretty_print_type(ty)
965     }
966
967     fn print_dyn_existential(
968         self,
969         predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
970     ) -> Result<Self::DynExistential, Self::Error> {
971         self.pretty_print_dyn_existential(predicates)
972     }
973
974     fn path_crate(
975         mut self,
976         cnum: CrateNum,
977     ) -> Result<Self::Path, Self::Error> {
978         self.empty_path = true;
979         if cnum == LOCAL_CRATE {
980             if self.tcx.sess.rust_2018() {
981                 // We add the `crate::` keyword on Rust 2018, only when desired.
982                 if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
983                     write!(self, "{}", kw::Crate)?;
984                     self.empty_path = false;
985                 }
986             }
987         } else {
988             write!(self, "{}", self.tcx.crate_name(cnum))?;
989             self.empty_path = false;
990         }
991         Ok(self)
992     }
993     fn path_qualified(
994         mut self,
995         self_ty: Ty<'tcx>,
996         trait_ref: Option<ty::TraitRef<'tcx>>,
997     ) -> Result<Self::Path, Self::Error> {
998         self = self.pretty_path_qualified(self_ty, trait_ref)?;
999         self.empty_path = false;
1000         Ok(self)
1001     }
1002
1003     fn path_append_impl(
1004         mut self,
1005         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
1006         _disambiguated_data: &DisambiguatedDefPathData,
1007         self_ty: Ty<'tcx>,
1008         trait_ref: Option<ty::TraitRef<'tcx>>,
1009     ) -> Result<Self::Path, Self::Error> {
1010         self = self.pretty_path_append_impl(|mut cx| {
1011             cx = print_prefix(cx)?;
1012             if !cx.empty_path {
1013                 write!(cx, "::")?;
1014             }
1015
1016             Ok(cx)
1017         }, self_ty, trait_ref)?;
1018         self.empty_path = false;
1019         Ok(self)
1020     }
1021     fn path_append(
1022         mut self,
1023         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
1024         disambiguated_data: &DisambiguatedDefPathData,
1025     ) -> Result<Self::Path, Self::Error> {
1026         self = print_prefix(self)?;
1027
1028         // Skip `::{{constructor}}` on tuple/unit structs.
1029         match disambiguated_data.data {
1030             DefPathData::Ctor => return Ok(self),
1031             _ => {}
1032         }
1033
1034         // FIXME(eddyb) `name` should never be empty, but it
1035         // currently is for `extern { ... }` "foreign modules".
1036         let name = disambiguated_data.data.as_interned_str().as_str();
1037         if !name.is_empty() {
1038             if !self.empty_path {
1039                 write!(self, "::")?;
1040             }
1041             write!(self, "{}", name)?;
1042
1043             // FIXME(eddyb) this will print e.g. `{{closure}}#3`, but it
1044             // might be nicer to use something else, e.g. `{closure#3}`.
1045             let dis = disambiguated_data.disambiguator;
1046             let print_dis =
1047                 disambiguated_data.data.get_opt_name().is_none() ||
1048                 dis != 0 && self.tcx.sess.verbose();
1049             if print_dis {
1050                 write!(self, "#{}", dis)?;
1051             }
1052
1053             self.empty_path = false;
1054         }
1055
1056         Ok(self)
1057     }
1058     fn path_generic_args(
1059         mut self,
1060         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
1061         args: &[Kind<'tcx>],
1062     ) -> Result<Self::Path, Self::Error> {
1063         self = print_prefix(self)?;
1064
1065         // Don't print `'_` if there's no unerased regions.
1066         let print_regions = args.iter().any(|arg| {
1067             match arg.unpack() {
1068                 UnpackedKind::Lifetime(r) => *r != ty::ReErased,
1069                 _ => false,
1070             }
1071         });
1072         let args = args.iter().cloned().filter(|arg| {
1073             match arg.unpack() {
1074                 UnpackedKind::Lifetime(_) => print_regions,
1075                 _ => true,
1076             }
1077         });
1078
1079         if args.clone().next().is_some() {
1080             if self.in_value {
1081                 write!(self, "::")?;
1082             }
1083             self.generic_delimiters(|cx| cx.comma_sep(args))
1084         } else {
1085             Ok(self)
1086         }
1087     }
1088 }
1089
1090 impl<F: fmt::Write> PrettyPrinter<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
1091     fn print_value_path(
1092         mut self,
1093         def_id: DefId,
1094         substs: &'tcx [Kind<'tcx>],
1095     ) -> Result<Self::Path, Self::Error> {
1096         let was_in_value = std::mem::replace(&mut self.in_value, true);
1097         self = self.print_def_path(def_id, substs)?;
1098         self.in_value = was_in_value;
1099
1100         Ok(self)
1101     }
1102
1103     fn in_binder<T>(
1104         self,
1105         value: &ty::Binder<T>,
1106     ) -> Result<Self, Self::Error>
1107         where T: Print<'gcx, 'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>
1108     {
1109         self.pretty_in_binder(value)
1110     }
1111
1112     fn generic_delimiters(
1113         mut self,
1114         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
1115     ) -> Result<Self, Self::Error> {
1116         write!(self, "<")?;
1117
1118         let was_in_value = std::mem::replace(&mut self.in_value, false);
1119         let mut inner = f(self)?;
1120         inner.in_value = was_in_value;
1121
1122         write!(inner, ">")?;
1123         Ok(inner)
1124     }
1125
1126     fn region_should_not_be_omitted(
1127         &self,
1128         region: ty::Region<'_>,
1129     ) -> bool {
1130         let highlight = self.region_highlight_mode;
1131         if highlight.region_highlighted(region).is_some() {
1132             return true;
1133         }
1134
1135         if self.tcx.sess.verbose() {
1136             return true;
1137         }
1138
1139         let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions;
1140
1141         match *region {
1142             ty::ReEarlyBound(ref data) => {
1143                 data.name.as_symbol() != kw::Invalid &&
1144                 data.name.as_symbol() != kw::UnderscoreLifetime
1145             }
1146
1147             ty::ReLateBound(_, br) |
1148             ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
1149             ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
1150                 if let ty::BrNamed(_, name) = br {
1151                     if name.as_symbol() != kw::Invalid &&
1152                        name.as_symbol() != kw::UnderscoreLifetime {
1153                         return true;
1154                     }
1155                 }
1156
1157                 if let Some((region, _)) = highlight.highlight_bound_region {
1158                     if br == region {
1159                         return true;
1160                     }
1161                 }
1162
1163                 false
1164             }
1165
1166             ty::ReScope(_) |
1167             ty::ReVar(_) if identify_regions => true,
1168
1169             ty::ReVar(_) |
1170             ty::ReScope(_) |
1171             ty::ReErased => false,
1172
1173             ty::ReStatic |
1174             ty::ReEmpty |
1175             ty::ReClosureBound(_) => true,
1176         }
1177     }
1178 }
1179
1180 // HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
1181 impl<F: fmt::Write> FmtPrinter<'_, '_, '_, F> {
1182     pub fn pretty_print_region(
1183         mut self,
1184         region: ty::Region<'_>,
1185     ) -> Result<Self, fmt::Error> {
1186         define_scoped_cx!(self);
1187
1188         // Watch out for region highlights.
1189         let highlight = self.region_highlight_mode;
1190         if let Some(n) = highlight.region_highlighted(region) {
1191             p!(write("'{}", n));
1192             return Ok(self);
1193         }
1194
1195         if self.tcx.sess.verbose() {
1196             p!(write("{:?}", region));
1197             return Ok(self);
1198         }
1199
1200         let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions;
1201
1202         // These printouts are concise.  They do not contain all the information
1203         // the user might want to diagnose an error, but there is basically no way
1204         // to fit that into a short string.  Hence the recommendation to use
1205         // `explain_region()` or `note_and_explain_region()`.
1206         match *region {
1207             ty::ReEarlyBound(ref data) => {
1208                 if data.name.as_symbol() != kw::Invalid {
1209                     p!(write("{}", data.name));
1210                     return Ok(self);
1211                 }
1212             }
1213             ty::ReLateBound(_, br) |
1214             ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
1215             ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
1216                 if let ty::BrNamed(_, name) = br {
1217                     if name.as_symbol() != kw::Invalid &&
1218                        name.as_symbol() != kw::UnderscoreLifetime {
1219                         p!(write("{}", name));
1220                         return Ok(self);
1221                     }
1222                 }
1223
1224                 if let Some((region, counter)) = highlight.highlight_bound_region {
1225                     if br == region {
1226                         p!(write("'{}", counter));
1227                         return Ok(self);
1228                     }
1229                 }
1230             }
1231             ty::ReScope(scope) if identify_regions => {
1232                 match scope.data {
1233                     region::ScopeData::Node =>
1234                         p!(write("'{}s", scope.item_local_id().as_usize())),
1235                     region::ScopeData::CallSite =>
1236                         p!(write("'{}cs", scope.item_local_id().as_usize())),
1237                     region::ScopeData::Arguments =>
1238                         p!(write("'{}as", scope.item_local_id().as_usize())),
1239                     region::ScopeData::Destruction =>
1240                         p!(write("'{}ds", scope.item_local_id().as_usize())),
1241                     region::ScopeData::Remainder(first_statement_index) => p!(write(
1242                         "'{}_{}rs",
1243                         scope.item_local_id().as_usize(),
1244                         first_statement_index.index()
1245                     )),
1246                 }
1247                 return Ok(self);
1248             }
1249             ty::ReVar(region_vid) if identify_regions => {
1250                 p!(write("{:?}", region_vid));
1251                 return Ok(self);
1252             }
1253             ty::ReVar(_) => {}
1254             ty::ReScope(_) |
1255             ty::ReErased => {}
1256             ty::ReStatic => {
1257                 p!(write("'static"));
1258                 return Ok(self);
1259             }
1260             ty::ReEmpty => {
1261                 p!(write("'<empty>"));
1262                 return Ok(self);
1263             }
1264
1265             // The user should never encounter these in unsubstituted form.
1266             ty::ReClosureBound(vid) => {
1267                 p!(write("{:?}", vid));
1268                 return Ok(self);
1269             }
1270         }
1271
1272         p!(write("'_"));
1273
1274         Ok(self)
1275     }
1276 }
1277
1278 // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
1279 // `region_index` and `used_region_names`.
1280 impl<F: fmt::Write> FmtPrinter<'_, 'gcx, 'tcx, F> {
1281     pub fn pretty_in_binder<T>(
1282         mut self,
1283         value: &ty::Binder<T>,
1284     ) -> Result<Self, fmt::Error>
1285         where T: Print<'gcx, 'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>
1286     {
1287         fn name_by_region_index(index: usize) -> InternedString {
1288             match index {
1289                 0 => InternedString::intern("'r"),
1290                 1 => InternedString::intern("'s"),
1291                 i => InternedString::intern(&format!("'t{}", i-2)),
1292             }
1293         }
1294
1295         // Replace any anonymous late-bound regions with named
1296         // variants, using gensym'd identifiers, so that we can
1297         // clearly differentiate between named and unnamed regions in
1298         // the output. We'll probably want to tweak this over time to
1299         // decide just how much information to give.
1300         if self.binder_depth == 0 {
1301             self.prepare_late_bound_region_info(value);
1302         }
1303
1304         let mut empty = true;
1305         let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
1306             write!(cx, "{}", if empty {
1307                 empty = false;
1308                 start
1309             } else {
1310                 cont
1311             })
1312         };
1313
1314         define_scoped_cx!(self);
1315
1316         let old_region_index = self.region_index;
1317         let mut region_index = old_region_index;
1318         let new_value = self.tcx.replace_late_bound_regions(value, |br| {
1319             let _ = start_or_continue(&mut self, "for<", ", ");
1320             let br = match br {
1321                 ty::BrNamed(_, name) => {
1322                     let _ = write!(self, "{}", name);
1323                     br
1324                 }
1325                 ty::BrAnon(_) |
1326                 ty::BrFresh(_) |
1327                 ty::BrEnv => {
1328                     let name = loop {
1329                         let name = name_by_region_index(region_index);
1330                         region_index += 1;
1331                         if !self.used_region_names.contains(&name) {
1332                             break name;
1333                         }
1334                     };
1335                     let _ = write!(self, "{}", name);
1336                     ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
1337                 }
1338             };
1339             self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
1340         }).0;
1341         start_or_continue(&mut self, "", "> ")?;
1342
1343         self.binder_depth += 1;
1344         self.region_index = region_index;
1345         let mut inner = new_value.print(self)?;
1346         inner.region_index = old_region_index;
1347         inner.binder_depth -= 1;
1348         Ok(inner)
1349     }
1350
1351     fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<T>)
1352         where T: TypeFoldable<'tcx>
1353     {
1354
1355         struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<InternedString>);
1356         impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> {
1357             fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
1358                 match *r {
1359                     ty::ReLateBound(_, ty::BrNamed(_, name)) => {
1360                         self.0.insert(name);
1361                     },
1362                     _ => {},
1363                 }
1364                 r.super_visit_with(self)
1365             }
1366         }
1367
1368         self.used_region_names.clear();
1369         let mut collector = LateBoundRegionNameCollector(&mut self.used_region_names);
1370         value.visit_with(&mut collector);
1371         self.region_index = 0;
1372     }
1373 }
1374
1375 impl<'gcx: 'tcx, 'tcx, T, P: PrettyPrinter<'gcx, 'tcx>> Print<'gcx, 'tcx, P>
1376     for ty::Binder<T>
1377     where T: Print<'gcx, 'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx>
1378 {
1379     type Output = P;
1380     type Error = P::Error;
1381     fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
1382         cx.in_binder(self)
1383     }
1384 }
1385
1386 impl<'gcx: 'tcx, 'tcx, T, U, P: PrettyPrinter<'gcx, 'tcx>> Print<'gcx, 'tcx, P>
1387     for ty::OutlivesPredicate<T, U>
1388     where T: Print<'gcx, 'tcx, P, Output = P, Error = P::Error>,
1389           U: Print<'gcx, 'tcx, P, Output = P, Error = P::Error>,
1390 {
1391     type Output = P;
1392     type Error = P::Error;
1393     fn print(&self, mut cx: P) -> Result<Self::Output, Self::Error> {
1394         define_scoped_cx!(cx);
1395         p!(print(self.0), write(" : "), print(self.1));
1396         Ok(cx)
1397     }
1398 }
1399
1400 macro_rules! forward_display_to_print {
1401     ($($ty:ty),+) => {
1402         $(impl fmt::Display for $ty {
1403             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1404                 ty::tls::with(|tcx| {
1405                     tcx.lift(self)
1406                         .expect("could not lift for printing")
1407                         .print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?;
1408                     Ok(())
1409                 })
1410             }
1411         })+
1412     };
1413 }
1414
1415 macro_rules! define_print_and_forward_display {
1416     (($self:ident, $cx:ident): $($ty:ty $print:block)+) => {
1417         $(impl<'gcx: 'tcx, 'tcx, P: PrettyPrinter<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for $ty {
1418             type Output = P;
1419             type Error = fmt::Error;
1420             fn print(&$self, $cx: P) -> Result<Self::Output, Self::Error> {
1421                 #[allow(unused_mut)]
1422                 let mut $cx = $cx;
1423                 define_scoped_cx!($cx);
1424                 let _: () = $print;
1425                 #[allow(unreachable_code)]
1426                 Ok($cx)
1427             }
1428         })+
1429
1430         forward_display_to_print!($($ty),+);
1431     };
1432 }
1433
1434 // HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting.
1435 impl fmt::Display for ty::RegionKind {
1436     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1437         ty::tls::with(|tcx| {
1438             self.print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?;
1439             Ok(())
1440         })
1441     }
1442 }
1443
1444 forward_display_to_print! {
1445     Ty<'tcx>,
1446     &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
1447
1448     // HACK(eddyb) these are exhaustive instead of generic,
1449     // because `for<'gcx: 'tcx, 'tcx>` isn't possible yet.
1450     ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
1451     ty::Binder<ty::TraitRef<'tcx>>,
1452     ty::Binder<ty::FnSig<'tcx>>,
1453     ty::Binder<ty::TraitPredicate<'tcx>>,
1454     ty::Binder<ty::SubtypePredicate<'tcx>>,
1455     ty::Binder<ty::ProjectionPredicate<'tcx>>,
1456     ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
1457     ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>,
1458
1459     ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
1460     ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
1461 }
1462
1463 define_print_and_forward_display! {
1464     (self, cx):
1465
1466     &'tcx ty::List<Ty<'tcx>> {
1467         p!(write("{{"));
1468         let mut tys = self.iter();
1469         if let Some(&ty) = tys.next() {
1470             p!(print(ty));
1471             for &ty in tys {
1472                 p!(write(", "), print(ty));
1473             }
1474         }
1475         p!(write("}}"))
1476     }
1477
1478     ty::TypeAndMut<'tcx> {
1479         p!(write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
1480             print(self.ty))
1481     }
1482
1483     ty::ExistentialTraitRef<'tcx> {
1484         // Use a type that can't appear in defaults of type parameters.
1485         let dummy_self = cx.tcx().mk_ty_infer(ty::FreshTy(0));
1486         let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
1487         p!(print(trait_ref))
1488     }
1489
1490     ty::ExistentialProjection<'tcx> {
1491         let name = cx.tcx().associated_item(self.item_def_id).ident;
1492         p!(write("{} = ", name), print(self.ty))
1493     }
1494
1495     ty::ExistentialPredicate<'tcx> {
1496         match *self {
1497             ty::ExistentialPredicate::Trait(x) => p!(print(x)),
1498             ty::ExistentialPredicate::Projection(x) => p!(print(x)),
1499             ty::ExistentialPredicate::AutoTrait(def_id) => {
1500                 p!(print_def_path(def_id, &[]));
1501             }
1502         }
1503     }
1504
1505     ty::FnSig<'tcx> {
1506         if self.unsafety == hir::Unsafety::Unsafe {
1507             p!(write("unsafe "));
1508         }
1509
1510         if self.abi != Abi::Rust {
1511             p!(write("extern {} ", self.abi));
1512         }
1513
1514         p!(write("fn"), pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
1515     }
1516
1517     ty::InferTy {
1518         if cx.tcx().sess.verbose() {
1519             p!(write("{:?}", self));
1520             return Ok(cx);
1521         }
1522         match *self {
1523             ty::TyVar(_) => p!(write("_")),
1524             ty::IntVar(_) => p!(write("{}", "{integer}")),
1525             ty::FloatVar(_) => p!(write("{}", "{float}")),
1526             ty::FreshTy(v) => p!(write("FreshTy({})", v)),
1527             ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)),
1528             ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v))
1529         }
1530     }
1531
1532     ty::TraitRef<'tcx> {
1533         p!(print_def_path(self.def_id, self.substs));
1534     }
1535
1536     &'tcx ty::Const<'tcx> {
1537         match self.val {
1538             ConstValue::Unevaluated(..) |
1539             ConstValue::Infer(..) => p!(write("_")),
1540             ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
1541             _ => p!(write("{:?}", self)),
1542         }
1543     }
1544
1545     ty::ParamTy {
1546         p!(write("{}", self.name))
1547     }
1548
1549     ty::ParamConst {
1550         p!(write("{}", self.name))
1551     }
1552
1553     ty::SubtypePredicate<'tcx> {
1554         p!(print(self.a), write(" <: "), print(self.b))
1555     }
1556
1557     ty::TraitPredicate<'tcx> {
1558         p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1559     }
1560
1561     ty::ProjectionPredicate<'tcx> {
1562         p!(print(self.projection_ty), write(" == "), print(self.ty))
1563     }
1564
1565     ty::ProjectionTy<'tcx> {
1566         p!(print_def_path(self.item_def_id, self.substs));
1567     }
1568
1569     ty::ClosureKind {
1570         match *self {
1571             ty::ClosureKind::Fn => p!(write("Fn")),
1572             ty::ClosureKind::FnMut => p!(write("FnMut")),
1573             ty::ClosureKind::FnOnce => p!(write("FnOnce")),
1574         }
1575     }
1576
1577     ty::Predicate<'tcx> {
1578         match *self {
1579             ty::Predicate::Trait(ref data) => p!(print(data)),
1580             ty::Predicate::Subtype(ref predicate) => p!(print(predicate)),
1581             ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)),
1582             ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)),
1583             ty::Predicate::Projection(ref predicate) => p!(print(predicate)),
1584             ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")),
1585             ty::Predicate::ObjectSafe(trait_def_id) => {
1586                 p!(write("the trait `"),
1587                    print_def_path(trait_def_id, &[]),
1588                    write("` is object-safe"))
1589             }
1590             ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
1591                 p!(write("the closure `"),
1592                    print_value_path(closure_def_id, &[]),
1593                    write("` implements the trait `{}`", kind))
1594             }
1595             ty::Predicate::ConstEvaluatable(def_id, substs) => {
1596                 p!(write("the constant `"),
1597                    print_value_path(def_id, substs),
1598                    write("` can be evaluated"))
1599             }
1600         }
1601     }
1602
1603     Kind<'tcx> {
1604         match self.unpack() {
1605             UnpackedKind::Lifetime(lt) => p!(print(lt)),
1606             UnpackedKind::Type(ty) => p!(print(ty)),
1607             UnpackedKind::Const(ct) => p!(print(ct)),
1608         }
1609     }
1610 }