@@ -41,7 +41,6 @@ use rustc_infer::infer::DefineOpaqueTypes;
41
41
use rustc_infer:: infer:: InferOk ;
42
42
use rustc_infer:: traits:: query:: NoSolution ;
43
43
use rustc_infer:: traits:: ObligationCause ;
44
- use rustc_middle:: middle:: stability;
45
44
use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AllowTwoPhase } ;
46
45
use rustc_middle:: ty:: error:: {
47
46
ExpectedFound ,
@@ -1662,6 +1661,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1662
1661
self . report_unknown_field (
1663
1662
adt_ty,
1664
1663
variant,
1664
+ expr_id,
1665
1665
field,
1666
1666
ast_fields,
1667
1667
adt. variant_descr ( ) ,
@@ -2049,6 +2049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2049
2049
& self ,
2050
2050
ty : Ty < ' tcx > ,
2051
2051
variant : & ' tcx ty:: VariantDef ,
2052
+ expr_id : HirId ,
2052
2053
field : & hir:: ExprField < ' _ > ,
2053
2054
skip_fields : & [ hir:: ExprField < ' _ > ] ,
2054
2055
kind_name : & str ,
@@ -2129,9 +2130,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2129
2130
} ,
2130
2131
_ => {
2131
2132
// prevent all specified fields from being suggested
2132
- let skip_fields: Vec < _ > = skip_fields. iter ( ) . map ( |x| x. ident . name ) . collect ( ) ;
2133
+ let available_field_names =
2134
+ self . available_field_names ( variant, expr_id, skip_fields) ;
2133
2135
if let Some ( field_name) =
2134
- self . suggest_field_name ( variant , field. ident . name , & skip_fields , expr_span )
2136
+ find_best_match_for_name ( & available_field_names , field. ident . name , None )
2135
2137
{
2136
2138
err. span_suggestion (
2137
2139
field. ident . span ,
@@ -2153,10 +2155,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2153
2155
format ! ( "`{ty}` does not have this field" ) ,
2154
2156
) ;
2155
2157
}
2156
- let mut available_field_names =
2157
- self . available_field_names ( variant, expr_span) ;
2158
- available_field_names
2159
- . retain ( |name| skip_fields. iter ( ) . all ( |skip| name != skip) ) ;
2160
2158
if available_field_names. is_empty ( ) {
2161
2159
err. note ( "all struct fields are already assigned" ) ;
2162
2160
} else {
@@ -2174,63 +2172,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2174
2172
err. emit ( )
2175
2173
}
2176
2174
2177
- // Return a hint about the closest match in field names
2178
- fn suggest_field_name (
2179
- & self ,
2180
- variant : & ' tcx ty:: VariantDef ,
2181
- field : Symbol ,
2182
- skip : & [ Symbol ] ,
2183
- // The span where stability will be checked
2184
- span : Span ,
2185
- ) -> Option < Symbol > {
2186
- let names = variant
2187
- . fields
2188
- . iter ( )
2189
- . filter_map ( |field| {
2190
- // ignore already set fields and private fields from non-local crates
2191
- // and unstable fields.
2192
- if skip. iter ( ) . any ( |& x| x == field. name )
2193
- || ( !variant. def_id . is_local ( ) && !field. vis . is_public ( ) )
2194
- || matches ! (
2195
- self . tcx. eval_stability( field. did, None , span, None ) ,
2196
- stability:: EvalResult :: Deny { .. }
2197
- )
2198
- {
2199
- None
2200
- } else {
2201
- Some ( field. name )
2202
- }
2203
- } )
2204
- . collect :: < Vec < Symbol > > ( ) ;
2205
-
2206
- find_best_match_for_name ( & names, field, None )
2207
- }
2208
-
2209
2175
fn available_field_names (
2210
2176
& self ,
2211
2177
variant : & ' tcx ty:: VariantDef ,
2212
- access_span : Span ,
2178
+ expr_id : HirId ,
2179
+ skip_fields : & [ hir:: ExprField < ' _ > ] ,
2213
2180
) -> Vec < Symbol > {
2214
- let body_owner_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
2215
2181
variant
2216
2182
. fields
2217
2183
. iter ( )
2218
2184
. filter ( |field| {
2219
- let def_scope = self
2220
- . tcx
2221
- . adjust_ident_and_get_scope (
2222
- field. ident ( self . tcx ) ,
2223
- variant. def_id ,
2224
- body_owner_hir_id,
2225
- )
2226
- . 1 ;
2227
- field. vis . is_accessible_from ( def_scope, self . tcx )
2228
- && !matches ! (
2229
- self . tcx. eval_stability( field. did, None , access_span, None ) ,
2230
- stability:: EvalResult :: Deny { .. }
2231
- )
2185
+ skip_fields. iter ( ) . all ( |& skip| skip. ident . name != field. name )
2186
+ && self . is_field_suggestable ( field, expr_id)
2232
2187
} )
2233
- . filter ( |field| !self . tcx . is_doc_hidden ( field. did ) )
2234
2188
. map ( |field| field. name )
2235
2189
. collect ( )
2236
2190
}
@@ -2460,7 +2414,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2460
2414
self . suggest_first_deref_field ( & mut err, expr, base, ident) ;
2461
2415
}
2462
2416
ty:: Adt ( def, _) if !def. is_enum ( ) => {
2463
- self . suggest_fields_on_recordish ( & mut err, def , ident , expr . span ) ;
2417
+ self . suggest_fields_on_recordish ( & mut err, expr . hir_id , def , ident ) ;
2464
2418
}
2465
2419
ty:: Param ( param_ty) => {
2466
2420
self . point_at_param_definition ( & mut err, param_ty) ;
@@ -2622,12 +2576,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2622
2576
fn suggest_fields_on_recordish (
2623
2577
& self ,
2624
2578
err : & mut Diagnostic ,
2579
+ expr_id : HirId ,
2625
2580
def : ty:: AdtDef < ' tcx > ,
2626
2581
field : Ident ,
2627
- access_span : Span ,
2628
2582
) {
2583
+ let available_field_names =
2584
+ self . available_field_names ( def. non_enum_variant ( ) , expr_id, & [ ] ) ;
2629
2585
if let Some ( suggested_field_name) =
2630
- self . suggest_field_name ( def . non_enum_variant ( ) , field. name , & [ ] , access_span )
2586
+ find_best_match_for_name ( & available_field_names , field. name , None )
2631
2587
{
2632
2588
err. span_suggestion (
2633
2589
field. span ,
@@ -2637,12 +2593,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2637
2593
) ;
2638
2594
} else {
2639
2595
err. span_label ( field. span , "unknown field" ) ;
2640
- let struct_variant_def = def. non_enum_variant ( ) ;
2641
- let field_names = self . available_field_names ( struct_variant_def, access_span) ;
2642
- if !field_names. is_empty ( ) {
2596
+ if !available_field_names. is_empty ( ) {
2643
2597
err. note ( format ! (
2644
2598
"available fields are: {}" ,
2645
- self . name_series_display( field_names ) ,
2599
+ self . name_series_display( available_field_names ) ,
2646
2600
) ) ;
2647
2601
}
2648
2602
}
0 commit comments