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