@@ -30,7 +30,12 @@ struct ExpectedSig<'tcx> {
30
30
}
31
31
32
32
struct ClosureSignatures < ' tcx > {
33
+ /// The signature users of the closure see.
33
34
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.
34
39
liberated_sig : ty:: FnSig < ' tcx > ,
35
40
}
36
41
@@ -444,18 +449,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
444
449
// Along the way, it also writes out entries for types that the user
445
450
// wrote into our typeck results, which are then later used by the privacy
446
451
// check.
447
- match self . check_supplied_sig_against_expectation (
452
+ match self . merge_supplied_sig_with_expectation (
448
453
hir_id,
449
454
expr_def_id,
450
455
decl,
451
456
body,
452
- & closure_sigs,
457
+ closure_sigs,
453
458
) {
454
459
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) ,
456
461
}
457
-
458
- closure_sigs
459
462
}
460
463
461
464
fn sig_of_closure_with_mismatched_number_of_arguments (
@@ -497,21 +500,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
497
500
/// Enforce the user's types against the expectation. See
498
501
/// `sig_of_closure_with_expectation` for details on the overall
499
502
/// 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 (
501
505
& self ,
502
506
hir_id : hir:: HirId ,
503
507
expr_def_id : DefId ,
504
508
decl : & hir:: FnDecl < ' _ > ,
505
509
body : & hir:: Body < ' _ > ,
506
- expected_sigs : & ClosureSignatures < ' tcx > ,
507
- ) -> InferResult < ' tcx , ( ) > {
510
+ mut expected_sigs : ClosureSignatures < ' tcx > ,
511
+ ) -> InferResult < ' tcx , ClosureSignatures < ' tcx > > {
508
512
// Get the signature S that the user gave.
509
513
//
510
514
// (See comment on `sig_of_closure_with_expectation` for the
511
515
// meaning of these letters.)
512
516
let supplied_sig = self . supplied_sig_of_closure ( hir_id, expr_def_id, decl, body) ;
513
517
514
- debug ! ( "check_supplied_sig_against_expectation: supplied_sig={:?}" , supplied_sig) ;
518
+ debug ! ( ? supplied_sig) ;
515
519
516
520
// FIXME(#45727): As discussed in [this comment][c1], naively
517
521
// forcing equality here actually results in suboptimal error
@@ -529,23 +533,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
529
533
// [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796
530
534
self . commit_if_ok ( |_| {
531
535
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 ( ) ;
532
550
533
551
// The liberated version of this signature should be a subtype
534
552
// of the liberated form of the expectation.
535
553
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) ,
540
555
expected_sigs. liberated_sig . inputs ( ) , // `liberated_sig` is E'.
541
556
) {
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
-
549
557
// Check that E' = S'.
550
558
let cause = self . misc ( hir_ty. span ) ;
551
559
let InferOk { value : ( ) , obligations } =
@@ -564,7 +572,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
564
572
. eq ( expected_sigs. liberated_sig . output ( ) , supplied_output_ty) ?;
565
573
all_obligations. extend ( obligations) ;
566
574
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 } )
568
586
} )
569
587
}
570
588
0 commit comments