Rollup merge of #116429 - fmease:clean-up-struct-field-suggs, r=compi… · rust-lang/rust@a9a389c
@@ -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::{
4746ExpectedFound,
@@ -1585,12 +1584,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15851584self.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);
1595159315961594self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized);
@@ -1601,12 +1599,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16011599&self,
16021600adt_ty: Ty<'tcx>,
16031601expected: Expectation<'tcx>,
1604-expr_id: hir::HirId,
1602+expr: &hir::Expr<'_>,
16051603span: Span,
16061604variant: &'tcx ty::VariantDef,
16071605ast_fields: &'tcx [hir::ExprField<'tcx>],
16081606base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
1609-expr_span: Span,
16101607) {
16111608let 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.
16481645if 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}
1651164816521649self.field_ty(field.span, v_field, args)
@@ -1662,10 +1659,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16621659self.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| {
17331730let 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));
17351732let ident = self.tcx.adjust_ident(f.ident(self.tcx), variant.def_id);
17361733if let Some(_) = remaining_fields.remove(&ident) {
17371734let 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 _ => {
18201817self.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() {
18291826debug!(?remaining_fields);
18301827let 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();
1835183218361833if !private_fields.is_empty() {
@@ -2049,16 +2046,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20492046&self,
20502047ty: Ty<'tcx>,
20512048variant: &'tcx ty::VariantDef,
2049+expr: &hir::Expr<'_>,
20522050field: &hir::ExprField<'_>,
20532051skip_fields: &[hir::ExprField<'_>],
20542052kind_name: &str,
2055-expr_span: Span,
20562053) -> ErrorGuaranteed {
20572054if variant.is_recovered() {
20582055let 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");
20622059self.set_tainted_by_errors(guar);
20632060return 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,
21062103format!(
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,
21242121format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",),
21252122format!("{ty}(/* fields */)"),
21262123Applicability::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);
21332130if 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> {
21532150format!("`{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));
21602153if 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}
217621692177-// 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-22092170fn available_field_names(
22102171&self,
22112172variant: &'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> {
24602409self.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) => {
24662415self.point_at_param_definition(&mut err, param_ty);
@@ -2622,12 +2571,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26222571fn suggest_fields_on_recordish(
26232572&self,
26242573err: &mut Diagnostic,
2574+expr: &hir::Expr<'_>,
26252575def: ty::AdtDef<'tcx>,
26262576field: Ident,
2627-access_span: Span,
26282577) {
2578+let available_field_names = self.available_field_names(def.non_enum_variant(), expr, &[]);
26292579if 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}