@@ -30,7 +30,12 @@ struct ExpectedSig<'tcx> {
3030}
3131
3232struct ClosureSignatures < ' tcx > {
33+ /// The signature users of the closure see.
3334 bound_sig : ty:: PolyFnSig < ' tcx > ,
35+ /// The signature within the function body.
36+ /// This mostly differs in the sense that lifetimes are now early bound and any
37+ /// opaque types from the signature expectation are overriden in case there are
38+ /// explicit hidden types written by the user in the closure signature.
3439 liberated_sig : ty:: FnSig < ' tcx > ,
3540}
3641
@@ -444,18 +449,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
444449 // Along the way, it also writes out entries for types that the user
445450 // wrote into our typeck results, which are then later used by the privacy
446451 // check.
447- match self . check_supplied_sig_against_expectation (
452+ match self . merge_supplied_sig_with_expectation (
448453 hir_id,
449454 expr_def_id,
450455 decl,
451456 body,
452- & closure_sigs,
457+ closure_sigs,
453458 ) {
454459 Ok ( infer_ok) => self . register_infer_ok_obligations ( infer_ok) ,
455- Err ( _) => return self . sig_of_closure_no_expectation ( hir_id, expr_def_id, decl, body) ,
460+ Err ( _) => self . sig_of_closure_no_expectation ( hir_id, expr_def_id, decl, body) ,
456461 }
457-
458- closure_sigs
459462 }
460463
461464 fn sig_of_closure_with_mismatched_number_of_arguments (
@@ -497,21 +500,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
497500 /// Enforce the user's types against the expectation. See
498501 /// `sig_of_closure_with_expectation` for details on the overall
499502 /// strategy.
500- fn check_supplied_sig_against_expectation (
503+ #[ instrument( level = "debug" , skip( self , hir_id, expr_def_id, decl, body, expected_sigs) ) ]
504+ fn merge_supplied_sig_with_expectation (
501505 & self ,
502506 hir_id : hir:: HirId ,
503507 expr_def_id : DefId ,
504508 decl : & hir:: FnDecl < ' _ > ,
505509 body : & hir:: Body < ' _ > ,
506- expected_sigs : & ClosureSignatures < ' tcx > ,
507- ) -> InferResult < ' tcx , ( ) > {
510+ mut expected_sigs : ClosureSignatures < ' tcx > ,
511+ ) -> InferResult < ' tcx , ClosureSignatures < ' tcx > > {
508512 // Get the signature S that the user gave.
509513 //
510514 // (See comment on `sig_of_closure_with_expectation` for the
511515 // meaning of these letters.)
512516 let supplied_sig = self . supplied_sig_of_closure ( hir_id, expr_def_id, decl, body) ;
513517
514- debug ! ( "check_supplied_sig_against_expectation: supplied_sig={:?}" , supplied_sig) ;
518+ debug ! ( ? supplied_sig) ;
515519
516520 // FIXME(#45727): As discussed in [this comment][c1], naively
517521 // forcing equality here actually results in suboptimal error
@@ -529,23 +533,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
529533 // [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796
530534 self . commit_if_ok ( |_| {
531535 let mut all_obligations = vec ! [ ] ;
536+ let inputs: Vec < _ > = iter:: zip (
537+ decl. inputs ,
538+ supplied_sig. inputs ( ) . skip_binder ( ) , // binder moved to (*) below
539+ )
540+ . map ( |( hir_ty, & supplied_ty) | {
541+ // Instantiate (this part of..) S to S', i.e., with fresh variables.
542+ self . replace_bound_vars_with_fresh_vars (
543+ hir_ty. span ,
544+ LateBoundRegionConversionTime :: FnCall ,
545+ // (*) binder moved to here
546+ supplied_sig. inputs ( ) . rebind ( supplied_ty) ,
547+ )
548+ } )
549+ . collect ( ) ;
532550
533551 // The liberated version of this signature should be a subtype
534552 // of the liberated form of the expectation.
535553 for ( ( hir_ty, & supplied_ty) , expected_ty) in iter:: zip (
536- iter:: zip (
537- decl. inputs ,
538- supplied_sig. inputs ( ) . skip_binder ( ) , // binder moved to (*) below
539- ) ,
554+ iter:: zip ( decl. inputs , & inputs) ,
540555 expected_sigs. liberated_sig . inputs ( ) , // `liberated_sig` is E'.
541556 ) {
542- // Instantiate (this part of..) S to S', i.e., with fresh variables.
543- let supplied_ty = self . replace_bound_vars_with_fresh_vars (
544- hir_ty. span ,
545- LateBoundRegionConversionTime :: FnCall ,
546- supplied_sig. inputs ( ) . rebind ( supplied_ty) ,
547- ) ; // recreated from (*) above
548-
549557 // Check that E' = S'.
550558 let cause = self . misc ( hir_ty. span ) ;
551559 let InferOk { value : ( ) , obligations } =
@@ -564,7 +572,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
564572 . eq ( expected_sigs. liberated_sig . output ( ) , supplied_output_ty) ?;
565573 all_obligations. extend ( obligations) ;
566574
567- Ok ( InferOk { value : ( ) , obligations : all_obligations } )
575+ let inputs = inputs. into_iter ( ) . map ( |ty| self . resolve_vars_if_possible ( ty) ) ;
576+
577+ expected_sigs. liberated_sig = self . tcx . mk_fn_sig (
578+ inputs,
579+ supplied_output_ty,
580+ expected_sigs. liberated_sig . c_variadic ,
581+ hir:: Unsafety :: Normal ,
582+ Abi :: RustCall ,
583+ ) ;
584+
585+ Ok ( InferOk { value : expected_sigs, obligations : all_obligations } )
568586 } )
569587 }
570588
0 commit comments