@@ -73,6 +73,9 @@ pub trait AstConv<'tcx> {
73
73
fn tcx < ' a > ( & ' a self ) -> & ' a ty:: ctxt < ' tcx > ;
74
74
fn get_item_ty ( & self , id : ast:: DefId ) -> ty:: Polytype < ' tcx > ;
75
75
fn get_trait_def ( & self , id : ast:: DefId ) -> Rc < ty:: TraitDef < ' tcx > > ;
76
+ fn get_free_substs ( & self ) -> Option < & Substs < ' tcx > > {
77
+ None
78
+ }
76
79
77
80
/// What type should we use when a type is omitted?
78
81
fn ty_infer ( & self , span : Span ) -> Ty < ' tcx > ;
@@ -517,9 +520,9 @@ fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
517
520
}
518
521
519
522
520
- /// Instantiates the path for the given trait reference, assuming that it's bound to a valid trait
521
- /// type. Returns the def_id for the defining trait. Fails if the type is a type other than a trait
522
- /// type.
523
+ /// Instantiates the path for the given trait reference, assuming that it's
524
+ /// bound to a valid trait type. Returns the def_id for the defining trait.
525
+ /// Fails if the type is a type other than a trait type.
523
526
pub fn instantiate_trait_ref < ' tcx , AC , RS > ( this : & AC ,
524
527
rscope : & RS ,
525
528
ast_trait_ref : & ast:: TraitRef ,
@@ -846,18 +849,29 @@ fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
846
849
847
850
debug ! ( "qpath_to_ty: trait_ref={}" , trait_ref. repr( this. tcx( ) ) ) ;
848
851
852
+ if let Some ( ty) = find_assoc_ty ( this, & * trait_ref, qpath. item_name ) {
853
+ return ty;
854
+ }
855
+
856
+ this. tcx ( ) . sess . span_bug ( ast_ty. span ,
857
+ "this associated type didn't get added \
858
+ as a parameter for some reason")
859
+ }
860
+
861
+ fn find_assoc_ty < ' tcx , AC > ( this : & AC ,
862
+ trait_ref : & ty:: TraitRef < ' tcx > ,
863
+ type_name : ast:: Ident )
864
+ -> Option < Ty < ' tcx > >
865
+ where AC : AstConv < ' tcx > {
849
866
let trait_def = this. get_trait_def ( trait_ref. def_id ) ;
850
867
851
868
for ty_param_def in trait_def. generics . types . get_slice ( AssocSpace ) . iter ( ) {
852
- if ty_param_def. name == qpath. item_name . name {
853
- debug ! ( "qpath_to_ty: corresponding ty_param_def={}" , ty_param_def) ;
854
- return trait_ref. substs . type_for_def ( ty_param_def) ;
869
+ if ty_param_def. name == type_name. name {
870
+ return Some ( trait_ref. substs . type_for_def ( ty_param_def) ) ;
855
871
}
856
872
}
857
873
858
- this. tcx ( ) . sess . span_bug ( ast_ty. span ,
859
- "this associated type didn't get added \
860
- as a parameter for some reason")
874
+ None
861
875
}
862
876
863
877
// Parses the programmer's textual representation of a type into our
@@ -1011,6 +1025,51 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
1011
1025
. get( ) ) . as_slice ( ) ) ;
1012
1026
ty:: mk_err ( )
1013
1027
}
1028
+ def:: DefAssociatedPath ( typ, assoc_ident) => {
1029
+ // FIXME(#19541): in both branches we should consider
1030
+ // associated types in super-traits.
1031
+ let ( assoc_tys, tp_name) : ( Vec < _ > , _ ) = match typ {
1032
+ def:: TyParamProvenance :: FromParam ( did) => {
1033
+ let ty_param_defs = tcx. ty_param_defs . borrow ( ) ;
1034
+ let tp_def = & ( * ty_param_defs) [ did. node ] ;
1035
+ let assoc_tys = tp_def. bounds . trait_bounds . iter ( )
1036
+ . filter_map ( |b| find_assoc_ty ( this, & * * b, assoc_ident) )
1037
+ . collect ( ) ;
1038
+ ( assoc_tys, token:: get_name ( tp_def. name ) . to_string ( ) )
1039
+ }
1040
+ def:: TyParamProvenance :: FromSelf ( did) => {
1041
+ let assoc_tys = find_assoc_ty ( this,
1042
+ & * this. get_trait_def ( did) . trait_ref ,
1043
+ assoc_ident)
1044
+ . into_iter ( ) . collect ( ) ;
1045
+ ( assoc_tys, "Self" . to_string ( ) )
1046
+ }
1047
+ } ;
1048
+
1049
+ if assoc_tys. len ( ) == 0 {
1050
+ tcx. sess . span_err ( ast_ty. span ,
1051
+ format ! ( "associated type `{}` not \
1052
+ found for type parameter `{}`",
1053
+ token:: get_ident( assoc_ident) ,
1054
+ tp_name) . as_slice ( ) ) ;
1055
+ return ty:: mk_err ( )
1056
+ }
1057
+
1058
+ if assoc_tys. len ( ) > 1 {
1059
+ tcx. sess . span_err ( ast_ty. span ,
1060
+ format ! ( "ambiguous associated type \
1061
+ `{}` in bounds of `{}`",
1062
+ token:: get_ident( assoc_ident) ,
1063
+ tp_name) . as_slice ( ) ) ;
1064
+ }
1065
+
1066
+ let mut result_ty = assoc_tys[ 0 ] ;
1067
+ if let Some ( substs) = this. get_free_substs ( ) {
1068
+ result_ty = result_ty. subst ( tcx, substs) ;
1069
+ }
1070
+
1071
+ result_ty
1072
+ }
1014
1073
_ => {
1015
1074
tcx. sess . span_fatal ( ast_ty. span ,
1016
1075
format ! ( "found value name used \
0 commit comments