@@ -871,24 +871,11 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
871
871
}
872
872
}
873
873
874
- if candidates. len ( ) > 1 {
875
- span_err ! ( tcx. sess, binding. span, E0217 ,
876
- "ambiguous associated type: `{}` defined in multiple supertraits `{}`" ,
877
- token:: get_name( binding. item_name) ,
878
- candidates. user_string( tcx) ) ;
879
- return Err ( ErrorReported ) ;
880
- }
881
-
882
- let candidate = match candidates. pop ( ) {
883
- Some ( c) => c,
884
- None => {
885
- span_err ! ( tcx. sess, binding. span, E0218 ,
886
- "no associated type `{}` defined in `{}`" ,
887
- token:: get_name( binding. item_name) ,
888
- trait_ref. user_string( tcx) ) ;
889
- return Err ( ErrorReported ) ;
890
- }
891
- } ;
874
+ let candidate = try!( one_bound_for_assoc_type ( tcx,
875
+ candidates,
876
+ & trait_ref. user_string ( tcx) ,
877
+ & token:: get_name ( binding. item_name ) ,
878
+ binding. span ) ) ;
892
879
893
880
Ok ( ty:: Binder ( ty:: ProjectionPredicate { // <-------------------------+
894
881
projection_ty : ty:: ProjectionTy { // |
@@ -1042,19 +1029,18 @@ fn report_ambiguous_associated_type(tcx: &ty::ctxt,
1042
1029
}
1043
1030
1044
1031
// Search for a bound on a type parameter which includes the associated item
1045
- // given by assoc_name. We assume that ty_path_def is the def for such a type
1046
- // parameter (which might be `Self`). This function will fail if there are no
1047
- // suitable bounds or there is any ambiguity.
1032
+ // given by assoc_name. ty_param_node_id is the node id for the type parameter
1033
+ // (which might be `Self`, but only if it is the `Self` of a trait, not an
1034
+ // impl). This function will fail if there are no suitable bounds or there is
1035
+ // any ambiguity.
1048
1036
fn find_bound_for_assoc_item < ' tcx > ( this : & AstConv < ' tcx > ,
1049
- ty_path_def : def :: Def ,
1037
+ ty_param_node_id : ast :: NodeId ,
1050
1038
assoc_name : ast:: Name ,
1051
1039
span : Span )
1052
1040
-> Result < ty:: PolyTraitRef < ' tcx > , ErrorReported >
1053
1041
{
1054
1042
let tcx = this. tcx ( ) ;
1055
1043
1056
- let ty_param_node_id = ty_path_def. local_node_id ( ) ;
1057
-
1058
1044
let bounds = match this. get_type_parameter_bounds ( span, ty_param_node_id) {
1059
1045
Ok ( v) => v,
1060
1046
Err ( ErrorReported ) => {
@@ -1069,35 +1055,52 @@ fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>,
1069
1055
1070
1056
// Check that there is exactly one way to find an associated type with the
1071
1057
// correct name.
1072
- let mut suitable_bounds: Vec < _ > =
1058
+ let suitable_bounds: Vec < _ > =
1073
1059
traits:: transitive_bounds ( tcx, & bounds)
1074
1060
. filter ( |b| this. trait_defines_associated_type_named ( b. def_id ( ) , assoc_name) )
1075
1061
. collect ( ) ;
1076
1062
1077
- let ty_param_name = tcx. ty_param_defs . borrow ( ) . get ( & ty_param_node_id) . unwrap ( ) . name ;
1078
- if suitable_bounds. len ( ) == 0 {
1063
+ let ty_param_name = tcx. type_parameter_def ( ty_param_node_id) . name ;
1064
+ one_bound_for_assoc_type ( tcx,
1065
+ suitable_bounds,
1066
+ & token:: get_name ( ty_param_name) ,
1067
+ & token:: get_name ( assoc_name) ,
1068
+ span)
1069
+ }
1070
+
1071
+
1072
+ // Checks that bounds contains exactly one element and reports appropriate
1073
+ // errors otherwise.
1074
+ fn one_bound_for_assoc_type < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
1075
+ bounds : Vec < ty:: PolyTraitRef < ' tcx > > ,
1076
+ ty_param_name : & str ,
1077
+ assoc_name : & str ,
1078
+ span : Span )
1079
+ -> Result < ty:: PolyTraitRef < ' tcx > , ErrorReported >
1080
+ {
1081
+ if bounds. len ( ) == 0 {
1079
1082
span_err ! ( tcx. sess, span, E0220 ,
1080
- "associated type `{}` not found for type parameter `{}`" ,
1081
- token :: get_name ( assoc_name) ,
1082
- token :: get_name ( ty_param_name) ) ;
1083
+ "associated type `{}` not found for `{}`" ,
1084
+ assoc_name,
1085
+ ty_param_name) ;
1083
1086
return Err ( ErrorReported ) ;
1084
1087
}
1085
1088
1086
- if suitable_bounds . len ( ) > 1 {
1089
+ if bounds . len ( ) > 1 {
1087
1090
span_err ! ( tcx. sess, span, E0221 ,
1088
- "ambiguous associated type `{}` in bounds of `{}`" ,
1089
- token :: get_name ( assoc_name) ,
1090
- token :: get_name ( ty_param_name) ) ;
1091
+ "ambiguous associated type `{}` in bounds of `{}`" ,
1092
+ assoc_name,
1093
+ ty_param_name) ;
1091
1094
1092
- for suitable_bound in & suitable_bounds {
1095
+ for bound in & bounds {
1093
1096
span_note ! ( tcx. sess, span,
1094
1097
"associated type `{}` could derive from `{}`" ,
1095
- token :: get_name ( ty_param_name) ,
1096
- suitable_bound . user_string( tcx) ) ;
1098
+ ty_param_name,
1099
+ bound . user_string( tcx) ) ;
1097
1100
}
1098
1101
}
1099
1102
1100
- Ok ( suitable_bounds . pop ( ) . unwrap ( ) . clone ( ) )
1103
+ Ok ( bounds [ 0 ] . clone ( ) )
1101
1104
}
1102
1105
1103
1106
// Create a type from a a path to an associated type.
@@ -1122,12 +1125,16 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
1122
1125
1123
1126
// Find the type of the associated item, and the trait where the associated
1124
1127
// item is declared.
1125
- let ( ty , trait_did ) = match ( & ty. sty , ty_path_def) {
1128
+ let bound = match ( & ty. sty , ty_path_def) {
1126
1129
( _, def:: DefSelfTy ( Some ( trait_did) , Some ( ( impl_id, _) ) ) ) => {
1127
1130
// `Self` in an impl of a trait - we have a concrete self type and a
1128
1131
// trait reference.
1129
1132
match tcx. map . expect_item ( impl_id) . node {
1130
1133
ast:: ItemImpl ( _, _, _, Some ( ref trait_ref) , _, _) => {
1134
+ if this. ensure_super_predicates ( span, trait_did) . is_err ( ) {
1135
+ return ( tcx. types . err , ty_path_def) ;
1136
+ }
1137
+
1131
1138
let trait_segment = & trait_ref. path . segments . last ( ) . unwrap ( ) ;
1132
1139
let trait_ref = ast_path_to_mono_trait_ref ( this,
1133
1140
& ExplicitRscope ,
@@ -1137,8 +1144,19 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
1137
1144
Some ( ty) ,
1138
1145
trait_segment) ;
1139
1146
1140
- let ty = this. projected_ty ( span, trait_ref, assoc_name) ;
1141
- ( ty, trait_did)
1147
+ let candidates: Vec < ty:: PolyTraitRef > =
1148
+ traits:: supertraits ( tcx, ty:: Binder ( trait_ref. clone ( ) ) )
1149
+ . filter ( |r| this. trait_defines_associated_type_named ( r. def_id ( ) , assoc_name) )
1150
+ . collect ( ) ;
1151
+
1152
+ match one_bound_for_assoc_type ( tcx,
1153
+ candidates,
1154
+ "Self" ,
1155
+ & token:: get_name ( assoc_name) ,
1156
+ span) {
1157
+ Ok ( bound) => bound,
1158
+ Err ( ErrorReported ) => return ( tcx. types . err , ty_path_def) ,
1159
+ }
1142
1160
}
1143
1161
_ => unreachable ! ( )
1144
1162
}
@@ -1147,17 +1165,13 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
1147
1165
( & ty:: ty_param( _) , def:: DefSelfTy ( Some ( _) , None ) ) => {
1148
1166
// A type parameter or Self, we need to find the associated item from
1149
1167
// a bound.
1150
- let bound = match find_bound_for_assoc_item ( this, ty_path_def, assoc_name, span) {
1168
+ let ty_param_node_id = ty_path_def. local_node_id ( ) ;
1169
+ match find_bound_for_assoc_item ( this, ty_param_node_id, assoc_name, span) {
1151
1170
Ok ( bound) => bound,
1152
1171
Err ( ErrorReported ) => return ( tcx. types . err , ty_path_def) ,
1153
- } ;
1154
- let trait_did = bound. 0 . def_id ;
1155
- let ty = this. projected_ty_from_poly_trait_ref ( span, bound, assoc_name) ;
1156
-
1157
- ( ty, trait_did)
1172
+ }
1158
1173
}
1159
1174
_ => {
1160
- println ! ( "{:?} {:?}" , ty. sty, ty_path_def) ;
1161
1175
report_ambiguous_associated_type ( tcx,
1162
1176
span,
1163
1177
& ty. user_string ( tcx) ,
@@ -1167,6 +1181,9 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
1167
1181
}
1168
1182
} ;
1169
1183
1184
+ let trait_did = bound. 0 . def_id ;
1185
+ let ty = this. projected_ty_from_poly_trait_ref ( span, bound, assoc_name) ;
1186
+
1170
1187
let item_did = if trait_did. krate == ast:: LOCAL_CRATE {
1171
1188
// `ty::trait_items` used below requires information generated
1172
1189
// by type collection, which may be in progress at this point.
0 commit comments