@@ -42,7 +42,7 @@ use rustc_middle::ty::{AdtKind, Visibility};
42
42
use rustc_span:: hygiene:: DesugaringKind ;
43
43
use rustc_span:: source_map:: Span ;
44
44
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
45
- use rustc_trait_selection:: traits:: { self , ObligationCauseCode , SelectionContext } ;
45
+ use rustc_trait_selection:: traits:: { self , ObligationCauseCode } ;
46
46
47
47
use std:: fmt:: Display ;
48
48
@@ -1574,51 +1574,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1574
1574
err : & mut DiagnosticBuilder < ' _ > ,
1575
1575
field_ident : Ident ,
1576
1576
base : & ' tcx hir:: Expr < ' tcx > ,
1577
- expr : & ' tcx hir:: Expr < ' tcx > ,
1578
- def_id : DefId ,
1577
+ ty : Ty < ' tcx > ,
1579
1578
) {
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
+ ) ;
1619
1599
}
1620
1600
}
1621
1601
}
1602
+ if add_label {
1603
+ err. span_label ( field_ident. span , & format ! ( "field not found in `{}`" , ty) ) ;
1604
+ }
1622
1605
}
1623
1606
1624
1607
fn ban_nonexisting_field (
@@ -1647,8 +1630,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1647
1630
ty:: Param ( param_ty) => {
1648
1631
self . point_at_param_definition ( & mut err, param_ty) ;
1649
1632
}
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 ( ) ) ;
1652
1635
}
1653
1636
_ => { }
1654
1637
}
0 commit comments