@@ -43,8 +43,7 @@ use rustc::metadata::cstore;
4343use rustc:: metadata:: csearch;
4444use rustc:: metadata:: decoder;
4545use rustc:: middle:: def;
46- use rustc:: middle:: subst;
47- use rustc:: middle:: subst:: VecPerParamSpace ;
46+ use rustc:: middle:: subst:: { mod, ParamSpace , VecPerParamSpace } ;
4847use rustc:: middle:: ty;
4948use rustc:: middle:: stability;
5049use rustc:: session:: config;
@@ -493,7 +492,7 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
493492#[ deriving( Clone , RustcEncodable , RustcDecodable , PartialEq ) ]
494493pub enum TyParamBound {
495494 RegionBound ( Lifetime ) ,
496- TraitBound ( Type )
495+ TraitBound ( PolyTrait )
497496}
498497
499498impl Clean < TyParamBound > for ast:: TyParamBound {
@@ -516,19 +515,55 @@ impl Clean<Vec<TyParamBound>> for ty::ExistentialBounds {
516515 }
517516}
518517
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;
520521 let lifetimes = substs. regions ( ) . get_slice ( subst:: TypeSpace )
521522 . iter ( )
522523 . filter_map ( |v| v. clean ( cx) )
523524 . collect ( ) ;
524525 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 {
526562 Path {
527563 global : false ,
528564 segments : vec ! [ PathSegment {
529565 name: name. to_string( ) ,
530- lifetimes: lifetimes,
531- types: types,
566+ params: external_path_params( cx, trait_did, substs)
532567 } ] ,
533568 }
534569}
@@ -543,25 +578,28 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
543578 let ( did, path) = match * self {
544579 ty:: BoundSend =>
545580 ( tcx. lang_items . send_trait ( ) . unwrap ( ) ,
546- external_path ( cx, "Send" , & empty) ) ,
581+ external_path ( cx, "Send" , None , & empty) ) ,
547582 ty:: BoundSized =>
548583 ( tcx. lang_items . sized_trait ( ) . unwrap ( ) ,
549- external_path ( cx, "Sized" , & empty) ) ,
584+ external_path ( cx, "Sized" , None , & empty) ) ,
550585 ty:: BoundCopy =>
551586 ( tcx. lang_items . copy_trait ( ) . unwrap ( ) ,
552- external_path ( cx, "Copy" , & empty) ) ,
587+ external_path ( cx, "Copy" , None , & empty) ) ,
553588 ty:: BoundSync =>
554589 ( tcx. lang_items . sync_trait ( ) . unwrap ( ) ,
555- external_path ( cx, "Sync" , & empty) ) ,
590+ external_path ( cx, "Sync" , None , & empty) ) ,
556591 } ;
557592 let fqn = csearch:: get_item_path ( tcx, did) ;
558593 let fqn = fqn. into_iter ( ) . map ( |i| i. to_string ( ) ) . collect ( ) ;
559594 cx. external_paths . borrow_mut ( ) . as_mut ( ) . unwrap ( ) . insert ( did,
560595 ( 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 ! [ ]
565603 } )
566604 }
567605}
@@ -582,13 +620,34 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
582620 let fqn = fqn. into_iter ( ) . map ( |i| i. to_string ( ) )
583621 . collect :: < Vec < String > > ( ) ;
584622 let path = external_path ( cx, fqn. last ( ) . unwrap ( ) . as_slice ( ) ,
585- & self . substs ) ;
623+ Some ( self . def_id ) , & self . substs ) ;
586624 cx. external_paths . borrow_mut ( ) . as_mut ( ) . unwrap ( ) . insert ( self . def_id ,
587625 ( 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
592651 } )
593652 }
594653}
@@ -615,7 +674,7 @@ impl<'tcx> Clean<(Vec<TyParamBound>, Option<Type>)> for ty::ParamBounds<'tcx> {
615674 ( v, None )
616675 } else {
617676 let ty = match ty:: BoundSized . clean ( cx) {
618- TraitBound ( ty ) => ty ,
677+ TraitBound ( polyt ) => polyt . trait_ ,
619678 _ => unreachable ! ( )
620679 } ;
621680 ( v, Some ( ty) )
@@ -627,7 +686,10 @@ impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
627686 fn clean ( & self , cx : & DocContext ) -> Option < Vec < TyParamBound > > {
628687 let mut v = Vec :: new ( ) ;
629688 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+ } ) ) ) ;
631693 if v. len ( ) > 0 { Some ( v) } else { None }
632694 }
633695}
@@ -1006,9 +1068,12 @@ impl Clean<Type> for ast::TraitRef {
10061068 }
10071069}
10081070
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+ }
10121077 }
10131078}
10141079
@@ -1129,6 +1194,13 @@ impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
11291194 }
11301195}
11311196
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+
11321204/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
11331205/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
11341206/// it does not preserve mutability or boxes.
@@ -1399,7 +1471,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
13991471 _ => TypeEnum ,
14001472 } ;
14011473 let path = external_path ( cx, fqn. last ( ) . unwrap ( ) . to_string ( ) . as_slice ( ) ,
1402- substs) ;
1474+ None , substs) ;
14031475 cx. external_paths . borrow_mut ( ) . as_mut ( ) . unwrap ( ) . insert ( did, ( fqn, kind) ) ;
14041476 ResolvedPath {
14051477 path : path,
@@ -1708,31 +1780,48 @@ impl Clean<Path> for ast::Path {
17081780}
17091781
17101782#[ 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+ }
17151792}
17161793
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 {
17201797 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+ }
17221802 }
17231803
17241804 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+ }
17291809 }
1730- } ;
1810+ }
1811+ }
1812+ }
1813+
1814+ #[ deriving( Clone , RustcEncodable , RustcDecodable , PartialEq ) ]
1815+ pub struct PathSegment {
1816+ pub name : String ,
1817+ pub params : PathParameters
1818+ }
17311819
1820+ impl Clean < PathSegment > for ast:: PathSegment {
1821+ fn clean ( & self , cx : & DocContext ) -> PathSegment {
17321822 PathSegment {
17331823 name : self . identifier . clean ( cx) ,
1734- lifetimes : lifetimes,
1735- types : types,
1824+ params : self . parameters . clean ( cx)
17361825 }
17371826 }
17381827}
@@ -2363,8 +2452,10 @@ fn lang_struct(cx: &DocContext, did: Option<ast::DefId>,
23632452 global : false ,
23642453 segments : vec ! [ PathSegment {
23652454 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+ }
23682459 } ] ,
23692460 } ,
23702461 }
0 commit comments