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