@@ -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
@@ -1583,51 +1583,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1583
1583
err : & mut DiagnosticBuilder < ' _ > ,
1584
1584
field_ident : Ident ,
1585
1585
base : & ' tcx hir:: Expr < ' tcx > ,
1586
- expr : & ' tcx hir:: Expr < ' tcx > ,
1587
- def_id : DefId ,
1586
+ ty : Ty < ' tcx > ,
1588
1587
) {
1589
- let param_env = self . tcx ( ) . param_env ( def_id) ;
1590
- let future_trait = self . tcx . require_lang_item ( LangItem :: Future , None ) ;
1591
- // Future::Output
1592
- let item_def_id =
1593
- self . tcx . associated_items ( future_trait) . in_definition_order ( ) . next ( ) . unwrap ( ) . def_id ;
1594
-
1595
- let projection_ty = self . tcx . projection_ty_from_predicates ( ( def_id, item_def_id) ) ;
1596
- debug ! ( "suggest_await_on_field_access: projection_ty={:?}" , projection_ty) ;
1597
-
1598
- let cause = self . misc ( expr. span ) ;
1599
- let mut selcx = SelectionContext :: new ( & self . infcx ) ;
1600
-
1601
- let mut obligations = vec ! [ ] ;
1602
- if let Some ( projection_ty) = projection_ty {
1603
- let normalized_ty = rustc_trait_selection:: traits:: normalize_projection_type (
1604
- & mut selcx,
1605
- param_env,
1606
- projection_ty,
1607
- cause,
1608
- 0 ,
1609
- & mut obligations,
1610
- ) ;
1611
- debug ! (
1612
- "suggest_await_on_field_access: normalized_ty={:?}, ty_kind={:?}" ,
1613
- self . resolve_vars_if_possible( & normalized_ty) ,
1614
- normalized_ty. kind( ) ,
1615
- ) ;
1616
- if let ty:: Adt ( def, _) = normalized_ty. kind ( ) {
1617
- // no field access on enum type
1618
- if !def. is_enum ( ) {
1619
- if def. non_enum_variant ( ) . fields . iter ( ) . any ( |field| field. ident == field_ident)
1620
- {
1621
- err. span_suggestion_verbose (
1622
- base. span . shrink_to_hi ( ) ,
1623
- "consider awaiting before field access" ,
1624
- ".await" . to_string ( ) ,
1625
- Applicability :: MaybeIncorrect ,
1626
- ) ;
1627
- }
1588
+ let output_ty = match self . infcx . get_impl_future_output_ty ( ty) {
1589
+ Some ( output_ty) => self . resolve_vars_if_possible ( & output_ty) ,
1590
+ _ => return ,
1591
+ } ;
1592
+ let mut add_label = true ;
1593
+ if let ty:: Adt ( def, _) = output_ty. kind ( ) {
1594
+ // no field access on enum type
1595
+ if !def. is_enum ( ) {
1596
+ if def. non_enum_variant ( ) . fields . iter ( ) . any ( |field| field. ident == field_ident) {
1597
+ add_label = false ;
1598
+ err. span_label (
1599
+ field_ident. span ,
1600
+ "field not available in `impl Future`, but it is available in its `Output`" ,
1601
+ ) ;
1602
+ err. span_suggestion_verbose (
1603
+ base. span . shrink_to_hi ( ) ,
1604
+ "consider `await`ing on the `Future` and access the field of its `Output`" ,
1605
+ ".await" . to_string ( ) ,
1606
+ Applicability :: MaybeIncorrect ,
1607
+ ) ;
1628
1608
}
1629
1609
}
1630
1610
}
1611
+ if add_label {
1612
+ err. span_label ( field_ident. span , & format ! ( "field not found in `{}`" , ty) ) ;
1613
+ }
1631
1614
}
1632
1615
1633
1616
fn ban_nonexisting_field (
@@ -1656,8 +1639,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1656
1639
ty:: Param ( param_ty) => {
1657
1640
self . point_at_param_definition ( & mut err, param_ty) ;
1658
1641
}
1659
- ty:: Opaque ( def_id , _) => {
1660
- self . suggest_await_on_field_access ( & mut err, field, base, expr , def_id ) ;
1642
+ ty:: Opaque ( _ , _) => {
1643
+ self . suggest_await_on_field_access ( & mut err, field, base, expr_t . peel_refs ( ) ) ;
1661
1644
}
1662
1645
_ => { }
1663
1646
}
0 commit comments