@@ -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 } ) ;
@@ -502,12 +510,42 @@ pub(crate) fn get_function_type_for_search<'tcx>(
502510 item : & clean:: Item ,
503511 tcx : TyCtxt < ' tcx > ,
504512 impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
513+ parent : Option < DefId > ,
505514 cache : & Cache ,
506515) -> Option < IndexItemFunctionType > {
516+ let mut trait_info = None ;
517+ let impl_or_trait_generics = impl_generics. or_else ( || {
518+ if let Some ( def_id) = parent &&
519+ let Some ( trait_) = cache. traits . get ( & def_id) &&
520+ let Some ( ( path, _) ) = cache. paths . get ( & def_id)
521+ . or_else ( || cache. external_paths . get ( & def_id) )
522+ {
523+ let path = clean:: Path {
524+ res : rustc_hir:: def:: Res :: Def ( rustc_hir:: def:: DefKind :: Trait , def_id) ,
525+ segments : path. iter ( ) . map ( |name| clean:: PathSegment {
526+ name : * name,
527+ args : clean:: GenericArgs :: AngleBracketed {
528+ args : Vec :: new ( ) . into_boxed_slice ( ) ,
529+ bindings : ThinVec :: new ( ) ,
530+ } ,
531+ } ) . collect ( ) ,
532+ } ;
533+ trait_info = Some ( ( clean:: Type :: Path { path } , trait_. generics . clone ( ) ) ) ;
534+ Some ( trait_info. as_ref ( ) . unwrap ( ) )
535+ } else {
536+ None
537+ }
538+ } ) ;
507539 let ( mut inputs, mut output, where_clause) = match * item. kind {
508- clean:: FunctionItem ( ref f) => get_fn_inputs_and_outputs ( f, tcx, impl_generics, cache) ,
509- clean:: MethodItem ( ref m, _) => get_fn_inputs_and_outputs ( m, tcx, impl_generics, cache) ,
510- clean:: TyMethodItem ( ref m) => get_fn_inputs_and_outputs ( m, tcx, impl_generics, cache) ,
540+ clean:: FunctionItem ( ref f) => {
541+ get_fn_inputs_and_outputs ( f, tcx, impl_or_trait_generics, cache)
542+ }
543+ clean:: MethodItem ( ref m, _) => {
544+ get_fn_inputs_and_outputs ( m, tcx, impl_or_trait_generics, cache)
545+ }
546+ clean:: TyMethodItem ( ref m) => {
547+ get_fn_inputs_and_outputs ( m, tcx, impl_or_trait_generics, cache)
548+ }
511549 _ => return None ,
512550 } ;
513551
@@ -517,33 +555,54 @@ pub(crate) fn get_function_type_for_search<'tcx>(
517555 Some ( IndexItemFunctionType { inputs, output, where_clause } )
518556}
519557
520- fn get_index_type ( clean_type : & clean:: Type , generics : Vec < RenderType > ) -> RenderType {
558+ fn get_index_type (
559+ clean_type : & clean:: Type ,
560+ generics : Vec < RenderType > ,
561+ rgen : & mut FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > ,
562+ ) -> RenderType {
521563 RenderType {
522- id : get_index_type_id ( clean_type) ,
564+ id : get_index_type_id ( clean_type, rgen ) ,
523565 generics : if generics. is_empty ( ) { None } else { Some ( generics) } ,
524566 bindings : None ,
525567 }
526568}
527569
528- fn get_index_type_id ( clean_type : & clean:: Type ) -> Option < RenderTypeId > {
570+ fn get_index_type_id (
571+ clean_type : & clean:: Type ,
572+ rgen : & mut FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > ,
573+ ) -> Option < RenderTypeId > {
574+ use rustc_hir:: def:: { DefKind , Res } ;
529575 match * clean_type {
530576 clean:: Type :: Path { ref path, .. } => Some ( RenderTypeId :: DefId ( path. def_id ( ) ) ) ,
531577 clean:: DynTrait ( ref bounds, _) => {
532578 bounds. get ( 0 ) . map ( |b| RenderTypeId :: DefId ( b. trait_ . def_id ( ) ) )
533579 }
534580 clean:: Primitive ( p) => Some ( RenderTypeId :: Primitive ( p) ) ,
535581 clean:: BorrowedRef { ref type_, .. } | clean:: RawPointer ( _, ref type_) => {
536- get_index_type_id ( type_)
582+ get_index_type_id ( type_, rgen )
537583 }
538584 // The type parameters are converted to generics in `simplify_fn_type`
539585 clean:: Slice ( _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Slice ) ) ,
540586 clean:: Array ( _, _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Array ) ) ,
541587 clean:: Tuple ( _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Tuple ) ) ,
588+ clean:: QPath ( ref data) => {
589+ if data. self_type . is_self_type ( )
590+ && let Some ( clean:: Path { res : Res :: Def ( DefKind :: Trait , trait_) , .. } ) = data. trait_
591+ {
592+ let idx = -isize:: try_from ( rgen. len ( ) + 1 ) . unwrap ( ) ;
593+ let ( idx, _) = rgen. entry ( SimplifiedParam :: AssociatedType ( trait_, data. assoc . name ) )
594+ . or_insert_with ( || {
595+ ( idx, Vec :: new ( ) )
596+ } ) ;
597+ Some ( RenderTypeId :: Index ( * idx) )
598+ } else {
599+ None
600+ }
601+ }
542602 // Not supported yet
543603 clean:: BareFunction ( _)
544604 | clean:: Generic ( _)
545605 | clean:: ImplTrait ( _)
546- | clean:: QPath { .. }
547606 | clean:: Infer => None ,
548607 }
549608}
@@ -554,6 +613,9 @@ enum SimplifiedParam {
554613 Symbol ( Symbol ) ,
555614 // every argument-position impl trait is its own type parameter
556615 Anonymous ( isize ) ,
616+ // in a trait definition, the associated types are all bound to
617+ // their own type parameter
618+ AssociatedType ( DefId , Symbol ) ,
557619}
558620
559621/// The point of this function is to lower generics and types into the simplified form that the
@@ -584,10 +646,17 @@ fn simplify_fn_type<'tcx, 'a>(
584646 }
585647
586648 // First, check if it's "Self".
649+ let mut is_self = false ;
587650 let mut arg = if let Some ( self_) = self_ {
588651 match & * arg {
589- Type :: BorrowedRef { type_, .. } if type_. is_self_type ( ) => self_,
590- type_ if type_. is_self_type ( ) => self_,
652+ Type :: BorrowedRef { type_, .. } if type_. is_self_type ( ) => {
653+ is_self = true ;
654+ self_
655+ }
656+ type_ if type_. is_self_type ( ) => {
657+ is_self = true ;
658+ self_
659+ }
591660 arg => arg,
592661 }
593662 } else {
@@ -704,7 +773,7 @@ fn simplify_fn_type<'tcx, 'a>(
704773 is_return,
705774 cache,
706775 ) ;
707- res. push ( get_index_type ( arg, ty_generics) ) ;
776+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
708777 } else if let Type :: Array ( ref ty, _) = * arg {
709778 let mut ty_generics = Vec :: new ( ) ;
710779 simplify_fn_type (
@@ -718,7 +787,7 @@ fn simplify_fn_type<'tcx, 'a>(
718787 is_return,
719788 cache,
720789 ) ;
721- res. push ( get_index_type ( arg, ty_generics) ) ;
790+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
722791 } else if let Type :: Tuple ( ref tys) = * arg {
723792 let mut ty_generics = Vec :: new ( ) ;
724793 for ty in tys {
@@ -734,7 +803,7 @@ fn simplify_fn_type<'tcx, 'a>(
734803 cache,
735804 ) ;
736805 }
737- res. push ( get_index_type ( arg, ty_generics) ) ;
806+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
738807 } else {
739808 // This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
740809 // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
@@ -771,7 +840,69 @@ fn simplify_fn_type<'tcx, 'a>(
771840 ) ;
772841 }
773842 }
774- let id = get_index_type_id ( & arg) ;
843+ // Every trait associated type on self gets assigned to a type parameter index
844+ // this same one is used later for any appearances of these types
845+ //
846+ // for example, Iterator::next is:
847+ //
848+ // trait Iterator {
849+ // fn next(&mut self) -> Option<Self::Item>
850+ // }
851+ //
852+ // Self is technically just Iterator, but we want to pretend it's more like this:
853+ //
854+ // fn next<T>(self: Iterator<Item=T>) -> Option<T>
855+ if is_self &&
856+ let Type :: Path { path } = arg &&
857+ let def_id = path. def_id ( ) &&
858+ let Some ( trait_) = cache. traits . get ( & def_id) &&
859+ trait_. items . iter ( ) . any ( |at| at. is_ty_associated_type ( ) )
860+ {
861+ for assoc_ty in & trait_. items {
862+ if let clean:: ItemKind :: TyAssocTypeItem ( _generics, bounds) = & * assoc_ty. kind &&
863+ let Some ( name) = assoc_ty. name
864+ {
865+ let idx = -isize:: try_from ( rgen. len ( ) + 1 ) . unwrap ( ) ;
866+ let ( idx, stored_bounds) = rgen. entry ( SimplifiedParam :: AssociatedType ( def_id, name) )
867+ . or_insert_with ( || {
868+ ( idx, Vec :: new ( ) )
869+ } ) ;
870+ let idx = * idx;
871+ if stored_bounds. is_empty ( ) {
872+ // Can't just pass stored_bounds to simplify_fn_type,
873+ // because it also accepts rgen as a parameter.
874+ // Instead, have it fill in this local, then copy it into the map afterward.
875+ let mut type_bounds = Vec :: new ( ) ;
876+ for bound in bounds {
877+ if let Some ( path) = bound. get_trait_path ( ) {
878+ let ty = Type :: Path { path } ;
879+ simplify_fn_type (
880+ self_,
881+ generics,
882+ & ty,
883+ tcx,
884+ recurse + 1 ,
885+ & mut type_bounds,
886+ rgen,
887+ is_return,
888+ cache,
889+ ) ;
890+ }
891+ }
892+ let stored_bounds = & mut rgen. get_mut ( & SimplifiedParam :: AssociatedType ( def_id, name) ) . unwrap ( ) . 1 ;
893+ if stored_bounds. is_empty ( ) {
894+ * stored_bounds = type_bounds;
895+ }
896+ }
897+ ty_bindings. push ( ( RenderTypeId :: AssociatedType ( name) , vec ! [ RenderType {
898+ id: Some ( RenderTypeId :: Index ( idx) ) ,
899+ generics: None ,
900+ bindings: None ,
901+ } ] ) )
902+ }
903+ }
904+ }
905+ let id = get_index_type_id ( & arg, rgen) ;
775906 if id. is_some ( ) || !ty_generics. is_empty ( ) {
776907 res. push ( RenderType {
777908 id,
@@ -871,13 +1002,15 @@ fn simplify_fn_binding<'tcx, 'a>(
8711002fn get_fn_inputs_and_outputs < ' tcx > (
8721003 func : & Function ,
8731004 tcx : TyCtxt < ' tcx > ,
874- impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
1005+ impl_or_trait_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
8751006 cache : & Cache ,
8761007) -> ( Vec < RenderType > , Vec < RenderType > , Vec < Vec < RenderType > > ) {
8771008 let decl = & func. decl ;
8781009
1010+ let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
1011+
8791012 let combined_generics;
880- let ( self_, generics) = if let Some ( ( impl_self, impl_generics) ) = impl_generics {
1013+ let ( self_, generics) = if let Some ( ( impl_self, impl_generics) ) = impl_or_trait_generics {
8811014 match ( impl_generics. is_empty ( ) , func. generics . is_empty ( ) ) {
8821015 ( true , _) => ( Some ( impl_self) , & func. generics ) ,
8831016 ( _, true ) => ( Some ( impl_self) , impl_generics) ,
@@ -899,8 +1032,6 @@ fn get_fn_inputs_and_outputs<'tcx>(
8991032 ( None , & func. generics )
9001033 } ;
9011034
902- let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
903-
9041035 let mut arg_types = Vec :: new ( ) ;
9051036 for arg in decl. inputs . values . iter ( ) {
9061037 simplify_fn_type (
0 commit comments