@@ -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 } ;
@@ -37,7 +39,13 @@ pub(crate) fn build_index<'tcx>(
37
39
desc,
38
40
parent : Some ( parent) ,
39
41
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
+ ) ,
41
49
aliases : item. attrs . get_doc_aliases ( ) ,
42
50
deprecation : item. deprecation ( tcx) ,
43
51
} ) ;
@@ -473,12 +481,42 @@ pub(crate) fn get_function_type_for_search<'tcx>(
473
481
item : & clean:: Item ,
474
482
tcx : TyCtxt < ' tcx > ,
475
483
impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
484
+ parent : Option < DefId > ,
476
485
cache : & Cache ,
477
486
) -> 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
+ } ) ;
478
510
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
+ }
482
520
_ => return None ,
483
521
} ;
484
522
@@ -488,33 +526,54 @@ pub(crate) fn get_function_type_for_search<'tcx>(
488
526
Some ( IndexItemFunctionType { inputs, output, where_clause } )
489
527
}
490
528
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 {
492
534
RenderType {
493
- id : get_index_type_id ( clean_type) ,
535
+ id : get_index_type_id ( clean_type, rgen ) ,
494
536
generics : if generics. is_empty ( ) { None } else { Some ( generics) } ,
495
537
bindings : None ,
496
538
}
497
539
}
498
540
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 } ;
500
546
match * clean_type {
501
547
clean:: Type :: Path { ref path, .. } => Some ( RenderTypeId :: DefId ( path. def_id ( ) ) ) ,
502
548
clean:: DynTrait ( ref bounds, _) => {
503
549
bounds. get ( 0 ) . map ( |b| RenderTypeId :: DefId ( b. trait_ . def_id ( ) ) )
504
550
}
505
551
clean:: Primitive ( p) => Some ( RenderTypeId :: Primitive ( p) ) ,
506
552
clean:: BorrowedRef { ref type_, .. } | clean:: RawPointer ( _, ref type_) => {
507
- get_index_type_id ( type_)
553
+ get_index_type_id ( type_, rgen )
508
554
}
509
555
// The type parameters are converted to generics in `simplify_fn_type`
510
556
clean:: Slice ( _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Slice ) ) ,
511
557
clean:: Array ( _, _) => Some ( RenderTypeId :: Primitive ( clean:: PrimitiveType :: Array ) ) ,
512
558
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
+ }
513
573
// Not supported yet
514
574
clean:: BareFunction ( _)
515
575
| clean:: Generic ( _)
516
576
| clean:: ImplTrait ( _)
517
- | clean:: QPath { .. }
518
577
| clean:: Infer => None ,
519
578
}
520
579
}
@@ -525,6 +584,9 @@ enum SimplifiedParam {
525
584
Symbol ( Symbol ) ,
526
585
// every argument-position impl trait is its own type parameter
527
586
Anonymous ( isize ) ,
587
+ // in a trait definition, the associated types are all bound to
588
+ // their own type parameter
589
+ AssociatedType ( DefId , Symbol ) ,
528
590
}
529
591
530
592
/// 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>(
555
617
}
556
618
557
619
// First, check if it's "Self".
620
+ let mut is_self = false ;
558
621
let mut arg = if let Some ( self_) = self_ {
559
622
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
+ }
562
631
arg => arg,
563
632
}
564
633
} else {
@@ -675,7 +744,7 @@ fn simplify_fn_type<'tcx, 'a>(
675
744
is_return,
676
745
cache,
677
746
) ;
678
- res. push ( get_index_type ( arg, ty_generics) ) ;
747
+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
679
748
} else if let Type :: Array ( ref ty, _) = * arg {
680
749
let mut ty_generics = Vec :: new ( ) ;
681
750
simplify_fn_type (
@@ -689,7 +758,7 @@ fn simplify_fn_type<'tcx, 'a>(
689
758
is_return,
690
759
cache,
691
760
) ;
692
- res. push ( get_index_type ( arg, ty_generics) ) ;
761
+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
693
762
} else if let Type :: Tuple ( ref tys) = * arg {
694
763
let mut ty_generics = Vec :: new ( ) ;
695
764
for ty in tys {
@@ -705,7 +774,7 @@ fn simplify_fn_type<'tcx, 'a>(
705
774
cache,
706
775
) ;
707
776
}
708
- res. push ( get_index_type ( arg, ty_generics) ) ;
777
+ res. push ( get_index_type ( arg, ty_generics, rgen ) ) ;
709
778
} else {
710
779
// This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
711
780
// 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>(
742
811
) ;
743
812
}
744
813
}
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) ;
746
877
if id. is_some ( ) || !ty_generics. is_empty ( ) {
747
878
res. push ( RenderType {
748
879
id,
@@ -842,13 +973,15 @@ fn simplify_fn_binding<'tcx, 'a>(
842
973
fn get_fn_inputs_and_outputs < ' tcx > (
843
974
func : & Function ,
844
975
tcx : TyCtxt < ' tcx > ,
845
- impl_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
976
+ impl_or_trait_generics : Option < & ( clean:: Type , clean:: Generics ) > ,
846
977
cache : & Cache ,
847
978
) -> ( Vec < RenderType > , Vec < RenderType > , Vec < Vec < RenderType > > ) {
848
979
let decl = & func. decl ;
849
980
981
+ let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
982
+
850
983
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 {
852
985
match ( impl_generics. is_empty ( ) , func. generics . is_empty ( ) ) {
853
986
( true , _) => ( Some ( impl_self) , & func. generics ) ,
854
987
( _, true ) => ( Some ( impl_self) , impl_generics) ,
@@ -870,8 +1003,6 @@ fn get_fn_inputs_and_outputs<'tcx>(
870
1003
( None , & func. generics )
871
1004
} ;
872
1005
873
- let mut rgen: FxHashMap < SimplifiedParam , ( isize , Vec < RenderType > ) > = Default :: default ( ) ;
874
-
875
1006
let mut arg_types = Vec :: new ( ) ;
876
1007
for arg in decl. inputs . values . iter ( ) {
877
1008
simplify_fn_type (
0 commit comments