@@ -854,16 +854,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
854
854
)
855
855
}
856
856
857
- fn trait_defines_associated_type_named ( & self , trait_def_id : DefId , assoc_name : Ident ) -> bool {
858
- self . tcx ( )
859
- . associated_items ( trait_def_id)
860
- . find_by_name_and_kind ( self . tcx ( ) , assoc_name, ty:: AssocKind :: Type , trait_def_id)
861
- . is_some ( )
862
- }
863
- fn trait_defines_associated_const_named ( & self , trait_def_id : DefId , assoc_name : Ident ) -> bool {
857
+ fn trait_defines_associated_item_named (
858
+ & self ,
859
+ trait_def_id : DefId ,
860
+ assoc_kind : ty:: AssocKind ,
861
+ assoc_name : Ident ,
862
+ ) -> bool {
864
863
self . tcx ( )
865
864
. associated_items ( trait_def_id)
866
- . find_by_name_and_kind ( self . tcx ( ) , assoc_name, ty :: AssocKind :: Const , trait_def_id)
865
+ . find_by_name_and_kind ( self . tcx ( ) , assoc_name, assoc_kind , trait_def_id)
867
866
. is_some ( )
868
867
}
869
868
@@ -1087,24 +1086,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1087
1086
1088
1087
let tcx = self . tcx ( ) ;
1089
1088
1090
- let candidate =
1091
- if self . trait_defines_associated_type_named ( trait_ref. def_id ( ) , binding. item_name ) {
1092
- // Simple case: X is defined in the current trait.
1089
+ // TODO: rtn comment goes here
1090
+ let associated_return_type_bound =
1091
+ binding. gen_args . parenthesized && self . tcx ( ) . features ( ) . associated_return_type_bounds ;
1092
+
1093
+ let candidate = if return_type_notation {
1094
+ if self . trait_defines_associated_item_named (
1095
+ trait_ref. def_id ( ) ,
1096
+ ty:: AssocKind :: Fn ,
1097
+ binding. item_name ,
1098
+ ) {
1093
1099
trait_ref
1094
1100
} else {
1095
- // Otherwise, we have to walk through the supertraits to find
1096
- // those that do.
1097
- self . one_bound_for_assoc_type (
1098
- || traits:: supertraits ( tcx, trait_ref) ,
1099
- trait_ref. print_only_trait_path ( ) ,
1100
- binding. item_name ,
1101
- path_span,
1102
- match binding. kind {
1103
- ConvertedBindingKind :: Equality ( term) => Some ( term) ,
1104
- _ => None ,
1105
- } ,
1106
- ) ?
1107
- } ;
1101
+ // TODO: error
1102
+ todo ! ( )
1103
+ }
1104
+ } else if self . trait_defines_associated_item_named (
1105
+ trait_ref. def_id ( ) ,
1106
+ ty:: AssocKind :: Type ,
1107
+ binding. item_name ,
1108
+ ) {
1109
+ // Simple case: X is defined in the current trait.
1110
+ trait_ref
1111
+ } else {
1112
+ // Otherwise, we have to walk through the supertraits to find
1113
+ // those that do.
1114
+ self . one_bound_for_assoc_type (
1115
+ || traits:: supertraits ( tcx, trait_ref) ,
1116
+ trait_ref. print_only_trait_path ( ) ,
1117
+ binding. item_name ,
1118
+ path_span,
1119
+ match binding. kind {
1120
+ ConvertedBindingKind :: Equality ( term) => Some ( term) ,
1121
+ _ => None ,
1122
+ } ,
1123
+ ) ?
1124
+ } ;
1108
1125
1109
1126
let ( assoc_ident, def_scope) =
1110
1127
tcx. adjust_ident_and_get_scope ( binding. item_name , candidate. def_id ( ) , hir_ref_id) ;
@@ -1116,9 +1133,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1116
1133
. filter_by_name_unhygienic ( assoc_ident. name )
1117
1134
. find ( |i| i. kind == kind && i. ident ( tcx) . normalize_to_macros_2_0 ( ) == assoc_ident)
1118
1135
} ;
1119
- let assoc_item = find_item_of_kind ( ty:: AssocKind :: Type )
1120
- . or_else ( || find_item_of_kind ( ty:: AssocKind :: Const ) )
1121
- . expect ( "missing associated type" ) ;
1136
+ let assoc_item = if return_type_notation {
1137
+ find_item_of_kind ( ty:: AssocKind :: Fn )
1138
+ } else {
1139
+ find_item_of_kind ( ty:: AssocKind :: Type )
1140
+ . or_else ( || find_item_of_kind ( ty:: AssocKind :: Const ) )
1141
+ }
1142
+ . expect ( "missing associated type" ) ;
1122
1143
1123
1144
if !assoc_item. visibility ( tcx) . is_accessible_from ( def_scope, tcx) {
1124
1145
tcx. sess
@@ -1145,28 +1166,54 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1145
1166
. or_insert ( binding. span ) ;
1146
1167
}
1147
1168
1148
- // Include substitutions for generic parameters of associated types
1149
- let projection_ty = candidate. map_bound ( |trait_ref| {
1150
- let ident = Ident :: new ( assoc_item. name , binding. item_name . span ) ;
1151
- let item_segment = hir:: PathSegment {
1152
- ident,
1153
- hir_id : binding. hir_id ,
1154
- res : Res :: Err ,
1155
- args : Some ( binding. gen_args ) ,
1156
- infer_args : false ,
1169
+ let projection_ty = if associated_return_type_bound {
1170
+ let generics = self . tcx ( ) . generics_of ( assoc_item. def_id ) ;
1171
+ if !generics. params . is_empty ( ) {
1172
+ todo ! ( ) ;
1173
+ }
1174
+ let output = self . tcx ( ) . fn_sig ( assoc_item. def_id ) . skip_binder ( ) . output ( ) ;
1175
+ let fn_bound_vars = output. bound_vars ( ) ;
1176
+
1177
+ let output = if let ty:: Alias ( ty:: Projection , alias_ty) = * output. skip_binder ( ) . kind ( )
1178
+ && tcx. def_kind ( alias_ty. def_id ) == DefKind :: ImplTraitPlaceholder
1179
+ {
1180
+ alias_ty
1181
+ } else {
1182
+ todo ! ( "found return type of {output:?}" ) ;
1157
1183
} ;
1158
1184
1159
- let substs_trait_ref_and_assoc_item = self . create_substs_for_associated_item (
1160
- path_span,
1161
- assoc_item. def_id ,
1162
- & item_segment,
1163
- trait_ref. substs ,
1164
- ) ;
1185
+ let trait_bound_vars = candidate. bound_vars ( ) ;
1186
+ let shifted_output = tcx. shift_bound_var_indices ( trait_bound_vars. len ( ) , output) ;
1187
+ let subst_output =
1188
+ ty:: EarlyBinder ( shifted_output) . subst ( tcx, candidate. skip_binder ( ) . substs ) ;
1189
+ let bound_vars =
1190
+ tcx. mk_bound_variable_kinds_from_iter ( trait_bound_vars. iter ( ) . chain ( fn_bound_vars) ) ;
1191
+
1192
+ ty:: Binder :: bind_with_vars ( subst_output, bound_vars)
1193
+ } else {
1194
+ // Include substitutions for generic parameters of associated types
1195
+ candidate. map_bound ( |trait_ref| {
1196
+ let ident = Ident :: new ( assoc_item. name , binding. item_name . span ) ;
1197
+ let item_segment = hir:: PathSegment {
1198
+ ident,
1199
+ hir_id : binding. hir_id ,
1200
+ res : Res :: Err ,
1201
+ args : Some ( binding. gen_args ) ,
1202
+ infer_args : false ,
1203
+ } ;
1165
1204
1166
- debug ! ( ?substs_trait_ref_and_assoc_item) ;
1205
+ let substs_trait_ref_and_assoc_item = self . create_substs_for_associated_item (
1206
+ path_span,
1207
+ assoc_item. def_id ,
1208
+ & item_segment,
1209
+ trait_ref. substs ,
1210
+ ) ;
1167
1211
1168
- self . tcx ( ) . mk_alias_ty ( assoc_item. def_id , substs_trait_ref_and_assoc_item)
1169
- } ) ;
1212
+ debug ! ( ?substs_trait_ref_and_assoc_item) ;
1213
+
1214
+ self . tcx ( ) . mk_alias_ty ( assoc_item. def_id , substs_trait_ref_and_assoc_item)
1215
+ } )
1216
+ } ;
1170
1217
1171
1218
if !speculative {
1172
1219
// Find any late-bound regions declared in `ty` that are not
@@ -1206,6 +1253,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1206
1253
}
1207
1254
1208
1255
match binding. kind {
1256
+ ConvertedBindingKind :: Equality ( ..) if associated_return_type_bound => {
1257
+ // TODO: error
1258
+ todo ! ( )
1259
+ }
1209
1260
ConvertedBindingKind :: Equality ( mut term) => {
1210
1261
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to
1211
1262
// the "projection predicate" for:
@@ -1267,7 +1318,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1267
1318
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
1268
1319
// parameter to have a skipped binder.
1269
1320
let param_ty = tcx. mk_alias ( ty:: Projection , projection_ty. skip_binder ( ) ) ;
1270
- self . add_bounds ( param_ty, ast_bounds. iter ( ) , bounds, candidate . bound_vars ( ) ) ;
1321
+ self . add_bounds ( param_ty, ast_bounds. iter ( ) , bounds, projection_ty . bound_vars ( ) ) ;
1271
1322
}
1272
1323
}
1273
1324
Ok ( ( ) )
@@ -1808,10 +1859,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1808
1859
where
1809
1860
I : Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
1810
1861
{
1811
- let mut matching_candidates = all_candidates ( )
1812
- . filter ( |r| self . trait_defines_associated_type_named ( r. def_id ( ) , assoc_name) ) ;
1813
- let mut const_candidates = all_candidates ( )
1814
- . filter ( |r| self . trait_defines_associated_const_named ( r. def_id ( ) , assoc_name) ) ;
1862
+ let mut matching_candidates = all_candidates ( ) . filter ( |r| {
1863
+ self . trait_defines_associated_item_named ( r. def_id ( ) , ty:: AssocKind :: Type , assoc_name)
1864
+ } ) ;
1865
+ let mut const_candidates = all_candidates ( ) . filter ( |r| {
1866
+ self . trait_defines_associated_item_named ( r. def_id ( ) , ty:: AssocKind :: Const , assoc_name)
1867
+ } ) ;
1815
1868
1816
1869
let ( bound, next_cand) = match ( matching_candidates. next ( ) , const_candidates. next ( ) ) {
1817
1870
( Some ( bound) , _) => ( bound, matching_candidates. next ( ) ) ,
0 commit comments