@@ -2479,19 +2479,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
24792479 ) ;
24802480 eq
24812481 } )
2482- . map ( |ty:: GeneratorInteriorTypeCause { span, scope_span, .. } | {
2483- ( span, source_map. span_to_snippet ( * span) , scope_span)
2482+ . map ( |ty:: GeneratorInteriorTypeCause { span, scope_span, expr , .. } | {
2483+ ( span, source_map. span_to_snippet ( * span) , scope_span, expr )
24842484 } ) ;
2485+
24852486 debug ! (
24862487 "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
24872488 generator_interior_types={:?} target_span={:?}",
24882489 target_ty, tables. generator_interior_types, target_span
24892490 ) ;
2490- if let Some ( ( target_span, Ok ( snippet) , scope_span) ) = target_span {
2491+ if let Some ( ( target_span, Ok ( snippet) , scope_span, expr ) ) = target_span {
24912492 self . note_obligation_cause_for_async_await (
24922493 err,
24932494 * target_span,
24942495 scope_span,
2496+ * expr,
24952497 snippet,
24962498 generator_did,
24972499 last_generator,
@@ -2514,6 +2516,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
25142516 err : & mut DiagnosticBuilder < ' _ > ,
25152517 target_span : Span ,
25162518 scope_span : & Option < Span > ,
2519+ expr : Option < hir:: HirId > ,
25172520 snippet : String ,
25182521 first_generator : DefId ,
25192522 last_generator : Option < DefId > ,
@@ -2549,6 +2552,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
25492552 // not implemented.
25502553 let is_send = self . tcx . is_diagnostic_item ( sym:: send_trait, trait_ref. def_id ) ;
25512554 let is_sync = self . tcx . is_diagnostic_item ( sym:: sync_trait, trait_ref. def_id ) ;
2555+ let hir = self . tcx . hir ( ) ;
25522556 let trait_explanation = if is_send || is_sync {
25532557 let ( trait_name, trait_verb) =
25542558 if is_send { ( "`Send`" , "sent" ) } else { ( "`Sync`" , "shared" ) } ;
@@ -2564,8 +2568,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
25642568
25652569 let message = if let Some ( name) = last_generator
25662570 . and_then ( |generator_did| self . tcx . parent ( generator_did) )
2567- . and_then ( |parent_did| self . tcx . hir ( ) . as_local_hir_id ( parent_did) )
2568- . and_then ( |parent_hir_id| self . tcx . hir ( ) . opt_name ( parent_hir_id) )
2571+ . and_then ( |parent_did| hir. as_local_hir_id ( parent_did) )
2572+ . and_then ( |parent_hir_id| hir. opt_name ( parent_hir_id) )
25692573 {
25702574 format ! ( "future returned by `{}` is not {}" , name, trait_name)
25712575 } else {
@@ -2581,7 +2585,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
25812585 } ;
25822586
25832587 // Look at the last interior type to get a span for the `.await`.
2584- let await_span = tables. generator_interior_types . iter ( ) . map ( |i| i . span ) . last ( ) . unwrap ( ) ;
2588+ let await_span = tables. generator_interior_types . iter ( ) . map ( |t| t . span ) . last ( ) . unwrap ( ) ;
25852589 let mut span = MultiSpan :: from_span ( await_span) ;
25862590 span. push_span_label (
25872591 await_span,
@@ -2606,6 +2610,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
26062610 ) ,
26072611 ) ;
26082612
2613+ if let Some ( expr_id) = expr {
2614+ let expr = hir. expect_expr ( expr_id) ;
2615+ let is_ref = tables. expr_adjustments ( expr) . iter ( ) . any ( |adj| adj. is_region_borrow ( ) ) ;
2616+ let parent = hir. get_parent_node ( expr_id) ;
2617+ if let Some ( hir:: Node :: Expr ( e) ) = hir. find ( parent) {
2618+ let method_span = hir. span ( parent) ;
2619+ if tables. is_method_call ( e) && is_ref {
2620+ err. span_help (
2621+ method_span,
2622+ "consider moving this method call into a `let` \
2623+ binding to create a shorter lived borrow",
2624+ ) ;
2625+ }
2626+ }
2627+ }
2628+
26092629 // Add a note for the item obligation that remains - normally a note pointing to the
26102630 // bound that introduced the obligation (e.g. `T: Send`).
26112631 debug ! ( "note_obligation_cause_for_async_await: next_code={:?}" , next_code) ;
0 commit comments