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;

4141

use rustc_infer::infer::InferOk;

4242

use rustc_infer::traits::query::NoSolution;

4343

use rustc_infer::traits::ObligationCause;

44-

use rustc_middle::middle::stability;

4544

use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};

4645

use 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

);

1595159315961594

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

}

1651164816521649

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();

1835183218361833

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

}

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-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

}