@@ -14,7 +14,7 @@ use rustc_middle::span_bug;
14
14
use rustc_middle:: ty:: visit:: { TypeVisitable , TypeVisitableExt } ;
15
15
use rustc_middle:: ty:: { self , GenericArgs , Ty , TyCtxt , TypeSuperVisitable , TypeVisitor } ;
16
16
use rustc_span:: def_id:: LocalDefId ;
17
- use rustc_span:: Span ;
17
+ use rustc_span:: { Span , DUMMY_SP } ;
18
18
use rustc_target:: spec:: abi:: Abi ;
19
19
use rustc_trait_selection:: error_reporting:: traits:: ArgKind ;
20
20
use rustc_trait_selection:: traits;
@@ -539,6 +539,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
539
539
/// we identify the `FnOnce<Args, Output = ?Fut>` bound, and if the output type is
540
540
/// an inference variable `?Fut`, we check if that is bounded by a `Future<Output = Ty>`
541
541
/// projection.
542
+ ///
543
+ /// This function is actually best-effort with the return type; if we don't find a
544
+ /// `Future` projection, we still will return arguments that we extracted from the `FnOnce`
545
+ /// projection, and the output will be an unconstrained type variable instead.
542
546
fn extract_sig_from_projection_and_future_bound (
543
547
& self ,
544
548
cause_span : Option < Span > ,
@@ -564,24 +568,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
564
568
} ;
565
569
566
570
// FIXME: We may want to elaborate here, though I assume this will be exceedingly rare.
571
+ let mut return_ty = None ;
567
572
for bound in self . obligations_for_self_ty ( return_vid) {
568
573
if let Some ( ret_projection) = bound. predicate . as_projection_clause ( )
569
574
&& let Some ( ret_projection) = ret_projection. no_bound_vars ( )
570
575
&& self . tcx . is_lang_item ( ret_projection. def_id ( ) , LangItem :: FutureOutput )
571
576
{
572
- let sig = projection. rebind ( self . tcx . mk_fn_sig (
573
- input_tys,
574
- ret_projection. term . expect_type ( ) ,
575
- false ,
576
- hir:: Safety :: Safe ,
577
- Abi :: Rust ,
578
- ) ) ;
579
-
580
- return Some ( ExpectedSig { cause_span, sig } ) ;
577
+ return_ty = Some ( ret_projection. term . expect_type ( ) ) ;
578
+ break ;
581
579
}
582
580
}
583
581
584
- None
582
+ // SUBTLE: If we didn't find a `Future<Output = ...>` bound for the return
583
+ // vid, we still want to attempt to provide inference guidance for the async
584
+ // closure's arguments. Instantiate a new vid to plug into the output type.
585
+ //
586
+ // You may be wondering, what if it's higher-ranked? Well, given that we
587
+ // found a type variable for the `FnOnce::Output` projection above, we know
588
+ // that the output can't mention any of the vars.
589
+ //
590
+ // Also note that we use a fresh var here for the signature since the signature
591
+ // records the output of the *future*, and `return_vid` above is the type
592
+ // variable of the future, not its output.
593
+ //
594
+ // FIXME: We probably should store this signature inference output in a way
595
+ // that does not misuse a `FnSig` type, but that can be done separately.
596
+ let return_ty =
597
+ return_ty. unwrap_or_else ( || self . next_ty_var ( cause_span. unwrap_or ( DUMMY_SP ) ) ) ;
598
+
599
+ let sig = projection. rebind ( self . tcx . mk_fn_sig (
600
+ input_tys,
601
+ return_ty,
602
+ false ,
603
+ hir:: Safety :: Safe ,
604
+ Abi :: Rust ,
605
+ ) ) ;
606
+
607
+ return Some ( ExpectedSig { cause_span, sig } ) ;
585
608
}
586
609
587
610
fn sig_of_closure (
0 commit comments