Rollup merge of #116429 - fmease:clean-up-struct-field-suggs, r=compi… · rust-lang/rust@a9a389c (original) (raw)

`@@ -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,

`

`@@ -1585,12 +1584,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

1585

1584

`self.check_expr_struct_fields(

`

1586

1585

` adt_ty,

`

1587

1586

` expected,

`

1588

``

`-

expr.hir_id,

`

``

1587

`+

expr,

`

1589

1588

` qpath.span(),

`

1590

1589

` variant,

`

1591

1590

` fields,

`

1592

1591

` base_expr,

`

1593

``

`-

expr.span,

`

1594

1592

`);

`

1595

1593

``

1596

1594

`self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized);

`

`@@ -1601,12 +1599,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

1601

1599

`&self,

`

1602

1600

`adt_ty: Ty<'tcx>,

`

1603

1601

`expected: Expectation<'tcx>,

`

1604

``

`-

expr_id: hir::HirId,

`

``

1602

`+

expr: &hir::Expr<'_>,

`

1605

1603

`span: Span,

`

1606

1604

`variant: &'tcx ty::VariantDef,

`

1607

1605

`ast_fields: &'tcx [hir::ExprField<'tcx>],

`

1608

1606

`base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,

`

1609

``

`-

expr_span: Span,

`

1610

1607

`) {

`

1611

1608

`let tcx = self.tcx;

`

1612

1609

``

`@@ -1646,7 +1643,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

1646

1643

`// struct-like enums (yet...), but it's definitely not

`

1647

1644

`// a bug to have constructed one.

`

1648

1645

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

`

1650

1647

`}

`

1651

1648

``

1652

1649

`self.field_ty(field.span, v_field, args)

`

`@@ -1662,10 +1659,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

1662

1659

`self.report_unknown_field(

`

1663

1660

` adt_ty,

`

1664

1661

` variant,

`

``

1662

`+

expr,

`

1665

1663

` field,

`

1666

1664

` ast_fields,

`

1667

1665

` adt.variant_descr(),

`

1668

``

`-

expr_span,

`

1669

1666

`)

`

1670

1667

`};

`

1671

1668

``

`@@ -1731,7 +1728,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

1731

1728

`.iter()

`

1732

1729

`.map(|f| {

`

1733

1730

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

`

1735

1732

`let ident = self.tcx.adjust_ident(f.ident(self.tcx), variant.def_id);

`

1736

1733

`if let Some(_) = remaining_fields.remove(&ident) {

`

1737

1734

`let target_ty = self.field_ty(base_expr.span, f, args);

`

`@@ -1814,7 +1811,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

1814

1811

` ty::Adt(adt, args) if adt.is_struct() => variant

`

1815

1812

`.fields

`

1816

1813

`.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)))

`

1818

1815

`.collect(),

`

1819

1816

` _ => {

`

1820

1817

`self.tcx

`

`@@ -1824,13 +1821,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

1824

1821

`}

`

1825

1822

`}

`

1826

1823

`};

`

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

`

1828

1825

`} else if adt_kind != AdtKind::Union && !remaining_fields.is_empty() {

`

1829

1826

`debug!(?remaining_fields);

`

1830

1827

`let private_fields: Vec<&ty::FieldDef> = variant

`

1831

1828

`.fields

`

1832

1829

`.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))

`

1834

1831

`.collect();

`

1835

1832

``

1836

1833

`if !private_fields.is_empty() {

`

`@@ -2049,16 +2046,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

2049

2046

`&self,

`

2050

2047

`ty: Ty<'tcx>,

`

2051

2048

`variant: &'tcx ty::VariantDef,

`

``

2049

`+

expr: &hir::Expr<'_>,

`

2052

2050

`field: &hir::ExprField<'_>,

`

2053

2051

`skip_fields: &[hir::ExprField<'_>],

`

2054

2052

`kind_name: &str,

`

2055

``

`-

expr_span: Span,

`

2056

2053

`) -> ErrorGuaranteed {

`

2057

2054

`if variant.is_recovered() {

`

2058

2055

`let guar = self

`

2059

2056

`.tcx

`

2060

2057

`.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");

`

2062

2059

`self.set_tainted_by_errors(guar);

`

2063

2060

`return guar;

`

2064

2061

`}

`

`@@ -2102,7 +2099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

2102

2099

`);

`

2103

2100

` err.span_label(field.ident.span, "field does not exist");

`

2104

2101

` err.span_suggestion_verbose(

`

2105

``

`-

expr_span,

`

``

2102

`+

expr.span,

`

2106

2103

`format!(

`

2107

2104

`` "{adt}::{variant} is a tuple {kind_name}, use the appropriate syntax",

``

2108

2105

` adt = ty,

`

`@@ -2120,7 +2117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

2120

2117

`` err.span_label(variant_ident_span, format!("{ty} defined here"));

``

2121

2118

` err.span_label(field.ident.span, "field does not exist");

`

2122

2119

` err.span_suggestion_verbose(

`

2123

``

`-

expr_span,

`

``

2120

`+

expr.span,

`

2124

2121

`` format!("{ty} is a tuple {kind_name}, use the appropriate syntax",),

``

2125

2122

`format!("{ty}(/* fields */)"),

`

2126

2123

`Applicability::HasPlaceholders,

`

`@@ -2129,9 +2126,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

2129

2126

`},

`

2130

2127

` _ => {

`

2131

2128

`// 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);

`

2133

2130

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

`

2135

2132

`{

`

2136

2133

` err.span_suggestion(

`

2137

2134

` field.ident.span,

`

`@@ -2153,10 +2150,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

2153

2150

`` format!("{ty} does not have this field"),

``

2154

2151

`);

`

2155

2152

`}

`

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

2153

`if available_field_names.is_empty() {

`

2161

2154

` err.note("all struct fields are already assigned");

`

2162

2155

`} else {

`

`@@ -2174,63 +2167,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

2174

2167

` err.emit()

`

2175

2168

`}

`

2176

2169

``

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 {

`

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

`

2205

``

-

2206

``

`-

find_best_match_for_name(&names, field, None)

`

2207

``

`-

}

`

2208

``

-

2209

2170

`fn available_field_names(

`

2210

2171

`&self,

`

2211

2172

`variant: &'tcx ty::VariantDef,

`

2212

``

`-

access_span: Span,

`

``

2173

`+

expr: &hir::Expr<'_>,

`

``

2174

`+

skip_fields: &[hir::ExprField<'_>],

`

2213

2175

`) -> Vec {

`

2214

``

`-

let body_owner_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);

`

2215

2176

` variant

`

2216

2177

`.fields

`

2217

2178

`.iter()

`

2218

2179

`.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)

`

2232

2182

`})

`

2233

``

`-

.filter(|field| !self.tcx.is_doc_hidden(field.did))

`

2234

2183

`.map(|field| field.name)

`

2235

2184

`.collect()

`

2236

2185

`}

`

`@@ -2460,7 +2409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

2460

2409

`self.suggest_first_deref_field(&mut err, expr, base, ident);

`

2461

2410

`}

`

2462

2411

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

`

2464

2413

`}

`

2465

2414

` ty::Param(param_ty) => {

`

2466

2415

`self.point_at_param_definition(&mut err, param_ty);

`

`@@ -2622,12 +2571,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

2622

2571

`fn suggest_fields_on_recordish(

`

2623

2572

`&self,

`

2624

2573

`err: &mut Diagnostic,

`

``

2574

`+

expr: &hir::Expr<'_>,

`

2625

2575

`def: ty::AdtDef<'tcx>,

`

2626

2576

`field: Ident,

`

2627

``

`-

access_span: Span,

`

2628

2577

`) {

`

``

2578

`+

let available_field_names = self.available_field_names(def.non_enum_variant(), expr, &[]);

`

2629

2579

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

`

2631

2581

`{

`

2632

2582

` err.span_suggestion(

`

2633

2583

` field.span,

`

`@@ -2637,12 +2587,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

2637

2587

`);

`

2638

2588

`} else {

`

2639

2589

` 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() {

`

2643

2591

` err.note(format!(

`

2644

2592

`"available fields are: {}",

`

2645

``

`-

self.name_series_display(field_names),

`

``

2593

`+

self.name_series_display(available_field_names),

`

2646

2594

`));

`

2647

2595

`}

`

2648

2596

`}

`