@@ -50,6 +50,7 @@ use super::region_constraints::GenericKind;
50
50
use super :: { InferCtxt , RegionVariableOrigin , SubregionOrigin , TypeTrace , ValuePairs } ;
51
51
52
52
use crate :: infer;
53
+ use crate :: infer:: OriginalQueryValues ;
53
54
use crate :: traits:: error_reporting:: report_object_safety_error;
54
55
use crate :: traits:: {
55
56
IfExpressionCause , MatchExpressionArmCause , ObligationCause , ObligationCauseCode ,
@@ -60,8 +61,10 @@ use rustc_errors::{pluralize, struct_span_err};
60
61
use rustc_errors:: { Applicability , DiagnosticBuilder , DiagnosticStyledString } ;
61
62
use rustc_hir as hir;
62
63
use rustc_hir:: def_id:: DefId ;
64
+ use rustc_hir:: lang_items:: LangItem ;
63
65
use rustc_hir:: { Item , ItemKind , Node } ;
64
66
use rustc_middle:: ty:: error:: TypeError ;
67
+ use rustc_middle:: ty:: ParamEnvAnd ;
65
68
use rustc_middle:: ty:: {
66
69
self ,
67
70
subst:: { Subst , SubstsRef } ,
@@ -1529,6 +1532,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1529
1532
} ;
1530
1533
if let Some ( exp_found) = exp_found {
1531
1534
self . suggest_as_ref_where_appropriate ( span, & exp_found, diag) ;
1535
+ self . suggest_await_on_expect_found ( cause, span, & exp_found, diag) ;
1532
1536
}
1533
1537
1534
1538
// 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> {
1547
1551
self . note_error_origin ( diag, cause, exp_found) ;
1548
1552
}
1549
1553
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
+
1550
1610
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
1551
1611
/// suggests it.
1552
1612
fn suggest_as_ref_where_appropriate (
0 commit comments