@@ -35,6 +35,7 @@ use rustc_hir::{ExprKind, QPath};
35
35
use rustc_infer:: infer;
36
36
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
37
37
use rustc_infer:: infer:: InferOk ;
38
+ use rustc_middle:: middle:: stability;
38
39
use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AllowTwoPhase } ;
39
40
use rustc_middle:: ty:: error:: ExpectedFound ;
40
41
use rustc_middle:: ty:: error:: TypeError :: { FieldMisMatch , Sorts } ;
@@ -1720,9 +1721,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1720
1721
_ => {
1721
1722
// prevent all specified fields from being suggested
1722
1723
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
+ ) {
1726
1730
err. span_suggestion (
1727
1731
field. ident . span ,
1728
1732
"a field with a similar name exists" ,
@@ -1743,7 +1747,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1743
1747
format ! ( "`{}` does not have this field" , ty) ,
1744
1748
) ;
1745
1749
}
1746
- let available_field_names = self . available_field_names ( variant) ;
1750
+ let available_field_names =
1751
+ self . available_field_names ( variant, expr_span) ;
1747
1752
if !available_field_names. is_empty ( ) {
1748
1753
err. note ( & format ! (
1749
1754
"available fields are: {}" ,
@@ -1759,19 +1764,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1759
1764
err. emit ( ) ;
1760
1765
}
1761
1766
1762
- // Return an hint about the closest match in field names
1767
+ // Return a hint about the closest match in field names
1763
1768
fn suggest_field_name (
1769
+ & self ,
1764
1770
variant : & ' tcx ty:: VariantDef ,
1765
1771
field : Symbol ,
1766
1772
skip : Vec < Symbol > ,
1773
+ // The span where stability will be checked
1774
+ span : Span ,
1767
1775
) -> Option < Symbol > {
1768
1776
let names = variant
1769
1777
. fields
1770
1778
. iter ( )
1771
1779
. filter_map ( |field| {
1772
1780
// ignore already set fields and private fields from non-local crates
1781
+ // and unstable fields.
1773
1782
if skip. iter ( ) . any ( |& x| x == field. name )
1774
1783
|| ( !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
+ )
1775
1788
{
1776
1789
None
1777
1790
} else {
@@ -1783,7 +1796,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1783
1796
find_best_match_for_name ( & names, field, None )
1784
1797
}
1785
1798
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 > {
1787
1804
variant
1788
1805
. fields
1789
1806
. iter ( )
@@ -1793,6 +1810,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1793
1810
. adjust_ident_and_get_scope ( field. ident ( self . tcx ) , variant. def_id , self . body_id )
1794
1811
. 1 ;
1795
1812
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
+ )
1796
1817
} )
1797
1818
. filter ( |field| !self . tcx . is_doc_hidden ( field. did ) )
1798
1819
. map ( |field| field. name )
@@ -1959,7 +1980,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1959
1980
self . suggest_first_deref_field ( & mut err, expr, base, field) ;
1960
1981
}
1961
1982
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 ) ;
1963
1984
}
1964
1985
ty:: Param ( param_ty) => {
1965
1986
self . point_at_param_definition ( & mut err, param_ty) ;
@@ -2122,9 +2143,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2122
2143
err : & mut DiagnosticBuilder < ' _ > ,
2123
2144
def : & ' tcx ty:: AdtDef ,
2124
2145
field : Ident ,
2146
+ access_span : Span ,
2125
2147
) {
2126
2148
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 )
2128
2150
{
2129
2151
err. span_suggestion (
2130
2152
field. span ,
@@ -2135,7 +2157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2135
2157
} else {
2136
2158
err. span_label ( field. span , "unknown field" ) ;
2137
2159
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 ) ;
2139
2161
if !field_names. is_empty ( ) {
2140
2162
err. note ( & format ! (
2141
2163
"available fields are: {}" ,
0 commit comments