@@ -1088,7 +1088,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1088
1088
1089
1089
// TODO: rtn comment goes here
1090
1090
let associated_return_type_bound =
1091
- binding. gen_args . parenthesized && self . tcx ( ) . features ( ) . associated_return_type_bounds ;
1091
+ binding. gen_args . parenthesized && tcx. features ( ) . associated_return_type_bounds ;
1092
1092
1093
1093
let candidate = if return_type_notation {
1094
1094
if self . trait_defines_associated_item_named (
@@ -1156,7 +1156,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1156
1156
dup_bindings
1157
1157
. entry ( assoc_item. def_id )
1158
1158
. and_modify ( |prev_span| {
1159
- self . tcx ( ) . sess . emit_err ( ValueOfAssociatedStructAlreadySpecified {
1159
+ tcx. sess . emit_err ( ValueOfAssociatedStructAlreadySpecified {
1160
1160
span : binding. span ,
1161
1161
prev_span : * prev_span,
1162
1162
item_name : binding. item_name ,
@@ -1166,14 +1166,53 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1166
1166
. or_insert ( binding. span ) ;
1167
1167
}
1168
1168
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 ( ) ;
1169
+ let projection_ty = if return_type_notation {
1170
+ // If we have an method return type bound, then we need to substitute
1171
+ // the method's early bound params with suitable late-bound params.
1172
+ let mut num_bound_vars = candidate. bound_vars ( ) . len ( ) ;
1173
+ let substs =
1174
+ candidate. skip_binder ( ) . substs . extend_to ( tcx, assoc_item. def_id , |param, _| {
1175
+ let subst = match param. kind {
1176
+ GenericParamDefKind :: Lifetime => tcx
1177
+ . mk_re_late_bound (
1178
+ ty:: INNERMOST ,
1179
+ ty:: BoundRegion {
1180
+ var : ty:: BoundVar :: from_usize ( num_bound_vars) ,
1181
+ kind : ty:: BoundRegionKind :: BrNamed ( param. def_id , param. name ) ,
1182
+ } ,
1183
+ )
1184
+ . into ( ) ,
1185
+ GenericParamDefKind :: Type { .. } => tcx
1186
+ . mk_bound (
1187
+ ty:: INNERMOST ,
1188
+ ty:: BoundTy {
1189
+ var : ty:: BoundVar :: from_usize ( num_bound_vars) ,
1190
+ kind : ty:: BoundTyKind :: Param ( param. def_id , param. name ) ,
1191
+ } ,
1192
+ )
1193
+ . into ( ) ,
1194
+ GenericParamDefKind :: Const { .. } => {
1195
+ let ty = tcx
1196
+ . type_of ( param. def_id )
1197
+ . no_bound_vars ( )
1198
+ . expect ( "ct params cannot have early bound vars" ) ;
1199
+ tcx. mk_const (
1200
+ ty:: ConstKind :: Bound (
1201
+ ty:: INNERMOST ,
1202
+ ty:: BoundVar :: from_usize ( num_bound_vars) ,
1203
+ ) ,
1204
+ ty,
1205
+ )
1206
+ . into ( )
1207
+ }
1208
+ } ;
1209
+ num_bound_vars += 1 ;
1210
+ subst
1211
+ } ) ;
1176
1212
1213
+ // Next, we need to check that the return-type notation is being used on
1214
+ // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
1215
+ let output = tcx. fn_sig ( assoc_item. def_id ) . skip_binder ( ) . output ( ) ;
1177
1216
let output = if let ty:: Alias ( ty:: Projection , alias_ty) = * output. skip_binder ( ) . kind ( )
1178
1217
&& tcx. def_kind ( alias_ty. def_id ) == DefKind :: ImplTraitPlaceholder
1179
1218
{
@@ -1182,13 +1221,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1182
1221
todo ! ( "found return type of {output:?}" ) ;
1183
1222
} ;
1184
1223
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) ) ;
1224
+ // Finally, move the fn return type's bound vars over to account for the early bound
1225
+ // params (and trait ref's late bound params). This logic is very similar to
1226
+ // `Predicate::subst_supertrait`, and it's no coincidence why.
1227
+ let shifted_output = tcx. shift_bound_var_indices ( num_bound_vars, output) ;
1228
+ let subst_output = ty:: EarlyBinder ( shifted_output) . subst ( tcx, substs) ;
1191
1229
1230
+ let bound_vars = tcx. late_bound_vars ( binding. hir_id ) ;
1192
1231
ty:: Binder :: bind_with_vars ( subst_output, bound_vars)
1193
1232
} else {
1194
1233
// Include substitutions for generic parameters of associated types
@@ -1211,7 +1250,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1211
1250
1212
1251
debug ! ( ?substs_trait_ref_and_assoc_item) ;
1213
1252
1214
- self . tcx ( ) . mk_alias_ty ( assoc_item. def_id , substs_trait_ref_and_assoc_item)
1253
+ tcx. mk_alias_ty ( assoc_item. def_id , substs_trait_ref_and_assoc_item)
1215
1254
} )
1216
1255
} ;
1217
1256
0 commit comments