@@ -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,
@@ -1585,12 +1584,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15851584 self.check_expr_struct_fields(
15861585 adt_ty,
15871586 expected,
1588- expr.hir_id ,
1587+ expr,
15891588 qpath.span(),
15901589 variant,
15911590 fields,
15921591 base_expr,
1593- expr.span,
15941592 );
15951593
15961594 self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized);
@@ -1601,12 +1599,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16011599 &self,
16021600 adt_ty: Ty<'tcx>,
16031601 expected: Expectation<'tcx>,
1604- expr_id: hir::HirId ,
1602+ expr: & hir::Expr<'_> ,
16051603 span: Span,
16061604 variant: &'tcx ty::VariantDef,
16071605 ast_fields: &'tcx [hir::ExprField<'tcx>],
16081606 base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
1609- expr_span: Span,
16101607 ) {
16111608 let tcx = self.tcx;
16121609
@@ -1646,7 +1643,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16461643 // struct-like enums (yet...), but it's definitely not
16471644 // a bug to have constructed one.
16481645 if adt_kind != AdtKind::Enum {
1649- tcx.check_stability(v_field.did, Some(expr_id ), field.span, None);
1646+ tcx.check_stability(v_field.did, Some(expr.hir_id ), field.span, None);
16501647 }
16511648
16521649 self.field_ty(field.span, v_field, args)
@@ -1662,10 +1659,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16621659 self.report_unknown_field(
16631660 adt_ty,
16641661 variant,
1662+ expr,
16651663 field,
16661664 ast_fields,
16671665 adt.variant_descr(),
1668- expr_span,
16691666 )
16701667 };
16711668
@@ -1731,7 +1728,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17311728 .iter()
17321729 .map(|f| {
17331730 let fru_ty = self
1734- .normalize(expr_span , self.field_ty(base_expr.span, f, fresh_args));
1731+ .normalize(expr.span , self.field_ty(base_expr.span, f, fresh_args));
17351732 let ident = self.tcx.adjust_ident(f.ident(self.tcx), variant.def_id);
17361733 if let Some(_) = remaining_fields.remove(&ident) {
17371734 let target_ty = self.field_ty(base_expr.span, f, args);
@@ -1814,7 +1811,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18141811 ty::Adt(adt, args) if adt.is_struct() => variant
18151812 .fields
18161813 .iter()
1817- .map(|f| self.normalize(expr_span , f.ty(self.tcx, args)))
1814+ .map(|f| self.normalize(expr.span , f.ty(self.tcx, args)))
18181815 .collect(),
18191816 _ => {
18201817 self.tcx
@@ -1824,13 +1821,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18241821 }
18251822 }
18261823 };
1827- self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id , fru_tys);
1824+ self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr.hir_id , fru_tys);
18281825 } else if adt_kind != AdtKind::Union && !remaining_fields.is_empty() {
18291826 debug!(?remaining_fields);
18301827 let private_fields: Vec<&ty::FieldDef> = variant
18311828 .fields
18321829 .iter()
1833- .filter(|field| !field.vis.is_accessible_from(tcx.parent_module(expr_id ), tcx))
1830+ .filter(|field| !field.vis.is_accessible_from(tcx.parent_module(expr.hir_id ), tcx))
18341831 .collect();
18351832
18361833 if !private_fields.is_empty() {
@@ -2049,16 +2046,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20492046 &self,
20502047 ty: Ty<'tcx>,
20512048 variant: &'tcx ty::VariantDef,
2049+ expr: &hir::Expr<'_>,
20522050 field: &hir::ExprField<'_>,
20532051 skip_fields: &[hir::ExprField<'_>],
20542052 kind_name: &str,
2055- expr_span: Span,
20562053 ) -> ErrorGuaranteed {
20572054 if variant.is_recovered() {
20582055 let guar = self
20592056 .tcx
20602057 .sess
2061- .delay_span_bug(expr_span , "parser recovered but no error was emitted");
2058+ .delay_span_bug(expr.span , "parser recovered but no error was emitted");
20622059 self.set_tainted_by_errors(guar);
20632060 return guar;
20642061 }
@@ -2102,7 +2099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21022099 );
21032100 err.span_label(field.ident.span, "field does not exist");
21042101 err.span_suggestion_verbose(
2105- expr_span ,
2102+ expr.span ,
21062103 format!(
21072104 "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
21082105 adt = ty,
@@ -2120,7 +2117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21202117 err.span_label(variant_ident_span, format!("`{ty}` defined here"));
21212118 err.span_label(field.ident.span, "field does not exist");
21222119 err.span_suggestion_verbose(
2123- expr_span ,
2120+ expr.span ,
21242121 format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",),
21252122 format!("{ty}(/* fields */)"),
21262123 Applicability::HasPlaceholders,
@@ -2129,9 +2126,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21292126 },
21302127 _ => {
21312128 // prevent all specified fields from being suggested
2132- let skip_fields: Vec<_> = skip_fields.iter().map(|x| x.ident.name).collect( );
2129+ let available_field_names = self.available_field_names(variant, expr, skip_fields );
21332130 if let Some(field_name) =
2134- self.suggest_field_name(variant , field.ident.name, &skip_fields, expr_span )
2131+ find_best_match_for_name(&available_field_names , field.ident.name, None )
21352132 {
21362133 err.span_suggestion(
21372134 field.ident.span,
@@ -2153,10 +2150,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21532150 format!("`{ty}` does not have this field"),
21542151 );
21552152 }
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));
21602153 if available_field_names.is_empty() {
21612154 err.note("all struct fields are already assigned");
21622155 } else {
@@ -2174,63 +2167,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21742167 err.emit()
21752168 }
21762169
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-
22092170 fn available_field_names(
22102171 &self,
22112172 variant: &'tcx ty::VariantDef,
2212- access_span: Span,
2173+ expr: &hir::Expr<'_>,
2174+ skip_fields: &[hir::ExprField<'_>],
22132175 ) -> Vec<Symbol> {
2214- let body_owner_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
22152176 variant
22162177 .fields
22172178 .iter()
22182179 .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- )
2180+ skip_fields.iter().all(|&skip| skip.ident.name != field.name)
2181+ && self.is_field_suggestable(field, expr.hir_id, expr.span)
22322182 })
2233- .filter(|field| !self.tcx.is_doc_hidden(field.did))
22342183 .map(|field| field.name)
22352184 .collect()
22362185 }
@@ -2460,7 +2409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24602409 self.suggest_first_deref_field(&mut err, expr, base, ident);
24612410 }
24622411 ty::Adt(def, _) if !def.is_enum() => {
2463- self.suggest_fields_on_recordish(&mut err, def, ident, expr.span );
2412+ self.suggest_fields_on_recordish(&mut err, expr, def, ident );
24642413 }
24652414 ty::Param(param_ty) => {
24662415 self.point_at_param_definition(&mut err, param_ty);
@@ -2622,12 +2571,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26222571 fn suggest_fields_on_recordish(
26232572 &self,
26242573 err: &mut Diagnostic,
2574+ expr: &hir::Expr<'_>,
26252575 def: ty::AdtDef<'tcx>,
26262576 field: Ident,
2627- access_span: Span,
26282577 ) {
2578+ let available_field_names = self.available_field_names(def.non_enum_variant(), expr, &[]);
26292579 if let Some(suggested_field_name) =
2630- self.suggest_field_name(def.non_enum_variant() , field.name, &[], access_span )
2580+ find_best_match_for_name(&available_field_names , field.name, None )
26312581 {
26322582 err.span_suggestion(
26332583 field.span,
@@ -2637,12 +2587,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26372587 );
26382588 } else {
26392589 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() {
2590+ if !available_field_names.is_empty() {
26432591 err.note(format!(
26442592 "available fields are: {}",
2645- self.name_series_display(field_names ),
2593+ self.name_series_display(available_field_names ),
26462594 ));
26472595 }
26482596 }
0 commit comments