@@ -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 } ;
@@ -39,7 +41,13 @@ pub(crate) fn build_index<'tcx>(
3941 parent : Some ( parent) ,
4042 parent_idx : None ,
4143 impl_id,
42- search_type : get_function_type_for_search ( item, tcx, impl_generics. as_ref ( ) , cache) ,
44+ search_type : get_function_type_for_search (
45+ item,
46+ tcx,
47+ impl_generics. as_ref ( ) ,
48+ Some ( parent) ,
49+ cache,
50+ ) ,
4351 aliases : item. attrs . get_doc_aliases ( ) ,
4452 deprecation : item. deprecation ( tcx) ,
4553 } ) ;
@@ -503,12 +511,42 @@ pub(crate) fn get_function_type_for_search<'tcx>(
503511 item : & clean:: Item ,
504512 tcx : TyCtxt < ' tcx > ,
505513 impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
514+ parent : Option < DefId > ,
506515 cache : & Cache ,
507516) -> Option < IndexItemFunctionType > {
517+ let mut trait_info = None ;
518+ let impl_or_trait_generics = impl_generics. or_else ( || {
519+ if let Some ( def_id) = parent &&
520+ let Some ( trait_) = cache. traits . get ( & def_id) &&
521+ let Some ( ( path, _) ) = cache. paths . get ( & def_id)
522+ . or_else ( || cache. external_paths . get ( & def_id) )
523+ {
524+ let path = clean:: Path {
525+ res : rustc_hir:: def:: Res :: Def ( rustc_hir:: def:: DefKind :: Trait , def_id) ,
526+ segments : path. iter ( ) . map ( |name| clean:: PathSegment {
527+ name : * name,
528+ args : clean:: GenericArgs :: AngleBracketed {
529+ args : Vec :: new ( ) . into_boxed_slice ( ) ,
530+ bindings : ThinVec :: new ( ) ,
531+ } ,
532+ } ) . collect ( ) ,
533+ } ;
534+ trait_info = Some ( ( clean:: Type :: Path { path } , trait_. generics . clone ( ) ) ) ;
535+ Some ( trait_info. as_ref ( ) . unwrap ( ) )
536+ } else {
537+ None
538+ }
539+ } ) ;
508540 let ( mut inputs, mut output, where_clause) = match * item. kind {
509- clean:: FunctionItem ( ref f) => get_fn_inputs_and_outputs ( f, tcx, impl_generics, cache) ,
510- clean:: MethodItem ( ref m, _) => get_fn_inputs_and_outputs ( m, tcx, impl_generics, cache) ,
511- clean:: TyMethodItem ( ref m) => get_fn_inputs_and_outputs ( m, tcx, impl_generics, cache) ,
541+ clean:: FunctionItem ( ref f) => {
542+ get_fn_inputs_and_outputs ( f, tcx, impl_or_trait_generics, cache)
543+ }
544+ clean:: MethodItem ( ref m, _) => {
545+ get_fn_inputs_and_outputs ( m, tcx, impl_or_trait_generics, cache)
546+ }
547+ clean:: TyMethodItem ( ref m) => {
548+ get_fn_inputs_and_outputs ( m, tcx, impl_or_trait_generics, cache)
549+ }
512550 _ => return None ,
513551 } ;
514552
@@ -518,33 +556,54 @@ pub(crate) fn get_function_type_for_search<'tcx>(
518556 Some ( IndexItemFunctionType { inputs, output, where_clause } )
519557}
520558
521- fn get_index_type ( clean_type : & clean:: Type , generics : Vec < RenderType > ) -> RenderType {
559+ fn get_index_type (
560+ clean_type : & clean:: Type ,
561+ generics : Vec < RenderType > ,
562+ rgen : & mut FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > ,
563+ ) -> RenderType {
522564 RenderType {
523- id : get_index_type_id ( clean_type) ,
565+ id : get_index_type_id ( clean_type, rgen ) ,
524566 generics : if generics. is_empty ( ) { None } else { Some ( generics) } ,
525567 bindings : None ,
526568 }
527569}
528570
529- fn get_index_type_id ( clean_type : & clean:: Type ) -> Option < RenderTypeId > {
571+ fn get_index_type_id (
572+ clean_type : & clean:: Type ,
573+ rgen : & mut FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > ,
574+ ) -> Option < RenderTypeId > {
575+ use rustc_hir:: def:: { DefKind , Res } ;
530576 match * clean_type {
531577 clean:: Type :: Path { ref path, .. } => Some ( RenderTypeId :: DefId ( path. def_id ( ) ) ) ,
532578 clean:: DynTrait ( ref bounds, _) => {
533579 bounds. get ( 0 ) . map ( |b| RenderTypeId :: DefId ( b. trait_ . def_id ( ) ) )
534580 }
535581 clean:: Primitive ( p) => Some ( RenderTypeId :: Primitive ( p) ) ,
536582 clean:: BorrowedRef { ref type_, .. } | clean:: RawPointer ( _, ref type_) => {
537- get_index_type_id ( type_)
583+ get_index_type_id ( type_, rgen )
538584 }
539585 // The type parameters are converted to generics in `simplify_fn_type`
540586 clean:: Slice ( _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Slice ) ) ,
541587 clean:: Array ( _, _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Array ) ) ,
542588 clean:: Tuple ( _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Tuple ) ) ,
589+ clean:: QPath ( ref data) => {
590+ if data. self_type . is_self_type ( )
591+ && let Some ( clean:: Path { res : Res :: Def ( DefKind :: Trait , trait_) , .. } ) = data. trait_
592+ {
593+ let idx = -isize:: try_from ( rgen. len ( ) + 1 ) . unwrap ( ) ;
594+ let ( idx, _) = rgen. entry ( SimplifiedParam :: AssociatedType ( trait_, data. assoc . name ) )
595+ . or_insert_with ( || {
596+ ( idx, Vec :: new ( ) )
597+ } ) ;
598+ Some ( RenderTypeId :: Index ( * idx) )
599+ } else {
600+ None
601+ }
602+ }
543603 // Not supported yet
544604 clean:: BareFunction ( _)
545605 | clean:: Generic ( _)
546606 | clean:: ImplTrait ( _)
547- | clean:: QPath { .. }
548607 | clean:: Infer => None ,
549608 }
550609}
@@ -555,6 +614,9 @@ enum SimplifiedParam {
555614 Symbol ( Symbol ) ,
556615 // every argument-position impl trait is its own type parameter
557616 Anonymous ( isize ) ,
617+ // in a trait definition, the associated types are all bound to
618+ // their own type parameter
619+ AssociatedType ( DefId , Symbol ) ,
558620}
559621
560622/// The point of this function is to lower generics and types into the simplified form that the
@@ -585,10 +647,17 @@ fn simplify_fn_type<'tcx, 'a>(
585647 }
586648
587649 // First, check if it's "Self".
650+ let mut is_self = false ;
588651 let mut arg = if let Some ( self_) = self_ {
589652 match & * arg {
590- Type :: BorrowedRef { type_, .. } if type_. is_self_type ( ) => self_,
591- type_ if type_. is_self_type ( ) => self_,
653+ Type :: BorrowedRef { type_, .. } if type_. is_self_type ( ) => {
654+ is_self = true ;
655+ self_
656+ }
657+ type_ if type_. is_self_type ( ) => {
658+ is_self = true ;
659+ self_
660+ }
592661 arg => arg,
593662 }
594663 } else {
@@ -705,7 +774,7 @@ fn simplify_fn_type<'tcx, 'a>(
705774 is_return,
706775 cache,
707776 ) ;
708- res. push ( get_index_type ( arg, ty_generics) ) ;
777+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
709778 } else if let Type :: Array ( ref ty, _) = * arg {
710779 let mut ty_generics = Vec :: new ( ) ;
711780 simplify_fn_type (
@@ -719,7 +788,7 @@ fn simplify_fn_type<'tcx, 'a>(
719788 is_return,
720789 cache,
721790 ) ;
722- res. push ( get_index_type ( arg, ty_generics) ) ;
791+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
723792 } else if let Type :: Tuple ( ref tys) = * arg {
724793 let mut ty_generics = Vec :: new ( ) ;
725794 for ty in tys {
@@ -735,7 +804,7 @@ fn simplify_fn_type<'tcx, 'a>(
735804 cache,
736805 ) ;
737806 }
738- res. push ( get_index_type ( arg, ty_generics) ) ;
807+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
739808 } else {
740809 // This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
741810 // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
@@ -772,7 +841,69 @@ fn simplify_fn_type<'tcx, 'a>(
772841 ) ;
773842 }
774843 }
775- let id = get_index_type_id ( & arg) ;
844+ // Every trait associated type on self gets assigned to a type parameter index
845+ // this same one is used later for any appearances of these types
846+ //
847+ // for example, Iterator::next is:
848+ //
849+ // trait Iterator {
850+ // fn next(&mut self) -> Option<Self::Item>
851+ // }
852+ //
853+ // Self is technically just Iterator, but we want to pretend it's more like this:
854+ //
855+ // fn next<T>(self: Iterator<Item=T>) -> Option<T>
856+ if is_self &&
857+ let Type :: Path { path } = arg &&
858+ let def_id = path. def_id ( ) &&
859+ let Some ( trait_) = cache. traits . get ( & def_id) &&
860+ trait_. items . iter ( ) . any ( |at| at. is_ty_associated_type ( ) )
861+ {
862+ for assoc_ty in & trait_. items {
863+ if let clean:: ItemKind :: TyAssocTypeItem ( _generics, bounds) = & * assoc_ty. kind &&
864+ let Some ( name) = assoc_ty. name
865+ {
866+ let idx = -isize:: try_from ( rgen. len ( ) + 1 ) . unwrap ( ) ;
867+ let ( idx, stored_bounds) = rgen. entry ( SimplifiedParam :: AssociatedType ( def_id, name) )
868+ . or_insert_with ( || {
869+ ( idx, Vec :: new ( ) )
870+ } ) ;
871+ let idx = * idx;
872+ if stored_bounds. is_empty ( ) {
873+ // Can't just pass stored_bounds to simplify_fn_type,
874+ // because it also accepts rgen as a parameter.
875+ // Instead, have it fill in this local, then copy it into the map afterward.
876+ let mut type_bounds = Vec :: new ( ) ;
877+ for bound in bounds {
878+ if let Some ( path) = bound. get_trait_path ( ) {
879+ let ty = Type :: Path { path } ;
880+ simplify_fn_type (
881+ self_,
882+ generics,
883+ & ty,
884+ tcx,
885+ recurse + 1 ,
886+ & mut type_bounds,
887+ rgen,
888+ is_return,
889+ cache,
890+ ) ;
891+ }
892+ }
893+ let stored_bounds = & mut rgen. get_mut ( & SimplifiedParam :: AssociatedType ( def_id, name) ) . unwrap ( ) . 1 ;
894+ if stored_bounds. is_empty ( ) {
895+ * stored_bounds = type_bounds;
896+ }
897+ }
898+ ty_bindings. push ( ( RenderTypeId :: AssociatedType ( name) , vec ! [ RenderType {
899+ id: Some ( RenderTypeId :: Index ( idx) ) ,
900+ generics: None ,
901+ bindings: None ,
902+ } ] ) )
903+ }
904+ }
905+ }
906+ let id = get_index_type_id ( & arg, rgen) ;
776907 if id. is_some ( ) || !ty_generics. is_empty ( ) {
777908 res. push ( RenderType {
778909 id,
@@ -872,13 +1003,15 @@ fn simplify_fn_binding<'tcx, 'a>(
8721003fn get_fn_inputs_and_outputs < ' tcx > (
8731004 func : & Function ,
8741005 tcx : TyCtxt < ' tcx > ,
875- impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
1006+ impl_or_trait_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
8761007 cache : & Cache ,
8771008) -> ( Vec < RenderType > , Vec < RenderType > , Vec < Vec < RenderType > > ) {
8781009 let decl = & func. decl ;
8791010
1011+ let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
1012+
8801013 let combined_generics;
881- let ( self_, generics) = if let Some ( ( impl_self, impl_generics) ) = impl_generics {
1014+ let ( self_, generics) = if let Some ( ( impl_self, impl_generics) ) = impl_or_trait_generics {
8821015 match ( impl_generics. is_empty ( ) , func. generics . is_empty ( ) ) {
8831016 ( true , _) => ( Some ( impl_self) , & func. generics ) ,
8841017 ( _, true ) => ( Some ( impl_self) , impl_generics) ,
@@ -900,8 +1033,6 @@ fn get_fn_inputs_and_outputs<'tcx>(
9001033 ( None , & func. generics )
9011034 } ;
9021035
903- let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
904-
9051036 let mut arg_types = Vec :: new ( ) ;
9061037 for arg in decl. inputs . values . iter ( ) {
9071038 simplify_fn_type (
0 commit comments