@@ -31,13 +31,14 @@ use rustc_infer::infer;
3131use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
3232use rustc_middle:: ty;
3333use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AllowTwoPhase } ;
34+ use rustc_middle:: ty:: subst:: SubstsRef ;
3435use rustc_middle:: ty:: Ty ;
3536use rustc_middle:: ty:: TypeFoldable ;
3637use rustc_middle:: ty:: { AdtKind , Visibility } ;
3738use rustc_span:: hygiene:: DesugaringKind ;
3839use rustc_span:: source_map:: Span ;
3940use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
40- use rustc_trait_selection:: traits:: { self , ObligationCauseCode } ;
41+ use rustc_trait_selection:: traits:: { self , ObligationCauseCode , SelectionContext } ;
4142
4243use std:: fmt:: Display ;
4344
@@ -1509,13 +1510,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15091510 self . tcx ( ) . ty_error ( )
15101511 }
15111512
1513+ fn suggest_await_on_field_access (
1514+ & self ,
1515+ err : & mut DiagnosticBuilder < ' _ > ,
1516+ field_ident : Ident ,
1517+ base : & ' tcx hir:: Expr < ' tcx > ,
1518+ expr : & ' tcx hir:: Expr < ' tcx > ,
1519+ def_id : DefId ,
1520+ substs : SubstsRef < ' tcx > ,
1521+ ) {
1522+ let param_env = self . tcx ( ) . param_env ( def_id) ;
1523+ let future_trait = self . tcx . require_lang_item ( lang_items:: FutureTraitLangItem , None ) ;
1524+ let future_trait_ref = ty:: TraitRef { def_id : future_trait, substs } ;
1525+ // Future::Output
1526+ let future_projection = ty:: ProjectionTy :: from_ref_and_name (
1527+ self . tcx ,
1528+ future_trait_ref,
1529+ Ident :: with_dummy_span ( sym:: Output ) ,
1530+ ) ;
1531+
1532+ let mut projection_ty = None ;
1533+ for ( predicate, _) in self . tcx . predicates_of ( def_id) . predicates {
1534+ if let ty:: PredicateAtom :: Projection ( projection_predicate) = predicate. skip_binders ( ) {
1535+ if future_projection. item_def_id == projection_predicate. projection_ty . item_def_id {
1536+ projection_ty = Some ( projection_predicate. projection_ty ) ;
1537+ break ;
1538+ }
1539+ }
1540+ }
1541+ debug ! ( "suggest_await_on_field_access: projection_ty={:?}" , projection_ty) ;
1542+
1543+ let cause = self . misc ( expr. span ) ;
1544+ let mut selcx = SelectionContext :: new ( & self . infcx ) ;
1545+
1546+ let mut obligations = vec ! [ ] ;
1547+ if let Some ( projection_ty) = projection_ty {
1548+ let normalized_ty = rustc_trait_selection:: traits:: normalize_projection_type (
1549+ & mut selcx,
1550+ param_env,
1551+ projection_ty,
1552+ cause,
1553+ 0 ,
1554+ & mut obligations,
1555+ ) ;
1556+ debug ! (
1557+ "suggest_await_on_field_access: normalized_ty={:?}, ty_kind={:?}" ,
1558+ self . resolve_vars_if_possible( & normalized_ty) ,
1559+ normalized_ty. kind,
1560+ ) ;
1561+ if let ty:: Adt ( def, _) = normalized_ty. kind {
1562+ if def. non_enum_variant ( ) . fields . iter ( ) . any ( |field| field. ident == field_ident) {
1563+ if let Ok ( base) = self . tcx . sess . source_map ( ) . span_to_snippet ( base. span ) {
1564+ let suggestion = format ! ( "{}.await.{}" , base, field_ident) ;
1565+ err. span_suggestion (
1566+ expr. span ,
1567+ "consider await before field access" ,
1568+ suggestion,
1569+ Applicability :: MaybeIncorrect ,
1570+ ) ;
1571+ }
1572+ }
1573+ }
1574+ }
1575+ }
1576+
15121577 fn ban_nonexisting_field (
15131578 & self ,
15141579 field : Ident ,
15151580 base : & ' tcx hir:: Expr < ' tcx > ,
15161581 expr : & ' tcx hir:: Expr < ' tcx > ,
15171582 expr_t : Ty < ' tcx > ,
15181583 ) {
1584+ debug ! (
1585+ "ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, expr_ty={:?}" ,
1586+ field, base, expr, expr_t
1587+ ) ;
15191588 let mut err = self . no_such_field_err ( field. span , field, expr_t) ;
15201589
15211590 match expr_t. peel_refs ( ) . kind {
@@ -1531,6 +1600,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15311600 ty:: Param ( param_ty) => {
15321601 self . point_at_param_definition ( & mut err, param_ty) ;
15331602 }
1603+ ty:: Opaque ( def_id, subts) => {
1604+ self . suggest_await_on_field_access ( & mut err, field, base, expr, def_id, subts) ;
1605+ }
15341606 _ => { }
15351607 }
15361608
0 commit comments