@@ -168,6 +168,37 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
168168 self . trait_def_id ( tcx)
169169 }
170170
171+ fn consider_implied_clause (
172+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
173+ goal : Goal < ' tcx , Self > ,
174+ assumption : ty:: Predicate < ' tcx > ,
175+ requirements : impl IntoIterator < Item = Goal < ' tcx , ty:: Predicate < ' tcx > > > ,
176+ ) -> QueryResult < ' tcx > {
177+ if let Some ( poly_projection_pred) = assumption. to_opt_poly_projection_pred ( )
178+ && poly_projection_pred. projection_def_id ( ) == goal. predicate . def_id ( )
179+ {
180+ ecx. infcx . probe ( |_| {
181+ let assumption_projection_pred =
182+ ecx. infcx . instantiate_binder_with_infer ( poly_projection_pred) ;
183+ let mut nested_goals = ecx. infcx . eq (
184+ goal. param_env ,
185+ goal. predicate . projection_ty ,
186+ assumption_projection_pred. projection_ty ,
187+ ) ?;
188+ nested_goals. extend ( requirements) ;
189+ let subst_certainty = ecx. evaluate_all ( nested_goals) ?;
190+
191+ ecx. eq_term_and_make_canonical_response (
192+ goal,
193+ subst_certainty,
194+ assumption_projection_pred. term ,
195+ )
196+ } )
197+ } else {
198+ Err ( NoSolution )
199+ }
200+ }
201+
171202 fn consider_impl_candidate (
172203 ecx : & mut EvalCtxt < ' _ , ' tcx > ,
173204 goal : Goal < ' tcx , ProjectionPredicate < ' tcx > > ,
@@ -260,36 +291,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
260291 } )
261292 }
262293
263- fn consider_assumption_with_certainty (
264- ecx : & mut EvalCtxt < ' _ , ' tcx > ,
265- goal : Goal < ' tcx , Self > ,
266- assumption : ty:: Predicate < ' tcx > ,
267- assumption_certainty : Certainty ,
268- ) -> QueryResult < ' tcx > {
269- if let Some ( poly_projection_pred) = assumption. to_opt_poly_projection_pred ( )
270- && poly_projection_pred. projection_def_id ( ) == goal. predicate . def_id ( )
271- {
272- ecx. infcx . probe ( |_| {
273- let assumption_projection_pred =
274- ecx. infcx . instantiate_binder_with_infer ( poly_projection_pred) ;
275- let nested_goals = ecx. infcx . eq (
276- goal. param_env ,
277- goal. predicate . projection_ty ,
278- assumption_projection_pred. projection_ty ,
279- ) ?;
280- let subst_certainty = ecx. evaluate_all ( nested_goals) ?;
281-
282- ecx. eq_term_and_make_canonical_response (
283- goal,
284- subst_certainty. unify_and ( assumption_certainty) ,
285- assumption_projection_pred. term ,
286- )
287- } )
288- } else {
289- Err ( NoSolution )
290- }
291- }
292-
293294 fn consider_auto_trait_candidate (
294295 _ecx : & mut EvalCtxt < ' _ , ' tcx > ,
295296 goal : Goal < ' tcx , Self > ,
@@ -331,31 +332,27 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
331332 goal_kind : ty:: ClosureKind ,
332333 ) -> QueryResult < ' tcx > {
333334 let tcx = ecx. tcx ( ) ;
334- if let Some ( tupled_inputs_and_output) =
335- structural_traits:: extract_tupled_inputs_and_output_from_callable (
336- tcx,
337- goal. predicate . self_ty ( ) ,
338- goal_kind,
339- ) ?
340- {
341- // A built-in `Fn` trait needs to check that its output is `Sized`
342- // (FIXME: technically we only need to check this if the type is a fn ptr...)
343- let output_is_sized_pred = tupled_inputs_and_output
344- . map_bound ( |( _, output) | tcx. at ( DUMMY_SP ) . mk_trait_ref ( LangItem :: Sized , [ output] ) ) ;
345- let ( _, output_is_sized_certainty) =
346- ecx. evaluate_goal ( goal. with ( tcx, output_is_sized_pred) ) ?;
347-
348- let pred = tupled_inputs_and_output
349- . map_bound ( |( inputs, output) | ty:: ProjectionPredicate {
350- projection_ty : tcx
351- . mk_alias_ty ( goal. predicate . def_id ( ) , [ goal. predicate . self_ty ( ) , inputs] ) ,
352- term : output. into ( ) ,
353- } )
354- . to_predicate ( tcx) ;
355- Self :: consider_assumption_with_certainty ( ecx, goal, pred, output_is_sized_certainty)
356- } else {
357- ecx. make_canonical_response ( Certainty :: AMBIGUOUS )
358- }
335+ let Some ( tupled_inputs_and_output) =
336+ structural_traits:: extract_tupled_inputs_and_output_from_callable (
337+ tcx,
338+ goal. predicate . self_ty ( ) ,
339+ goal_kind,
340+ ) ? else {
341+ return ecx. make_canonical_response ( Certainty :: AMBIGUOUS ) ;
342+ } ;
343+ let output_is_sized_pred = tupled_inputs_and_output
344+ . map_bound ( |( _, output) | tcx. at ( DUMMY_SP ) . mk_trait_ref ( LangItem :: Sized , [ output] ) ) ;
345+
346+ let pred = tupled_inputs_and_output
347+ . map_bound ( |( inputs, output) | ty:: ProjectionPredicate {
348+ projection_ty : tcx
349+ . mk_alias_ty ( goal. predicate . def_id ( ) , [ goal. predicate . self_ty ( ) , inputs] ) ,
350+ term : output. into ( ) ,
351+ } )
352+ . to_predicate ( tcx) ;
353+ // A built-in `Fn` impl only holds if the output is sized.
354+ // (FIXME: technically we only need to check this if the type is a fn ptr...)
355+ Self :: consider_implied_clause ( ecx, goal, pred, [ goal. with ( tcx, output_is_sized_pred) ] )
359356 }
360357
361358 fn consider_builtin_tuple_candidate (
@@ -474,14 +471,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
474471
475472 let term = substs. as_generator ( ) . return_ty ( ) . into ( ) ;
476473
477- Self :: consider_assumption (
474+ Self :: consider_implied_clause (
478475 ecx,
479476 goal,
480477 ty:: Binder :: dummy ( ty:: ProjectionPredicate {
481478 projection_ty : ecx. tcx ( ) . mk_alias_ty ( goal. predicate . def_id ( ) , [ self_ty] ) ,
482479 term,
483480 } )
484481 . to_predicate ( tcx) ,
482+ // Technically, we need to check that the future type is Sized,
483+ // but that's already proven by the generator being WF.
484+ [ ] ,
485485 )
486486 }
487487
@@ -511,7 +511,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
511511 bug ! ( "unexpected associated item `<{self_ty} as Generator>::{name}`" )
512512 } ;
513513
514- Self :: consider_assumption (
514+ Self :: consider_implied_clause (
515515 ecx,
516516 goal,
517517 ty:: Binder :: dummy ( ty:: ProjectionPredicate {
@@ -521,6 +521,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
521521 term,
522522 } )
523523 . to_predicate ( tcx) ,
524+ // Technically, we need to check that the future type is Sized,
525+ // but that's already proven by the generator being WF.
526+ [ ] ,
524527 )
525528 }
526529
0 commit comments