@@ -43,8 +43,7 @@ use rustc::metadata::cstore;
43
43
use rustc:: metadata:: csearch;
44
44
use rustc:: metadata:: decoder;
45
45
use rustc:: middle:: def;
46
- use rustc:: middle:: subst;
47
- use rustc:: middle:: subst:: VecPerParamSpace ;
46
+ use rustc:: middle:: subst:: { mod, ParamSpace , VecPerParamSpace } ;
48
47
use rustc:: middle:: ty;
49
48
use rustc:: middle:: stability;
50
49
use rustc:: session:: config;
@@ -493,7 +492,7 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
493
492
#[ deriving( Clone , RustcEncodable , RustcDecodable , PartialEq ) ]
494
493
pub enum TyParamBound {
495
494
RegionBound ( Lifetime ) ,
496
- TraitBound ( Type )
495
+ TraitBound ( PolyTrait )
497
496
}
498
497
499
498
impl Clean < TyParamBound > for ast:: TyParamBound {
@@ -516,19 +515,55 @@ impl Clean<Vec<TyParamBound>> for ty::ExistentialBounds {
516
515
}
517
516
}
518
517
519
- fn external_path ( cx : & DocContext , name : & str , substs : & subst:: Substs ) -> Path {
518
+ fn external_path_params ( cx : & DocContext , trait_did : Option < ast:: DefId > ,
519
+ substs : & subst:: Substs ) -> PathParameters {
520
+ use rustc:: middle:: ty:: sty;
520
521
let lifetimes = substs. regions ( ) . get_slice ( subst:: TypeSpace )
521
522
. iter ( )
522
523
. filter_map ( |v| v. clean ( cx) )
523
524
. collect ( ) ;
524
525
let types = substs. types . get_slice ( subst:: TypeSpace ) . to_vec ( ) ;
525
- let types = types. clean ( cx) ;
526
+
527
+ match ( trait_did, cx. tcx_opt ( ) ) {
528
+ // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
529
+ ( Some ( did) , Some ( ref tcx) ) if tcx. lang_items . fn_trait_kind ( did) . is_some ( ) => {
530
+ assert_eq ! ( types. len( ) , 2 ) ;
531
+ let inputs = match types[ 0 ] . sty {
532
+ sty:: ty_tup( ref tys) => tys. iter ( ) . map ( |t| t. clean ( cx) ) . collect ( ) ,
533
+ _ => {
534
+ return PathParameters :: AngleBracketed {
535
+ lifetimes : lifetimes,
536
+ types : types. clean ( cx)
537
+ }
538
+ }
539
+ } ;
540
+ let output = match types[ 1 ] . sty {
541
+ sty:: ty_tup( ref v) if v. is_empty ( ) => None , // -> ()
542
+ _ => Some ( types[ 1 ] . clean ( cx) )
543
+ } ;
544
+ PathParameters :: Parenthesized {
545
+ inputs : inputs,
546
+ output : output
547
+ }
548
+ } ,
549
+ ( _, _) => {
550
+ PathParameters :: AngleBracketed {
551
+ lifetimes : lifetimes,
552
+ types : types. clean ( cx) ,
553
+ }
554
+ }
555
+ }
556
+ }
557
+
558
+ // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
559
+ // from Fn<(A, B,), C> to Fn(A, B) -> C
560
+ fn external_path ( cx : & DocContext , name : & str , trait_did : Option < ast:: DefId > ,
561
+ substs : & subst:: Substs ) -> Path {
526
562
Path {
527
563
global : false ,
528
564
segments : vec ! [ PathSegment {
529
565
name: name. to_string( ) ,
530
- lifetimes: lifetimes,
531
- types: types,
566
+ params: external_path_params( cx, trait_did, substs)
532
567
} ] ,
533
568
}
534
569
}
@@ -543,25 +578,28 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
543
578
let ( did, path) = match * self {
544
579
ty:: BoundSend =>
545
580
( tcx. lang_items . send_trait ( ) . unwrap ( ) ,
546
- external_path ( cx, "Send" , & empty) ) ,
581
+ external_path ( cx, "Send" , None , & empty) ) ,
547
582
ty:: BoundSized =>
548
583
( tcx. lang_items . sized_trait ( ) . unwrap ( ) ,
549
- external_path ( cx, "Sized" , & empty) ) ,
584
+ external_path ( cx, "Sized" , None , & empty) ) ,
550
585
ty:: BoundCopy =>
551
586
( tcx. lang_items . copy_trait ( ) . unwrap ( ) ,
552
- external_path ( cx, "Copy" , & empty) ) ,
587
+ external_path ( cx, "Copy" , None , & empty) ) ,
553
588
ty:: BoundSync =>
554
589
( tcx. lang_items . sync_trait ( ) . unwrap ( ) ,
555
- external_path ( cx, "Sync" , & empty) ) ,
590
+ external_path ( cx, "Sync" , None , & empty) ) ,
556
591
} ;
557
592
let fqn = csearch:: get_item_path ( tcx, did) ;
558
593
let fqn = fqn. into_iter ( ) . map ( |i| i. to_string ( ) ) . collect ( ) ;
559
594
cx. external_paths . borrow_mut ( ) . as_mut ( ) . unwrap ( ) . insert ( did,
560
595
( fqn, TypeTrait ) ) ;
561
- TraitBound ( ResolvedPath {
562
- path : path,
563
- typarams : None ,
564
- did : did,
596
+ TraitBound ( PolyTrait {
597
+ trait_ : ResolvedPath {
598
+ path : path,
599
+ typarams : None ,
600
+ did : did,
601
+ } ,
602
+ lifetimes : vec ! [ ]
565
603
} )
566
604
}
567
605
}
@@ -582,13 +620,34 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
582
620
let fqn = fqn. into_iter ( ) . map ( |i| i. to_string ( ) )
583
621
. collect :: < Vec < String > > ( ) ;
584
622
let path = external_path ( cx, fqn. last ( ) . unwrap ( ) . as_slice ( ) ,
585
- & self . substs ) ;
623
+ Some ( self . def_id ) , & self . substs ) ;
586
624
cx. external_paths . borrow_mut ( ) . as_mut ( ) . unwrap ( ) . insert ( self . def_id ,
587
625
( fqn, TypeTrait ) ) ;
588
- TraitBound ( ResolvedPath {
589
- path : path,
590
- typarams : None ,
591
- did : self . def_id ,
626
+
627
+ debug ! ( "ty::TraitRef\n substs.types(TypeSpace): {}\n " ,
628
+ self . substs. types. get_slice( ParamSpace :: TypeSpace ) ) ;
629
+
630
+ // collect any late bound regions
631
+ let mut late_bounds = vec ! [ ] ;
632
+ for & ty_s in self . substs . types . get_slice ( ParamSpace :: TypeSpace ) . iter ( ) {
633
+ use rustc:: middle:: ty:: { Region , sty} ;
634
+ if let sty:: ty_tup( ref ts) = ty_s. sty {
635
+ for & ty_s in ts. iter ( ) {
636
+ if let sty:: ty_rptr( ref reg, _) = ty_s. sty {
637
+ if let & Region :: ReLateBound ( _, _) = reg {
638
+ debug ! ( " hit an ReLateBound {}" , reg) ;
639
+ if let Some ( lt) = reg. clean ( cx) {
640
+ late_bounds. push ( lt)
641
+ }
642
+ }
643
+ }
644
+ }
645
+ }
646
+ }
647
+
648
+ TraitBound ( PolyTrait {
649
+ trait_ : ResolvedPath { path : path, typarams : None , did : self . def_id , } ,
650
+ lifetimes : late_bounds
592
651
} )
593
652
}
594
653
}
@@ -615,7 +674,7 @@ impl<'tcx> Clean<(Vec<TyParamBound>, Option<Type>)> for ty::ParamBounds<'tcx> {
615
674
( v, None )
616
675
} else {
617
676
let ty = match ty:: BoundSized . clean ( cx) {
618
- TraitBound ( ty ) => ty ,
677
+ TraitBound ( polyt ) => polyt . trait_ ,
619
678
_ => unreachable ! ( )
620
679
} ;
621
680
( v, Some ( ty) )
@@ -627,7 +686,10 @@ impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
627
686
fn clean ( & self , cx : & DocContext ) -> Option < Vec < TyParamBound > > {
628
687
let mut v = Vec :: new ( ) ;
629
688
v. extend ( self . regions ( ) . iter ( ) . filter_map ( |r| r. clean ( cx) ) . map ( RegionBound ) ) ;
630
- v. extend ( self . types . iter ( ) . map ( |t| TraitBound ( t. clean ( cx) ) ) ) ;
689
+ v. extend ( self . types . iter ( ) . map ( |t| TraitBound ( PolyTrait {
690
+ trait_ : t. clean ( cx) ,
691
+ lifetimes : vec ! [ ]
692
+ } ) ) ) ;
631
693
if v. len ( ) > 0 { Some ( v) } else { None }
632
694
}
633
695
}
@@ -1006,9 +1068,12 @@ impl Clean<Type> for ast::TraitRef {
1006
1068
}
1007
1069
}
1008
1070
1009
- impl Clean < Type > for ast:: PolyTraitRef {
1010
- fn clean ( & self , cx : & DocContext ) -> Type {
1011
- self . trait_ref . clean ( cx)
1071
+ impl Clean < PolyTrait > for ast:: PolyTraitRef {
1072
+ fn clean ( & self , cx : & DocContext ) -> PolyTrait {
1073
+ PolyTrait {
1074
+ trait_ : self . trait_ref . clean ( cx) ,
1075
+ lifetimes : self . bound_lifetimes . clean ( cx)
1076
+ }
1012
1077
}
1013
1078
}
1014
1079
@@ -1129,6 +1194,13 @@ impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
1129
1194
}
1130
1195
}
1131
1196
1197
+ /// A trait reference, which may have higher ranked lifetimes.
1198
+ #[ deriving( Clone , RustcEncodable , RustcDecodable , PartialEq ) ]
1199
+ pub struct PolyTrait {
1200
+ pub trait_ : Type ,
1201
+ pub lifetimes : Vec < Lifetime >
1202
+ }
1203
+
1132
1204
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
1133
1205
/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
1134
1206
/// it does not preserve mutability or boxes.
@@ -1399,7 +1471,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
1399
1471
_ => TypeEnum ,
1400
1472
} ;
1401
1473
let path = external_path ( cx, fqn. last ( ) . unwrap ( ) . to_string ( ) . as_slice ( ) ,
1402
- substs) ;
1474
+ None , substs) ;
1403
1475
cx. external_paths . borrow_mut ( ) . as_mut ( ) . unwrap ( ) . insert ( did, ( fqn, kind) ) ;
1404
1476
ResolvedPath {
1405
1477
path : path,
@@ -1708,31 +1780,48 @@ impl Clean<Path> for ast::Path {
1708
1780
}
1709
1781
1710
1782
#[ deriving( Clone , RustcEncodable , RustcDecodable , PartialEq ) ]
1711
- pub struct PathSegment {
1712
- pub name : String ,
1713
- pub lifetimes : Vec < Lifetime > ,
1714
- pub types : Vec < Type > ,
1783
+ pub enum PathParameters {
1784
+ AngleBracketed {
1785
+ lifetimes : Vec < Lifetime > ,
1786
+ types : Vec < Type > ,
1787
+ } ,
1788
+ Parenthesized {
1789
+ inputs : Vec < Type > ,
1790
+ output : Option < Type >
1791
+ }
1715
1792
}
1716
1793
1717
- impl Clean < PathSegment > for ast:: PathSegment {
1718
- fn clean ( & self , cx : & DocContext ) -> PathSegment {
1719
- let ( lifetimes , types ) = match self . parameters {
1794
+ impl Clean < PathParameters > for ast:: PathParameters {
1795
+ fn clean ( & self , cx : & DocContext ) -> PathParameters {
1796
+ match * self {
1720
1797
ast:: AngleBracketedParameters ( ref data) => {
1721
- ( data. lifetimes . clean ( cx) , data. types . clean ( cx) )
1798
+ PathParameters :: AngleBracketed {
1799
+ lifetimes : data. lifetimes . clean ( cx) ,
1800
+ types : data. types . clean ( cx)
1801
+ }
1722
1802
}
1723
1803
1724
1804
ast:: ParenthesizedParameters ( ref data) => {
1725
- // FIXME -- rustdoc should be taught about Foo() notation
1726
- let inputs = Tuple ( data. inputs . clean ( cx) ) ;
1727
- let output = data. output . as_ref ( ) . map ( |t| t . clean ( cx) ) . unwrap_or ( Tuple ( Vec :: new ( ) ) ) ;
1728
- ( Vec :: new ( ) , vec ! [ inputs , output ] )
1805
+ PathParameters :: Parenthesized {
1806
+ inputs : data. inputs . clean ( cx) ,
1807
+ output : data. output . clean ( cx)
1808
+ }
1729
1809
}
1730
- } ;
1810
+ }
1811
+ }
1812
+ }
1813
+
1814
+ #[ deriving( Clone , RustcEncodable , RustcDecodable , PartialEq ) ]
1815
+ pub struct PathSegment {
1816
+ pub name : String ,
1817
+ pub params : PathParameters
1818
+ }
1731
1819
1820
+ impl Clean < PathSegment > for ast:: PathSegment {
1821
+ fn clean ( & self , cx : & DocContext ) -> PathSegment {
1732
1822
PathSegment {
1733
1823
name : self . identifier . clean ( cx) ,
1734
- lifetimes : lifetimes,
1735
- types : types,
1824
+ params : self . parameters . clean ( cx)
1736
1825
}
1737
1826
}
1738
1827
}
@@ -2363,8 +2452,10 @@ fn lang_struct(cx: &DocContext, did: Option<ast::DefId>,
2363
2452
global : false ,
2364
2453
segments : vec ! [ PathSegment {
2365
2454
name: name. to_string( ) ,
2366
- lifetimes: vec![ ] ,
2367
- types: vec![ t. clean( cx) ] ,
2455
+ params: PathParameters :: AngleBracketed {
2456
+ lifetimes: vec![ ] ,
2457
+ types: vec![ t. clean( cx) ] ,
2458
+ }
2368
2459
} ] ,
2369
2460
} ,
2370
2461
}
0 commit comments