]> git.proxmox.com Git - rustc.git/blob - src/librustc/util/ppaux.rs
Imported Upstream version 1.1.0+dfsg1
[rustc.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
12 use middle::def;
13 use middle::region;
14 use middle::subst::{VecPerParamSpace,Subst};
15 use middle::subst;
16 use middle::ty::{BoundRegion, BrAnon, BrNamed};
17 use middle::ty::{ReEarlyBound, BrFresh, ctxt};
18 use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
19 use middle::ty::{ReSkolemized, ReVar, BrEnv};
20 use middle::ty::{mt, Ty, ParamTy};
21 use middle::ty::{ty_bool, ty_char, ty_struct, ty_enum};
22 use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn};
23 use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup};
24 use middle::ty::ty_closure;
25 use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
26 use middle::ty;
27 use middle::ty_fold::TypeFoldable;
28
29 use std::collections::HashMap;
30 use std::collections::hash_state::HashState;
31 use std::hash::Hash;
32 use std::rc::Rc;
33 use syntax::abi;
34 use syntax::ast_map;
35 use syntax::codemap::{Span, Pos};
36 use syntax::parse::token;
37 use syntax::print::pprust;
38 use syntax::ptr::P;
39 use syntax::{ast, ast_util};
40 use syntax::owned_slice::OwnedSlice;
41
42 /// Produces a string suitable for debugging output.
43 pub trait Repr<'tcx> {
44 fn repr(&self, tcx: &ctxt<'tcx>) -> String;
45 }
46
47 /// Produces a string suitable for showing to the user.
48 pub trait UserString<'tcx> : Repr<'tcx> {
49 fn user_string(&self, tcx: &ctxt<'tcx>) -> String;
50 }
51
52 pub fn note_and_explain_region(cx: &ctxt,
53 prefix: &str,
54 region: ty::Region,
55 suffix: &str) -> Option<Span> {
56 match explain_region_and_span(cx, region) {
57 (ref str, Some(span)) => {
58 cx.sess.span_note(
59 span,
60 &format!("{}{}{}", prefix, *str, suffix));
61 Some(span)
62 }
63 (ref str, None) => {
64 cx.sess.note(
65 &format!("{}{}{}", prefix, *str, suffix));
66 None
67 }
68 }
69 }
70
71 /// When a free region is associated with `item`, how should we describe the item in the error
72 /// message.
73 fn item_scope_tag(item: &ast::Item) -> &'static str {
74 match item.node {
75 ast::ItemImpl(..) => "impl",
76 ast::ItemStruct(..) => "struct",
77 ast::ItemEnum(..) => "enum",
78 ast::ItemTrait(..) => "trait",
79 ast::ItemFn(..) => "function body",
80 _ => "item"
81 }
82 }
83
84 pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
85 -> (String, Option<Span>) {
86 return match region {
87 ReScope(scope) => {
88 let new_string;
89 let on_unknown_scope = || {
90 (format!("unknown scope: {:?}. Please report a bug.", scope), None)
91 };
92 let span = match scope.span(&cx.map) {
93 Some(s) => s,
94 None => return on_unknown_scope(),
95 };
96 let tag = match cx.map.find(scope.node_id()) {
97 Some(ast_map::NodeBlock(_)) => "block",
98 Some(ast_map::NodeExpr(expr)) => match expr.node {
99 ast::ExprCall(..) => "call",
100 ast::ExprMethodCall(..) => "method call",
101 ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let",
102 ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) => "while let",
103 ast::ExprMatch(_, _, ast::MatchSource::ForLoopDesugar) => "for",
104 ast::ExprMatch(..) => "match",
105 _ => "expression",
106 },
107 Some(ast_map::NodeStmt(_)) => "statement",
108 Some(ast_map::NodeItem(it)) => item_scope_tag(&*it),
109 Some(_) | None => {
110 // this really should not happen
111 return on_unknown_scope();
112 }
113 };
114 let scope_decorated_tag = match scope {
115 region::CodeExtent::Misc(_) => tag,
116 region::CodeExtent::ParameterScope { .. } => {
117 "scope of parameters for function"
118 }
119 region::CodeExtent::DestructionScope(_) => {
120 new_string = format!("destruction scope surrounding {}", tag);
121 &*new_string
122 }
123 region::CodeExtent::Remainder(r) => {
124 new_string = format!("block suffix following statement {}",
125 r.first_statement_index);
126 &*new_string
127 }
128 };
129 explain_span(cx, scope_decorated_tag, span)
130
131 }
132
133 ReFree(ref fr) => {
134 let prefix = match fr.bound_region {
135 BrAnon(idx) => {
136 format!("the anonymous lifetime #{} defined on", idx + 1)
137 }
138 BrFresh(_) => "an anonymous lifetime defined on".to_string(),
139 _ => {
140 format!("the lifetime {} as defined on",
141 bound_region_ptr_to_string(cx, fr.bound_region))
142 }
143 };
144
145 match cx.map.find(fr.scope.node_id) {
146 Some(ast_map::NodeBlock(ref blk)) => {
147 let (msg, opt_span) = explain_span(cx, "block", blk.span);
148 (format!("{} {}", prefix, msg), opt_span)
149 }
150 Some(ast_map::NodeItem(it)) => {
151 let tag = item_scope_tag(&*it);
152 let (msg, opt_span) = explain_span(cx, tag, it.span);
153 (format!("{} {}", prefix, msg), opt_span)
154 }
155 Some(_) | None => {
156 // this really should not happen
157 (format!("{} unknown free region bounded by scope {:?}", prefix, fr.scope), None)
158 }
159 }
160 }
161
162 ReStatic => { ("the static lifetime".to_string(), None) }
163
164 ReEmpty => { ("the empty lifetime".to_string(), None) }
165
166 ReEarlyBound(ref data) => {
167 (format!("{}", token::get_name(data.name)), None)
168 }
169
170 // I believe these cases should not occur (except when debugging,
171 // perhaps)
172 ty::ReInfer(_) | ty::ReLateBound(..) => {
173 (format!("lifetime {:?}", region), None)
174 }
175 };
176
177 fn explain_span(cx: &ctxt, heading: &str, span: Span)
178 -> (String, Option<Span>) {
179 let lo = cx.sess.codemap().lookup_char_pos_adj(span.lo);
180 (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
181 Some(span))
182 }
183 }
184
185 pub fn bound_region_ptr_to_string(cx: &ctxt, br: BoundRegion) -> String {
186 bound_region_to_string(cx, "", false, br)
187 }
188
189 pub fn bound_region_to_string(cx: &ctxt,
190 prefix: &str, space: bool,
191 br: BoundRegion) -> String {
192 let space_str = if space { " " } else { "" };
193
194 if cx.sess.verbose() {
195 return format!("{}{}{}", prefix, br.repr(cx), space_str)
196 }
197
198 match br {
199 BrNamed(_, name) => {
200 format!("{}{}{}", prefix, token::get_name(name), space_str)
201 }
202 BrAnon(_) | BrFresh(_) | BrEnv => prefix.to_string()
203 }
204 }
205
206 // In general, if you are giving a region error message,
207 // you should use `explain_region()` or, better yet,
208 // `note_and_explain_region()`
209 pub fn region_ptr_to_string(cx: &ctxt, region: Region) -> String {
210 region_to_string(cx, "&", true, region)
211 }
212
213 pub fn region_to_string(cx: &ctxt, prefix: &str, space: bool, region: Region) -> String {
214 let space_str = if space { " " } else { "" };
215
216 if cx.sess.verbose() {
217 return format!("{}{}{}", prefix, region.repr(cx), space_str)
218 }
219
220 // These printouts are concise. They do not contain all the information
221 // the user might want to diagnose an error, but there is basically no way
222 // to fit that into a short string. Hence the recommendation to use
223 // `explain_region()` or `note_and_explain_region()`.
224 match region {
225 ty::ReScope(_) => prefix.to_string(),
226 ty::ReEarlyBound(ref data) => {
227 token::get_name(data.name).to_string()
228 }
229 ty::ReLateBound(_, br) => bound_region_to_string(cx, prefix, space, br),
230 ty::ReFree(ref fr) => bound_region_to_string(cx, prefix, space, fr.bound_region),
231 ty::ReInfer(ReSkolemized(_, br)) => {
232 bound_region_to_string(cx, prefix, space, br)
233 }
234 ty::ReInfer(ReVar(_)) => prefix.to_string(),
235 ty::ReStatic => format!("{}'static{}", prefix, space_str),
236 ty::ReEmpty => format!("{}'<empty>{}", prefix, space_str),
237 }
238 }
239
240 pub fn mutability_to_string(m: ast::Mutability) -> String {
241 match m {
242 ast::MutMutable => "mut ".to_string(),
243 ast::MutImmutable => "".to_string(),
244 }
245 }
246
247 pub fn mt_to_string<'tcx>(cx: &ctxt<'tcx>, m: &mt<'tcx>) -> String {
248 format!("{}{}",
249 mutability_to_string(m.mutbl),
250 ty_to_string(cx, m.ty))
251 }
252
253 pub fn vec_map_to_string<T, F>(ts: &[T], f: F) -> String where
254 F: FnMut(&T) -> String,
255 {
256 let tstrs = ts.iter().map(f).collect::<Vec<String>>();
257 format!("[{}]", tstrs.connect(", "))
258 }
259
260 pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
261 fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>,
262 opt_def_id: Option<ast::DefId>,
263 unsafety: ast::Unsafety,
264 abi: abi::Abi,
265 ident: Option<ast::Ident>,
266 sig: &ty::PolyFnSig<'tcx>)
267 -> String {
268 let mut s = String::new();
269
270 match unsafety {
271 ast::Unsafety::Normal => {}
272 ast::Unsafety::Unsafe => {
273 s.push_str(&unsafety.to_string());
274 s.push(' ');
275 }
276 };
277
278 if abi != abi::Rust {
279 s.push_str(&format!("extern {} ", abi.to_string()));
280 };
281
282 s.push_str("fn");
283
284 match ident {
285 Some(i) => {
286 s.push(' ');
287 s.push_str(&token::get_ident(i));
288 }
289 _ => { }
290 }
291
292 push_sig_to_string(cx, &mut s, '(', ')', sig);
293
294 match opt_def_id {
295 Some(def_id) => {
296 s.push_str(" {");
297 let path_str = ty::item_path_str(cx, def_id);
298 s.push_str(&path_str[..]);
299 s.push_str("}");
300 }
301 None => { }
302 }
303
304 s
305 }
306
307 fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String {
308 let mut s = String::new();
309 s.push_str("[closure");
310 push_sig_to_string(cx, &mut s, '(', ')', &cty.sig);
311 s.push(']');
312 s
313 }
314
315 fn push_sig_to_string<'tcx>(cx: &ctxt<'tcx>,
316 s: &mut String,
317 bra: char,
318 ket: char,
319 sig: &ty::PolyFnSig<'tcx>) {
320 s.push(bra);
321 let strs = sig.0.inputs
322 .iter()
323 .map(|a| ty_to_string(cx, *a))
324 .collect::<Vec<_>>();
325 s.push_str(&strs.connect(", "));
326 if sig.0.variadic {
327 s.push_str(", ...");
328 }
329 s.push(ket);
330
331 match sig.0.output {
332 ty::FnConverging(t) => {
333 if !ty::type_is_nil(t) {
334 s.push_str(" -> ");
335 s.push_str(&ty_to_string(cx, t));
336 }
337 }
338 ty::FnDiverging => {
339 s.push_str(" -> !");
340 }
341 }
342 }
343
344 fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
345 let print_var_ids = cx.sess.verbose();
346 match ty {
347 ty::TyVar(ref vid) if print_var_ids => vid.repr(cx),
348 ty::IntVar(ref vid) if print_var_ids => vid.repr(cx),
349 ty::FloatVar(ref vid) if print_var_ids => vid.repr(cx),
350 ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => format!("_"),
351 ty::FreshTy(v) => format!("FreshTy({})", v),
352 ty::FreshIntTy(v) => format!("FreshIntTy({})", v),
353 ty::FreshFloatTy(v) => format!("FreshFloatTy({})", v)
354 }
355 }
356
357 // pretty print the structural type representation:
358 match typ.sty {
359 ty_bool => "bool".to_string(),
360 ty_char => "char".to_string(),
361 ty_int(t) => ast_util::int_ty_to_string(t, None).to_string(),
362 ty_uint(t) => ast_util::uint_ty_to_string(t, None).to_string(),
363 ty_float(t) => ast_util::float_ty_to_string(t).to_string(),
364 ty_uniq(typ) => format!("Box<{}>", ty_to_string(cx, typ)),
365 ty_ptr(ref tm) => {
366 format!("*{} {}", match tm.mutbl {
367 ast::MutMutable => "mut",
368 ast::MutImmutable => "const",
369 }, ty_to_string(cx, tm.ty))
370 }
371 ty_rptr(r, ref tm) => {
372 let mut buf = region_ptr_to_string(cx, *r);
373 buf.push_str(&mt_to_string(cx, tm));
374 buf
375 }
376 ty_tup(ref elems) => {
377 let strs = elems
378 .iter()
379 .map(|elem| ty_to_string(cx, *elem))
380 .collect::<Vec<_>>();
381 match &strs[..] {
382 [ref string] => format!("({},)", string),
383 strs => format!("({})", strs.connect(", "))
384 }
385 }
386 ty_bare_fn(opt_def_id, ref f) => {
387 bare_fn_to_string(cx, opt_def_id, f.unsafety, f.abi, None, &f.sig)
388 }
389 ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty),
390 ty_err => "[type error]".to_string(),
391 ty_param(ref param_ty) => param_ty.user_string(cx),
392 ty_enum(did, substs) | ty_struct(did, substs) => {
393 let base = ty::item_path_str(cx, did);
394 parameterized(cx, &base, substs, did, &[],
395 || ty::lookup_item_type(cx, did).generics)
396 }
397 ty_trait(ref data) => {
398 data.user_string(cx)
399 }
400 ty::ty_projection(ref data) => {
401 format!("<{} as {}>::{}",
402 data.trait_ref.self_ty().user_string(cx),
403 data.trait_ref.user_string(cx),
404 data.item_name.user_string(cx))
405 }
406 ty_str => "str".to_string(),
407 ty_closure(ref did, substs) => {
408 let closure_tys = cx.closure_tys.borrow();
409 closure_tys.get(did).map(|closure_type| {
410 closure_to_string(cx, &closure_type.subst(cx, substs))
411 }).unwrap_or_else(|| {
412 if did.krate == ast::LOCAL_CRATE {
413 let span = cx.map.span(did.node);
414 format!("[closure {}]", span.repr(cx))
415 } else {
416 format!("[closure]")
417 }
418 })
419 }
420 ty_vec(t, sz) => {
421 let inner_str = ty_to_string(cx, t);
422 match sz {
423 Some(n) => format!("[{}; {}]", inner_str, n),
424 None => format!("[{}]", inner_str),
425 }
426 }
427 }
428 }
429
430 pub fn explicit_self_category_to_str(category: &ty::ExplicitSelfCategory)
431 -> &'static str {
432 match *category {
433 ty::StaticExplicitSelfCategory => "static",
434 ty::ByValueExplicitSelfCategory => "self",
435 ty::ByReferenceExplicitSelfCategory(_, ast::MutMutable) => {
436 "&mut self"
437 }
438 ty::ByReferenceExplicitSelfCategory(_, ast::MutImmutable) => "&self",
439 ty::ByBoxExplicitSelfCategory => "Box<self>",
440 }
441 }
442
443 pub fn parameterized<'tcx,GG>(cx: &ctxt<'tcx>,
444 base: &str,
445 substs: &subst::Substs<'tcx>,
446 did: ast::DefId,
447 projections: &[ty::ProjectionPredicate<'tcx>],
448 get_generics: GG)
449 -> String
450 where GG : FnOnce() -> ty::Generics<'tcx>
451 {
452 if cx.sess.verbose() {
453 let mut strings = vec![];
454 match substs.regions {
455 subst::ErasedRegions => {
456 strings.push(format!(".."));
457 }
458 subst::NonerasedRegions(ref regions) => {
459 for region in regions.iter() {
460 strings.push(region.repr(cx));
461 }
462 }
463 }
464 for ty in substs.types.iter() {
465 strings.push(ty.repr(cx));
466 }
467 for projection in projections.iter() {
468 strings.push(format!("{}={}",
469 projection.projection_ty.item_name.user_string(cx),
470 projection.ty.user_string(cx)));
471 }
472 return if strings.is_empty() {
473 format!("{}", base)
474 } else {
475 format!("{}<{}>", base, strings.connect(","))
476 };
477 }
478
479 let mut strs = Vec::new();
480
481 match substs.regions {
482 subst::ErasedRegions => { }
483 subst::NonerasedRegions(ref regions) => {
484 for &r in regions.iter() {
485 let s = region_to_string(cx, "", false, r);
486 if s.is_empty() {
487 // This happens when the value of the region
488 // parameter is not easily serialized. This may be
489 // because the user omitted it in the first place,
490 // or because it refers to some block in the code,
491 // etc. I'm not sure how best to serialize this.
492 strs.push(format!("'_"));
493 } else {
494 strs.push(s)
495 }
496 }
497 }
498 }
499
500 // It is important to execute this conditionally, only if -Z
501 // verbose is false. Otherwise, debug logs can sometimes cause
502 // ICEs trying to fetch the generics early in the pipeline. This
503 // is kind of a hacky workaround in that -Z verbose is required to
504 // avoid those ICEs.
505 let generics = get_generics();
506
507 let has_self = substs.self_ty().is_some();
508 let tps = substs.types.get_slice(subst::TypeSpace);
509 let ty_params = generics.types.get_slice(subst::TypeSpace);
510 let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
511 let num_defaults = if has_defaults {
512 ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
513 match def.default {
514 Some(default) => {
515 if !has_self && ty::type_has_self(default) {
516 // In an object type, there is no `Self`, and
517 // thus if the default value references Self,
518 // the user will be required to give an
519 // explicit value. We can't even do the
520 // substitution below to check without causing
521 // an ICE. (#18956).
522 false
523 } else {
524 default.subst(cx, substs) == actual
525 }
526 }
527 None => false
528 }
529 }).count()
530 } else {
531 0
532 };
533
534 for t in &tps[..tps.len() - num_defaults] {
535 strs.push(ty_to_string(cx, *t))
536 }
537
538 for projection in projections {
539 strs.push(format!("{}={}",
540 projection.projection_ty.item_name.user_string(cx),
541 projection.ty.user_string(cx)));
542 }
543
544 if cx.lang_items.fn_trait_kind(did).is_some() && projections.len() == 1 {
545 let projection_ty = projections[0].ty;
546 let tail =
547 if ty::type_is_nil(projection_ty) {
548 format!("")
549 } else {
550 format!(" -> {}", projection_ty.user_string(cx))
551 };
552 format!("{}({}){}",
553 base,
554 if strs[0].starts_with("(") && strs[0].ends_with(",)") {
555 &strs[0][1 .. strs[0].len() - 2] // Remove '(' and ',)'
556 } else if strs[0].starts_with("(") && strs[0].ends_with(")") {
557 &strs[0][1 .. strs[0].len() - 1] // Remove '(' and ')'
558 } else {
559 &strs[0][..]
560 },
561 tail)
562 } else if !strs.is_empty() {
563 format!("{}<{}>", base, strs.connect(", "))
564 } else {
565 format!("{}", base)
566 }
567 }
568
569 pub fn ty_to_short_str<'tcx>(cx: &ctxt<'tcx>, typ: Ty<'tcx>) -> String {
570 let mut s = typ.repr(cx).to_string();
571 if s.len() >= 32 {
572 s = (&s[0..32]).to_string();
573 }
574 return s;
575 }
576
577 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Option<T> {
578 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
579 match self {
580 &None => "None".to_string(),
581 &Some(ref t) => t.repr(tcx),
582 }
583 }
584 }
585
586 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for P<T> {
587 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
588 (**self).repr(tcx)
589 }
590 }
591
592 impl<'tcx,T:Repr<'tcx>,U:Repr<'tcx>> Repr<'tcx> for Result<T,U> {
593 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
594 match self {
595 &Ok(ref t) => t.repr(tcx),
596 &Err(ref u) => format!("Err({})", u.repr(tcx))
597 }
598 }
599 }
600
601 impl<'tcx> Repr<'tcx> for () {
602 fn repr(&self, _tcx: &ctxt) -> String {
603 "()".to_string()
604 }
605 }
606
607 impl<'a, 'tcx, T: ?Sized +Repr<'tcx>> Repr<'tcx> for &'a T {
608 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
609 Repr::repr(*self, tcx)
610 }
611 }
612
613 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Rc<T> {
614 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
615 (&**self).repr(tcx)
616 }
617 }
618
619 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Box<T> {
620 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
621 (&**self).repr(tcx)
622 }
623 }
624
625 fn repr_vec<'tcx, T:Repr<'tcx>>(tcx: &ctxt<'tcx>, v: &[T]) -> String {
626 vec_map_to_string(v, |t| t.repr(tcx))
627 }
628
629 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for [T] {
630 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
631 repr_vec(tcx, self)
632 }
633 }
634
635 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice<T> {
636 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
637 repr_vec(tcx, &self[..])
638 }
639 }
640
641 // This is necessary to handle types like Option<Vec<T>>, for which
642 // autoderef cannot convert the &[T] handler
643 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Vec<T> {
644 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
645 repr_vec(tcx, &self[..])
646 }
647 }
648
649 impl<'tcx, T:UserString<'tcx>> UserString<'tcx> for Vec<T> {
650 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
651 let strs: Vec<String> =
652 self.iter().map(|t| t.user_string(tcx)).collect();
653 strs.connect(", ")
654 }
655 }
656
657 impl<'tcx> Repr<'tcx> for def::Def {
658 fn repr(&self, _tcx: &ctxt) -> String {
659 format!("{:?}", *self)
660 }
661 }
662
663 /// This curious type is here to help pretty-print trait objects. In
664 /// a trait object, the projections are stored separately from the
665 /// main trait bound, but in fact we want to package them together
666 /// when printing out; they also have separate binders, but we want
667 /// them to share a binder when we print them out. (And the binder
668 /// pretty-printing logic is kind of clever and we don't want to
669 /// reproduce it.) So we just repackage up the structure somewhat.
670 ///
671 /// Right now there is only one trait in an object that can have
672 /// projection bounds, so we just stuff them altogether. But in
673 /// reality we should eventually sort things out better.
674 type TraitAndProjections<'tcx> =
675 (ty::TraitRef<'tcx>, Vec<ty::ProjectionPredicate<'tcx>>);
676
677 impl<'tcx> UserString<'tcx> for TraitAndProjections<'tcx> {
678 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
679 let &(ref trait_ref, ref projection_bounds) = self;
680 let base = ty::item_path_str(tcx, trait_ref.def_id);
681 parameterized(tcx,
682 &base,
683 trait_ref.substs,
684 trait_ref.def_id,
685 &projection_bounds[..],
686 || ty::lookup_trait_def(tcx, trait_ref.def_id).generics.clone())
687 }
688 }
689
690 impl<'tcx> UserString<'tcx> for ty::TyTrait<'tcx> {
691 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
692 let &ty::TyTrait { ref principal, ref bounds } = self;
693
694 let mut components = vec![];
695
696 let tap: ty::Binder<TraitAndProjections<'tcx>> =
697 ty::Binder((principal.0.clone(),
698 bounds.projection_bounds.iter().map(|x| x.0.clone()).collect()));
699
700 // Generate the main trait ref, including associated types.
701 components.push(tap.user_string(tcx));
702
703 // Builtin bounds.
704 for bound in &bounds.builtin_bounds {
705 components.push(bound.user_string(tcx));
706 }
707
708 // Region, if not obviously implied by builtin bounds.
709 if bounds.region_bound != ty::ReStatic {
710 // Region bound is implied by builtin bounds:
711 components.push(bounds.region_bound.user_string(tcx));
712 }
713
714 components.retain(|s| !s.is_empty());
715
716 components.connect(" + ")
717 }
718 }
719
720 impl<'tcx> Repr<'tcx> for ty::TypeParameterDef<'tcx> {
721 fn repr(&self, _tcx: &ctxt<'tcx>) -> String {
722 format!("TypeParameterDef({:?}, {:?}/{})",
723 self.def_id,
724 self.space,
725 self.index)
726 }
727 }
728
729 impl<'tcx> Repr<'tcx> for ty::RegionParameterDef {
730 fn repr(&self, tcx: &ctxt) -> String {
731 format!("RegionParameterDef(name={}, def_id={}, bounds={})",
732 token::get_name(self.name),
733 self.def_id.repr(tcx),
734 self.bounds.repr(tcx))
735 }
736 }
737
738 impl<'tcx> Repr<'tcx> for ty::TyS<'tcx> {
739 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
740 ty_to_string(tcx, self)
741 }
742 }
743
744 impl<'tcx> Repr<'tcx> for ty::mt<'tcx> {
745 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
746 mt_to_string(tcx, self)
747 }
748 }
749
750 impl<'tcx> Repr<'tcx> for subst::Substs<'tcx> {
751 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
752 format!("Substs[types={}, regions={}]",
753 self.types.repr(tcx),
754 self.regions.repr(tcx))
755 }
756 }
757
758 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for subst::VecPerParamSpace<T> {
759 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
760 format!("[{};{};{}]",
761 self.get_slice(subst::TypeSpace).repr(tcx),
762 self.get_slice(subst::SelfSpace).repr(tcx),
763 self.get_slice(subst::FnSpace).repr(tcx))
764 }
765 }
766
767 impl<'tcx> Repr<'tcx> for ty::ItemSubsts<'tcx> {
768 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
769 format!("ItemSubsts({})", self.substs.repr(tcx))
770 }
771 }
772
773 impl<'tcx> Repr<'tcx> for subst::RegionSubsts {
774 fn repr(&self, tcx: &ctxt) -> String {
775 match *self {
776 subst::ErasedRegions => "erased".to_string(),
777 subst::NonerasedRegions(ref regions) => regions.repr(tcx)
778 }
779 }
780 }
781
782 impl<'tcx> Repr<'tcx> for ty::BuiltinBounds {
783 fn repr(&self, _tcx: &ctxt) -> String {
784 let mut res = Vec::new();
785 for b in self {
786 res.push(match b {
787 ty::BoundSend => "Send".to_string(),
788 ty::BoundSized => "Sized".to_string(),
789 ty::BoundCopy => "Copy".to_string(),
790 ty::BoundSync => "Sync".to_string(),
791 });
792 }
793 res.connect("+")
794 }
795 }
796
797 impl<'tcx> Repr<'tcx> for ty::ParamBounds<'tcx> {
798 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
799 let mut res = Vec::new();
800 res.push(self.builtin_bounds.repr(tcx));
801 for t in &self.trait_bounds {
802 res.push(t.repr(tcx));
803 }
804 res.connect("+")
805 }
806 }
807
808 impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
809 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
810 // when printing out the debug representation, we don't need
811 // to enumerate the `for<...>` etc because the debruijn index
812 // tells you everything you need to know.
813 let base = ty::item_path_str(tcx, self.def_id);
814 let result = parameterized(tcx, &base, self.substs, self.def_id, &[],
815 || ty::lookup_trait_def(tcx, self.def_id).generics.clone());
816 match self.substs.self_ty() {
817 None => result,
818 Some(sty) => format!("<{} as {}>", sty.repr(tcx), result)
819 }
820 }
821 }
822
823 impl<'tcx> Repr<'tcx> for ty::TraitDef<'tcx> {
824 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
825 format!("TraitDef(generics={}, trait_ref={})",
826 self.generics.repr(tcx),
827 self.trait_ref.repr(tcx))
828 }
829 }
830
831 impl<'tcx> Repr<'tcx> for ast::TraitItem {
832 fn repr(&self, _tcx: &ctxt) -> String {
833 let kind = match self.node {
834 ast::ConstTraitItem(..) => "ConstTraitItem",
835 ast::MethodTraitItem(..) => "MethodTraitItem",
836 ast::TypeTraitItem(..) => "TypeTraitItem",
837 };
838 format!("{}({}, id={})", kind, self.ident, self.id)
839 }
840 }
841
842 impl<'tcx> Repr<'tcx> for ast::Expr {
843 fn repr(&self, _tcx: &ctxt) -> String {
844 format!("expr({}: {})", self.id, pprust::expr_to_string(self))
845 }
846 }
847
848 impl<'tcx> Repr<'tcx> for ast::Path {
849 fn repr(&self, _tcx: &ctxt) -> String {
850 format!("path({})", pprust::path_to_string(self))
851 }
852 }
853
854 impl<'tcx> UserString<'tcx> for ast::Path {
855 fn user_string(&self, _tcx: &ctxt) -> String {
856 pprust::path_to_string(self)
857 }
858 }
859
860 impl<'tcx> Repr<'tcx> for ast::Ty {
861 fn repr(&self, _tcx: &ctxt) -> String {
862 format!("type({})", pprust::ty_to_string(self))
863 }
864 }
865
866 impl<'tcx> Repr<'tcx> for ast::Item {
867 fn repr(&self, tcx: &ctxt) -> String {
868 format!("item({})", tcx.map.node_to_string(self.id))
869 }
870 }
871
872 impl<'tcx> Repr<'tcx> for ast::Lifetime {
873 fn repr(&self, _tcx: &ctxt) -> String {
874 format!("lifetime({}: {})", self.id, pprust::lifetime_to_string(self))
875 }
876 }
877
878 impl<'tcx> Repr<'tcx> for ast::Stmt {
879 fn repr(&self, _tcx: &ctxt) -> String {
880 format!("stmt({}: {})",
881 ast_util::stmt_id(self),
882 pprust::stmt_to_string(self))
883 }
884 }
885
886 impl<'tcx> Repr<'tcx> for ast::Pat {
887 fn repr(&self, _tcx: &ctxt) -> String {
888 format!("pat({}: {})", self.id, pprust::pat_to_string(self))
889 }
890 }
891
892 impl<'tcx> Repr<'tcx> for ty::BoundRegion {
893 fn repr(&self, tcx: &ctxt) -> String {
894 match *self {
895 ty::BrAnon(id) => format!("BrAnon({})", id),
896 ty::BrNamed(id, name) => {
897 format!("BrNamed({}, {})", id.repr(tcx), token::get_name(name))
898 }
899 ty::BrFresh(id) => format!("BrFresh({})", id),
900 ty::BrEnv => "BrEnv".to_string()
901 }
902 }
903 }
904
905 impl<'tcx> Repr<'tcx> for ty::Region {
906 fn repr(&self, tcx: &ctxt) -> String {
907 match *self {
908 ty::ReEarlyBound(ref data) => {
909 format!("ReEarlyBound({}, {:?}, {}, {})",
910 data.param_id,
911 data.space,
912 data.index,
913 token::get_name(data.name))
914 }
915
916 ty::ReLateBound(binder_id, ref bound_region) => {
917 format!("ReLateBound({:?}, {})",
918 binder_id,
919 bound_region.repr(tcx))
920 }
921
922 ty::ReFree(ref fr) => fr.repr(tcx),
923
924 ty::ReScope(id) => {
925 format!("ReScope({:?})", id)
926 }
927
928 ty::ReStatic => {
929 "ReStatic".to_string()
930 }
931
932 ty::ReInfer(ReVar(ref vid)) => {
933 format!("{:?}", vid)
934 }
935
936 ty::ReInfer(ReSkolemized(id, ref bound_region)) => {
937 format!("re_skolemized({}, {})", id, bound_region.repr(tcx))
938 }
939
940 ty::ReEmpty => {
941 "ReEmpty".to_string()
942 }
943 }
944 }
945 }
946
947 impl<'tcx> UserString<'tcx> for ty::Region {
948 fn user_string(&self, tcx: &ctxt) -> String {
949 region_to_string(tcx, "", false, *self)
950 }
951 }
952
953 impl<'tcx> Repr<'tcx> for ty::FreeRegion {
954 fn repr(&self, tcx: &ctxt) -> String {
955 format!("ReFree({}, {})",
956 self.scope.repr(tcx),
957 self.bound_region.repr(tcx))
958 }
959 }
960
961 impl<'tcx> Repr<'tcx> for region::CodeExtent {
962 fn repr(&self, _tcx: &ctxt) -> String {
963 match *self {
964 region::CodeExtent::ParameterScope { fn_id, body_id } =>
965 format!("ParameterScope({}, {})", fn_id, body_id),
966 region::CodeExtent::Misc(node_id) =>
967 format!("Misc({})", node_id),
968 region::CodeExtent::DestructionScope(node_id) =>
969 format!("DestructionScope({})", node_id),
970 region::CodeExtent::Remainder(rem) =>
971 format!("Remainder({}, {})", rem.block, rem.first_statement_index),
972 }
973 }
974 }
975
976 impl<'tcx> Repr<'tcx> for region::DestructionScopeData {
977 fn repr(&self, _tcx: &ctxt) -> String {
978 match *self {
979 region::DestructionScopeData{ node_id } =>
980 format!("DestructionScopeData {{ node_id: {} }}", node_id),
981 }
982 }
983 }
984
985 impl<'tcx> Repr<'tcx> for ast::DefId {
986 fn repr(&self, tcx: &ctxt) -> String {
987 // Unfortunately, there seems to be no way to attempt to print
988 // a path for a def-id, so I'll just make a best effort for now
989 // and otherwise fallback to just printing the crate/node pair
990 if self.krate == ast::LOCAL_CRATE {
991 match tcx.map.find(self.node) {
992 Some(ast_map::NodeItem(..)) |
993 Some(ast_map::NodeForeignItem(..)) |
994 Some(ast_map::NodeImplItem(..)) |
995 Some(ast_map::NodeTraitItem(..)) |
996 Some(ast_map::NodeVariant(..)) |
997 Some(ast_map::NodeStructCtor(..)) => {
998 return format!(
999 "{:?}:{}",
1000 *self,
1001 ty::item_path_str(tcx, *self))
1002 }
1003 _ => {}
1004 }
1005 }
1006 return format!("{:?}", *self)
1007 }
1008 }
1009
1010 impl<'tcx> Repr<'tcx> for ty::TypeScheme<'tcx> {
1011 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1012 format!("TypeScheme {{generics: {}, ty: {}}}",
1013 self.generics.repr(tcx),
1014 self.ty.repr(tcx))
1015 }
1016 }
1017
1018 impl<'tcx> Repr<'tcx> for ty::Generics<'tcx> {
1019 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1020 format!("Generics(types: {}, regions: {})",
1021 self.types.repr(tcx),
1022 self.regions.repr(tcx))
1023 }
1024 }
1025
1026 impl<'tcx> Repr<'tcx> for ty::GenericPredicates<'tcx> {
1027 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1028 format!("GenericPredicates(predicates: {})",
1029 self.predicates.repr(tcx))
1030 }
1031 }
1032
1033 impl<'tcx> Repr<'tcx> for ty::InstantiatedPredicates<'tcx> {
1034 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1035 format!("InstantiatedPredicates({})",
1036 self.predicates.repr(tcx))
1037 }
1038 }
1039
1040 impl<'tcx> Repr<'tcx> for ty::ItemVariances {
1041 fn repr(&self, tcx: &ctxt) -> String {
1042 format!("ItemVariances(types={}, \
1043 regions={})",
1044 self.types.repr(tcx),
1045 self.regions.repr(tcx))
1046 }
1047 }
1048
1049 impl<'tcx> Repr<'tcx> for ty::Variance {
1050 fn repr(&self, _: &ctxt) -> String {
1051 // The first `.to_string()` returns a &'static str (it is not an implementation
1052 // of the ToString trait). Because of that, we need to call `.to_string()` again
1053 // if we want to have a `String`.
1054 let result: &'static str = (*self).to_string();
1055 result.to_string()
1056 }
1057 }
1058
1059 impl<'tcx> Repr<'tcx> for ty::ImplOrTraitItem<'tcx> {
1060 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1061 format!("ImplOrTraitItem({})",
1062 match *self {
1063 ty::ImplOrTraitItem::MethodTraitItem(ref i) => i.repr(tcx),
1064 ty::ImplOrTraitItem::ConstTraitItem(ref i) => i.repr(tcx),
1065 ty::ImplOrTraitItem::TypeTraitItem(ref i) => i.repr(tcx),
1066 })
1067 }
1068 }
1069
1070 impl<'tcx> Repr<'tcx> for ty::AssociatedConst<'tcx> {
1071 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1072 format!("AssociatedConst(name: {}, ty: {}, vis: {}, def_id: {})",
1073 self.name.repr(tcx),
1074 self.ty.repr(tcx),
1075 self.vis.repr(tcx),
1076 self.def_id.repr(tcx))
1077 }
1078 }
1079
1080 impl<'tcx> Repr<'tcx> for ty::AssociatedType {
1081 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1082 format!("AssociatedType(name: {}, vis: {}, def_id: {})",
1083 self.name.repr(tcx),
1084 self.vis.repr(tcx),
1085 self.def_id.repr(tcx))
1086 }
1087 }
1088
1089 impl<'tcx> Repr<'tcx> for ty::Method<'tcx> {
1090 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1091 format!("Method(name: {}, generics: {}, predicates: {}, fty: {}, \
1092 explicit_self: {}, vis: {}, def_id: {})",
1093 self.name.repr(tcx),
1094 self.generics.repr(tcx),
1095 self.predicates.repr(tcx),
1096 self.fty.repr(tcx),
1097 self.explicit_self.repr(tcx),
1098 self.vis.repr(tcx),
1099 self.def_id.repr(tcx))
1100 }
1101 }
1102
1103 impl<'tcx> Repr<'tcx> for ast::Name {
1104 fn repr(&self, _tcx: &ctxt) -> String {
1105 token::get_name(*self).to_string()
1106 }
1107 }
1108
1109 impl<'tcx> UserString<'tcx> for ast::Name {
1110 fn user_string(&self, _tcx: &ctxt) -> String {
1111 token::get_name(*self).to_string()
1112 }
1113 }
1114
1115 impl<'tcx> Repr<'tcx> for ast::Ident {
1116 fn repr(&self, _tcx: &ctxt) -> String {
1117 token::get_ident(*self).to_string()
1118 }
1119 }
1120
1121 impl<'tcx> Repr<'tcx> for ast::ExplicitSelf_ {
1122 fn repr(&self, _tcx: &ctxt) -> String {
1123 format!("{:?}", *self)
1124 }
1125 }
1126
1127 impl<'tcx> Repr<'tcx> for ast::Visibility {
1128 fn repr(&self, _tcx: &ctxt) -> String {
1129 format!("{:?}", *self)
1130 }
1131 }
1132
1133 impl<'tcx> Repr<'tcx> for ty::BareFnTy<'tcx> {
1134 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1135 format!("BareFnTy {{unsafety: {}, abi: {}, sig: {}}}",
1136 self.unsafety,
1137 self.abi.to_string(),
1138 self.sig.repr(tcx))
1139 }
1140 }
1141
1142
1143 impl<'tcx> Repr<'tcx> for ty::FnSig<'tcx> {
1144 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1145 format!("fn{} -> {}", self.inputs.repr(tcx), self.output.repr(tcx))
1146 }
1147 }
1148
1149 impl<'tcx> Repr<'tcx> for ty::FnOutput<'tcx> {
1150 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1151 match *self {
1152 ty::FnConverging(ty) =>
1153 format!("FnConverging({0})", ty.repr(tcx)),
1154 ty::FnDiverging =>
1155 "FnDiverging".to_string()
1156 }
1157 }
1158 }
1159
1160 impl<'tcx> Repr<'tcx> for ty::MethodCallee<'tcx> {
1161 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1162 format!("MethodCallee {{origin: {}, ty: {}, {}}}",
1163 self.origin.repr(tcx),
1164 self.ty.repr(tcx),
1165 self.substs.repr(tcx))
1166 }
1167 }
1168
1169 impl<'tcx> Repr<'tcx> for ty::MethodOrigin<'tcx> {
1170 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1171 match self {
1172 &ty::MethodStatic(def_id) => {
1173 format!("MethodStatic({})", def_id.repr(tcx))
1174 }
1175 &ty::MethodStaticClosure(def_id) => {
1176 format!("MethodStaticClosure({})", def_id.repr(tcx))
1177 }
1178 &ty::MethodTypeParam(ref p) => {
1179 p.repr(tcx)
1180 }
1181 &ty::MethodTraitObject(ref p) => {
1182 p.repr(tcx)
1183 }
1184 }
1185 }
1186 }
1187
1188 impl<'tcx> Repr<'tcx> for ty::MethodParam<'tcx> {
1189 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1190 format!("MethodParam({},{})",
1191 self.trait_ref.repr(tcx),
1192 self.method_num)
1193 }
1194 }
1195
1196 impl<'tcx> Repr<'tcx> for ty::MethodObject<'tcx> {
1197 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1198 format!("MethodObject({},{},{})",
1199 self.trait_ref.repr(tcx),
1200 self.method_num,
1201 self.vtable_index)
1202 }
1203 }
1204
1205 impl<'tcx> Repr<'tcx> for ty::BuiltinBound {
1206 fn repr(&self, _tcx: &ctxt) -> String {
1207 format!("{:?}", *self)
1208 }
1209 }
1210
1211 impl<'tcx> UserString<'tcx> for ty::BuiltinBound {
1212 fn user_string(&self, _tcx: &ctxt) -> String {
1213 match *self {
1214 ty::BoundSend => "Send".to_string(),
1215 ty::BoundSized => "Sized".to_string(),
1216 ty::BoundCopy => "Copy".to_string(),
1217 ty::BoundSync => "Sync".to_string(),
1218 }
1219 }
1220 }
1221
1222 impl<'tcx> Repr<'tcx> for Span {
1223 fn repr(&self, tcx: &ctxt) -> String {
1224 tcx.sess.codemap().span_to_string(*self).to_string()
1225 }
1226 }
1227
1228 impl<'tcx, A:UserString<'tcx>> UserString<'tcx> for Rc<A> {
1229 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1230 let this: &A = &**self;
1231 this.user_string(tcx)
1232 }
1233 }
1234
1235 impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> {
1236 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1237 let mut result = Vec::new();
1238 let s = self.builtin_bounds.user_string(tcx);
1239 if !s.is_empty() {
1240 result.push(s);
1241 }
1242 for n in &self.trait_bounds {
1243 result.push(n.user_string(tcx));
1244 }
1245 result.connect(" + ")
1246 }
1247 }
1248
1249 impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
1250 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1251 let mut res = Vec::new();
1252
1253 let region_str = self.region_bound.repr(tcx);
1254 if !region_str.is_empty() {
1255 res.push(region_str);
1256 }
1257
1258 for bound in &self.builtin_bounds {
1259 res.push(bound.repr(tcx));
1260 }
1261
1262 for projection_bound in &self.projection_bounds {
1263 res.push(projection_bound.repr(tcx));
1264 }
1265
1266 res.connect("+")
1267 }
1268 }
1269
1270 impl<'tcx> UserString<'tcx> for ty::BuiltinBounds {
1271 fn user_string(&self, tcx: &ctxt) -> String {
1272 self.iter()
1273 .map(|bb| bb.user_string(tcx))
1274 .collect::<Vec<String>>()
1275 .connect("+")
1276 .to_string()
1277 }
1278 }
1279
1280 impl<'tcx, T> UserString<'tcx> for ty::Binder<T>
1281 where T : UserString<'tcx> + TypeFoldable<'tcx>
1282 {
1283 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1284 // Replace any anonymous late-bound regions with named
1285 // variants, using gensym'd identifiers, so that we can
1286 // clearly differentiate between named and unnamed regions in
1287 // the output. We'll probably want to tweak this over time to
1288 // decide just how much information to give.
1289 let mut names = Vec::new();
1290 let (unbound_value, _) = ty::replace_late_bound_regions(tcx, self, |br| {
1291 ty::ReLateBound(ty::DebruijnIndex::new(1), match br {
1292 ty::BrNamed(_, name) => {
1293 names.push(token::get_name(name));
1294 br
1295 }
1296 ty::BrAnon(_) |
1297 ty::BrFresh(_) |
1298 ty::BrEnv => {
1299 let name = token::gensym("'r");
1300 names.push(token::get_name(name));
1301 ty::BrNamed(ast_util::local_def(ast::DUMMY_NODE_ID), name)
1302 }
1303 })
1304 });
1305 let names: Vec<_> = names.iter().map(|s| &s[..]).collect();
1306
1307 let value_str = unbound_value.user_string(tcx);
1308 if names.is_empty() {
1309 value_str
1310 } else {
1311 format!("for<{}> {}", names.connect(","), value_str)
1312 }
1313 }
1314 }
1315
1316 impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> {
1317 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1318 let path_str = ty::item_path_str(tcx, self.def_id);
1319 parameterized(tcx, &path_str, self.substs, self.def_id, &[],
1320 || ty::lookup_trait_def(tcx, self.def_id).generics.clone())
1321 }
1322 }
1323
1324 impl<'tcx> UserString<'tcx> for Ty<'tcx> {
1325 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1326 ty_to_string(tcx, *self)
1327 }
1328 }
1329
1330 impl<'tcx> UserString<'tcx> for ast::Ident {
1331 fn user_string(&self, _tcx: &ctxt) -> String {
1332 token::get_name(self.name).to_string()
1333 }
1334 }
1335
1336 impl<'tcx> Repr<'tcx> for abi::Abi {
1337 fn repr(&self, _tcx: &ctxt) -> String {
1338 self.to_string()
1339 }
1340 }
1341
1342 impl<'tcx> UserString<'tcx> for abi::Abi {
1343 fn user_string(&self, _tcx: &ctxt) -> String {
1344 self.to_string()
1345 }
1346 }
1347
1348 impl<'tcx> Repr<'tcx> for ty::UpvarId {
1349 fn repr(&self, tcx: &ctxt) -> String {
1350 format!("UpvarId({};`{}`;{})",
1351 self.var_id,
1352 ty::local_var_name_str(tcx, self.var_id),
1353 self.closure_expr_id)
1354 }
1355 }
1356
1357 impl<'tcx> Repr<'tcx> for ast::Mutability {
1358 fn repr(&self, _tcx: &ctxt) -> String {
1359 format!("{:?}", *self)
1360 }
1361 }
1362
1363 impl<'tcx> Repr<'tcx> for ty::BorrowKind {
1364 fn repr(&self, _tcx: &ctxt) -> String {
1365 format!("{:?}", *self)
1366 }
1367 }
1368
1369 impl<'tcx> Repr<'tcx> for ty::UpvarBorrow {
1370 fn repr(&self, tcx: &ctxt) -> String {
1371 format!("UpvarBorrow({}, {})",
1372 self.kind.repr(tcx),
1373 self.region.repr(tcx))
1374 }
1375 }
1376
1377 impl<'tcx> Repr<'tcx> for ty::UpvarCapture {
1378 fn repr(&self, tcx: &ctxt) -> String {
1379 match *self {
1380 ty::UpvarCapture::ByValue => format!("ByValue"),
1381 ty::UpvarCapture::ByRef(ref data) => format!("ByRef({})", data.repr(tcx)),
1382 }
1383 }
1384 }
1385
1386 impl<'tcx> Repr<'tcx> for ty::IntVid {
1387 fn repr(&self, _tcx: &ctxt) -> String {
1388 format!("{:?}", self)
1389 }
1390 }
1391
1392 impl<'tcx> Repr<'tcx> for ty::FloatVid {
1393 fn repr(&self, _tcx: &ctxt) -> String {
1394 format!("{:?}", self)
1395 }
1396 }
1397
1398 impl<'tcx> Repr<'tcx> for ty::RegionVid {
1399 fn repr(&self, _tcx: &ctxt) -> String {
1400 format!("{:?}", self)
1401 }
1402 }
1403
1404 impl<'tcx> Repr<'tcx> for ty::TyVid {
1405 fn repr(&self, _tcx: &ctxt) -> String {
1406 format!("{:?}", self)
1407 }
1408 }
1409
1410 impl<'tcx> Repr<'tcx> for ty::IntVarValue {
1411 fn repr(&self, _tcx: &ctxt) -> String {
1412 format!("{:?}", *self)
1413 }
1414 }
1415
1416 impl<'tcx> Repr<'tcx> for ast::IntTy {
1417 fn repr(&self, _tcx: &ctxt) -> String {
1418 format!("{:?}", *self)
1419 }
1420 }
1421
1422 impl<'tcx> Repr<'tcx> for ast::UintTy {
1423 fn repr(&self, _tcx: &ctxt) -> String {
1424 format!("{:?}", *self)
1425 }
1426 }
1427
1428 impl<'tcx> Repr<'tcx> for ast::FloatTy {
1429 fn repr(&self, _tcx: &ctxt) -> String {
1430 format!("{:?}", *self)
1431 }
1432 }
1433
1434 impl<'tcx> Repr<'tcx> for ty::ExplicitSelfCategory {
1435 fn repr(&self, _: &ctxt) -> String {
1436 explicit_self_category_to_str(self).to_string()
1437 }
1438 }
1439
1440 impl<'tcx> UserString<'tcx> for ParamTy {
1441 fn user_string(&self, _tcx: &ctxt) -> String {
1442 format!("{}", token::get_name(self.name))
1443 }
1444 }
1445
1446 impl<'tcx> Repr<'tcx> for ParamTy {
1447 fn repr(&self, tcx: &ctxt) -> String {
1448 let ident = self.user_string(tcx);
1449 format!("{}/{:?}.{}", ident, self.space, self.idx)
1450 }
1451 }
1452
1453 impl<'tcx, A:Repr<'tcx>, B:Repr<'tcx>> Repr<'tcx> for (A,B) {
1454 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1455 let &(ref a, ref b) = self;
1456 format!("({},{})", a.repr(tcx), b.repr(tcx))
1457 }
1458 }
1459
1460 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for ty::Binder<T> {
1461 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1462 format!("Binder({})", self.0.repr(tcx))
1463 }
1464 }
1465
1466 impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
1467 where K: Hash + Eq + Repr<'tcx>,
1468 V: Repr<'tcx>,
1469 S: HashState,
1470 {
1471 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1472 format!("HashMap({})",
1473 self.iter()
1474 .map(|(k,v)| format!("{} => {}", k.repr(tcx), v.repr(tcx)))
1475 .collect::<Vec<String>>()
1476 .connect(", "))
1477 }
1478 }
1479
1480 impl<'tcx, T, U> Repr<'tcx> for ty::OutlivesPredicate<T,U>
1481 where T : Repr<'tcx> + TypeFoldable<'tcx>,
1482 U : Repr<'tcx> + TypeFoldable<'tcx>,
1483 {
1484 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1485 format!("OutlivesPredicate({}, {})",
1486 self.0.repr(tcx),
1487 self.1.repr(tcx))
1488 }
1489 }
1490
1491 impl<'tcx, T, U> UserString<'tcx> for ty::OutlivesPredicate<T,U>
1492 where T : UserString<'tcx> + TypeFoldable<'tcx>,
1493 U : UserString<'tcx> + TypeFoldable<'tcx>,
1494 {
1495 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1496 format!("{} : {}",
1497 self.0.user_string(tcx),
1498 self.1.user_string(tcx))
1499 }
1500 }
1501
1502 impl<'tcx> Repr<'tcx> for ty::EquatePredicate<'tcx> {
1503 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1504 format!("EquatePredicate({}, {})",
1505 self.0.repr(tcx),
1506 self.1.repr(tcx))
1507 }
1508 }
1509
1510 impl<'tcx> UserString<'tcx> for ty::EquatePredicate<'tcx> {
1511 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1512 format!("{} == {}",
1513 self.0.user_string(tcx),
1514 self.1.user_string(tcx))
1515 }
1516 }
1517
1518 impl<'tcx> Repr<'tcx> for ty::TraitPredicate<'tcx> {
1519 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1520 format!("TraitPredicate({})",
1521 self.trait_ref.repr(tcx))
1522 }
1523 }
1524
1525 impl<'tcx> UserString<'tcx> for ty::TraitPredicate<'tcx> {
1526 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1527 format!("{} : {}",
1528 self.trait_ref.self_ty().user_string(tcx),
1529 self.trait_ref.user_string(tcx))
1530 }
1531 }
1532
1533 impl<'tcx> UserString<'tcx> for ty::ProjectionPredicate<'tcx> {
1534 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1535 format!("{} == {}",
1536 self.projection_ty.user_string(tcx),
1537 self.ty.user_string(tcx))
1538 }
1539 }
1540
1541 impl<'tcx> Repr<'tcx> for ty::ProjectionTy<'tcx> {
1542 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1543 format!("{}::{}",
1544 self.trait_ref.repr(tcx),
1545 self.item_name.repr(tcx))
1546 }
1547 }
1548
1549 impl<'tcx> UserString<'tcx> for ty::ProjectionTy<'tcx> {
1550 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1551 format!("<{} as {}>::{}",
1552 self.trait_ref.self_ty().user_string(tcx),
1553 self.trait_ref.user_string(tcx),
1554 self.item_name.user_string(tcx))
1555 }
1556 }
1557
1558 impl<'tcx> UserString<'tcx> for ty::Predicate<'tcx> {
1559 fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1560 match *self {
1561 ty::Predicate::Trait(ref data) => data.user_string(tcx),
1562 ty::Predicate::Equate(ref predicate) => predicate.user_string(tcx),
1563 ty::Predicate::RegionOutlives(ref predicate) => predicate.user_string(tcx),
1564 ty::Predicate::TypeOutlives(ref predicate) => predicate.user_string(tcx),
1565 ty::Predicate::Projection(ref predicate) => predicate.user_string(tcx),
1566 }
1567 }
1568 }
1569
1570 impl<'tcx> Repr<'tcx> for ast::Unsafety {
1571 fn repr(&self, _: &ctxt<'tcx>) -> String {
1572 format!("{:?}", *self)
1573 }
1574 }