@@ -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,36 @@ 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
+ let return_ty =
590
+ return_ty. unwrap_or_else ( || self . next_ty_var ( cause_span. unwrap_or ( DUMMY_SP ) ) ) ;
591
+
592
+ let sig = projection. rebind ( self . tcx . mk_fn_sig (
593
+ input_tys,
594
+ return_ty,
595
+ false ,
596
+ hir:: Safety :: Safe ,
597
+ Abi :: Rust ,
598
+ ) ) ;
599
+
600
+ return Some ( ExpectedSig { cause_span, sig } ) ;
585
601
}
586
602
587
603
fn sig_of_closure (
0 commit comments