@@ -298,17 +298,9 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
298
298
299
299
fn closure_to_string < ' tcx > ( cx : & ctxt < ' tcx > , cty : & ty:: ClosureTy < ' tcx > ) -> String {
300
300
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 ( ']' ) ;
312
304
s
313
305
}
314
306
@@ -399,18 +391,10 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
399
391
ty_enum( did, substs) | ty_struct( did, substs) => {
400
392
let base = ty:: item_path_str ( cx, did) ;
401
393
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, & [ ] )
403
395
}
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)
414
398
}
415
399
ty:: ty_projection( ref data) => {
416
400
format ! ( "<{} as {}>::{}" ,
@@ -420,14 +404,15 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
420
404
}
421
405
ty_str => "str" . to_string ( ) ,
422
406
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| {
424
409
closure_to_string ( cx, & cl. closure_type . subst ( cx, substs) )
425
410
} ) . unwrap_or_else ( || {
426
411
if did. krate == ast:: LOCAL_CRATE {
427
412
let span = cx. map . span ( did. node ) ;
428
- format ! ( "closure[ {}]" , span. repr( cx) )
413
+ format ! ( "[closure {}]" , span. repr( cx) )
429
414
} else {
430
- format ! ( "closure" )
415
+ format ! ( "[ closure] " )
431
416
}
432
417
} )
433
418
}
@@ -458,7 +443,8 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
458
443
base : & str ,
459
444
substs : & subst:: Substs < ' tcx > ,
460
445
generics : & ty:: Generics < ' tcx > ,
461
- did : ast:: DefId )
446
+ did : ast:: DefId ,
447
+ projections : & [ ty:: ProjectionPredicate < ' tcx > ] )
462
448
-> String
463
449
{
464
450
if cx. sess . verbose ( ) {
@@ -511,16 +497,30 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
511
497
strs. push ( ty_to_string ( cx, * t) )
512
498
}
513
499
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 ! ( "{}({}){}" ,
516
515
base,
517
516
if strs[ 0 ] . starts_with( "(" ) && strs[ 0 ] . ends_with( ",)" ) {
518
517
& strs[ 0 ] [ 1 .. strs[ 0 ] . len( ) - 2 ] // Remove '(' and ',)'
519
518
} else if strs[ 0 ] . starts_with( "(" ) && strs[ 0 ] . ends_with( ")" ) {
520
519
& strs[ 0 ] [ 1 .. strs[ 0 ] . len( ) - 1 ] // Remove '(' and ')'
521
520
} else {
522
521
& strs[ 0 ] [ ]
523
- } )
522
+ } ,
523
+ tail)
524
524
} else if strs. len ( ) > 0 {
525
525
format ! ( "{}<{}>" , base, strs. connect( ", " ) )
526
526
} else {
@@ -622,6 +622,65 @@ impl<'tcx> Repr<'tcx> for def::Def {
622
622
}
623
623
}
624
624
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
+
625
684
impl < ' tcx > Repr < ' tcx > for ty:: TypeParameterDef < ' tcx > {
626
685
fn repr ( & self , tcx : & ctxt < ' tcx > ) -> String {
627
686
format ! ( "TypeParameterDef({:?}, {}, {:?}/{})" ,
@@ -700,12 +759,6 @@ impl<'tcx> Repr<'tcx> for ty::BuiltinBounds {
700
759
}
701
760
}
702
761
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
-
709
762
impl < ' tcx > Repr < ' tcx > for ty:: ParamBounds < ' tcx > {
710
763
fn repr ( & self , tcx : & ctxt < ' tcx > ) -> String {
711
764
let mut res = Vec :: new ( ) ;
@@ -726,7 +779,8 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
726
779
let trait_def = ty:: lookup_trait_def ( tcx, self . def_id ) ;
727
780
format ! ( "TraitRef({}, {})" ,
728
781
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, & [ ] ) )
730
784
}
731
785
}
732
786
@@ -1109,14 +1163,8 @@ impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> {
1109
1163
}
1110
1164
}
1111
1165
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 {
1120
1168
let mut res = Vec :: new ( ) ;
1121
1169
1122
1170
let region_str = self . region_bound . user_string ( tcx) ;
@@ -1128,6 +1176,10 @@ impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> {
1128
1176
res. push ( bound. user_string ( tcx) ) ;
1129
1177
}
1130
1178
1179
+ for projection_bound in self . projection_bounds . iter ( ) {
1180
+ res. push ( projection_bound. user_string ( tcx) ) ;
1181
+ }
1182
+
1131
1183
res. connect ( "+" )
1132
1184
}
1133
1185
}
@@ -1183,7 +1235,7 @@ impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> {
1183
1235
let path_str = ty:: item_path_str ( tcx, self . def_id ) ;
1184
1236
let trait_def = ty:: lookup_trait_def ( tcx, self . def_id ) ;
1185
1237
parameterized ( tcx, path_str. as_slice ( ) , self . substs ,
1186
- & trait_def. generics , self . def_id )
1238
+ & trait_def. generics , self . def_id , & [ ] )
1187
1239
}
1188
1240
}
1189
1241
0 commit comments