@@ -50,6 +50,7 @@ use super::region_constraints::GenericKind;
5050use super :: { InferCtxt , RegionVariableOrigin , SubregionOrigin , TypeTrace , ValuePairs } ;
5151
5252use crate :: infer;
53+ use crate :: infer:: OriginalQueryValues ;
5354use crate :: traits:: error_reporting:: report_object_safety_error;
5455use crate :: traits:: {
5556 IfExpressionCause , MatchExpressionArmCause , ObligationCause , ObligationCauseCode ,
@@ -60,8 +61,10 @@ use rustc_errors::{pluralize, struct_span_err};
6061use rustc_errors:: { Applicability , DiagnosticBuilder , DiagnosticStyledString } ;
6162use rustc_hir as hir;
6263use rustc_hir:: def_id:: DefId ;
64+ use rustc_hir:: lang_items:: LangItem ;
6365use rustc_hir:: { Item , ItemKind , Node } ;
6466use rustc_middle:: ty:: error:: TypeError ;
67+ use rustc_middle:: ty:: ParamEnvAnd ;
6568use rustc_middle:: ty:: {
6669 self ,
6770 subst:: { Subst , SubstsRef } ,
@@ -1529,6 +1532,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15291532 } ;
15301533 if let Some ( exp_found) = exp_found {
15311534 self . suggest_as_ref_where_appropriate ( span, & exp_found, diag) ;
1535+ self . suggest_await_on_expect_found ( cause, span, & exp_found, diag) ;
15321536 }
15331537
15341538 // In some (most?) cases cause.body_id points to actual body, but in some cases
@@ -1547,6 +1551,62 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15471551 self . note_error_origin ( diag, cause, exp_found) ;
15481552 }
15491553
1554+ fn suggest_await_on_expect_found (
1555+ & self ,
1556+ cause : & ObligationCause < ' tcx > ,
1557+ exp_span : Span ,
1558+ exp_found : & ty:: error:: ExpectedFound < Ty < ' tcx > > ,
1559+ diag : & mut DiagnosticBuilder < ' tcx > ,
1560+ ) {
1561+ debug ! (
1562+ "suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}" ,
1563+ exp_span, exp_found. expected, exp_found. found
1564+ ) ;
1565+
1566+ if let ty:: Opaque ( def_id, _) = exp_found. expected . kind {
1567+ let future_trait = self . tcx . require_lang_item ( LangItem :: Future , None ) ;
1568+ // Future::Output
1569+ let item_def_id = self
1570+ . tcx
1571+ . associated_items ( future_trait)
1572+ . in_definition_order ( )
1573+ . next ( )
1574+ . unwrap ( )
1575+ . def_id ;
1576+
1577+ let projection_ty = self . tcx . projection_ty_from_predicates ( ( def_id, item_def_id) ) ;
1578+ if let Some ( projection_ty) = projection_ty {
1579+ let projection_query = self . canonicalize_query (
1580+ & ParamEnvAnd { param_env : self . tcx . param_env ( def_id) , value : projection_ty } ,
1581+ & mut OriginalQueryValues :: default ( ) ,
1582+ ) ;
1583+ if let Ok ( resp) = self . tcx . normalize_projection_ty ( projection_query) {
1584+ let normalized_ty = resp. value . value . normalized_ty ;
1585+ debug ! ( "suggest_await_on_expect_found: normalized={:?}" , normalized_ty) ;
1586+ if ty:: TyS :: same_type ( normalized_ty, exp_found. found ) {
1587+ let span = if let ObligationCauseCode :: Pattern {
1588+ span,
1589+ origin_expr : _,
1590+ root_ty : _,
1591+ } = cause. code
1592+ {
1593+ // scrutinee's span
1594+ span. unwrap_or ( exp_span)
1595+ } else {
1596+ exp_span
1597+ } ;
1598+ diag. span_suggestion_verbose (
1599+ span. shrink_to_hi ( ) ,
1600+ "consider awaiting on the future" ,
1601+ ".await" . to_string ( ) ,
1602+ Applicability :: MaybeIncorrect ,
1603+ ) ;
1604+ }
1605+ }
1606+ }
1607+ }
1608+ }
1609+
15501610 /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
15511611 /// suggests it.
15521612 fn suggest_as_ref_where_appropriate (
0 commit comments