@@ -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
} ) ;
@@ -502,12 +510,42 @@ pub(crate) fn get_function_type_for_search<'tcx>(
502
510
item : & clean:: Item ,
503
511
tcx : TyCtxt < ' tcx > ,
504
512
impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
513
+ parent : Option < DefId > ,
505
514
cache : & Cache ,
506
515
) -> 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
+ } ) ;
507
539
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
+ }
511
549
_ => return None ,
512
550
} ;
513
551
@@ -517,33 +555,54 @@ pub(crate) fn get_function_type_for_search<'tcx>(
517
555
Some ( IndexItemFunctionType { inputs, output, where_clause } )
518
556
}
519
557
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 {
521
563
RenderType {
522
- id : get_index_type_id ( clean_type) ,
564
+ id : get_index_type_id ( clean_type, rgen ) ,
523
565
generics : if generics. is_empty ( ) { None } else { Some ( generics) } ,
524
566
bindings : None ,
525
567
}
526
568
}
527
569
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 } ;
529
575
match * clean_type {
530
576
clean:: Type :: Path { ref path, .. } => Some ( RenderTypeId :: DefId ( path. def_id ( ) ) ) ,
531
577
clean:: DynTrait ( ref bounds, _) => {
532
578
bounds. get ( 0 ) . map ( |b| RenderTypeId :: DefId ( b. trait_ . def_id ( ) ) )
533
579
}
534
580
clean:: Primitive ( p) => Some ( RenderTypeId :: Primitive ( p) ) ,
535
581
clean:: BorrowedRef { ref type_, .. } | clean:: RawPointer ( _, ref type_) => {
536
- get_index_type_id ( type_)
582
+ get_index_type_id ( type_, rgen )
537
583
}
538
584
// The type parameters are converted to generics in `simplify_fn_type`
539
585
clean:: Slice ( _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Slice ) ) ,
540
586
clean:: Array ( _, _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Array ) ) ,
541
587
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
+ }
542
602
// Not supported yet
543
603
clean:: BareFunction ( _)
544
604
| clean:: Generic ( _)
545
605
| clean:: ImplTrait ( _)
546
- | clean:: QPath { .. }
547
606
| clean:: Infer => None ,
548
607
}
549
608
}
@@ -554,6 +613,9 @@ enum SimplifiedParam {
554
613
Symbol ( Symbol ) ,
555
614
// every argument-position impl trait is its own type parameter
556
615
Anonymous ( isize ) ,
616
+ // in a trait definition, the associated types are all bound to
617
+ // their own type parameter
618
+ AssociatedType ( DefId , Symbol ) ,
557
619
}
558
620
559
621
/// 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>(
584
646
}
585
647
586
648
// First, check if it's "Self".
649
+ let mut is_self = false ;
587
650
let mut arg = if let Some ( self_) = self_ {
588
651
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
+ }
591
660
arg => arg,
592
661
}
593
662
} else {
@@ -704,7 +773,7 @@ fn simplify_fn_type<'tcx, 'a>(
704
773
is_return,
705
774
cache,
706
775
) ;
707
- res. push ( get_index_type ( arg, ty_generics) ) ;
776
+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
708
777
} else if let Type :: Array ( ref ty, _) = * arg {
709
778
let mut ty_generics = Vec :: new ( ) ;
710
779
simplify_fn_type (
@@ -718,7 +787,7 @@ fn simplify_fn_type<'tcx, 'a>(
718
787
is_return,
719
788
cache,
720
789
) ;
721
- res. push ( get_index_type ( arg, ty_generics) ) ;
790
+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
722
791
} else if let Type :: Tuple ( ref tys) = * arg {
723
792
let mut ty_generics = Vec :: new ( ) ;
724
793
for ty in tys {
@@ -734,7 +803,7 @@ fn simplify_fn_type<'tcx, 'a>(
734
803
cache,
735
804
) ;
736
805
}
737
- res. push ( get_index_type ( arg, ty_generics) ) ;
806
+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
738
807
} else {
739
808
// This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
740
809
// 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>(
771
840
) ;
772
841
}
773
842
}
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) ;
775
906
if id. is_some ( ) || !ty_generics. is_empty ( ) {
776
907
res. push ( RenderType {
777
908
id,
@@ -871,13 +1002,15 @@ fn simplify_fn_binding<'tcx, 'a>(
871
1002
fn get_fn_inputs_and_outputs < ' tcx > (
872
1003
func : & Function ,
873
1004
tcx : TyCtxt < ' tcx > ,
874
- impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
1005
+ impl_or_trait_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
875
1006
cache : & Cache ,
876
1007
) -> ( Vec < RenderType > , Vec < RenderType > , Vec < Vec < RenderType > > ) {
877
1008
let decl = & func. decl ;
878
1009
1010
+ let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
1011
+
879
1012
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 {
881
1014
match ( impl_generics. is_empty ( ) , func. generics . is_empty ( ) ) {
882
1015
( true , _) => ( Some ( impl_self) , & func. generics ) ,
883
1016
( _, true ) => ( Some ( impl_self) , impl_generics) ,
@@ -899,8 +1032,6 @@ fn get_fn_inputs_and_outputs<'tcx>(
899
1032
( None , & func. generics )
900
1033
} ;
901
1034
902
- let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
903
-
904
1035
let mut arg_types = Vec :: new ( ) ;
905
1036
for arg in decl. inputs . values . iter ( ) {
906
1037
simplify_fn_type (
0 commit comments