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