@@ -35,6 +35,7 @@ use rustc_hir::{ExprKind, QPath};
3535use rustc_infer:: infer;
3636use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
3737use rustc_infer:: infer:: InferOk ;
38+ use rustc_middle:: middle:: stability;
3839use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AllowTwoPhase } ;
3940use rustc_middle:: ty:: error:: ExpectedFound ;
4041use rustc_middle:: ty:: error:: TypeError :: { FieldMisMatch , Sorts } ;
@@ -1720,9 +1721,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17201721 _ => {
17211722 // prevent all specified fields from being suggested
17221723 let skip_fields = skip_fields. iter ( ) . map ( |x| x. ident . name ) ;
1723- if let Some ( field_name) =
1724- Self :: suggest_field_name ( variant, field. ident . name , skip_fields. collect ( ) )
1725- {
1724+ if let Some ( field_name) = self . suggest_field_name (
1725+ variant,
1726+ field. ident . name ,
1727+ skip_fields. collect ( ) ,
1728+ expr_span,
1729+ ) {
17261730 err. span_suggestion (
17271731 field. ident . span ,
17281732 "a field with a similar name exists" ,
@@ -1743,7 +1747,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17431747 format ! ( "`{}` does not have this field" , ty) ,
17441748 ) ;
17451749 }
1746- let available_field_names = self . available_field_names ( variant) ;
1750+ let available_field_names =
1751+ self . available_field_names ( variant, expr_span) ;
17471752 if !available_field_names. is_empty ( ) {
17481753 err. note ( & format ! (
17491754 "available fields are: {}" ,
@@ -1759,19 +1764,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17591764 err. emit ( ) ;
17601765 }
17611766
1762- // Return an hint about the closest match in field names
1767+ // Return a hint about the closest match in field names
17631768 fn suggest_field_name (
1769+ & self ,
17641770 variant : & ' tcx ty:: VariantDef ,
17651771 field : Symbol ,
17661772 skip : Vec < Symbol > ,
1773+ // The span where stability will be checked
1774+ span : Span ,
17671775 ) -> Option < Symbol > {
17681776 let names = variant
17691777 . fields
17701778 . iter ( )
17711779 . filter_map ( |field| {
17721780 // ignore already set fields and private fields from non-local crates
1781+ // and unstable fields.
17731782 if skip. iter ( ) . any ( |& x| x == field. name )
17741783 || ( !variant. def_id . is_local ( ) && !field. vis . is_public ( ) )
1784+ || matches ! (
1785+ self . tcx. eval_stability( field. did, None , span, None ) ,
1786+ stability:: EvalResult :: Deny { .. }
1787+ )
17751788 {
17761789 None
17771790 } else {
@@ -1783,7 +1796,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17831796 find_best_match_for_name ( & names, field, None )
17841797 }
17851798
1786- fn available_field_names ( & self , variant : & ' tcx ty:: VariantDef ) -> Vec < Symbol > {
1799+ fn available_field_names (
1800+ & self ,
1801+ variant : & ' tcx ty:: VariantDef ,
1802+ access_span : Span ,
1803+ ) -> Vec < Symbol > {
17871804 variant
17881805 . fields
17891806 . iter ( )
@@ -1793,6 +1810,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17931810 . adjust_ident_and_get_scope ( field. ident ( self . tcx ) , variant. def_id , self . body_id )
17941811 . 1 ;
17951812 field. vis . is_accessible_from ( def_scope, self . tcx )
1813+ && !matches ! (
1814+ self . tcx. eval_stability( field. did, None , access_span, None ) ,
1815+ stability:: EvalResult :: Deny { .. }
1816+ )
17961817 } )
17971818 . filter ( |field| !self . tcx . is_doc_hidden ( field. did ) )
17981819 . map ( |field| field. name )
@@ -1959,7 +1980,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19591980 self . suggest_first_deref_field ( & mut err, expr, base, field) ;
19601981 }
19611982 ty:: Adt ( def, _) if !def. is_enum ( ) => {
1962- self . suggest_fields_on_recordish ( & mut err, def, field) ;
1983+ self . suggest_fields_on_recordish ( & mut err, def, field, expr . span ) ;
19631984 }
19641985 ty:: Param ( param_ty) => {
19651986 self . point_at_param_definition ( & mut err, param_ty) ;
@@ -2122,9 +2143,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21222143 err : & mut DiagnosticBuilder < ' _ > ,
21232144 def : & ' tcx ty:: AdtDef ,
21242145 field : Ident ,
2146+ access_span : Span ,
21252147 ) {
21262148 if let Some ( suggested_field_name) =
2127- Self :: suggest_field_name ( def. non_enum_variant ( ) , field. name , vec ! [ ] )
2149+ self . suggest_field_name ( def. non_enum_variant ( ) , field. name , vec ! [ ] , access_span )
21282150 {
21292151 err. span_suggestion (
21302152 field. span ,
@@ -2135,7 +2157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21352157 } else {
21362158 err. span_label ( field. span , "unknown field" ) ;
21372159 let struct_variant_def = def. non_enum_variant ( ) ;
2138- let field_names = self . available_field_names ( struct_variant_def) ;
2160+ let field_names = self . available_field_names ( struct_variant_def, access_span ) ;
21392161 if !field_names. is_empty ( ) {
21402162 err. note ( & format ! (
21412163 "available fields are: {}" ,
0 commit comments