@@ -41,7 +41,6 @@ use rustc_infer::infer::DefineOpaqueTypes;
4141use rustc_infer:: infer:: InferOk ;
4242use rustc_infer:: traits:: query:: NoSolution ;
4343use rustc_infer:: traits:: ObligationCause ;
44- use rustc_middle:: middle:: stability;
4544use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AllowTwoPhase } ;
4645use rustc_middle:: ty:: error:: {
4746 ExpectedFound ,
@@ -1662,6 +1661,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16621661 self . report_unknown_field (
16631662 adt_ty,
16641663 variant,
1664+ expr_id,
16651665 field,
16661666 ast_fields,
16671667 adt. variant_descr ( ) ,
@@ -2049,6 +2049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20492049 & self ,
20502050 ty : Ty < ' tcx > ,
20512051 variant : & ' tcx ty:: VariantDef ,
2052+ expr_id : HirId ,
20522053 field : & hir:: ExprField < ' _ > ,
20532054 skip_fields : & [ hir:: ExprField < ' _ > ] ,
20542055 kind_name : & str ,
@@ -2129,9 +2130,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21292130 } ,
21302131 _ => {
21312132 // 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) ;
21332135 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 )
21352137 {
21362138 err. span_suggestion (
21372139 field. ident . span ,
@@ -2153,10 +2155,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21532155 format ! ( "`{ty}` does not have this field" ) ,
21542156 ) ;
21552157 }
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) ) ;
21602158 if available_field_names. is_empty ( ) {
21612159 err. note ( "all struct fields are already assigned" ) ;
21622160 } else {
@@ -2174,63 +2172,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21742172 err. emit ( )
21752173 }
21762174
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-
22092175 fn available_field_names (
22102176 & self ,
22112177 variant : & ' tcx ty:: VariantDef ,
2212- access_span : Span ,
2178+ expr_id : HirId ,
2179+ skip_fields : & [ hir:: ExprField < ' _ > ] ,
22132180 ) -> Vec < Symbol > {
2214- let body_owner_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
22152181 variant
22162182 . fields
22172183 . iter ( )
22182184 . 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)
22322187 } )
2233- . filter ( |field| !self . tcx . is_doc_hidden ( field. did ) )
22342188 . map ( |field| field. name )
22352189 . collect ( )
22362190 }
@@ -2460,7 +2414,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24602414 self . suggest_first_deref_field ( & mut err, expr, base, ident) ;
24612415 }
24622416 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 ) ;
24642418 }
24652419 ty:: Param ( param_ty) => {
24662420 self . point_at_param_definition ( & mut err, param_ty) ;
@@ -2622,12 +2576,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26222576 fn suggest_fields_on_recordish (
26232577 & self ,
26242578 err : & mut Diagnostic ,
2579+ expr_id : HirId ,
26252580 def : ty:: AdtDef < ' tcx > ,
26262581 field : Ident ,
2627- access_span : Span ,
26282582 ) {
2583+ let available_field_names =
2584+ self . available_field_names ( def. non_enum_variant ( ) , expr_id, & [ ] ) ;
26292585 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 )
26312587 {
26322588 err. span_suggestion (
26332589 field. span ,
@@ -2637,12 +2593,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26372593 ) ;
26382594 } else {
26392595 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 ( ) {
26432597 err. note ( format ! (
26442598 "available fields are: {}" ,
2645- self . name_series_display( field_names ) ,
2599+ self . name_series_display( available_field_names ) ,
26462600 ) ) ;
26472601 }
26482602 }
0 commit comments