@@ -24,7 +24,7 @@ use crate::hir::def_id::DefId;
2424use  crate :: infer:: { self ,  InferCtxt } ; 
2525use  crate :: infer:: type_variable:: { TypeVariableOrigin ,  TypeVariableOriginKind } ; 
2626use  crate :: session:: DiagnosticMessageId ; 
27- use  crate :: ty:: { self ,  AdtKind ,  ToPredicate ,  ToPolyTraitRef ,  Ty ,  TyCtxt ,  TypeFoldable } ; 
27+ use  crate :: ty:: { self ,  AdtKind ,  DefIdTree ,   ToPredicate ,  ToPolyTraitRef ,  Ty ,  TyCtxt ,  TypeFoldable } ; 
2828use  crate :: ty:: GenericParamDefKind ; 
2929use  crate :: ty:: error:: ExpectedFound ; 
3030use  crate :: ty:: fast_reject; 
@@ -37,7 +37,7 @@ use errors::{Applicability, DiagnosticBuilder, pluralise};
3737use  std:: fmt; 
3838use  syntax:: ast; 
3939use  syntax:: symbol:: { sym,  kw} ; 
40- use  syntax_pos:: { DUMMY_SP ,  Span ,  ExpnKind } ; 
40+ use  syntax_pos:: { DUMMY_SP ,  Span ,  ExpnKind ,   MultiSpan } ; 
4141
4242impl < ' a ,  ' tcx >  InferCtxt < ' a ,  ' tcx >  { 
4343    pub  fn  report_fulfillment_errors ( 
@@ -550,7 +550,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
550550            self . suggest_new_overflow_limit ( & mut  err) ; 
551551        } 
552552
553-         self . note_obligation_cause ( & mut  err,  obligation) ; 
553+         self . note_obligation_cause_code ( & mut  err,  & obligation. predicate ,  & obligation. cause . code , 
554+                                         & mut  vec ! [ ] ) ; 
554555
555556        err. emit ( ) ; 
556557        self . tcx . sess . abort_if_errors ( ) ; 
@@ -940,7 +941,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
940941                bug ! ( "overflow should be handled before the `report_selection_error` path" ) ; 
941942            } 
942943        } ; 
944+ 
943945        self . note_obligation_cause ( & mut  err,  obligation) ; 
946+ 
944947        err. emit ( ) ; 
945948    } 
946949
@@ -1604,15 +1607,165 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16041607        } ) 
16051608    } 
16061609
1607-     fn  note_obligation_cause < T > ( & self , 
1608-                                 err :  & mut  DiagnosticBuilder < ' _ > , 
1609-                                 obligation :  & Obligation < ' tcx ,  T > ) 
1610-         where  T :  fmt:: Display 
1611-     { 
1612-         self . note_obligation_cause_code ( err, 
1613-                                         & obligation. predicate , 
1614-                                         & obligation. cause . code , 
1615-                                         & mut  vec ! [ ] ) ; 
1610+     fn  note_obligation_cause ( 
1611+         & self , 
1612+         err :  & mut  DiagnosticBuilder < ' _ > , 
1613+         obligation :  & PredicateObligation < ' tcx > , 
1614+     )  { 
1615+         // First, attempt to add note to this error with an async-await-specific 
1616+         // message, and fall back to regular note otherwise. 
1617+         if  !self . note_obligation_cause_for_async_await ( err,  obligation)  { 
1618+             self . note_obligation_cause_code ( err,  & obligation. predicate ,  & obligation. cause . code , 
1619+                                             & mut  vec ! [ ] ) ; 
1620+         } 
1621+     } 
1622+ 
1623+     /// Adds an async-await specific note to the diagnostic: 
1624+      /// 
1625+      /// ```ignore (diagnostic) 
1626+      /// note: future does not implement `std::marker::Send` because this value is used across an 
1627+      ///       await 
1628+      ///   --> $DIR/issue-64130-non-send-future-diags.rs:15:5 
1629+      ///    | 
1630+      /// LL |     let g = x.lock().unwrap(); 
1631+      ///    |         - has type `std::sync::MutexGuard<'_, u32>` 
1632+      /// LL |     baz().await; 
1633+      ///    |     ^^^^^^^^^^^ await occurs here, with `g` maybe used later 
1634+      /// LL | } 
1635+      ///    | - `g` is later dropped here 
1636+      /// ``` 
1637+      /// 
1638+      /// Returns `true` if an async-await specific note was added to the diagnostic. 
1639+      fn  note_obligation_cause_for_async_await ( 
1640+         & self , 
1641+         err :  & mut  DiagnosticBuilder < ' _ > , 
1642+         obligation :  & PredicateObligation < ' tcx > , 
1643+     )  -> bool  { 
1644+         debug ! ( "note_obligation_cause_for_async_await: obligation.predicate={:?} \  
1645+                  obligation.cause.span={:?}",  obligation. predicate,  obligation. cause. span) ; 
1646+         let  source_map = self . tcx . sess . source_map ( ) ; 
1647+ 
1648+         // Look into the obligation predicate to determine the type in the generator which meant 
1649+         // that the predicate was not satisifed. 
1650+         let  ( trait_ref,  target_ty)  = match  obligation. predicate  { 
1651+             ty:: Predicate :: Trait ( trait_predicate)  =>
1652+                 ( trait_predicate. skip_binder ( ) . trait_ref ,  trait_predicate. skip_binder ( ) . self_ty ( ) ) , 
1653+             _ => return  false , 
1654+         } ; 
1655+         debug ! ( "note_obligation_cause_for_async_await: target_ty={:?}" ,  target_ty) ; 
1656+ 
1657+         // Attempt to detect an async-await error by looking at the obligation causes, looking 
1658+         // for only generators, generator witnesses, opaque types or `std::future::GenFuture` to 
1659+         // be present. 
1660+         // 
1661+         // When a future does not implement a trait because of a captured type in one of the 
1662+         // generators somewhere in the call stack, then the result is a chain of obligations. 
1663+         // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that 
1664+         // future is passed as an argument to a function C which requires a `Send` type, then the 
1665+         // chain looks something like this: 
1666+         // 
1667+         // - `BuiltinDerivedObligation` with a generator witness (B) 
1668+         // - `BuiltinDerivedObligation` with a generator (B) 
1669+         // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B) 
1670+         // - `BuiltinDerivedObligation` with `impl std::future::Future` (B) 
1671+         // - `BuiltinDerivedObligation` with `impl std::future::Future` (B) 
1672+         // - `BuiltinDerivedObligation` with a generator witness (A) 
1673+         // - `BuiltinDerivedObligation` with a generator (A) 
1674+         // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A) 
1675+         // - `BuiltinDerivedObligation` with `impl std::future::Future` (A) 
1676+         // - `BuiltinDerivedObligation` with `impl std::future::Future` (A) 
1677+         // - `BindingObligation` with `impl_send (Send requirement) 
1678+         // 
1679+         // The first obligations in the chain can be used to get the details of the type that is 
1680+         // captured but the entire chain must be inspected to detect this case. 
1681+         let  mut  generator = None ; 
1682+         let  mut  next_code = Some ( & obligation. cause . code ) ; 
1683+         while  let  Some ( code)  = next_code { 
1684+             debug ! ( "note_obligation_cause_for_async_await: code={:?}" ,  code) ; 
1685+             match  code { 
1686+                 ObligationCauseCode :: BuiltinDerivedObligation ( derived_obligation)  |
1687+                 ObligationCauseCode :: ImplDerivedObligation ( derived_obligation)  => { 
1688+                     debug ! ( "note_obligation_cause_for_async_await: self_ty.kind={:?}" , 
1689+                            derived_obligation. parent_trait_ref. self_ty( ) . kind) ; 
1690+                     match  derived_obligation. parent_trait_ref . self_ty ( ) . kind  { 
1691+                         ty:: Adt ( ty:: AdtDef  {  did,  .. } ,  ..)  if 
1692+                             self . tcx . is_diagnostic_item ( sym:: gen_future,  * did)  => { } , 
1693+                         ty:: Generator ( did,  ..)  => generator = generator. or ( Some ( did) ) , 
1694+                         ty:: GeneratorWitness ( _)  | ty:: Opaque ( ..)  => { } , 
1695+                         _ => return  false , 
1696+                     } 
1697+ 
1698+                     next_code = Some ( derived_obligation. parent_code . as_ref ( ) ) ; 
1699+                 } , 
1700+                 ObligationCauseCode :: ItemObligation ( _)  | ObligationCauseCode :: BindingObligation ( ..) 
1701+                     if  generator. is_some ( )  => break , 
1702+                 _ => return  false , 
1703+             } 
1704+         } 
1705+ 
1706+         let  generator_did = generator. expect ( "can only reach this if there was a generator" ) ; 
1707+ 
1708+         // Only continue to add a note if the generator is from an `async` function. 
1709+         let  parent_node = self . tcx . parent ( generator_did) 
1710+             . and_then ( |parent_did| self . tcx . hir ( ) . get_if_local ( parent_did) ) ; 
1711+         debug ! ( "note_obligation_cause_for_async_await: parent_node={:?}" ,  parent_node) ; 
1712+         if  let  Some ( hir:: Node :: Item ( hir:: Item  { 
1713+             kind :  hir:: ItemKind :: Fn ( _,  header,  _,  _) , 
1714+             ..
1715+         } ) )  = parent_node { 
1716+             debug ! ( "note_obligation_cause_for_async_await: header={:?}" ,  header) ; 
1717+             if  header. asyncness  != hir:: IsAsync :: Async  { 
1718+                 return  false ; 
1719+             } 
1720+         } 
1721+ 
1722+         let  span = self . tcx . def_span ( generator_did) ; 
1723+         let  tables = self . tcx . typeck_tables_of ( generator_did) ; 
1724+         debug ! ( "note_obligation_cause_for_async_await: generator_did={:?} span={:?} " , 
1725+                generator_did,  span) ; 
1726+ 
1727+         // Look for a type inside the generator interior that matches the target type to get 
1728+         // a span. 
1729+         let  target_span = tables. generator_interior_types . iter ( ) 
1730+             . find ( |ty:: GeneratorInteriorTypeCause  {  ty,  .. } | ty:: TyS :: same_type ( * ty,  target_ty) ) 
1731+             . map ( |ty:: GeneratorInteriorTypeCause  {  span,  scope_span,  .. } |
1732+                  ( span,  source_map. span_to_snippet ( * span) ,  scope_span) ) ; 
1733+         if  let  Some ( ( target_span,  Ok ( snippet) ,  scope_span) )  = target_span { 
1734+             // Look at the last interior type to get a span for the `.await`. 
1735+             let  await_span = tables. generator_interior_types . iter ( ) . map ( |i| i. span ) . last ( ) . unwrap ( ) ; 
1736+             let  mut  span = MultiSpan :: from_span ( await_span) ; 
1737+             span. push_span_label ( 
1738+                 await_span,  format ! ( "await occurs here, with `{}` maybe used later" ,  snippet) ) ; 
1739+ 
1740+             span. push_span_label ( * target_span,  format ! ( "has type `{}`" ,  target_ty) ) ; 
1741+ 
1742+             // If available, use the scope span to annotate the drop location. 
1743+             if  let  Some ( scope_span)  = scope_span { 
1744+                 span. push_span_label ( 
1745+                     source_map. end_point ( * scope_span) , 
1746+                     format ! ( "`{}` is later dropped here" ,  snippet) , 
1747+                 ) ; 
1748+             } 
1749+ 
1750+             err. span_note ( span,  & format ! ( 
1751+                 "future does not implement `{}` as this value is used across an await" , 
1752+                 trait_ref, 
1753+             ) ) ; 
1754+ 
1755+             // Add a note for the item obligation that remains - normally a note pointing to the 
1756+             // bound that introduced the obligation (e.g. `T: Send`). 
1757+             debug ! ( "note_obligation_cause_for_async_await: next_code={:?}" ,  next_code) ; 
1758+             self . note_obligation_cause_code ( 
1759+                 err, 
1760+                 & obligation. predicate , 
1761+                 next_code. unwrap ( ) , 
1762+                 & mut  Vec :: new ( ) , 
1763+             ) ; 
1764+ 
1765+             true 
1766+         }  else  { 
1767+             false 
1768+         } 
16161769    } 
16171770
16181771    fn  note_obligation_cause_code < T > ( & self , 
0 commit comments