@@ -74,6 +74,14 @@ pub trait AstConv<'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
76
77
+ /// Return an (optional) substitution to convert bound type parameters that
78
+ /// are in scope into free ones. This function should only return Some
79
+ /// within a fn body.
80
+ /// See ParameterEnvironment::free_substs for more information.
81
+ fn get_free_substs ( & self ) -> Option < & Substs < ' tcx > > {
82
+ None
83
+ }
84
+
77
85
/// What type should we use when a type is omitted?
78
86
fn ty_infer ( & self , span : Span ) -> Ty < ' tcx > ;
79
87
@@ -517,9 +525,9 @@ fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
517
525
}
518
526
519
527
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.
528
+ /// Instantiates the path for the given trait reference, assuming that it's
529
+ /// bound to a valid trait type. Returns the def_id for the defining trait.
530
+ /// Fails if the type is a type other than a trait type.
523
531
pub fn instantiate_trait_ref < ' tcx , AC , RS > ( this : & AC ,
524
532
rscope : & RS ,
525
533
ast_trait_ref : & ast:: TraitRef ,
@@ -846,18 +854,29 @@ fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
846
854
847
855
debug ! ( "qpath_to_ty: trait_ref={}" , trait_ref. repr( this. tcx( ) ) ) ;
848
856
857
+ if let Some ( ty) = find_assoc_ty ( this, & * trait_ref, qpath. item_name ) {
858
+ return ty;
859
+ }
860
+
861
+ this. tcx ( ) . sess . span_bug ( ast_ty. span ,
862
+ "this associated type didn't get added \
863
+ as a parameter for some reason")
864
+ }
865
+
866
+ fn find_assoc_ty < ' tcx , AC > ( this : & AC ,
867
+ trait_ref : & ty:: TraitRef < ' tcx > ,
868
+ type_name : ast:: Ident )
869
+ -> Option < Ty < ' tcx > >
870
+ where AC : AstConv < ' tcx > {
849
871
let trait_def = this. get_trait_def ( trait_ref. def_id ) ;
850
872
851
873
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) ;
874
+ if ty_param_def. name == type_name. name {
875
+ return Some ( trait_ref. substs . type_for_def ( ty_param_def) ) ;
855
876
}
856
877
}
857
878
858
- this. tcx ( ) . sess . span_bug ( ast_ty. span ,
859
- "this associated type didn't get added \
860
- as a parameter for some reason")
879
+ None
861
880
}
862
881
863
882
// Parses the programmer's textual representation of a type into our
@@ -1011,6 +1030,45 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
1011
1030
. get( ) ) . as_slice ( ) ) ;
1012
1031
ty:: mk_err ( )
1013
1032
}
1033
+ def:: DefAssociatedPath ( typ, assoc_ident) => {
1034
+ // FIXME(#19541): in both branches we should consider
1035
+ // associated types in super-traits.
1036
+ let ( assoc_tys, tp_name) : ( Vec < _ > , _ ) = match typ {
1037
+ def:: TyParamProvenance :: FromParam ( did) |
1038
+ def:: TyParamProvenance :: FromSelf ( did) => {
1039
+ let ty_param_defs = tcx. ty_param_defs . borrow ( ) ;
1040
+ let tp_def = & ( * ty_param_defs) [ did. node ] ;
1041
+ let assoc_tys = tp_def. bounds . trait_bounds . iter ( )
1042
+ . filter_map ( |b| find_assoc_ty ( this, & * * b, assoc_ident) )
1043
+ . collect ( ) ;
1044
+ ( assoc_tys, token:: get_name ( tp_def. name ) . to_string ( ) )
1045
+ }
1046
+ } ;
1047
+
1048
+ if assoc_tys. len ( ) == 0 {
1049
+ tcx. sess . span_err ( ast_ty. span ,
1050
+ format ! ( "associated type `{}` not \
1051
+ found for type parameter `{}`",
1052
+ token:: get_ident( assoc_ident) ,
1053
+ tp_name) . as_slice ( ) ) ;
1054
+ return ty:: mk_err ( )
1055
+ }
1056
+
1057
+ if assoc_tys. len ( ) > 1 {
1058
+ tcx. sess . span_err ( ast_ty. span ,
1059
+ format ! ( "ambiguous associated type \
1060
+ `{}` in bounds of `{}`",
1061
+ token:: get_ident( assoc_ident) ,
1062
+ tp_name) . as_slice ( ) ) ;
1063
+ }
1064
+
1065
+ let mut result_ty = assoc_tys[ 0 ] ;
1066
+ if let Some ( substs) = this. get_free_substs ( ) {
1067
+ result_ty = result_ty. subst ( tcx, substs) ;
1068
+ }
1069
+
1070
+ result_ty
1071
+ }
1014
1072
_ => {
1015
1073
tcx. sess . span_fatal ( ast_ty. span ,
1016
1074
format ! ( "found value name used \
0 commit comments