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