]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
Rollup merge of #58842 - mati865:53005, r=alexcrichton
[rust.git] / src / librustc / util / ppaux.rs
1 use crate::hir::def_id::DefId;
2 use crate::hir::map::definitions::DefPathData;
3 use crate::middle::region;
4 use crate::ty::subst::{self, Subst, SubstsRef};
5 use crate::ty::{BrAnon, BrEnv, BrFresh, BrNamed};
6 use crate::ty::{Bool, Char, Adt};
7 use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
8 use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
9 use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
10 use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer};
11 use crate::ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
12 use crate::util::nodemap::FxHashSet;
13
14 use std::cell::Cell;
15 use std::fmt;
16 use std::usize;
17
18 use rustc_target::spec::abi::Abi;
19 use syntax::ast::CRATE_NODE_ID;
20 use syntax::symbol::{Symbol, InternedString};
21 use crate::hir;
22
23 /// The "region highlights" are used to control region printing during
24 /// specific error messages. When a "region highlight" is enabled, it
25 /// gives an alternate way to print specific regions. For now, we
26 /// always print those regions using a number, so something like "`'0`".
27 ///
28 /// Regions not selected by the region highlight mode are presently
29 /// unaffected.
30 #[derive(Copy, Clone, Default)]
31 pub struct RegionHighlightMode {
32     /// If enabled, when we see the selected region, use "`'N`"
33     /// instead of the ordinary behavior.
34     highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
35
36     /// If enabled, when printing a "free region" that originated from
37     /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
38     /// have names print as normal.
39     ///
40     /// This is used when you have a signature like `fn foo(x: &u32,
41     /// y: &'a u32)` and we want to give a name to the region of the
42     /// reference `x`.
43     highlight_bound_region: Option<(ty::BoundRegion, usize)>,
44 }
45
46 thread_local! {
47     /// Mechanism for highlighting of specific regions for display in NLL region inference errors.
48     /// Contains region to highlight and counter for number to use when highlighting.
49     static REGION_HIGHLIGHT_MODE: Cell<RegionHighlightMode> =
50         Cell::new(RegionHighlightMode::default())
51 }
52
53 impl RegionHighlightMode {
54     /// Reads and returns the current region highlight settings (accesses thread-local state).
55     pub fn get() -> Self {
56         REGION_HIGHLIGHT_MODE.with(|c| c.get())
57     }
58
59     // Internal helper to update current settings during the execution of `op`.
60     fn set<R>(
61         old_mode: Self,
62         new_mode: Self,
63         op: impl FnOnce() -> R,
64     ) -> R {
65         REGION_HIGHLIGHT_MODE.with(|c| {
66             c.set(new_mode);
67             let result = op();
68             c.set(old_mode);
69             result
70         })
71     }
72
73     /// If `region` and `number` are both `Some`, invokes
74     /// `highlighting_region`; otherwise, just invokes `op` directly.
75     pub fn maybe_highlighting_region<R>(
76         region: Option<ty::Region<'_>>,
77         number: Option<usize>,
78         op: impl FnOnce() -> R,
79     ) -> R {
80         if let Some(k) = region {
81             if let Some(n) = number {
82                 return Self::highlighting_region(k, n, op);
83             }
84         }
85
86         op()
87     }
88
89     /// During the execution of `op`, highlights the region inference
90     /// variable `vid` as `'N`. We can only highlight one region `vid`
91     /// at a time.
92     pub fn highlighting_region<R>(
93         region: ty::Region<'_>,
94         number: usize,
95         op: impl FnOnce() -> R,
96     ) -> R {
97         let old_mode = Self::get();
98         let mut new_mode = old_mode;
99         let first_avail_slot = new_mode.highlight_regions.iter_mut()
100             .filter(|s| s.is_none())
101             .next()
102             .unwrap_or_else(|| {
103                 panic!(
104                     "can only highlight {} placeholders at a time",
105                     old_mode.highlight_regions.len(),
106                 )
107             });
108         *first_avail_slot = Some((*region, number));
109         Self::set(old_mode, new_mode, op)
110     }
111
112     /// Convenience wrapper for `highlighting_region`.
113     pub fn highlighting_region_vid<R>(
114         vid: ty::RegionVid,
115         number: usize,
116         op: impl FnOnce() -> R,
117     ) -> R {
118         Self::highlighting_region(&ty::ReVar(vid), number, op)
119     }
120
121     /// Returns `true` if any placeholders are highlighted, and `false` otherwise.
122     fn any_region_vids_highlighted(&self) -> bool {
123         Self::get()
124             .highlight_regions
125             .iter()
126             .any(|h| match h {
127                 Some((ty::ReVar(_), _)) => true,
128                 _ => false,
129             })
130     }
131
132     /// Returns `Some(n)` with the number to use for the given region, if any.
133     fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
134         Self::get()
135             .highlight_regions
136             .iter()
137             .filter_map(|h| match h {
138                 Some((r, n)) if r == region => Some(*n),
139                 _ => None,
140             })
141             .next()
142     }
143
144     /// During the execution of `op`, highlight the given bound
145     /// region. We can only highlight one bound region at a time. See
146     /// the field `highlight_bound_region` for more detailed notes.
147     pub fn highlighting_bound_region<R>(
148         br: ty::BoundRegion,
149         number: usize,
150         op: impl FnOnce() -> R,
151     ) -> R {
152         let old_mode = Self::get();
153         assert!(old_mode.highlight_bound_region.is_none());
154         Self::set(
155             old_mode,
156             Self {
157                 highlight_bound_region: Some((br, number)),
158                 ..old_mode
159             },
160             op,
161         )
162     }
163
164     /// Returns `true` if any placeholders are highlighted, and `false` otherwise.
165     pub fn any_placeholders_highlighted(&self) -> bool {
166         Self::get()
167             .highlight_regions
168             .iter()
169             .any(|h| match h {
170                 Some((ty::RePlaceholder(_), _)) => true,
171                 _ => false,
172             })
173     }
174
175     /// Returns `Some(N)` if the placeholder `p` is highlighted to print as "`'N`".
176     pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option<usize> {
177         self.region_highlighted(&ty::RePlaceholder(p))
178     }
179 }
180
181 macro_rules! gen_display_debug_body {
182     ( $with:path ) => {
183         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184             let mut cx = PrintContext::new();
185             $with(self, f, &mut cx)
186         }
187     };
188 }
189 macro_rules! gen_display_debug {
190     ( ($($x:tt)+) $target:ty, display yes ) => {
191         impl<$($x)+> fmt::Display for $target {
192             gen_display_debug_body! { Print::print_display }
193         }
194     };
195     ( () $target:ty, display yes ) => {
196         impl fmt::Display for $target {
197             gen_display_debug_body! { Print::print_display }
198         }
199     };
200     ( ($($x:tt)+) $target:ty, debug yes ) => {
201         impl<$($x)+> fmt::Debug for $target {
202             gen_display_debug_body! { Print::print_debug }
203         }
204     };
205     ( () $target:ty, debug yes ) => {
206         impl fmt::Debug for $target {
207             gen_display_debug_body! { Print::print_debug }
208         }
209     };
210     ( $generic:tt $target:ty, $t:ident no ) => {};
211 }
212 macro_rules! gen_print_impl {
213     ( ($($x:tt)+) $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => {
214         impl<$($x)+> Print for $target {
215             fn print<F: fmt::Write>(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result {
216                 if $cx.is_debug $dbg
217                 else $disp
218             }
219         }
220     };
221     ( () $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => {
222         impl Print for $target {
223             fn print<F: fmt::Write>(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result {
224                 if $cx.is_debug $dbg
225                 else $disp
226             }
227         }
228     };
229     ( $generic:tt $target:ty,
230       $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => {
231         gen_print_impl! { $generic $target, $vars $disp $dbg }
232         gen_display_debug! { $generic $target, display $gendisp }
233         gen_display_debug! { $generic $target, debug $gendbg }
234     }
235 }
236 macro_rules! define_print {
237     ( $generic:tt $target:ty,
238       $vars:tt { display $disp:block debug $dbg:block } ) => {
239         gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
240     };
241     ( $generic:tt $target:ty,
242       $vars:tt { debug $dbg:block display $disp:block } ) => {
243         gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
244     };
245     ( $generic:tt $target:ty,
246       $vars:tt { debug $dbg:block } ) => {
247         gen_print_impl! { $generic $target, $vars no {
248             bug!(concat!("display not implemented for ", stringify!($target)));
249         } yes $dbg }
250     };
251     ( $generic:tt $target:ty,
252       ($self:ident, $f:ident, $cx:ident) { display $disp:block } ) => {
253         gen_print_impl! { $generic $target, ($self, $f, $cx) yes $disp no {
254             write!($f, "{:?}", $self)
255         } }
256     };
257 }
258 macro_rules! define_print_multi {
259     ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => {
260         $(define_print! { $generic $target, $vars $def })*
261     };
262 }
263 macro_rules! print_inner {
264     ( $f:expr, $cx:expr, write ($($data:expr),+) ) => {
265         write!($f, $($data),+)
266     };
267     ( $f:expr, $cx:expr, $kind:ident ($data:expr) ) => {
268         $data.$kind($f, $cx)
269     };
270 }
271 macro_rules! print {
272     ( $f:expr, $cx:expr $(, $kind:ident $data:tt)+ ) => {
273         Ok(())$(.and_then(|_| print_inner!($f, $cx, $kind $data)))+
274     };
275 }
276
277
278 struct LateBoundRegionNameCollector(FxHashSet<InternedString>);
279 impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector {
280     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
281         match *r {
282             ty::ReLateBound(_, ty::BrNamed(_, name)) => {
283                 self.0.insert(name);
284             },
285             _ => {},
286         }
287         r.super_visit_with(self)
288     }
289 }
290
291 #[derive(Debug)]
292 pub struct PrintContext {
293     is_debug: bool,
294     is_verbose: bool,
295     identify_regions: bool,
296     used_region_names: Option<FxHashSet<InternedString>>,
297     region_index: usize,
298     binder_depth: usize,
299 }
300 impl PrintContext {
301     fn new() -> Self {
302         ty::tls::with_opt(|tcx| {
303             let (is_verbose, identify_regions) = tcx.map(
304                 |tcx| (tcx.sess.verbose(), tcx.sess.opts.debugging_opts.identify_regions)
305             ).unwrap_or((false, false));
306             PrintContext {
307                 is_debug: false,
308                 is_verbose: is_verbose,
309                 identify_regions: identify_regions,
310                 used_region_names: None,
311                 region_index: 0,
312                 binder_depth: 0,
313             }
314         })
315     }
316     fn prepare_late_bound_region_info<'tcx, T>(&mut self, value: &ty::Binder<T>)
317     where T: TypeFoldable<'tcx>
318     {
319         let mut collector = LateBoundRegionNameCollector(Default::default());
320         value.visit_with(&mut collector);
321         self.used_region_names = Some(collector.0);
322         self.region_index = 0;
323     }
324 }
325
326 pub trait Print {
327     fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result;
328     fn print_to_string(&self, cx: &mut PrintContext) -> String {
329         let mut result = String::new();
330         let _ = self.print(&mut result, cx);
331         result
332     }
333     fn print_display<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result {
334         let old_debug = cx.is_debug;
335         cx.is_debug = false;
336         let result = self.print(f, cx);
337         cx.is_debug = old_debug;
338         result
339     }
340     fn print_display_to_string(&self, cx: &mut PrintContext) -> String {
341         let mut result = String::new();
342         let _ = self.print_display(&mut result, cx);
343         result
344     }
345     fn print_debug<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result {
346         let old_debug = cx.is_debug;
347         cx.is_debug = true;
348         let result = self.print(f, cx);
349         cx.is_debug = old_debug;
350         result
351     }
352     fn print_debug_to_string(&self, cx: &mut PrintContext) -> String {
353         let mut result = String::new();
354         let _ = self.print_debug(&mut result, cx);
355         result
356     }
357 }
358
359 impl PrintContext {
360     fn fn_sig<F: fmt::Write>(&mut self,
361                              f: &mut F,
362                              inputs: &[Ty<'_>],
363                              c_variadic: bool,
364                              output: Ty<'_>)
365                              -> fmt::Result {
366         write!(f, "(")?;
367         let mut inputs = inputs.iter();
368         if let Some(&ty) = inputs.next() {
369             print!(f, self, print_display(ty))?;
370             for &ty in inputs {
371                 print!(f, self, write(", "), print_display(ty))?;
372             }
373             if c_variadic {
374                 write!(f, ", ...")?;
375             }
376         }
377         write!(f, ")")?;
378         if !output.is_unit() {
379             print!(f, self, write(" -> "), print_display(output))?;
380         }
381
382         Ok(())
383     }
384
385     fn parameterized<F: fmt::Write>(&mut self,
386                                     f: &mut F,
387                                     substs: SubstsRef<'_>,
388                                     did: DefId,
389                                     projections: &[ty::ProjectionPredicate<'_>])
390                                     -> fmt::Result {
391         let key = ty::tls::with(|tcx| tcx.def_key(did));
392
393         let verbose = self.is_verbose;
394         let mut num_supplied_defaults = 0;
395         let mut has_self = false;
396         let mut own_counts: GenericParamCount = Default::default();
397         let mut is_value_path = false;
398         let mut item_name = Some(key.disambiguated_data.data.as_interned_str());
399         let fn_trait_kind = ty::tls::with(|tcx| {
400             // Unfortunately, some kinds of items (e.g., closures) don't have
401             // generics. So walk back up the find the closest parent that DOES
402             // have them.
403             let mut item_def_id = did;
404             loop {
405                 let key = tcx.def_key(item_def_id);
406                 match key.disambiguated_data.data {
407                     DefPathData::AssocTypeInTrait(_) |
408                     DefPathData::AssocTypeInImpl(_) |
409                     DefPathData::AssocExistentialInImpl(_) |
410                     DefPathData::Trait(_) |
411                     DefPathData::TraitAlias(_) |
412                     DefPathData::Impl |
413                     DefPathData::TypeNs(_) => {
414                         break;
415                     }
416                     DefPathData::ValueNs(_) |
417                     DefPathData::EnumVariant(_) => {
418                         is_value_path = true;
419                         break;
420                     }
421                     DefPathData::CrateRoot |
422                     DefPathData::Misc |
423                     DefPathData::Module(_) |
424                     DefPathData::MacroDef(_) |
425                     DefPathData::ClosureExpr |
426                     DefPathData::TypeParam(_) |
427                     DefPathData::LifetimeParam(_) |
428                     DefPathData::ConstParam(_) |
429                     DefPathData::Field(_) |
430                     DefPathData::StructCtor |
431                     DefPathData::AnonConst |
432                     DefPathData::ImplTrait |
433                     DefPathData::GlobalMetaData(_) => {
434                         // if we're making a symbol for something, there ought
435                         // to be a value or type-def or something in there
436                         // *somewhere*
437                         item_def_id.index = key.parent.unwrap_or_else(|| {
438                             bug!("finding type for {:?}, encountered def-id {:?} with no \
439                                  parent", did, item_def_id);
440                         });
441                     }
442                 }
443             }
444             let mut generics = tcx.generics_of(item_def_id);
445             let child_own_counts = generics.own_counts();
446             let mut path_def_id = did;
447             has_self = generics.has_self;
448
449             let mut child_types = 0;
450             if let Some(def_id) = generics.parent {
451                 // Methods.
452                 assert!(is_value_path);
453                 child_types = child_own_counts.types;
454                 generics = tcx.generics_of(def_id);
455                 own_counts = generics.own_counts();
456
457                 if has_self {
458                     print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
459                 }
460
461                 path_def_id = def_id;
462             } else {
463                 item_name = None;
464
465                 if is_value_path {
466                     // Functions.
467                     assert_eq!(has_self, false);
468                 } else {
469                     // Types and traits.
470                     own_counts = child_own_counts;
471                 }
472             }
473
474             if !verbose {
475                 let mut type_params =
476                     generics.params.iter().rev().filter_map(|param| match param.kind {
477                         GenericParamDefKind::Lifetime => None,
478                         GenericParamDefKind::Type { has_default, .. } => {
479                             Some((param.def_id, has_default))
480                         }
481                     }).peekable();
482                 let has_default = {
483                     let has_default = type_params.peek().map(|(_, has_default)| has_default);
484                     *has_default.unwrap_or(&false)
485                 };
486                 if has_default {
487                     if let Some(substs) = tcx.lift(&substs) {
488                         let types = substs.types().rev().skip(child_types);
489                         for ((def_id, has_default), actual) in type_params.zip(types) {
490                             if !has_default {
491                                 break;
492                             }
493                             if tcx.type_of(def_id).subst(tcx, substs) != actual {
494                                 break;
495                             }
496                             num_supplied_defaults += 1;
497                         }
498                     }
499                 }
500             }
501
502             print!(f, self, write("{}", tcx.item_path_str(path_def_id)))?;
503             Ok(tcx.lang_items().fn_trait_kind(path_def_id))
504         })?;
505
506         if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
507             let projection_ty = projections[0].ty;
508             if let Tuple(ref args) = substs.type_at(1).sty {
509                 return self.fn_sig(f, args, false, projection_ty);
510             }
511         }
512
513         let empty = Cell::new(true);
514         let start_or_continue = |f: &mut F, start: &str, cont: &str| {
515             if empty.get() {
516                 empty.set(false);
517                 write!(f, "{}", start)
518             } else {
519                 write!(f, "{}", cont)
520             }
521         };
522
523         let print_regions = |f: &mut F, start: &str, skip, count| {
524             // Don't print any regions if they're all erased.
525             let regions = || substs.regions().skip(skip).take(count);
526             if regions().all(|r: ty::Region<'_>| *r == ty::ReErased) {
527                 return Ok(());
528             }
529
530             for region in regions() {
531                 let region: ty::Region<'_> = region;
532                 start_or_continue(f, start, ", ")?;
533                 if verbose {
534                     write!(f, "{:?}", region)?;
535                 } else {
536                     let s = region.to_string();
537                     if s.is_empty() {
538                         // This happens when the value of the region
539                         // parameter is not easily serialized. This may be
540                         // because the user omitted it in the first place,
541                         // or because it refers to some block in the code,
542                         // etc. I'm not sure how best to serialize this.
543                         write!(f, "'_")?;
544                     } else {
545                         write!(f, "{}", s)?;
546                     }
547                 }
548             }
549
550             Ok(())
551         };
552
553         print_regions(f, "<", 0, own_counts.lifetimes)?;
554
555         let tps = substs.types()
556                         .take(own_counts.types - num_supplied_defaults)
557                         .skip(has_self as usize);
558
559         for ty in tps {
560             start_or_continue(f, "<", ", ")?;
561             ty.print_display(f, self)?;
562         }
563
564         for projection in projections {
565             start_or_continue(f, "<", ", ")?;
566             ty::tls::with(|tcx|
567                 print!(f, self,
568                        write("{}=",
569                              tcx.associated_item(projection.projection_ty.item_def_id).ident),
570                        print_display(projection.ty))
571             )?;
572         }
573
574         start_or_continue(f, "", ">")?;
575
576         // For values, also print their name and type parameters.
577         if is_value_path {
578             empty.set(true);
579
580             if has_self {
581                 write!(f, ">")?;
582             }
583
584             if let Some(item_name) = item_name {
585                 write!(f, "::{}", item_name)?;
586             }
587
588             print_regions(f, "::<", own_counts.lifetimes, usize::MAX)?;
589
590             // FIXME: consider being smart with defaults here too
591             for ty in substs.types().skip(own_counts.types) {
592                 start_or_continue(f, "::<", ", ")?;
593                 ty.print_display(f, self)?;
594             }
595
596             start_or_continue(f, "", ">")?;
597         }
598
599         Ok(())
600     }
601
602     fn in_binder<'a, 'gcx, 'tcx, T, U, F>(&mut self,
603                                           f: &mut F,
604                                           tcx: TyCtxt<'a, 'gcx, 'tcx>,
605                                           original: &ty::Binder<T>,
606                                           lifted: Option<ty::Binder<U>>) -> fmt::Result
607         where T: Print, U: Print + TypeFoldable<'tcx>, F: fmt::Write
608     {
609         fn name_by_region_index(index: usize) -> InternedString {
610             match index {
611                 0 => Symbol::intern("'r"),
612                 1 => Symbol::intern("'s"),
613                 i => Symbol::intern(&format!("'t{}", i-2)),
614             }.as_interned_str()
615         }
616
617         // Replace any anonymous late-bound regions with named
618         // variants, using gensym'd identifiers, so that we can
619         // clearly differentiate between named and unnamed regions in
620         // the output. We'll probably want to tweak this over time to
621         // decide just how much information to give.
622         let value = if let Some(v) = lifted {
623             v
624         } else {
625             return original.skip_binder().print_display(f, self);
626         };
627
628         if self.binder_depth == 0 {
629             self.prepare_late_bound_region_info(&value);
630         }
631
632         let mut empty = true;
633         let mut start_or_continue = |f: &mut F, start: &str, cont: &str| {
634             if empty {
635                 empty = false;
636                 write!(f, "{}", start)
637             } else {
638                 write!(f, "{}", cont)
639             }
640         };
641
642         let old_region_index = self.region_index;
643         let mut region_index = old_region_index;
644         let new_value = tcx.replace_late_bound_regions(&value, |br| {
645             let _ = start_or_continue(f, "for<", ", ");
646             let br = match br {
647                 ty::BrNamed(_, name) => {
648                     let _ = write!(f, "{}", name);
649                     br
650                 }
651                 ty::BrAnon(_) |
652                 ty::BrFresh(_) |
653                 ty::BrEnv => {
654                     let name = loop {
655                         let name = name_by_region_index(region_index);
656                         region_index += 1;
657                         if !self.is_name_used(&name) {
658                             break name;
659                         }
660                     };
661                     let _ = write!(f, "{}", name);
662                     ty::BrNamed(tcx.hir().local_def_id(CRATE_NODE_ID), name)
663                 }
664             };
665             tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
666         }).0;
667         start_or_continue(f, "", "> ")?;
668
669         // Push current state to gcx, and restore after writing new_value.
670         self.binder_depth += 1;
671         self.region_index = region_index;
672         let result = new_value.print_display(f, self);
673         self.region_index = old_region_index;
674         self.binder_depth -= 1;
675         result
676     }
677
678     fn is_name_used(&self, name: &InternedString) -> bool {
679         match self.used_region_names {
680             Some(ref names) => names.contains(name),
681             None => false,
682         }
683     }
684 }
685
686 pub fn verbose() -> bool {
687     ty::tls::with(|tcx| tcx.sess.verbose())
688 }
689
690 pub fn identify_regions() -> bool {
691     ty::tls::with(|tcx| tcx.sess.opts.debugging_opts.identify_regions)
692 }
693
694 pub fn parameterized<F: fmt::Write>(f: &mut F,
695                                     substs: SubstsRef<'_>,
696                                     did: DefId,
697                                     projections: &[ty::ProjectionPredicate<'_>])
698                                     -> fmt::Result {
699     PrintContext::new().parameterized(f, substs, did, projections)
700 }
701
702 impl<'a, T: Print> Print for &'a T {
703     fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result {
704         (*self).print(f, cx)
705     }
706 }
707
708 define_print! {
709     ('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, f, cx) {
710         display {
711             // Generate the main trait ref, including associated types.
712             ty::tls::with(|tcx| {
713                 // Use a type that can't appear in defaults of type parameters.
714                 let dummy_self = tcx.mk_infer(ty::FreshTy(0));
715                 let mut first = true;
716
717                 if let Some(principal) = self.principal() {
718                     let principal = tcx
719                         .lift(&principal)
720                         .expect("could not lift TraitRef for printing")
721                         .with_self_ty(tcx, dummy_self);
722                     let projections = self.projection_bounds().map(|p| {
723                         tcx.lift(&p)
724                             .expect("could not lift projection for printing")
725                             .with_self_ty(tcx, dummy_self)
726                     }).collect::<Vec<_>>();
727                     cx.parameterized(f, principal.substs, principal.def_id, &projections)?;
728                     first = false;
729                 }
730
731                 // Builtin bounds.
732                 let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
733                     tcx.item_path_str(did)
734                 }).collect();
735
736                 // The auto traits come ordered by `DefPathHash`. While
737                 // `DefPathHash` is *stable* in the sense that it depends on
738                 // neither the host nor the phase of the moon, it depends
739                 // "pseudorandomly" on the compiler version and the target.
740                 //
741                 // To avoid that causing instabilities in compiletest
742                 // output, sort the auto-traits alphabetically.
743                 auto_traits.sort();
744
745                 for auto_trait in auto_traits {
746                     if !first {
747                         write!(f, " + ")?;
748                     }
749                     first = false;
750
751                     write!(f, "{}", auto_trait)?;
752                 }
753
754                 Ok(())
755             })?;
756
757             Ok(())
758         }
759     }
760 }
761
762 impl fmt::Debug for ty::GenericParamDef {
763     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
764         let type_name = match self.kind {
765             ty::GenericParamDefKind::Lifetime => "Lifetime",
766             ty::GenericParamDefKind::Type {..} => "Type",
767         };
768         write!(f, "{}({}, {:?}, {})",
769                type_name,
770                self.name,
771                self.def_id,
772                self.index)
773     }
774 }
775
776 impl fmt::Debug for ty::TraitDef {
777     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
778         ty::tls::with(|tcx| {
779             write!(f, "{}", tcx.item_path_str(self.def_id))
780         })
781     }
782 }
783
784 impl fmt::Debug for ty::AdtDef {
785     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
786         ty::tls::with(|tcx| {
787             write!(f, "{}", tcx.item_path_str(self.did))
788         })
789     }
790 }
791
792 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
793     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
794         write!(f, "ClosureUpvar({:?},{:?})",
795                self.def,
796                self.ty)
797     }
798 }
799
800 impl fmt::Debug for ty::UpvarId {
801     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
802         write!(f, "UpvarId({:?};`{}`;{:?})",
803                self.var_path.hir_id,
804                ty::tls::with(|tcx| tcx.hir().name_by_hir_id(self.var_path.hir_id)),
805                self.closure_expr_id)
806     }
807 }
808
809 impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
810     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
811         write!(f, "UpvarBorrow({:?}, {:?})",
812                self.kind, self.region)
813     }
814 }
815
816 define_print! {
817     ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, f, cx) {
818         display {
819             write!(f, "{{")?;
820             let mut tys = self.iter();
821             if let Some(&ty) = tys.next() {
822                 print!(f, cx, print(ty))?;
823                 for &ty in tys {
824                     print!(f, cx, write(", "), print(ty))?;
825                 }
826             }
827             write!(f, "}}")
828         }
829     }
830 }
831
832 define_print! {
833     ('tcx) ty::TypeAndMut<'tcx>, (self, f, cx) {
834         display {
835             print!(f, cx,
836                    write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
837                    print(self.ty))
838         }
839     }
840 }
841
842 define_print! {
843     ('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) {
844         display {
845             cx.parameterized(f, self.substs, self.def_id, &[])
846         }
847         debug {
848             ty::tls::with(|tcx| {
849                 let dummy_self = tcx.mk_infer(ty::FreshTy(0));
850
851                 let trait_ref = *tcx.lift(&ty::Binder::bind(*self))
852                                    .expect("could not lift TraitRef for printing")
853                                    .with_self_ty(tcx, dummy_self).skip_binder();
854                 cx.parameterized(f, trait_ref.substs, trait_ref.def_id, &[])
855             })
856         }
857     }
858 }
859
860 define_print! {
861     ('tcx) ty::adjustment::Adjustment<'tcx>, (self, f, cx) {
862         debug {
863             print!(f, cx, write("{:?} -> ", self.kind), print(self.target))
864         }
865     }
866 }
867
868 define_print! {
869     () ty::BoundRegion, (self, f, cx) {
870         display {
871             if cx.is_verbose {
872                 return self.print_debug(f, cx);
873             }
874
875             if let Some((region, counter)) = RegionHighlightMode::get().highlight_bound_region {
876                 if *self == region {
877                     return match *self {
878                         BrNamed(_, name) => write!(f, "{}", name),
879                         BrAnon(_) | BrFresh(_) | BrEnv => write!(f, "'{}", counter)
880                     };
881                 }
882             }
883
884             match *self {
885                 BrNamed(_, name) => write!(f, "{}", name),
886                 BrAnon(_) | BrFresh(_) | BrEnv => Ok(())
887             }
888         }
889         debug {
890             return match *self {
891                 BrAnon(n) => write!(f, "BrAnon({:?})", n),
892                 BrFresh(n) => write!(f, "BrFresh({:?})", n),
893                 BrNamed(did, name) => {
894                     write!(f, "BrNamed({:?}:{:?}, {})",
895                            did.krate, did.index, name)
896                 }
897                 BrEnv => write!(f, "BrEnv"),
898             };
899         }
900     }
901 }
902
903 define_print! {
904     () ty::PlaceholderRegion, (self, f, cx) {
905         display {
906             if cx.is_verbose {
907                 return self.print_debug(f, cx);
908             }
909
910             let highlight = RegionHighlightMode::get();
911             if let Some(counter) = highlight.placeholder_highlight(*self) {
912                 write!(f, "'{}", counter)
913             } else if highlight.any_placeholders_highlighted() {
914                 write!(f, "'_")
915             } else {
916                 write!(f, "{}", self.name)
917             }
918         }
919     }
920 }
921
922 define_print! {
923     () ty::RegionKind, (self, f, cx) {
924         display {
925             if cx.is_verbose {
926                 return self.print_debug(f, cx);
927             }
928
929             // Watch out for region highlights.
930             if let Some(n) = RegionHighlightMode::get().region_highlighted(self) {
931                 return write!(f, "'{:?}", n);
932             }
933
934             // These printouts are concise.  They do not contain all the information
935             // the user might want to diagnose an error, but there is basically no way
936             // to fit that into a short string.  Hence the recommendation to use
937             // `explain_region()` or `note_and_explain_region()`.
938             match *self {
939                 ty::ReEarlyBound(ref data) => {
940                     write!(f, "{}", data.name)
941                 }
942                 ty::ReLateBound(_, br) |
943                 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
944                     write!(f, "{}", br)
945                 }
946                 ty::RePlaceholder(p) => {
947                     write!(f, "{}", p)
948                 }
949                 ty::ReScope(scope) if cx.identify_regions => {
950                     match scope.data {
951                         region::ScopeData::Node =>
952                             write!(f, "'{}s", scope.item_local_id().as_usize()),
953                         region::ScopeData::CallSite =>
954                             write!(f, "'{}cs", scope.item_local_id().as_usize()),
955                         region::ScopeData::Arguments =>
956                             write!(f, "'{}as", scope.item_local_id().as_usize()),
957                         region::ScopeData::Destruction =>
958                             write!(f, "'{}ds", scope.item_local_id().as_usize()),
959                         region::ScopeData::Remainder(first_statement_index) => write!(
960                             f,
961                             "'{}_{}rs",
962                             scope.item_local_id().as_usize(),
963                             first_statement_index.index()
964                         ),
965                     }
966                 }
967                 ty::ReVar(region_vid) => {
968                     if RegionHighlightMode::get().any_region_vids_highlighted() {
969                         write!(f, "{:?}", region_vid)
970                     } else if cx.identify_regions {
971                         write!(f, "'{}rv", region_vid.index())
972                     } else {
973                         Ok(())
974                     }
975                 }
976                 ty::ReScope(_) |
977                 ty::ReErased => Ok(()),
978                 ty::ReStatic => write!(f, "'static"),
979                 ty::ReEmpty => write!(f, "'<empty>"),
980
981                 // The user should never encounter these in unsubstituted form.
982                 ty::ReClosureBound(vid) => write!(f, "{:?}", vid),
983             }
984         }
985         debug {
986             match *self {
987                 ty::ReEarlyBound(ref data) => {
988                     write!(f, "ReEarlyBound({}, {})",
989                            data.index,
990                            data.name)
991                 }
992
993                 ty::ReClosureBound(ref vid) => {
994                     write!(f, "ReClosureBound({:?})",
995                            vid)
996                 }
997
998                 ty::ReLateBound(binder_id, ref bound_region) => {
999                     write!(f, "ReLateBound({:?}, {:?})",
1000                            binder_id,
1001                            bound_region)
1002                 }
1003
1004                 ty::ReFree(ref fr) => write!(f, "{:?}", fr),
1005
1006                 ty::ReScope(id) => {
1007                     write!(f, "ReScope({:?})", id)
1008                 }
1009
1010                 ty::ReStatic => write!(f, "ReStatic"),
1011
1012                 ty::ReVar(ref vid) => {
1013                     write!(f, "{:?}", vid)
1014                 }
1015
1016                 ty::RePlaceholder(placeholder) => {
1017                     write!(f, "RePlaceholder({:?})", placeholder)
1018                 }
1019
1020                 ty::ReEmpty => write!(f, "ReEmpty"),
1021
1022                 ty::ReErased => write!(f, "ReErased")
1023             }
1024         }
1025     }
1026 }
1027
1028 define_print! {
1029     () ty::FreeRegion, (self, f, cx) {
1030         debug {
1031             write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region)
1032         }
1033     }
1034 }
1035
1036 define_print! {
1037     () ty::Variance, (self, f, cx) {
1038         debug {
1039             f.write_str(match *self {
1040                 ty::Covariant => "+",
1041                 ty::Contravariant => "-",
1042                 ty::Invariant => "o",
1043                 ty::Bivariant => "*",
1044             })
1045         }
1046     }
1047 }
1048
1049 define_print! {
1050     ('tcx) ty::GenericPredicates<'tcx>, (self, f, cx) {
1051         debug {
1052             write!(f, "GenericPredicates({:?})", self.predicates)
1053         }
1054     }
1055 }
1056
1057 define_print! {
1058     ('tcx) ty::InstantiatedPredicates<'tcx>, (self, f, cx) {
1059         debug {
1060             write!(f, "InstantiatedPredicates({:?})", self.predicates)
1061         }
1062     }
1063 }
1064
1065 define_print! {
1066     ('tcx) ty::FnSig<'tcx>, (self, f, cx) {
1067         display {
1068             if self.unsafety == hir::Unsafety::Unsafe {
1069                 write!(f, "unsafe ")?;
1070             }
1071
1072             if self.abi != Abi::Rust {
1073                 write!(f, "extern {} ", self.abi)?;
1074             }
1075
1076             write!(f, "fn")?;
1077             cx.fn_sig(f, self.inputs(), self.c_variadic, self.output())
1078         }
1079         debug {
1080             write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output())
1081         }
1082     }
1083 }
1084
1085 impl fmt::Debug for ty::TyVid {
1086     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1087         write!(f, "_#{}t", self.index)
1088     }
1089 }
1090
1091 impl fmt::Debug for ty::IntVid {
1092     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1093         write!(f, "_#{}i", self.index)
1094     }
1095 }
1096
1097 impl fmt::Debug for ty::FloatVid {
1098     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1099         write!(f, "_#{}f", self.index)
1100     }
1101 }
1102
1103 impl fmt::Debug for ty::RegionVid {
1104     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1105         if let Some(counter) = RegionHighlightMode::get().region_highlighted(&ty::ReVar(*self)) {
1106             return write!(f, "'{:?}", counter);
1107         } else if RegionHighlightMode::get().any_region_vids_highlighted() {
1108             return write!(f, "'_");
1109         }
1110
1111         write!(f, "'_#{}r", self.index())
1112     }
1113 }
1114
1115 define_print! {
1116     () ty::InferTy, (self, f, cx) {
1117         display {
1118             if cx.is_verbose {
1119                 print!(f, cx, print_debug(self))
1120             } else {
1121                 match *self {
1122                     ty::TyVar(_) => write!(f, "_"),
1123                     ty::IntVar(_) => write!(f, "{}", "{integer}"),
1124                     ty::FloatVar(_) => write!(f, "{}", "{float}"),
1125                     ty::FreshTy(v) => write!(f, "FreshTy({})", v),
1126                     ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
1127                     ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
1128                 }
1129             }
1130         }
1131         debug {
1132             match *self {
1133                 ty::TyVar(ref v) => write!(f, "{:?}", v),
1134                 ty::IntVar(ref v) => write!(f, "{:?}", v),
1135                 ty::FloatVar(ref v) => write!(f, "{:?}", v),
1136                 ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
1137                 ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
1138                 ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
1139             }
1140         }
1141     }
1142 }
1143
1144 impl fmt::Debug for ty::IntVarValue {
1145     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1146         match *self {
1147             ty::IntType(ref v) => v.fmt(f),
1148             ty::UintType(ref v) => v.fmt(f),
1149         }
1150     }
1151 }
1152
1153 impl fmt::Debug for ty::FloatVarValue {
1154     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1155         self.0.fmt(f)
1156     }
1157 }
1158
1159 // The generic impl doesn't work yet because projections are not
1160 // normalized under HRTB.
1161 /*impl<T> fmt::Display for ty::Binder<T>
1162     where T: fmt::Display + for<'a> ty::Lift<'a>,
1163           for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
1164 {
1165     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1166         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
1167     }
1168 }*/
1169
1170 define_print_multi! {
1171     [
1172     ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
1173     ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
1174     ('tcx) ty::Binder<ty::FnSig<'tcx>>,
1175     ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
1176     ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
1177     ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
1178     ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
1179     ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
1180     ]
1181     (self, f, cx) {
1182         display {
1183             ty::tls::with(|tcx| cx.in_binder(f, tcx, self, tcx.lift(self)))
1184         }
1185     }
1186 }
1187
1188 define_print! {
1189     ('tcx) ty::TraitRef<'tcx>, (self, f, cx) {
1190         display {
1191             cx.parameterized(f, self.substs, self.def_id, &[])
1192         }
1193         debug {
1194             // when printing out the debug representation, we don't need
1195             // to enumerate the `for<...>` etc because the debruijn index
1196             // tells you everything you need to know.
1197             print!(f, cx,
1198                    write("<"),
1199                    print(self.self_ty()),
1200                    write(" as "))?;
1201             cx.parameterized(f, self.substs, self.def_id, &[])?;
1202             write!(f, ">")
1203         }
1204     }
1205 }
1206
1207 define_print! {
1208     ('tcx) ty::TyKind<'tcx>, (self, f, cx) {
1209         display {
1210             match *self {
1211                 Bool => write!(f, "bool"),
1212                 Char => write!(f, "char"),
1213                 Int(t) => write!(f, "{}", t.ty_to_string()),
1214                 Uint(t) => write!(f, "{}", t.ty_to_string()),
1215                 Float(t) => write!(f, "{}", t.ty_to_string()),
1216                 RawPtr(ref tm) => {
1217                     write!(f, "*{} ", match tm.mutbl {
1218                         hir::MutMutable => "mut",
1219                         hir::MutImmutable => "const",
1220                     })?;
1221                     tm.ty.print(f, cx)
1222                 }
1223                 Ref(r, ty, mutbl) => {
1224                     write!(f, "&")?;
1225                     let s = r.print_to_string(cx);
1226                     if s != "'_" {
1227                         write!(f, "{}", s)?;
1228                         if !s.is_empty() {
1229                             write!(f, " ")?;
1230                         }
1231                     }
1232                     ty::TypeAndMut { ty, mutbl }.print(f, cx)
1233                 }
1234                 Never => write!(f, "!"),
1235                 Tuple(ref tys) => {
1236                     write!(f, "(")?;
1237                     let mut tys = tys.iter();
1238                     if let Some(&ty) = tys.next() {
1239                         print!(f, cx, print(ty), write(","))?;
1240                         if let Some(&ty) = tys.next() {
1241                             print!(f, cx, write(" "), print(ty))?;
1242                             for &ty in tys {
1243                                 print!(f, cx, write(", "), print(ty))?;
1244                             }
1245                         }
1246                     }
1247                     write!(f, ")")
1248                 }
1249                 FnDef(def_id, substs) => {
1250                     ty::tls::with(|tcx| {
1251                         let mut sig = tcx.fn_sig(def_id);
1252                         if let Some(substs) = tcx.lift(&substs) {
1253                             sig = sig.subst(tcx, substs);
1254                         }
1255                         print!(f, cx, print(sig), write(" {{"))
1256                     })?;
1257                     cx.parameterized(f, substs, def_id, &[])?;
1258                     write!(f, "}}")
1259                 }
1260                 FnPtr(ref bare_fn) => {
1261                     bare_fn.print(f, cx)
1262                 }
1263                 Infer(infer_ty) => write!(f, "{}", infer_ty),
1264                 Error => write!(f, "[type error]"),
1265                 Param(ref param_ty) => write!(f, "{}", param_ty),
1266                 Bound(debruijn, bound_ty) => {
1267                     match bound_ty.kind {
1268                         ty::BoundTyKind::Anon => {
1269                             if debruijn == ty::INNERMOST {
1270                                 write!(f, "^{}", bound_ty.var.index())
1271                             } else {
1272                                 write!(f, "^{}_{}", debruijn.index(), bound_ty.var.index())
1273                             }
1274                         }
1275
1276                         ty::BoundTyKind::Param(p) => write!(f, "{}", p),
1277                     }
1278                 }
1279                 Adt(def, substs) => cx.parameterized(f, substs, def.did, &[]),
1280                 Dynamic(data, r) => {
1281                     let r = r.print_to_string(cx);
1282                     if !r.is_empty() {
1283                         write!(f, "(")?;
1284                     }
1285                     write!(f, "dyn ")?;
1286                     data.print(f, cx)?;
1287                     if !r.is_empty() {
1288                         write!(f, " + {})", r)
1289                     } else {
1290                         Ok(())
1291                     }
1292                 }
1293                 Foreign(def_id) => parameterized(f, subst::InternalSubsts::empty(), def_id, &[]),
1294                 Projection(ref data) => data.print(f, cx),
1295                 UnnormalizedProjection(ref data) => {
1296                     write!(f, "Unnormalized(")?;
1297                     data.print(f, cx)?;
1298                     write!(f, ")")
1299                 }
1300                 Placeholder(placeholder) => {
1301                     write!(f, "Placeholder({:?})", placeholder)
1302                 }
1303                 Opaque(def_id, substs) => {
1304                     if cx.is_verbose {
1305                         return write!(f, "Opaque({:?}, {:?})", def_id, substs);
1306                     }
1307
1308                     ty::tls::with(|tcx| {
1309                         let def_key = tcx.def_key(def_id);
1310                         if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
1311                             write!(f, "{}", name)?;
1312                             let mut substs = substs.iter();
1313                             if let Some(first) = substs.next() {
1314                                 write!(f, "::<")?;
1315                                 write!(f, "{}", first)?;
1316                                 for subst in substs {
1317                                     write!(f, ", {}", subst)?;
1318                                 }
1319                                 write!(f, ">")?;
1320                             }
1321                             return Ok(());
1322                         }
1323                         // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1324                         // by looking up the projections associated with the def_id.
1325                         let predicates_of = tcx.predicates_of(def_id);
1326                         let substs = tcx.lift(&substs).unwrap_or_else(|| {
1327                             tcx.intern_substs(&[])
1328                         });
1329                         let bounds = predicates_of.instantiate(tcx, substs);
1330
1331                         let mut first = true;
1332                         let mut is_sized = false;
1333                         write!(f, "impl")?;
1334                         for predicate in bounds.predicates {
1335                             if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
1336                                 // Don't print +Sized, but rather +?Sized if absent.
1337                                 if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
1338                                     is_sized = true;
1339                                     continue;
1340                                 }
1341
1342                                 print!(f, cx,
1343                                        write("{}", if first { " " } else { "+" }),
1344                                        print(trait_ref))?;
1345                                 first = false;
1346                             }
1347                         }
1348                         if !is_sized {
1349                             write!(f, "{}?Sized", if first { " " } else { "+" })?;
1350                         } else if first {
1351                             write!(f, " Sized")?;
1352                         }
1353                         Ok(())
1354                     })
1355                 }
1356                 Str => write!(f, "str"),
1357                 Generator(did, substs, movability) => ty::tls::with(|tcx| {
1358                     let upvar_tys = substs.upvar_tys(did, tcx);
1359                     let witness = substs.witness(did, tcx);
1360                     if movability == hir::GeneratorMovability::Movable {
1361                         write!(f, "[generator")?;
1362                     } else {
1363                         write!(f, "[static generator")?;
1364                     }
1365
1366                     if let Some(node_id) = tcx.hir().as_local_node_id(did) {
1367                         write!(f, "@{:?}", tcx.hir().span(node_id))?;
1368                         let mut sep = " ";
1369                         tcx.with_freevars(node_id, |freevars| {
1370                             for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1371                                 print!(f, cx,
1372                                        write("{}{}:",
1373                                              sep,
1374                                              tcx.hir().name(freevar.var_id())),
1375                                        print(upvar_ty))?;
1376                                 sep = ", ";
1377                             }
1378                             Ok(())
1379                         })?
1380                     } else {
1381                         // cross-crate closure types should only be
1382                         // visible in codegen bug reports, I imagine.
1383                         write!(f, "@{:?}", did)?;
1384                         let mut sep = " ";
1385                         for (index, upvar_ty) in upvar_tys.enumerate() {
1386                             print!(f, cx,
1387                                    write("{}{}:", sep, index),
1388                                    print(upvar_ty))?;
1389                             sep = ", ";
1390                         }
1391                     }
1392
1393                     print!(f, cx, write(" "), print(witness), write("]"))
1394                 }),
1395                 GeneratorWitness(types) => {
1396                     ty::tls::with(|tcx| cx.in_binder(f, tcx, &types, tcx.lift(&types)))
1397                 }
1398                 Closure(did, substs) => ty::tls::with(|tcx| {
1399                     let upvar_tys = substs.upvar_tys(did, tcx);
1400                     write!(f, "[closure")?;
1401
1402                     if let Some(node_id) = tcx.hir().as_local_node_id(did) {
1403                         if tcx.sess.opts.debugging_opts.span_free_formats {
1404                             write!(f, "@{:?}", node_id)?;
1405                         } else {
1406                             write!(f, "@{:?}", tcx.hir().span(node_id))?;
1407                         }
1408                         let mut sep = " ";
1409                         tcx.with_freevars(node_id, |freevars| {
1410                             for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1411                                 print!(f, cx,
1412                                        write("{}{}:",
1413                                              sep,
1414                                              tcx.hir().name(freevar.var_id())),
1415                                        print(upvar_ty))?;
1416                                 sep = ", ";
1417                             }
1418                             Ok(())
1419                         })?
1420                     } else {
1421                         // cross-crate closure types should only be
1422                         // visible in codegen bug reports, I imagine.
1423                         write!(f, "@{:?}", did)?;
1424                         let mut sep = " ";
1425                         for (index, upvar_ty) in upvar_tys.enumerate() {
1426                             print!(f, cx,
1427                                    write("{}{}:", sep, index),
1428                                    print(upvar_ty))?;
1429                             sep = ", ";
1430                         }
1431                     }
1432
1433                     if cx.is_verbose {
1434                         write!(
1435                             f,
1436                             " closure_kind_ty={:?} closure_sig_ty={:?}",
1437                             substs.closure_kind_ty(did, tcx),
1438                             substs.closure_sig_ty(did, tcx),
1439                         )?;
1440                     }
1441
1442                     write!(f, "]")
1443                 }),
1444                 Array(ty, sz) => {
1445                     print!(f, cx, write("["), print(ty), write("; "))?;
1446                     match sz {
1447                         ty::LazyConst::Unevaluated(_def_id, _substs) => {
1448                             write!(f, "_")?;
1449                         }
1450                         ty::LazyConst::Evaluated(c) => ty::tls::with(|tcx| {
1451                             write!(f, "{}", c.unwrap_usize(tcx))
1452                         })?,
1453                     }
1454                     write!(f, "]")
1455                 }
1456                 Slice(ty) => {
1457                     print!(f, cx, write("["), print(ty), write("]"))
1458                 }
1459             }
1460         }
1461     }
1462 }
1463
1464 define_print! {
1465     ('tcx) ty::TyS<'tcx>, (self, f, cx) {
1466         display {
1467             self.sty.print(f, cx)
1468         }
1469         debug {
1470             self.sty.print_display(f, cx)
1471         }
1472     }
1473 }
1474
1475 define_print! {
1476     () ty::ParamTy, (self, f, cx) {
1477         display {
1478             write!(f, "{}", self.name)
1479         }
1480         debug {
1481             write!(f, "{}/#{}", self.name, self.idx)
1482         }
1483     }
1484 }
1485
1486 define_print! {
1487     ('tcx, T: Print + fmt::Debug, U: Print + fmt::Debug) ty::OutlivesPredicate<T, U>,
1488     (self, f, cx) {
1489         display {
1490             print!(f, cx, print(self.0), write(" : "), print(self.1))
1491         }
1492     }
1493 }
1494
1495 define_print! {
1496     ('tcx) ty::SubtypePredicate<'tcx>, (self, f, cx) {
1497         display {
1498             print!(f, cx, print(self.a), write(" <: "), print(self.b))
1499         }
1500     }
1501 }
1502
1503 define_print! {
1504     ('tcx) ty::TraitPredicate<'tcx>, (self, f, cx) {
1505         debug {
1506             write!(f, "TraitPredicate({:?})",
1507                    self.trait_ref)
1508         }
1509         display {
1510             print!(f, cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1511         }
1512     }
1513 }
1514
1515 define_print! {
1516     ('tcx) ty::ProjectionPredicate<'tcx>, (self, f, cx) {
1517         debug {
1518             print!(f, cx,
1519                    write("ProjectionPredicate("),
1520                    print(self.projection_ty),
1521                    write(", "),
1522                    print(self.ty),
1523                    write(")"))
1524         }
1525         display {
1526             print!(f, cx, print(self.projection_ty), write(" == "), print(self.ty))
1527         }
1528     }
1529 }
1530
1531 define_print! {
1532     ('tcx) ty::ProjectionTy<'tcx>, (self, f, cx) {
1533         display {
1534             // FIXME(tschottdorf): use something like
1535             //   parameterized(f, self.substs, self.item_def_id, &[])
1536             // (which currently ICEs).
1537             let (trait_ref, item_name) = ty::tls::with(|tcx|
1538                 (self.trait_ref(tcx), tcx.associated_item(self.item_def_id).ident)
1539             );
1540             print!(f, cx, print_debug(trait_ref), write("::{}", item_name))
1541         }
1542     }
1543 }
1544
1545 define_print! {
1546     () ty::ClosureKind, (self, f, cx) {
1547         display {
1548             match *self {
1549                 ty::ClosureKind::Fn => write!(f, "Fn"),
1550                 ty::ClosureKind::FnMut => write!(f, "FnMut"),
1551                 ty::ClosureKind::FnOnce => write!(f, "FnOnce"),
1552             }
1553         }
1554     }
1555 }
1556
1557 define_print! {
1558     ('tcx) ty::Predicate<'tcx>, (self, f, cx) {
1559         display {
1560             match *self {
1561                 ty::Predicate::Trait(ref data) => data.print(f, cx),
1562                 ty::Predicate::Subtype(ref predicate) => predicate.print(f, cx),
1563                 ty::Predicate::RegionOutlives(ref predicate) => predicate.print(f, cx),
1564                 ty::Predicate::TypeOutlives(ref predicate) => predicate.print(f, cx),
1565                 ty::Predicate::Projection(ref predicate) => predicate.print(f, cx),
1566                 ty::Predicate::WellFormed(ty) => print!(f, cx, print(ty), write(" well-formed")),
1567                 ty::Predicate::ObjectSafe(trait_def_id) =>
1568                     ty::tls::with(|tcx| {
1569                         write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
1570                     }),
1571                 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) =>
1572                     ty::tls::with(|tcx| {
1573                         write!(f, "the closure `{}` implements the trait `{}`",
1574                                tcx.item_path_str(closure_def_id), kind)
1575                     }),
1576                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1577                     write!(f, "the constant `")?;
1578                     cx.parameterized(f, substs, def_id, &[])?;
1579                     write!(f, "` can be evaluated")
1580                 }
1581             }
1582         }
1583         debug {
1584             match *self {
1585                 ty::Predicate::Trait(ref a) => a.print(f, cx),
1586                 ty::Predicate::Subtype(ref pair) => pair.print(f, cx),
1587                 ty::Predicate::RegionOutlives(ref pair) => pair.print(f, cx),
1588                 ty::Predicate::TypeOutlives(ref pair) => pair.print(f, cx),
1589                 ty::Predicate::Projection(ref pair) => pair.print(f, cx),
1590                 ty::Predicate::WellFormed(ty) => ty.print(f, cx),
1591                 ty::Predicate::ObjectSafe(trait_def_id) => {
1592                     write!(f, "ObjectSafe({:?})", trait_def_id)
1593                 }
1594                 ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
1595                     write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
1596                 }
1597                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1598                     write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
1599                 }
1600             }
1601         }
1602     }
1603 }