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