@@ -854,16 +854,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
854854 )
855855 }
856856
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 {
864863 self . tcx ( )
865864 . 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)
867866 . is_some ( )
868867 }
869868
@@ -1087,24 +1086,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10871086
10881087 let tcx = self . tcx ( ) ;
10891088
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+ ) {
10931099 trait_ref
10941100 } 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+ } ;
11081125
11091126 let ( assoc_ident, def_scope) =
11101127 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 {
11161133 . filter_by_name_unhygienic ( assoc_ident. name )
11171134 . find ( |i| i. kind == kind && i. ident ( tcx) . normalize_to_macros_2_0 ( ) == assoc_ident)
11181135 } ;
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" ) ;
11221143
11231144 if !assoc_item. visibility ( tcx) . is_accessible_from ( def_scope, tcx) {
11241145 tcx. sess
@@ -1145,28 +1166,54 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11451166 . or_insert ( binding. span ) ;
11461167 }
11471168
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:?}" ) ;
11571183 } ;
11581184
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+ } ;
11651204
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+ ) ;
11671211
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+ } ;
11701217
11711218 if !speculative {
11721219 // Find any late-bound regions declared in `ty` that are not
@@ -1206,6 +1253,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12061253 }
12071254
12081255 match binding. kind {
1256+ ConvertedBindingKind :: Equality ( ..) if associated_return_type_bound => {
1257+ // TODO: error
1258+ todo ! ( )
1259+ }
12091260 ConvertedBindingKind :: Equality ( mut term) => {
12101261 // "Desugar" a constraint like `T: Iterator<Item = u32>` this to
12111262 // the "projection predicate" for:
@@ -1267,7 +1318,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12671318 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
12681319 // parameter to have a skipped binder.
12691320 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 ( ) ) ;
12711322 }
12721323 }
12731324 Ok ( ( ) )
@@ -1808,10 +1859,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
18081859 where
18091860 I : Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
18101861 {
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+ } ) ;
18151868
18161869 let ( bound, next_cand) = match ( matching_candidates. next ( ) , const_candidates. next ( ) ) {
18171870 ( Some ( bound) , _) => ( bound, matching_candidates. next ( ) ) ,
0 commit comments