@@ -3,8 +3,10 @@ use std::collections::BTreeMap;
3
3
4
4
use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
5
5
use rustc_middle:: ty:: TyCtxt ;
6
+ use rustc_span:: def_id:: DefId ;
6
7
use rustc_span:: symbol:: Symbol ;
7
8
use serde:: ser:: { Serialize , SerializeSeq , SerializeStruct , Serializer } ;
9
+ use thin_vec:: ThinVec ;
8
10
9
11
use crate :: clean;
10
12
use crate :: clean:: types:: { Function , Generics , ItemId , Type , WherePredicate } ;
@@ -39,7 +41,13 @@ pub(crate) fn build_index<'tcx>(
39
41
parent : Some ( parent) ,
40
42
parent_idx : None ,
41
43
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
+ ) ,
43
51
aliases : item. attrs . get_doc_aliases ( ) ,
44
52
deprecation : item. deprecation ( tcx) ,
45
53
} ) ;
@@ -503,12 +511,42 @@ pub(crate) fn get_function_type_for_search<'tcx>(
503
511
item : & clean:: Item ,
504
512
tcx : TyCtxt < ' tcx > ,
505
513
impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
514
+ parent : Option < DefId > ,
506
515
cache : & Cache ,
507
516
) -> 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
+ } ) ;
508
540
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
+ }
512
550
_ => return None ,
513
551
} ;
514
552
@@ -518,33 +556,54 @@ pub(crate) fn get_function_type_for_search<'tcx>(
518
556
Some ( IndexItemFunctionType { inputs, output, where_clause } )
519
557
}
520
558
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 {
522
564
RenderType {
523
- id : get_index_type_id ( clean_type) ,
565
+ id : get_index_type_id ( clean_type, rgen ) ,
524
566
generics : if generics. is_empty ( ) { None } else { Some ( generics) } ,
525
567
bindings : None ,
526
568
}
527
569
}
528
570
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 } ;
530
576
match * clean_type {
531
577
clean:: Type :: Path { ref path, .. } => Some ( RenderTypeId :: DefId ( path. def_id ( ) ) ) ,
532
578
clean:: DynTrait ( ref bounds, _) => {
533
579
bounds. get ( 0 ) . map ( |b| RenderTypeId :: DefId ( b. trait_ . def_id ( ) ) )
534
580
}
535
581
clean:: Primitive ( p) => Some ( RenderTypeId :: Primitive ( p) ) ,
536
582
clean:: BorrowedRef { ref type_, .. } | clean:: RawPointer ( _, ref type_) => {
537
- get_index_type_id ( type_)
583
+ get_index_type_id ( type_, rgen )
538
584
}
539
585
// The type parameters are converted to generics in `simplify_fn_type`
540
586
clean:: Slice ( _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Slice ) ) ,
541
587
clean:: Array ( _, _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Array ) ) ,
542
588
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
+ }
543
603
// Not supported yet
544
604
clean:: BareFunction ( _)
545
605
| clean:: Generic ( _)
546
606
| clean:: ImplTrait ( _)
547
- | clean:: QPath { .. }
548
607
| clean:: Infer => None ,
549
608
}
550
609
}
@@ -555,6 +614,9 @@ enum SimplifiedParam {
555
614
Symbol ( Symbol ) ,
556
615
// every argument-position impl trait is its own type parameter
557
616
Anonymous ( isize ) ,
617
+ // in a trait definition, the associated types are all bound to
618
+ // their own type parameter
619
+ AssociatedType ( DefId , Symbol ) ,
558
620
}
559
621
560
622
/// 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>(
585
647
}
586
648
587
649
// First, check if it's "Self".
650
+ let mut is_self = false ;
588
651
let mut arg = if let Some ( self_) = self_ {
589
652
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
+ }
592
661
arg => arg,
593
662
}
594
663
} else {
@@ -705,7 +774,7 @@ fn simplify_fn_type<'tcx, 'a>(
705
774
is_return,
706
775
cache,
707
776
) ;
708
- res. push ( get_index_type ( arg, ty_generics) ) ;
777
+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
709
778
} else if let Type :: Array ( ref ty, _) = * arg {
710
779
let mut ty_generics = Vec :: new ( ) ;
711
780
simplify_fn_type (
@@ -719,7 +788,7 @@ fn simplify_fn_type<'tcx, 'a>(
719
788
is_return,
720
789
cache,
721
790
) ;
722
- res. push ( get_index_type ( arg, ty_generics) ) ;
791
+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
723
792
} else if let Type :: Tuple ( ref tys) = * arg {
724
793
let mut ty_generics = Vec :: new ( ) ;
725
794
for ty in tys {
@@ -735,7 +804,7 @@ fn simplify_fn_type<'tcx, 'a>(
735
804
cache,
736
805
) ;
737
806
}
738
- res. push ( get_index_type ( arg, ty_generics) ) ;
807
+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
739
808
} else {
740
809
// This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
741
810
// 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>(
772
841
) ;
773
842
}
774
843
}
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) ;
776
907
if id. is_some ( ) || !ty_generics. is_empty ( ) {
777
908
res. push ( RenderType {
778
909
id,
@@ -872,13 +1003,15 @@ fn simplify_fn_binding<'tcx, 'a>(
872
1003
fn get_fn_inputs_and_outputs < ' tcx > (
873
1004
func : & Function ,
874
1005
tcx : TyCtxt < ' tcx > ,
875
- impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
1006
+ impl_or_trait_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
876
1007
cache : & Cache ,
877
1008
) -> ( Vec < RenderType > , Vec < RenderType > , Vec < Vec < RenderType > > ) {
878
1009
let decl = & func. decl ;
879
1010
1011
+ let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
1012
+
880
1013
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 {
882
1015
match ( impl_generics. is_empty ( ) , func. generics . is_empty ( ) ) {
883
1016
( true , _) => ( Some ( impl_self) , & func. generics ) ,
884
1017
( _, true ) => ( Some ( impl_self) , impl_generics) ,
@@ -900,8 +1033,6 @@ fn get_fn_inputs_and_outputs<'tcx>(
900
1033
( None , & func. generics )
901
1034
} ;
902
1035
903
- let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
904
-
905
1036
let mut arg_types = Vec :: new ( ) ;
906
1037
for arg in decl. inputs . values . iter ( ) {
907
1038
simplify_fn_type (
0 commit comments