@@ -3,8 +3,10 @@ use std::collections::BTreeMap;
33
44use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
55use rustc_middle:: ty:: TyCtxt ;
6+ use rustc_span:: def_id:: DefId ;
67use rustc_span:: symbol:: Symbol ;
78use serde:: ser:: { Serialize , SerializeSeq , SerializeStruct , Serializer } ;
9+ use thin_vec:: ThinVec ;
810
911use crate :: clean;
1012use crate :: clean:: types:: { Function , Generics , ItemId , Type , WherePredicate } ;
@@ -37,7 +39,13 @@ pub(crate) fn build_index<'tcx>(
3739 desc,
3840 parent : Some ( parent) ,
3941 parent_idx : None ,
40- search_type : get_function_type_for_search ( item, tcx, impl_generics. as_ref ( ) , cache) ,
42+ search_type : get_function_type_for_search (
43+ item,
44+ tcx,
45+ impl_generics. as_ref ( ) ,
46+ Some ( parent) ,
47+ cache,
48+ ) ,
4149 aliases : item. attrs . get_doc_aliases ( ) ,
4250 deprecation : item. deprecation ( tcx) ,
4351 } ) ;
@@ -473,12 +481,42 @@ pub(crate) fn get_function_type_for_search<'tcx>(
473481 item : & clean:: Item ,
474482 tcx : TyCtxt < ' tcx > ,
475483 impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
484+ parent : Option < DefId > ,
476485 cache : & Cache ,
477486) -> Option < IndexItemFunctionType > {
487+ let mut trait_info = None ;
488+ let impl_or_trait_generics = impl_generics. or_else ( || {
489+ if let Some ( def_id) = parent &&
490+ let Some ( trait_) = cache. traits . get ( & def_id) &&
491+ let Some ( ( path, _) ) = cache. paths . get ( & def_id)
492+ . or_else ( || cache. external_paths . get ( & def_id) )
493+ {
494+ let path = clean:: Path {
495+ res : rustc_hir:: def:: Res :: Def ( rustc_hir:: def:: DefKind :: Trait , def_id) ,
496+ segments : path. iter ( ) . map ( |name| clean:: PathSegment {
497+ name : * name,
498+ args : clean:: GenericArgs :: AngleBracketed {
499+ args : Vec :: new ( ) . into_boxed_slice ( ) ,
500+ bindings : ThinVec :: new ( ) ,
501+ } ,
502+ } ) . collect ( ) ,
503+ } ;
504+ trait_info = Some ( ( clean:: Type :: Path { path } , trait_. generics . clone ( ) ) ) ;
505+ Some ( trait_info. as_ref ( ) . unwrap ( ) )
506+ } else {
507+ None
508+ }
509+ } ) ;
478510 let ( mut inputs, mut output, where_clause) = match * item. kind {
479- clean:: FunctionItem ( ref f) => get_fn_inputs_and_outputs ( f, tcx, impl_generics, cache) ,
480- clean:: MethodItem ( ref m, _) => get_fn_inputs_and_outputs ( m, tcx, impl_generics, cache) ,
481- clean:: TyMethodItem ( ref m) => get_fn_inputs_and_outputs ( m, tcx, impl_generics, cache) ,
511+ clean:: FunctionItem ( ref f) => {
512+ get_fn_inputs_and_outputs ( f, tcx, impl_or_trait_generics, cache)
513+ }
514+ clean:: MethodItem ( ref m, _) => {
515+ get_fn_inputs_and_outputs ( m, tcx, impl_or_trait_generics, cache)
516+ }
517+ clean:: TyMethodItem ( ref m) => {
518+ get_fn_inputs_and_outputs ( m, tcx, impl_or_trait_generics, cache)
519+ }
482520 _ => return None ,
483521 } ;
484522
@@ -488,33 +526,54 @@ pub(crate) fn get_function_type_for_search<'tcx>(
488526 Some ( IndexItemFunctionType { inputs, output, where_clause } )
489527}
490528
491- fn get_index_type ( clean_type : & clean:: Type , generics : Vec < RenderType > ) -> RenderType {
529+ fn get_index_type (
530+ clean_type : & clean:: Type ,
531+ generics : Vec < RenderType > ,
532+ rgen : & mut FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > ,
533+ ) -> RenderType {
492534 RenderType {
493- id : get_index_type_id ( clean_type) ,
535+ id : get_index_type_id ( clean_type, rgen ) ,
494536 generics : if generics. is_empty ( ) { None } else { Some ( generics) } ,
495537 bindings : None ,
496538 }
497539}
498540
499- fn get_index_type_id ( clean_type : & clean:: Type ) -> Option < RenderTypeId > {
541+ fn get_index_type_id (
542+ clean_type : & clean:: Type ,
543+ rgen : & mut FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > ,
544+ ) -> Option < RenderTypeId > {
545+ use rustc_hir:: def:: { DefKind , Res } ;
500546 match * clean_type {
501547 clean:: Type :: Path { ref path, .. } => Some ( RenderTypeId :: DefId ( path. def_id ( ) ) ) ,
502548 clean:: DynTrait ( ref bounds, _) => {
503549 bounds. get ( 0 ) . map ( |b| RenderTypeId :: DefId ( b. trait_ . def_id ( ) ) )
504550 }
505551 clean:: Primitive ( p) => Some ( RenderTypeId :: Primitive ( p) ) ,
506552 clean:: BorrowedRef { ref type_, .. } | clean:: RawPointer ( _, ref type_) => {
507- get_index_type_id ( type_)
553+ get_index_type_id ( type_, rgen )
508554 }
509555 // The type parameters are converted to generics in `simplify_fn_type`
510556 clean:: Slice ( _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Slice ) ) ,
511557 clean:: Array ( _, _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Array ) ) ,
512558 clean:: Tuple ( _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Tuple ) ) ,
559+ clean:: QPath ( ref data) => {
560+ if data. self_type . is_self_type ( )
561+ && let Some ( clean:: Path { res : Res :: Def ( DefKind :: Trait , trait_) , .. } ) = data. trait_
562+ {
563+ let idx = -isize:: try_from ( rgen. len ( ) + 1 ) . unwrap ( ) ;
564+ let ( idx, _) = rgen. entry ( SimplifiedParam :: AssociatedType ( trait_, data. assoc . name ) )
565+ . or_insert_with ( || {
566+ ( idx, Vec :: new ( ) )
567+ } ) ;
568+ Some ( RenderTypeId :: Index ( * idx) )
569+ } else {
570+ None
571+ }
572+ }
513573 // Not supported yet
514574 clean:: BareFunction ( _)
515575 | clean:: Generic ( _)
516576 | clean:: ImplTrait ( _)
517- | clean:: QPath { .. }
518577 | clean:: Infer => None ,
519578 }
520579}
@@ -525,6 +584,9 @@ enum SimplifiedParam {
525584 Symbol ( Symbol ) ,
526585 // every argument-position impl trait is its own type parameter
527586 Anonymous ( isize ) ,
587+ // in a trait definition, the associated types are all bound to
588+ // their own type parameter
589+ AssociatedType ( DefId , Symbol ) ,
528590}
529591
530592/// The point of this function is to lower generics and types into the simplified form that the
@@ -555,10 +617,17 @@ fn simplify_fn_type<'tcx, 'a>(
555617 }
556618
557619 // First, check if it's "Self".
620+ let mut is_self = false ;
558621 let mut arg = if let Some ( self_) = self_ {
559622 match & * arg {
560- Type :: BorrowedRef { type_, .. } if type_. is_self_type ( ) => self_,
561- type_ if type_. is_self_type ( ) => self_,
623+ Type :: BorrowedRef { type_, .. } if type_. is_self_type ( ) => {
624+ is_self = true ;
625+ self_
626+ }
627+ type_ if type_. is_self_type ( ) => {
628+ is_self = true ;
629+ self_
630+ }
562631 arg => arg,
563632 }
564633 } else {
@@ -675,7 +744,7 @@ fn simplify_fn_type<'tcx, 'a>(
675744 is_return,
676745 cache,
677746 ) ;
678- res. push ( get_index_type ( arg, ty_generics) ) ;
747+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
679748 } else if let Type :: Array ( ref ty, _) = * arg {
680749 let mut ty_generics = Vec :: new ( ) ;
681750 simplify_fn_type (
@@ -689,7 +758,7 @@ fn simplify_fn_type<'tcx, 'a>(
689758 is_return,
690759 cache,
691760 ) ;
692- res. push ( get_index_type ( arg, ty_generics) ) ;
761+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
693762 } else if let Type :: Tuple ( ref tys) = * arg {
694763 let mut ty_generics = Vec :: new ( ) ;
695764 for ty in tys {
@@ -705,7 +774,7 @@ fn simplify_fn_type<'tcx, 'a>(
705774 cache,
706775 ) ;
707776 }
708- res. push ( get_index_type ( arg, ty_generics) ) ;
777+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
709778 } else {
710779 // This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
711780 // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
@@ -742,7 +811,69 @@ fn simplify_fn_type<'tcx, 'a>(
742811 ) ;
743812 }
744813 }
745- let id = get_index_type_id ( & arg) ;
814+ // Every trait associated type on self gets assigned to a type parameter index
815+ // this same one is used later for any appearances of these types
816+ //
817+ // for example, Iterator::next is:
818+ //
819+ // trait Iterator {
820+ // fn next(&mut self) -> Option<Self::Item>
821+ // }
822+ //
823+ // Self is technically just Iterator, but we want to pretend it's more like this:
824+ //
825+ // fn next<T>(self: Iterator<Item=T>) -> Option<T>
826+ if is_self &&
827+ let Type :: Path { path } = arg &&
828+ let def_id = path. def_id ( ) &&
829+ let Some ( trait_) = cache. traits . get ( & def_id) &&
830+ trait_. items . iter ( ) . any ( |at| at. is_ty_associated_type ( ) )
831+ {
832+ for assoc_ty in & trait_. items {
833+ if let clean:: ItemKind :: TyAssocTypeItem ( _generics, bounds) = & * assoc_ty. kind &&
834+ let Some ( name) = assoc_ty. name
835+ {
836+ let idx = -isize:: try_from ( rgen. len ( ) + 1 ) . unwrap ( ) ;
837+ let ( idx, stored_bounds) = rgen. entry ( SimplifiedParam :: AssociatedType ( def_id, name) )
838+ . or_insert_with ( || {
839+ ( idx, Vec :: new ( ) )
840+ } ) ;
841+ let idx = * idx;
842+ if stored_bounds. is_empty ( ) {
843+ // Can't just pass stored_bounds to simplify_fn_type,
844+ // because it also accepts rgen as a parameter.
845+ // Instead, have it fill in this local, then copy it into the map afterward.
846+ let mut type_bounds = Vec :: new ( ) ;
847+ for bound in bounds {
848+ if let Some ( path) = bound. get_trait_path ( ) {
849+ let ty = Type :: Path { path } ;
850+ simplify_fn_type (
851+ self_,
852+ generics,
853+ & ty,
854+ tcx,
855+ recurse + 1 ,
856+ & mut type_bounds,
857+ rgen,
858+ is_return,
859+ cache,
860+ ) ;
861+ }
862+ }
863+ let stored_bounds = & mut rgen. get_mut ( & SimplifiedParam :: AssociatedType ( def_id, name) ) . unwrap ( ) . 1 ;
864+ if stored_bounds. is_empty ( ) {
865+ * stored_bounds = type_bounds;
866+ }
867+ }
868+ ty_bindings. push ( ( RenderTypeId :: AssociatedType ( name) , vec ! [ RenderType {
869+ id: Some ( RenderTypeId :: Index ( idx) ) ,
870+ generics: None ,
871+ bindings: None ,
872+ } ] ) )
873+ }
874+ }
875+ }
876+ let id = get_index_type_id ( & arg, rgen) ;
746877 if id. is_some ( ) || !ty_generics. is_empty ( ) {
747878 res. push ( RenderType {
748879 id,
@@ -842,13 +973,15 @@ fn simplify_fn_binding<'tcx, 'a>(
842973fn get_fn_inputs_and_outputs < ' tcx > (
843974 func : & Function ,
844975 tcx : TyCtxt < ' tcx > ,
845- impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
976+ impl_or_trait_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
846977 cache : & Cache ,
847978) -> ( Vec < RenderType > , Vec < RenderType > , Vec < Vec < RenderType > > ) {
848979 let decl = & func. decl ;
849980
981+ let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
982+
850983 let combined_generics;
851- let ( self_, generics) = if let Some ( ( impl_self, impl_generics) ) = impl_generics {
984+ let ( self_, generics) = if let Some ( ( impl_self, impl_generics) ) = impl_or_trait_generics {
852985 match ( impl_generics. is_empty ( ) , func. generics . is_empty ( ) ) {
853986 ( true , _) => ( Some ( impl_self) , & func. generics ) ,
854987 ( _, true ) => ( Some ( impl_self) , impl_generics) ,
@@ -870,8 +1003,6 @@ fn get_fn_inputs_and_outputs<'tcx>(
8701003 ( None , & func. generics )
8711004 } ;
8721005
873- let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
874-
8751006 let mut arg_types = Vec :: new ( ) ;
8761007 for arg in decl. inputs . values . iter ( ) {
8771008 simplify_fn_type (
0 commit comments