Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 5ca9f52

Browse files
committed
Handle missing fields diagnostics
1 parent d18afd3 commit 5ca9f52

File tree

11 files changed

+59
-12
lines changed

11 files changed

+59
-12
lines changed

src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ pub struct FieldData {
8585
pub name: Name,
8686
pub type_ref: TypeRefId,
8787
pub visibility: RawVisibility,
88+
pub has_default: bool,
8889
}
8990

9091
fn repr_from_value(
@@ -478,5 +479,6 @@ fn lower_field(
478479
name: field.name.clone(),
479480
type_ref: field.type_ref,
480481
visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
482+
has_default: field.has_default,
481483
}
482484
}

src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,9 +603,10 @@ impl ExprCollector<'_> {
603603
})
604604
.collect();
605605
let spread = nfl.spread().map(|s| self.collect_expr(s));
606-
Expr::RecordLit { path, fields, spread }
606+
let ellipsis = nfl.dotdot_token().is_some();
607+
Expr::RecordLit { path, fields, spread, ellipsis }
607608
} else {
608-
Expr::RecordLit { path, fields: Box::default(), spread: None }
609+
Expr::RecordLit { path, fields: Box::default(), spread: None, ellipsis: false }
609610
};
610611

611612
self.alloc_expr(record_lit, syntax_ptr)

src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ impl Printer<'_> {
398398
self.print_expr(*expr);
399399
}
400400
}
401-
Expr::RecordLit { path, fields, spread } => {
401+
Expr::RecordLit { path, fields, spread, ellipsis: _ } => {
402402
match path {
403403
Some(path) => self.print_path(path),
404404
None => w!(self, "�"),

src/tools/rust-analyzer/crates/hir-def/src/hir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ pub enum Expr {
252252
path: Option<Box<Path>>,
253253
fields: Box<[RecordLitField]>,
254254
spread: Option<ExprId>,
255+
ellipsis: bool,
255256
},
256257
Field {
257258
expr: ExprId,

src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,7 @@ pub struct Field {
10061006
pub name: Name,
10071007
pub type_ref: TypeRefId,
10081008
pub visibility: RawVisibilityId,
1009+
pub has_default: bool,
10091010
}
10101011

10111012
#[derive(Debug, Clone, Eq, PartialEq)]

src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,9 @@ impl<'a> Ctx<'a> {
319319
};
320320
let visibility = self.lower_visibility(field);
321321
let type_ref = TypeRef::from_ast_opt(body_ctx, field.ty());
322+
let has_default = field.expr().is_some();
322323

323-
Field { name, type_ref, visibility }
324+
Field { name, type_ref, visibility, has_default }
324325
}
325326

326327
fn lower_tuple_field(
@@ -332,7 +333,7 @@ impl<'a> Ctx<'a> {
332333
let name = Name::new_tuple_field(idx);
333334
let visibility = self.lower_visibility(field);
334335
let type_ref = TypeRef::from_ast_opt(body_ctx, field.ty());
335-
Field { name, type_ref, visibility }
336+
Field { name, type_ref, visibility, has_default: false }
336337
}
337338

338339
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {

src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ impl Printer<'_> {
135135
self.whitespace();
136136
w!(self, "{{");
137137
self.indented(|this| {
138-
for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() {
138+
for (idx, Field { name, type_ref, visibility, has_default: _ }) in
139+
fields.iter().enumerate()
140+
{
139141
this.print_attrs_of(
140142
AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
141143
"\n",
@@ -151,7 +153,9 @@ impl Printer<'_> {
151153
FieldsShape::Tuple => {
152154
w!(self, "(");
153155
self.indented(|this| {
154-
for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() {
156+
for (idx, Field { name, type_ref, visibility, has_default: _ }) in
157+
fields.iter().enumerate()
158+
{
155159
this.print_attrs_of(
156160
AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
157161
"\n",

src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,8 @@ pub fn record_literal_missing_fields(
547547
id: ExprId,
548548
expr: &Expr,
549549
) -> Option<(VariantId, Vec<LocalFieldId>, /*exhaustive*/ bool)> {
550-
let (fields, exhaustive) = match expr {
551-
Expr::RecordLit { fields, spread, .. } => (fields, spread.is_none()),
550+
let (fields, exhaustive, ellipsis) = match expr {
551+
Expr::RecordLit { fields, spread, ellipsis, .. } => (fields, spread.is_none(), *ellipsis),
552552
_ => return None,
553553
};
554554

@@ -563,7 +563,13 @@ pub fn record_literal_missing_fields(
563563
let missed_fields: Vec<LocalFieldId> = variant_data
564564
.fields()
565565
.iter()
566-
.filter_map(|(f, d)| if specified_fields.contains(&d.name) { None } else { Some(f) })
566+
.filter_map(|(f, d)| {
567+
if (ellipsis && d.has_default) || specified_fields.contains(&d.name) {
568+
None
569+
} else {
570+
Some(f)
571+
}
572+
})
567573
.collect();
568574
if missed_fields.is_empty() {
569575
return None;

src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ impl InferenceContext<'_> {
121121
Expr::Become { expr } => {
122122
self.infer_mut_expr(*expr, Mutability::Not);
123123
}
124-
Expr::RecordLit { path: _, fields, spread } => {
124+
Expr::RecordLit { path: _, fields, spread, ellipsis: _ } => {
125125
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread))
126126
}
127127
&Expr::Index { base, index } => {

src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
823823
}
824824
Expr::Become { .. } => not_supported!("tail-calls"),
825825
Expr::Yield { .. } => not_supported!("yield"),
826-
Expr::RecordLit { fields, path, spread } => {
826+
Expr::RecordLit { fields, path, spread, ellipsis: _ } => {
827827
let spread_place = match spread {
828828
&Some(it) => {
829829
let Some((p, c)) = self.lower_expr_as_place(current, it, true)? else {

0 commit comments

Comments
 (0)