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