Skip to content

Commit 7d68250

Browse files
committed
When pretty-printing object types, include the output associated type
1 parent 006f3ea commit 7d68250

File tree

1 file changed

+97
-45
lines changed

1 file changed

+97
-45
lines changed

src/librustc/util/ppaux.rs

Lines changed: 97 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -298,17 +298,9 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
298298

299299
fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String {
300300
let mut s = String::new();
301-
302-
match cty.unsafety {
303-
ast::Unsafety::Normal => {}
304-
ast::Unsafety::Unsafe => {
305-
s.push_str(cty.unsafety.to_string().as_slice());
306-
s.push(' ');
307-
}
308-
};
309-
310-
push_sig_to_string(cx, &mut s, '|', '|', &cty.sig);
311-
301+
s.push_str("[closure");
302+
push_sig_to_string(cx, &mut s, '(', ')', &cty.sig);
303+
s.push(']');
312304
s
313305
}
314306

@@ -399,18 +391,10 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
399391
ty_enum(did, substs) | ty_struct(did, substs) => {
400392
let base = ty::item_path_str(cx, did);
401393
let generics = ty::lookup_item_type(cx, did).generics;
402-
parameterized(cx, base.as_slice(), substs, &generics, did)
394+
parameterized(cx, base.as_slice(), substs, &generics, did, &[])
403395
}
404-
ty_trait(box ty::TyTrait {
405-
ref principal, ref bounds
406-
}) => {
407-
let principal = principal.user_string(cx);
408-
let bound_str = bounds.user_string(cx);
409-
let bound_sep = if bound_str.is_empty() { "" } else { " + " };
410-
format!("{}{}{}",
411-
principal,
412-
bound_sep,
413-
bound_str)
396+
ty_trait(ref data) => {
397+
data.user_string(cx)
414398
}
415399
ty::ty_projection(ref data) => {
416400
format!("<{} as {}>::{}",
@@ -420,14 +404,15 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
420404
}
421405
ty_str => "str".to_string(),
422406
ty_closure(ref did, _, substs) => {
423-
cx.closures.borrow().get(did).map(|cl| {
407+
let closures = cx.closures.borrow();
408+
closures.get(did).map(|cl| {
424409
closure_to_string(cx, &cl.closure_type.subst(cx, substs))
425410
}).unwrap_or_else(|| {
426411
if did.krate == ast::LOCAL_CRATE {
427412
let span = cx.map.span(did.node);
428-
format!("closure[{}]", span.repr(cx))
413+
format!("[closure {}]", span.repr(cx))
429414
} else {
430-
format!("closure")
415+
format!("[closure]")
431416
}
432417
})
433418
}
@@ -458,7 +443,8 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
458443
base: &str,
459444
substs: &subst::Substs<'tcx>,
460445
generics: &ty::Generics<'tcx>,
461-
did: ast::DefId)
446+
did: ast::DefId,
447+
projections: &[ty::ProjectionPredicate<'tcx>])
462448
-> String
463449
{
464450
if cx.sess.verbose() {
@@ -511,16 +497,30 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
511497
strs.push(ty_to_string(cx, *t))
512498
}
513499

514-
if cx.lang_items.fn_trait_kind(did).is_some() {
515-
format!("{}({})", // TODO
500+
for projection in projections.iter() {
501+
strs.push(format!("{}={}",
502+
projection.projection_ty.item_name.user_string(cx),
503+
projection.ty.user_string(cx)));
504+
}
505+
506+
if cx.lang_items.fn_trait_kind(did).is_some() && projections.len() == 1 {
507+
let projection_ty = projections[0].ty;
508+
let tail =
509+
if ty::type_is_nil(projection_ty) {
510+
format!("")
511+
} else {
512+
format!(" -> {}", projection_ty.user_string(cx))
513+
};
514+
format!("{}({}){}",
516515
base,
517516
if strs[0].starts_with("(") && strs[0].ends_with(",)") {
518517
&strs[0][1 .. strs[0].len() - 2] // Remove '(' and ',)'
519518
} else if strs[0].starts_with("(") && strs[0].ends_with(")") {
520519
&strs[0][1 .. strs[0].len() - 1] // Remove '(' and ')'
521520
} else {
522521
&strs[0][]
523-
})
522+
},
523+
tail)
524524
} else if strs.len() > 0 {
525525
format!("{}<{}>", base, strs.connect(", "))
526526
} else {
@@ -622,6 +622,65 @@ impl<'tcx> Repr<'tcx> for def::Def {
622622
}
623623
}
624624

625+
/// This curious type is here to help pretty-print trait objects. In
626+
/// a trait object, the projections are stored separately from the
627+
/// main trait bound, but in fact we want to package them together
628+
/// when printing out; they also have separate binders, but we want
629+
/// them to share a binder when we print them out. (And the binder
630+
/// pretty-printing logic is kind of clever and we don't want to
631+
/// reproduce it.) So we just repackage up the structure somewhat.
632+
///
633+
/// Right now there is only one trait in an object that can have
634+
/// projection bounds, so we just stuff them altogether. But in
635+
/// reality we should eventually sort things out better.
636+
type TraitAndProjections<'tcx> =
637+
(Rc<ty::TraitRef<'tcx>>, Vec<ty::ProjectionPredicate<'tcx>>);
638+
639+
impl<'tcx> UserString<'tcx> for TraitAndProjections<'tcx> {
640+
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
641+
let &(ref trait_ref, ref projection_bounds) = self;
642+
let base = ty::item_path_str(tcx, trait_ref.def_id);
643+
let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id);
644+
parameterized(tcx,
645+
base.as_slice(),
646+
trait_ref.substs,
647+
&trait_def.generics,
648+
trait_ref.def_id,
649+
&projection_bounds[])
650+
}
651+
}
652+
653+
impl<'tcx> UserString<'tcx> for ty::TyTrait<'tcx> {
654+
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
655+
let &ty::TyTrait { ref principal, ref bounds } = self;
656+
657+
let mut components = vec![];
658+
659+
let tap: ty::Binder<TraitAndProjections<'tcx>> =
660+
ty::Binder((principal.0.clone(),
661+
bounds.projection_bounds.iter().map(|x| x.0.clone()).collect()));
662+
663+
// Generate the main trait ref, including associated types.
664+
components.push(tap.user_string(tcx));
665+
666+
// Builtin bounds.
667+
for bound in bounds.builtin_bounds.iter() {
668+
components.push(bound.user_string(tcx));
669+
}
670+
671+
// Region, if not obviously implied by builtin bounds.
672+
if bounds.region_bound != ty::ReStatic ||
673+
!bounds.builtin_bounds.contains(&ty::BoundSend)
674+
{ // Region bound is implied by builtin bounds:
675+
components.push(bounds.region_bound.user_string(tcx));
676+
}
677+
678+
components.retain(|s| !s.is_empty());
679+
680+
components.connect(" + ")
681+
}
682+
}
683+
625684
impl<'tcx> Repr<'tcx> for ty::TypeParameterDef<'tcx> {
626685
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
627686
format!("TypeParameterDef({:?}, {}, {:?}/{})",
@@ -700,12 +759,6 @@ impl<'tcx> Repr<'tcx> for ty::BuiltinBounds {
700759
}
701760
}
702761

703-
impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
704-
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
705-
self.user_string(tcx)
706-
}
707-
}
708-
709762
impl<'tcx> Repr<'tcx> for ty::ParamBounds<'tcx> {
710763
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
711764
let mut res = Vec::new();
@@ -726,7 +779,8 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
726779
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
727780
format!("TraitRef({}, {})",
728781
self.substs.self_ty().repr(tcx),
729-
parameterized(tcx, base.as_slice(), self.substs, &trait_def.generics, self.def_id))
782+
parameterized(tcx, base.as_slice(), self.substs,
783+
&trait_def.generics, self.def_id, &[]))
730784
}
731785
}
732786

@@ -1109,14 +1163,8 @@ impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> {
11091163
}
11101164
}
11111165

1112-
impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> {
1113-
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1114-
if self.builtin_bounds.contains(&ty::BoundSend) &&
1115-
self.region_bound == ty::ReStatic
1116-
{ // Region bound is implied by builtin bounds:
1117-
return self.builtin_bounds.repr(tcx);
1118-
}
1119-
1166+
impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
1167+
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
11201168
let mut res = Vec::new();
11211169

11221170
let region_str = self.region_bound.user_string(tcx);
@@ -1128,6 +1176,10 @@ impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> {
11281176
res.push(bound.user_string(tcx));
11291177
}
11301178

1179+
for projection_bound in self.projection_bounds.iter() {
1180+
res.push(projection_bound.user_string(tcx));
1181+
}
1182+
11311183
res.connect("+")
11321184
}
11331185
}
@@ -1183,7 +1235,7 @@ impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> {
11831235
let path_str = ty::item_path_str(tcx, self.def_id);
11841236
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
11851237
parameterized(tcx, path_str.as_slice(), self.substs,
1186-
&trait_def.generics, self.def_id)
1238+
&trait_def.generics, self.def_id, &[])
11871239
}
11881240
}
11891241

0 commit comments

Comments
 (0)