@@ -42,7 +42,7 @@ use rustc_middle::ty::{AdtKind, Visibility};
4242use rustc_span:: hygiene:: DesugaringKind ;
4343use rustc_span:: source_map:: Span ;
4444use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
45- use rustc_trait_selection:: traits:: { self , ObligationCauseCode , SelectionContext } ;
45+ use rustc_trait_selection:: traits:: { self , ObligationCauseCode } ;
4646
4747use std:: fmt:: Display ;
4848
@@ -1574,51 +1574,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15741574 err : & mut DiagnosticBuilder < ' _ > ,
15751575 field_ident : Ident ,
15761576 base : & ' tcx hir:: Expr < ' tcx > ,
1577- expr : & ' tcx hir:: Expr < ' tcx > ,
1578- def_id : DefId ,
1577+ ty : Ty < ' tcx > ,
15791578 ) {
1580- let param_env = self . tcx ( ) . param_env ( def_id) ;
1581- let future_trait = self . tcx . require_lang_item ( LangItem :: Future , None ) ;
1582- // Future::Output
1583- let item_def_id =
1584- self . tcx . associated_items ( future_trait) . in_definition_order ( ) . next ( ) . unwrap ( ) . def_id ;
1585-
1586- let projection_ty = self . tcx . projection_ty_from_predicates ( ( def_id, item_def_id) ) ;
1587- debug ! ( "suggest_await_on_field_access: projection_ty={:?}" , projection_ty) ;
1588-
1589- let cause = self . misc ( expr. span ) ;
1590- let mut selcx = SelectionContext :: new ( & self . infcx ) ;
1591-
1592- let mut obligations = vec ! [ ] ;
1593- if let Some ( projection_ty) = projection_ty {
1594- let normalized_ty = rustc_trait_selection:: traits:: normalize_projection_type (
1595- & mut selcx,
1596- param_env,
1597- projection_ty,
1598- cause,
1599- 0 ,
1600- & mut obligations,
1601- ) ;
1602- debug ! (
1603- "suggest_await_on_field_access: normalized_ty={:?}, ty_kind={:?}" ,
1604- self . resolve_vars_if_possible( & normalized_ty) ,
1605- normalized_ty. kind( ) ,
1606- ) ;
1607- if let ty:: Adt ( def, _) = normalized_ty. kind ( ) {
1608- // no field access on enum type
1609- if !def. is_enum ( ) {
1610- if def. non_enum_variant ( ) . fields . iter ( ) . any ( |field| field. ident == field_ident)
1611- {
1612- err. span_suggestion_verbose (
1613- base. span . shrink_to_hi ( ) ,
1614- "consider awaiting before field access" ,
1615- ".await" . to_string ( ) ,
1616- Applicability :: MaybeIncorrect ,
1617- ) ;
1618- }
1579+ let output_ty = match self . infcx . get_impl_future_output_ty ( ty) {
1580+ Some ( output_ty) => self . resolve_vars_if_possible ( & output_ty) ,
1581+ _ => return ,
1582+ } ;
1583+ let mut add_label = true ;
1584+ if let ty:: Adt ( def, _) = output_ty. kind ( ) {
1585+ // no field access on enum type
1586+ if !def. is_enum ( ) {
1587+ if def. non_enum_variant ( ) . fields . iter ( ) . any ( |field| field. ident == field_ident) {
1588+ add_label = false ;
1589+ err. span_label (
1590+ field_ident. span ,
1591+ "field not available in `impl Future`, but it is available in its `Output`" ,
1592+ ) ;
1593+ err. span_suggestion_verbose (
1594+ base. span . shrink_to_hi ( ) ,
1595+ "consider `await`ing on the `Future` and access the field of its `Output`" ,
1596+ ".await" . to_string ( ) ,
1597+ Applicability :: MaybeIncorrect ,
1598+ ) ;
16191599 }
16201600 }
16211601 }
1602+ if add_label {
1603+ err. span_label ( field_ident. span , & format ! ( "field not found in `{}`" , ty) ) ;
1604+ }
16221605 }
16231606
16241607 fn ban_nonexisting_field (
@@ -1647,8 +1630,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16471630 ty:: Param ( param_ty) => {
16481631 self . point_at_param_definition ( & mut err, param_ty) ;
16491632 }
1650- ty:: Opaque ( def_id , _) => {
1651- self . suggest_await_on_field_access ( & mut err, field, base, expr , def_id ) ;
1633+ ty:: Opaque ( _ , _) => {
1634+ self . suggest_await_on_field_access ( & mut err, field, base, expr_t . peel_refs ( ) ) ;
16521635 }
16531636 _ => { }
16541637 }
0 commit comments