From 55d385182055b655e7d807eb473dcbc32f1fb17f Mon Sep 17 00:00:00 2001 From: David Barsky Date: Mon, 27 Jan 2025 17:20:11 -0500 Subject: [PATCH 1/9] Back out "Remove `has_default` from `FieldId`" This backs out commit 8aa6c09fcee6270c787a6f00615d76343fbe5c07. --- crates/hir-def/src/lib.rs | 1 + crates/hir-ty/src/infer/closure.rs | 5 ++- crates/hir-ty/src/infer/expr.rs | 6 ++-- crates/hir-ty/src/mir/lower.rs | 5 +++ .../hir-ty/src/mir/lower/pattern_matching.rs | 10 ++++-- crates/hir-ty/src/tests.rs | 8 ++--- crates/hir/src/display.rs | 4 +-- crates/hir/src/from_id.rs | 4 +-- crates/hir/src/lib.rs | 34 +++++++++---------- crates/hir/src/semantics/child_by_source.rs | 6 +++- crates/hir/src/source_analyzer.rs | 16 +++++++-- 11 files changed, 64 insertions(+), 35 deletions(-) diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 6bc8741c33c5..80aa5516602e 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -519,6 +519,7 @@ pub type LocalModuleId = Idx; pub struct FieldId { pub parent: VariantId, pub local_id: LocalFieldId, + pub has_default: bool, } impl FieldId { diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 0e9aed416004..def0cb705d8f 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -1167,9 +1167,11 @@ impl InferenceContext<'_> { }; let mut p = place.clone(); self.current_capture_span_stack.push(MirSpan::PatId(arg)); + let has_default = vd.fields()[local_id].has_default; p.projections.push(ProjectionElem::Field(Either::Left(FieldId { parent: variant, local_id, + has_default, }))); self.consume_with_pat(p, arg); self.current_capture_span_stack.pop(); @@ -1219,12 +1221,13 @@ impl InferenceContext<'_> { .iter() .zip(fields.clone()) .chain(ar.iter().rev().zip(fields.rev())); - for (&arg, (i, _)) in it { + for (&arg, (i, d)) in it { let mut p = place.clone(); self.current_capture_span_stack.push(MirSpan::PatId(arg)); p.projections.push(ProjectionElem::Field(Either::Left(FieldId { parent: variant, local_id: i, + has_default: d.has_default, }))); self.consume_with_pat(p, arg); self.current_capture_span_stack.pop(); diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 179565440c36..b91f32b09e53 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -1748,13 +1748,15 @@ impl InferenceContext<'_> { TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { let vd = &self.db.struct_data(*s).variant_data; let local_id = vd.field(name)?; - let field = FieldId { parent: (*s).into(), local_id }; + let has_default = vd.fields()[local_id].has_default; + let field = FieldId { parent: (*s).into(), local_id, has_default }; (field, parameters.clone()) } TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { let vd = &self.db.union_data(*u).variant_data; let local_id = vd.field(name)?; - let field = FieldId { parent: (*u).into(), local_id }; + let has_default = vd.fields()[local_id].has_default; + let field = FieldId { parent: (*u).into(), local_id, has_default }; (field, parameters.clone()) } _ => return None, diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 940d992001d5..b254bc8e5495 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -872,10 +872,13 @@ impl<'ctx> MirLowerCtx<'ctx> { None => { let local_id = LocalFieldId::from_raw(RawIdx::from(i as u32)); + let has_default = + variant_data.fields()[local_id].has_default; let p = sp.project( ProjectionElem::Field(Either::Left(FieldId { parent: variant_id, local_id, + has_default, })), &mut self.result.projection_store, ); @@ -897,10 +900,12 @@ impl<'ctx> MirLowerCtx<'ctx> { }; let local_id = variant_data.field(name).ok_or(MirLowerError::UnresolvedField)?; + let has_default = variant_data.fields()[local_id].has_default; let place = place.project( PlaceElem::Field(Either::Left(FieldId { parent: union_id.into(), local_id, + has_default, })), &mut self.result.projection_store, ); diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 2ffea34c85a1..43e6eb88988f 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -632,10 +632,12 @@ impl MirLowerCtx<'_> { .map(|x| { let field_id = variant_data.field(&x.name).ok_or(MirLowerError::UnresolvedField)?; + let has_default = variant_data.fields()[field_id].has_default; Ok(( PlaceElem::Field(Either::Left(FieldId { parent: v, local_id: field_id, + has_default, })), x.pat, )) @@ -644,8 +646,12 @@ impl MirLowerCtx<'_> { self.pattern_match_adt(current, current_else, it.into_iter(), cond_place, mode)? } AdtPatternShape::Tuple { args, ellipsis } => { - let fields = variant_data.fields().iter().map(|(x, _)| { - PlaceElem::Field(Either::Left(FieldId { parent: v, local_id: x })) + let fields = variant_data.fields().iter().map(|(x, d)| { + PlaceElem::Field(Either::Left(FieldId { + parent: v, + local_id: x, + has_default: d.has_default, + })) }); self.pattern_match_tuple_like( current, diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index 96e7130ecf03..56b7e6cba082 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -143,7 +143,7 @@ fn check_impl( let vd = db.variant_data(variant_id); defs.extend(vd.fields().iter().filter_map(|(local_id, fd)| { if fd.has_default { - let field = FieldId { parent: variant_id, local_id }; + let field = FieldId { parent: variant_id, local_id, has_default: true }; Some(DefWithBodyId::FieldId(field)) } else { None @@ -161,7 +161,7 @@ fn check_impl( let vd = db.variant_data(variant_id); defs.extend(vd.fields().iter().filter_map(|(local_id, fd)| { if fd.has_default { - let field = FieldId { parent: variant_id, local_id }; + let field = FieldId { parent: variant_id, local_id, has_default: true }; Some(DefWithBodyId::FieldId(field)) } else { None @@ -433,7 +433,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { let vd = db.variant_data(variant_id); defs.extend(vd.fields().iter().filter_map(|(local_id, fd)| { if fd.has_default { - let field = FieldId { parent: variant_id, local_id }; + let field = FieldId { parent: variant_id, local_id, has_default: true }; Some(DefWithBodyId::FieldId(field)) } else { None @@ -451,7 +451,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { let vd = db.variant_data(variant_id); defs.extend(vd.fields().iter().filter_map(|(local_id, fd)| { if fd.has_default { - let field = FieldId { parent: variant_id, local_id }; + let field = FieldId { parent: variant_id, local_id, has_default: true }; Some(DefWithBodyId::FieldId(field)) } else { None diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 6f4168ab0867..7bd80442f067 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -252,8 +252,8 @@ impl HirDisplay for Struct { f.write_char('(')?; let mut it = variant_data.fields().iter().peekable(); - while let Some((id, _)) = it.next() { - let field = Field { parent: (*self).into(), id }; + while let Some((id, d)) = it.next() { + let field = Field { parent: (*self).into(), id, has_default: d.has_default }; write_visibility(module_id, field.visibility(f.db), f)?; field.ty(f.db).hir_fmt(f)?; if it.peek().is_some() { diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index dd26e894d793..5c12cf21da3c 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs @@ -237,13 +237,13 @@ impl From for VariantId { impl From for FieldId { fn from(def: Field) -> Self { - FieldId { parent: def.parent.into(), local_id: def.id } + FieldId { parent: def.parent.into(), local_id: def.id, has_default: def.has_default } } } impl From for Field { fn from(def: FieldId) -> Self { - Field { parent: def.parent.into(), id: def.local_id } + Field { parent: def.parent.into(), id: def.local_id, has_default: def.has_default } } } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index a38c0211e877..42e4483789c2 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -415,24 +415,18 @@ impl ModuleDef { def.diagnostics(db, &mut acc); } - let vd: Option<(VariantDef, Arc)> = match self { - ModuleDef::Adt(Adt::Struct(it)) => { - Some((it.into(), db.struct_data(it.id).variant_data.clone())) - } - ModuleDef::Adt(Adt::Union(it)) => { - Some((it.into(), db.union_data(it.id).variant_data.clone())) - } - ModuleDef::Variant(it) => { - Some((it.into(), db.enum_variant_data(it.id).variant_data.clone())) - } + let fields = match self { + ModuleDef::Adt(Adt::Struct(it)) => Some(it.fields(db)), + ModuleDef::Adt(Adt::Union(it)) => Some(it.fields(db)), + ModuleDef::Variant(it) => Some(it.fields(db)), _ => None, }; - if let Some((parent, vd)) = vd { - for (id, fd) in vd.fields().iter() { - if !fd.has_default { + if let Some(fields) = fields { + for field in fields { + if !field.has_default { continue; } - let def: DefWithBody = DefWithBody::Field(Field { parent, id }); + let def: DefWithBody = field.into(); def.diagnostics(db, &mut acc, style_lints); } } @@ -1258,6 +1252,7 @@ impl From<&Field> for DefWithBodyId { pub struct Field { pub(crate) parent: VariantDef, pub(crate) id: LocalFieldId, + pub(crate) has_default: bool, } #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] @@ -1423,7 +1418,7 @@ impl Struct { .variant_data .fields() .iter() - .map(|(id, _)| Field { parent: self.into(), id }) + .map(|(id, d)| Field { parent: self.into(), id, has_default: d.has_default }) .collect() } @@ -1485,7 +1480,7 @@ impl Union { .variant_data .fields() .iter() - .map(|(id, _)| Field { parent: self.into(), id }) + .map(|(id, d)| Field { parent: self.into(), id, has_default: d.has_default }) .collect() } @@ -1615,7 +1610,7 @@ impl Variant { self.variant_data(db) .fields() .iter() - .map(|(id, _)| Field { parent: self.into(), id }) + .map(|(id, d)| Field { parent: self.into(), id, has_default: d.has_default }) .collect() } @@ -5203,10 +5198,13 @@ impl Type { _ => return Vec::new(), }; + let var_data = db.variant_data(variant_id); + let fields = var_data.fields(); db.field_types(variant_id) .iter() .map(|(local_id, ty)| { - let def = Field { parent: variant_id.into(), id: local_id }; + let has_default = fields[local_id].has_default; + let def = Field { parent: variant_id.into(), id: local_id, has_default }; let ty = ty.clone().substitute(Interner, substs); (def, self.derived(ty)) }) diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs index d5dfb9857186..ef10a4e148cd 100644 --- a/crates/hir/src/semantics/child_by_source.rs +++ b/crates/hir/src/semantics/child_by_source.rs @@ -160,7 +160,11 @@ impl ChildBySource for VariantId { let arena_map = arena_map.as_ref(); let parent = *self; for (local_id, source) in arena_map.value.iter() { - let id = FieldId { parent, local_id }; + let has_default = match source { + Either::Left(_) => false, + Either::Right(rec) => rec.expr().is_some(), + }; + let id = FieldId { parent, local_id, has_default }; match source.clone() { Either::Left(source) => res[keys::TUPLE_FIELD].insert(AstPtr::new(&source), id), Either::Right(source) => res[keys::RECORD_FIELD].insert(AstPtr::new(&source), id), diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 7d6f11018175..671a4603c26b 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -630,8 +630,10 @@ impl SourceAnalyzer { let (adt, subst) = self.infer.as_ref()?.type_of_expr_or_pat(expr_id)?.as_adt()?; let variant = self.infer.as_ref()?.variant_resolution_for_expr_or_pat(expr_id)?; let variant_data = variant.variant_data(db.upcast()); + let fields = variant_data.fields(); let local_id = variant_data.field(&local_name)?; - let field = FieldId { parent: variant, local_id }; + let field = + FieldId { parent: variant, local_id, has_default: fields[local_id].has_default }; let field_ty = db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); Some(( @@ -652,8 +654,10 @@ impl SourceAnalyzer { let pat_id = self.pat_id(&record_pat.into())?; let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id)?; let variant_data = variant.variant_data(db.upcast()); + let fields = variant_data.fields(); let local_id = variant_data.field(&field_name)?; - let field = FieldId { parent: variant, local_id }; + let field = + FieldId { parent: variant, local_id, has_default: fields[local_id].has_default }; let (adt, subst) = self.infer.as_ref()?.type_of_pat.get(pat_id)?.as_adt()?; let field_ty = db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); @@ -1062,11 +1066,17 @@ impl SourceAnalyzer { missing_fields: Vec, ) -> Vec<(Field, Type)> { let field_types = db.field_types(variant); + let var_data = db.variant_data(variant); + let fields = var_data.fields(); missing_fields .into_iter() .map(|local_id| { - let field = FieldId { parent: variant, local_id }; + let field = FieldId { + parent: variant, + local_id, + has_default: fields[local_id].has_default, + }; let ty = field_types[local_id].clone().substitute(Interner, substs); (field.into(), Type::new_with_resolver_inner(db, &self.resolver, ty)) }) From 34d05b3bd084723dbbd27b8180b54f5f2190e4a5 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Mon, 27 Jan 2025 17:20:11 -0500 Subject: [PATCH 2/9] Back out "Fix a mistake in condition" This backs out commit e5c38558f5dbc37cbc91f9fda58144ce02e1f5aa. --- crates/hir-ty/src/diagnostics/expr.rs | 2 +- crates/hir-ty/src/tests.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index d744fe64c0d0..dd55febbf042 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -550,7 +550,7 @@ pub fn record_literal_missing_fields( ) -> Option<(VariantId, Vec, /*has spread expr*/ bool)> { let (fields, has_spread_expr, has_ellipsis) = match expr { Expr::RecordLit { fields, spread, .. } => { - (fields, !matches!(spread, Spread::Base(_)), matches!(spread, Spread::Yes)) + (fields, matches!(spread, Spread::Base(_)), matches!(spread, Spread::Yes)) } _ => return None, }; diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index 56b7e6cba082..5177ed07b1fb 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -202,6 +202,7 @@ fn check_impl( for def in defs { let (body, body_source_map) = db.body_with_source_map(def); let inference_result = db.infer(def); + dbg!(&inference_result); for (pat, mut ty) in inference_result.type_of_pat.iter() { if let Pat::Bind { id, .. } = body.pats[pat] { From 52ee4ee1df8a0b0f342b11510cd0a3fb632b4b63 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Mon, 27 Jan 2025 17:20:11 -0500 Subject: [PATCH 3/9] Back out "Add a test for field default value body as defining usage of TAIT" This backs out commit 4fe18a6fb5a1181a04c47391f558ebab5b8b0f39. --- crates/hir-def/src/lib.rs | 6 +- crates/hir-ty/src/tests.rs | 112 ++++-------------- .../src/tests/type_alias_impl_traits.rs | 50 +------- 3 files changed, 27 insertions(+), 141 deletions(-) diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 80aa5516602e..cf97d27fd1fd 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -1399,7 +1399,11 @@ impl HasModule for DefWithBodyId { DefWithBodyId::ConstId(it) => it.module(db), DefWithBodyId::VariantId(it) => it.module(db), DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db), - DefWithBodyId::FieldId(it) => it.module(db), + DefWithBodyId::FieldId(it) => match it.parent { + VariantId::EnumVariantId(it) => it.module(db), + VariantId::StructId(it) => it.module(db), + VariantId::UnionId(it) => it.module(db), + }, } } } diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index 5177ed07b1fb..a5af712b42f2 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -16,7 +16,6 @@ use std::env; use std::sync::LazyLock; use base_db::SourceDatabaseFileInputExt as _; -use either::Either; use expect_test::Expect; use hir_def::{ db::DefDatabase, @@ -24,14 +23,12 @@ use hir_def::{ hir::{ExprId, Pat, PatId}, item_scope::ItemScope, nameres::DefMap, - src::{HasChildSource, HasSource}, - AdtId, AssocItemId, DefWithBodyId, FieldId, HasModule, LocalModuleId, Lookup, ModuleDefId, - SyntheticSyntax, + src::HasSource, + AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId, SyntheticSyntax, }; use hir_expand::{db::ExpandDatabase, FileRange, InFile}; use itertools::Itertools; use rustc_hash::FxHashMap; -use span::TextSize; use stdx::format_to; use syntax::{ ast::{self, AstNode, HasName}, @@ -135,40 +132,14 @@ fn check_impl( None => continue, }; let def_map = module.def_map(&db); - visit_module(&db, &def_map, module.local_id, &mut |it| match it { - ModuleDefId::FunctionId(it) => defs.push(it.into()), - ModuleDefId::EnumVariantId(it) => { - defs.push(it.into()); - let variant_id = it.into(); - let vd = db.variant_data(variant_id); - defs.extend(vd.fields().iter().filter_map(|(local_id, fd)| { - if fd.has_default { - let field = FieldId { parent: variant_id, local_id, has_default: true }; - Some(DefWithBodyId::FieldId(field)) - } else { - None - } - })); - } - ModuleDefId::ConstId(it) => defs.push(it.into()), - ModuleDefId::StaticId(it) => defs.push(it.into()), - ModuleDefId::AdtId(it) => { - let variant_id = match it { - AdtId::StructId(it) => it.into(), - AdtId::UnionId(it) => it.into(), - AdtId::EnumId(_) => return, - }; - let vd = db.variant_data(variant_id); - defs.extend(vd.fields().iter().filter_map(|(local_id, fd)| { - if fd.has_default { - let field = FieldId { parent: variant_id, local_id, has_default: true }; - Some(DefWithBodyId::FieldId(field)) - } else { - None - } - })); - } - _ => {} + visit_module(&db, &def_map, module.local_id, &mut |it| { + defs.push(match it { + ModuleDefId::FunctionId(it) => it.into(), + ModuleDefId::EnumVariantId(it) => it.into(), + ModuleDefId::ConstId(it) => it.into(), + ModuleDefId::StaticId(it) => it.into(), + _ => return, + }) }); } defs.sort_by_key(|def| match def { @@ -189,20 +160,12 @@ fn check_impl( loc.source(&db).value.syntax().text_range().start() } DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(), - DefWithBodyId::FieldId(it) => { - let cs = it.parent.child_source(&db); - match cs.value.get(it.local_id) { - Some(Either::Left(it)) => it.syntax().text_range().start(), - Some(Either::Right(it)) => it.syntax().text_range().end(), - None => TextSize::new(u32::MAX), - } - } + DefWithBodyId::FieldId(_) => unreachable!(), }); let mut unexpected_type_mismatches = String::new(); for def in defs { let (body, body_source_map) = db.body_with_source_map(def); let inference_result = db.infer(def); - dbg!(&inference_result); for (pat, mut ty) in inference_result.type_of_pat.iter() { if let Pat::Bind { id, .. } = body.pats[pat] { @@ -426,40 +389,14 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { let def_map = module.def_map(&db); let mut defs: Vec = Vec::new(); - visit_module(&db, &def_map, module.local_id, &mut |it| match it { - ModuleDefId::FunctionId(it) => defs.push(it.into()), - ModuleDefId::EnumVariantId(it) => { - defs.push(it.into()); - let variant_id = it.into(); - let vd = db.variant_data(variant_id); - defs.extend(vd.fields().iter().filter_map(|(local_id, fd)| { - if fd.has_default { - let field = FieldId { parent: variant_id, local_id, has_default: true }; - Some(DefWithBodyId::FieldId(field)) - } else { - None - } - })); - } - ModuleDefId::ConstId(it) => defs.push(it.into()), - ModuleDefId::StaticId(it) => defs.push(it.into()), - ModuleDefId::AdtId(it) => { - let variant_id = match it { - AdtId::StructId(it) => it.into(), - AdtId::UnionId(it) => it.into(), - AdtId::EnumId(_) => return, - }; - let vd = db.variant_data(variant_id); - defs.extend(vd.fields().iter().filter_map(|(local_id, fd)| { - if fd.has_default { - let field = FieldId { parent: variant_id, local_id, has_default: true }; - Some(DefWithBodyId::FieldId(field)) - } else { - None - } - })); - } - _ => {} + visit_module(&db, &def_map, module.local_id, &mut |it| { + defs.push(match it { + ModuleDefId::FunctionId(it) => it.into(), + ModuleDefId::EnumVariantId(it) => it.into(), + ModuleDefId::ConstId(it) => it.into(), + ModuleDefId::StaticId(it) => it.into(), + _ => return, + }) }); defs.sort_by_key(|def| match def { DefWithBodyId::FunctionId(it) => { @@ -479,14 +416,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { loc.source(&db).value.syntax().text_range().start() } DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(), - DefWithBodyId::FieldId(it) => { - let cs = it.parent.child_source(&db); - match cs.value.get(it.local_id) { - Some(Either::Left(it)) => it.syntax().text_range().start(), - Some(Either::Right(it)) => it.syntax().text_range().end(), - None => TextSize::new(u32::MAX), - } - } + DefWithBodyId::FieldId(_) => unreachable!(), }); for def in defs { let (body, source_map) = db.body_with_source_map(def); @@ -547,7 +477,7 @@ pub(crate) fn visit_module( let body = db.body(it.into()); visit_body(db, &body, cb); } - ModuleDefId::AdtId(AdtId::EnumId(it)) => { + ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => { db.enum_data(it).variants.iter().for_each(|&(it, _)| { let body = db.body(it.into()); cb(it.into()); diff --git a/crates/hir-ty/src/tests/type_alias_impl_traits.rs b/crates/hir-ty/src/tests/type_alias_impl_traits.rs index a2aada57da97..e2b7bf379cc3 100644 --- a/crates/hir-ty/src/tests/type_alias_impl_traits.rs +++ b/crates/hir-ty/src/tests/type_alias_impl_traits.rs @@ -157,53 +157,5 @@ static ALIAS: i32 = { 217..218 '5': i32 205..211: expected impl Trait + ?Sized, got Struct "#]], - ); -} - -#[test] -fn defining_type_alias_impl_trait_from_default_fields() { - check_no_mismatches( - r#" -trait Trait {} - -struct Struct; - -impl Trait for Struct {} - -type AliasTy = impl Trait; - -struct Foo { - foo: AliasTy = { - let x: AliasTy = Struct; - x - }, -} -"#, - ); - - check_infer_with_mismatches( - r#" -trait Trait {} - -struct Struct; - -impl Trait for Struct {} - -type AliasTy = impl Trait; - -struct Foo { - foo: i32 = { - let x: AliasTy = Struct; - 5 - }, -} -"#, - expect![[r#" - 114..164 '{ ... }': i32 - 128..129 'x': impl Trait + ?Sized - 141..147 'Struct': Struct - 157..158 '5': i32 - 141..147: expected impl Trait + ?Sized, got Struct - "#]], - ); + ) } From e1b9a01c693a57aca8d113452c0e110b20eaaeef Mon Sep 17 00:00:00 2001 From: David Barsky Date: Mon, 27 Jan 2025 17:20:11 -0500 Subject: [PATCH 4/9] Back out "Implement `HasResolver` and `HasModule` for `FieldId`" This backs out commit ce9da9063097c26006886b3f403a0c50790c285a. --- crates/hir-def/src/lib.rs | 12 +++++------- crates/hir-def/src/resolver.rs | 27 ++++++++++++++------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index cf97d27fd1fd..1f06331783df 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -1357,12 +1357,6 @@ impl HasModule for VariantId { } } -impl HasModule for FieldId { - fn module(&self, db: &dyn DefDatabase) -> ModuleId { - self.parent.module(db) - } -} - impl HasModule for MacroId { fn module(&self, db: &dyn DefDatabase) -> ModuleId { match *self { @@ -1386,7 +1380,11 @@ impl HasModule for TypeOwnerId { TypeOwnerId::ImplId(it) => it.module(db), TypeOwnerId::EnumVariantId(it) => it.module(db), TypeOwnerId::InTypeConstId(it) => it.lookup(db).owner.module(db), - TypeOwnerId::FieldId(it) => it.module(db), + TypeOwnerId::FieldId(it) => match it.parent { + VariantId::EnumVariantId(it) => it.module(db), + VariantId::StructId(it) => it.module(db), + VariantId::UnionId(it) => it.module(db), + }, } } } diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index b415efafa6fb..52998942965d 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -27,11 +27,10 @@ use crate::{ type_ref::{LifetimeRef, TypesMap}, visibility::{RawVisibility, Visibility}, AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, - ExternBlockId, ExternCrateId, FieldId, FunctionId, FxIndexMap, GenericDefId, GenericParamId, - HasModule, ImplId, ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, - Macro2Id, MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, - TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, - VariantId, + ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, GenericParamId, HasModule, + ImplId, ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, + MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, + TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId, }; #[derive(Debug, Clone)] @@ -1228,7 +1227,11 @@ impl HasResolver for TypeOwnerId { TypeOwnerId::TypeAliasId(it) => it.resolver(db), TypeOwnerId::ImplId(it) => it.resolver(db), TypeOwnerId::EnumVariantId(it) => it.resolver(db), - TypeOwnerId::FieldId(it) => it.resolver(db), + TypeOwnerId::FieldId(it) => match it.parent { + VariantId::EnumVariantId(it) => it.resolver(db), + VariantId::StructId(it) => it.resolver(db), + VariantId::UnionId(it) => it.resolver(db), + }, } } } @@ -1241,7 +1244,11 @@ impl HasResolver for DefWithBodyId { DefWithBodyId::StaticId(s) => s.resolver(db), DefWithBodyId::VariantId(v) => v.resolver(db), DefWithBodyId::InTypeConstId(c) => c.lookup(db).owner.resolver(db), - DefWithBodyId::FieldId(f) => f.resolver(db), + DefWithBodyId::FieldId(f) => match f.parent { + VariantId::EnumVariantId(it) => it.resolver(db), + VariantId::StructId(it) => it.resolver(db), + VariantId::UnionId(it) => it.resolver(db), + }, } } } @@ -1288,12 +1295,6 @@ impl HasResolver for VariantId { } } -impl HasResolver for FieldId { - fn resolver(self, db: &dyn DefDatabase) -> Resolver { - self.parent.resolver(db) - } -} - impl HasResolver for MacroId { fn resolver(self, db: &dyn DefDatabase) -> Resolver { match self { From 77c1507048d9bd4398d2ec64167026043465f997 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Mon, 27 Jan 2025 17:20:11 -0500 Subject: [PATCH 5/9] Back out "Compute diagnostics of a field body iff it has one" This backs out commit b4d4d02db8a95f5507fbd0aa90904d7b774f0027. --- crates/hir-def/src/lib.rs | 1 - crates/hir-ty/src/infer/closure.rs | 5 +---- crates/hir-ty/src/infer/expr.rs | 12 ++++-------- crates/hir-ty/src/mir/lower.rs | 11 +++-------- .../hir-ty/src/mir/lower/pattern_matching.rs | 10 ++-------- crates/hir/src/display.rs | 4 ++-- crates/hir/src/from_id.rs | 4 ++-- crates/hir/src/lib.rs | 15 ++++----------- crates/hir/src/semantics/child_by_source.rs | 6 +----- crates/hir/src/source_analyzer.rs | 18 +++--------------- 10 files changed, 22 insertions(+), 64 deletions(-) diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 1f06331783df..95700b54db23 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -519,7 +519,6 @@ pub type LocalModuleId = Idx; pub struct FieldId { pub parent: VariantId, pub local_id: LocalFieldId, - pub has_default: bool, } impl FieldId { diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index def0cb705d8f..0e9aed416004 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -1167,11 +1167,9 @@ impl InferenceContext<'_> { }; let mut p = place.clone(); self.current_capture_span_stack.push(MirSpan::PatId(arg)); - let has_default = vd.fields()[local_id].has_default; p.projections.push(ProjectionElem::Field(Either::Left(FieldId { parent: variant, local_id, - has_default, }))); self.consume_with_pat(p, arg); self.current_capture_span_stack.pop(); @@ -1221,13 +1219,12 @@ impl InferenceContext<'_> { .iter() .zip(fields.clone()) .chain(ar.iter().rev().zip(fields.rev())); - for (&arg, (i, d)) in it { + for (&arg, (i, _)) in it { let mut p = place.clone(); self.current_capture_span_stack.push(MirSpan::PatId(arg)); p.projections.push(ProjectionElem::Field(Either::Left(FieldId { parent: variant, local_id: i, - has_default: d.has_default, }))); self.consume_with_pat(p, arg); self.current_capture_span_stack.pop(); diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index b91f32b09e53..8b3ec1ff2ad0 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -1746,17 +1746,13 @@ impl InferenceContext<'_> { }); } TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { - let vd = &self.db.struct_data(*s).variant_data; - let local_id = vd.field(name)?; - let has_default = vd.fields()[local_id].has_default; - let field = FieldId { parent: (*s).into(), local_id, has_default }; + let local_id = self.db.struct_data(*s).variant_data.field(name)?; + let field = FieldId { parent: (*s).into(), local_id }; (field, parameters.clone()) } TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { - let vd = &self.db.union_data(*u).variant_data; - let local_id = vd.field(name)?; - let has_default = vd.fields()[local_id].has_default; - let field = FieldId { parent: (*u).into(), local_id, has_default }; + let local_id = self.db.union_data(*u).variant_data.field(name)?; + let field = FieldId { parent: (*u).into(), local_id }; (field, parameters.clone()) } _ => return None, diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index b254bc8e5495..5d89ebd4ef40 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -870,15 +870,12 @@ impl<'ctx> MirLowerCtx<'ctx> { .map(|(i, it)| match it { Some(it) => it, None => { - let local_id = - LocalFieldId::from_raw(RawIdx::from(i as u32)); - let has_default = - variant_data.fields()[local_id].has_default; let p = sp.project( ProjectionElem::Field(Either::Left(FieldId { parent: variant_id, - local_id, - has_default, + local_id: LocalFieldId::from_raw(RawIdx::from( + i as u32, + )), })), &mut self.result.projection_store, ); @@ -900,12 +897,10 @@ impl<'ctx> MirLowerCtx<'ctx> { }; let local_id = variant_data.field(name).ok_or(MirLowerError::UnresolvedField)?; - let has_default = variant_data.fields()[local_id].has_default; let place = place.project( PlaceElem::Field(Either::Left(FieldId { parent: union_id.into(), local_id, - has_default, })), &mut self.result.projection_store, ); diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 43e6eb88988f..2ffea34c85a1 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -632,12 +632,10 @@ impl MirLowerCtx<'_> { .map(|x| { let field_id = variant_data.field(&x.name).ok_or(MirLowerError::UnresolvedField)?; - let has_default = variant_data.fields()[field_id].has_default; Ok(( PlaceElem::Field(Either::Left(FieldId { parent: v, local_id: field_id, - has_default, })), x.pat, )) @@ -646,12 +644,8 @@ impl MirLowerCtx<'_> { self.pattern_match_adt(current, current_else, it.into_iter(), cond_place, mode)? } AdtPatternShape::Tuple { args, ellipsis } => { - let fields = variant_data.fields().iter().map(|(x, d)| { - PlaceElem::Field(Either::Left(FieldId { - parent: v, - local_id: x, - has_default: d.has_default, - })) + let fields = variant_data.fields().iter().map(|(x, _)| { + PlaceElem::Field(Either::Left(FieldId { parent: v, local_id: x })) }); self.pattern_match_tuple_like( current, diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 7bd80442f067..6f4168ab0867 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -252,8 +252,8 @@ impl HirDisplay for Struct { f.write_char('(')?; let mut it = variant_data.fields().iter().peekable(); - while let Some((id, d)) = it.next() { - let field = Field { parent: (*self).into(), id, has_default: d.has_default }; + while let Some((id, _)) = it.next() { + let field = Field { parent: (*self).into(), id }; write_visibility(module_id, field.visibility(f.db), f)?; field.ty(f.db).hir_fmt(f)?; if it.peek().is_some() { diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index 5c12cf21da3c..dd26e894d793 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs @@ -237,13 +237,13 @@ impl From for VariantId { impl From for FieldId { fn from(def: Field) -> Self { - FieldId { parent: def.parent.into(), local_id: def.id, has_default: def.has_default } + FieldId { parent: def.parent.into(), local_id: def.id } } } impl From for Field { fn from(def: FieldId) -> Self { - Field { parent: def.parent.into(), id: def.local_id, has_default: def.has_default } + Field { parent: def.parent.into(), id: def.local_id } } } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 42e4483789c2..ff9832d31019 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -423,9 +423,6 @@ impl ModuleDef { }; if let Some(fields) = fields { for field in fields { - if !field.has_default { - continue; - } let def: DefWithBody = field.into(); def.diagnostics(db, &mut acc, style_lints); } @@ -1252,7 +1249,6 @@ impl From<&Field> for DefWithBodyId { pub struct Field { pub(crate) parent: VariantDef, pub(crate) id: LocalFieldId, - pub(crate) has_default: bool, } #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] @@ -1418,7 +1414,7 @@ impl Struct { .variant_data .fields() .iter() - .map(|(id, d)| Field { parent: self.into(), id, has_default: d.has_default }) + .map(|(id, _)| Field { parent: self.into(), id }) .collect() } @@ -1480,7 +1476,7 @@ impl Union { .variant_data .fields() .iter() - .map(|(id, d)| Field { parent: self.into(), id, has_default: d.has_default }) + .map(|(id, _)| Field { parent: self.into(), id }) .collect() } @@ -1610,7 +1606,7 @@ impl Variant { self.variant_data(db) .fields() .iter() - .map(|(id, d)| Field { parent: self.into(), id, has_default: d.has_default }) + .map(|(id, _)| Field { parent: self.into(), id }) .collect() } @@ -5198,13 +5194,10 @@ impl Type { _ => return Vec::new(), }; - let var_data = db.variant_data(variant_id); - let fields = var_data.fields(); db.field_types(variant_id) .iter() .map(|(local_id, ty)| { - let has_default = fields[local_id].has_default; - let def = Field { parent: variant_id.into(), id: local_id, has_default }; + let def = Field { parent: variant_id.into(), id: local_id }; let ty = ty.clone().substitute(Interner, substs); (def, self.derived(ty)) }) diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs index ef10a4e148cd..d5dfb9857186 100644 --- a/crates/hir/src/semantics/child_by_source.rs +++ b/crates/hir/src/semantics/child_by_source.rs @@ -160,11 +160,7 @@ impl ChildBySource for VariantId { let arena_map = arena_map.as_ref(); let parent = *self; for (local_id, source) in arena_map.value.iter() { - let has_default = match source { - Either::Left(_) => false, - Either::Right(rec) => rec.expr().is_some(), - }; - let id = FieldId { parent, local_id, has_default }; + let id = FieldId { parent, local_id }; match source.clone() { Either::Left(source) => res[keys::TUPLE_FIELD].insert(AstPtr::new(&source), id), Either::Right(source) => res[keys::RECORD_FIELD].insert(AstPtr::new(&source), id), diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 671a4603c26b..98c30540b497 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -630,10 +630,7 @@ impl SourceAnalyzer { let (adt, subst) = self.infer.as_ref()?.type_of_expr_or_pat(expr_id)?.as_adt()?; let variant = self.infer.as_ref()?.variant_resolution_for_expr_or_pat(expr_id)?; let variant_data = variant.variant_data(db.upcast()); - let fields = variant_data.fields(); - let local_id = variant_data.field(&local_name)?; - let field = - FieldId { parent: variant, local_id, has_default: fields[local_id].has_default }; + let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; let field_ty = db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); Some(( @@ -654,10 +651,7 @@ impl SourceAnalyzer { let pat_id = self.pat_id(&record_pat.into())?; let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id)?; let variant_data = variant.variant_data(db.upcast()); - let fields = variant_data.fields(); - let local_id = variant_data.field(&field_name)?; - let field = - FieldId { parent: variant, local_id, has_default: fields[local_id].has_default }; + let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? }; let (adt, subst) = self.infer.as_ref()?.type_of_pat.get(pat_id)?.as_adt()?; let field_ty = db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); @@ -1066,17 +1060,11 @@ impl SourceAnalyzer { missing_fields: Vec, ) -> Vec<(Field, Type)> { let field_types = db.field_types(variant); - let var_data = db.variant_data(variant); - let fields = var_data.fields(); missing_fields .into_iter() .map(|local_id| { - let field = FieldId { - parent: variant, - local_id, - has_default: fields[local_id].has_default, - }; + let field = FieldId { parent: variant, local_id }; let ty = field_types[local_id].clone().substitute(Interner, substs); (field.into(), Type::new_with_resolver_inner(db, &self.resolver, ty)) }) From f3451d54d6519d45cf7e5716ff3da4e0a72fd9d3 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Mon, 27 Jan 2025 17:20:11 -0500 Subject: [PATCH 6/9] Back out "Merge record lit's ellipsis into pre-existing spread's variant" This backs out commit c134b20c9cbc88a36e77acb8522e8dc4573bd906. --- crates/hir-def/src/expr_store.rs | 6 +++--- crates/hir-def/src/expr_store/lower.rs | 12 +++++------- crates/hir-def/src/expr_store/pretty.rs | 18 ++++++------------ crates/hir-def/src/hir.rs | 10 ++-------- crates/hir-ty/src/diagnostics/expr.rs | 13 +++++-------- crates/hir-ty/src/infer/closure.rs | 4 ++-- crates/hir-ty/src/infer/expr.rs | 4 ++-- crates/hir-ty/src/infer/mutability.rs | 12 ++++-------- crates/hir-ty/src/mir/lower.rs | 8 ++++---- crates/hir/src/source_analyzer.rs | 2 +- 10 files changed, 34 insertions(+), 55 deletions(-) diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs index d0695d0eac76..9df6eaade757 100644 --- a/crates/hir-def/src/expr_store.rs +++ b/crates/hir-def/src/expr_store.rs @@ -25,7 +25,7 @@ use crate::{ db::DefDatabase, hir::{ Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label, LabelId, Pat, - PatId, RecordFieldPat, Spread, Statement, + PatId, RecordFieldPat, Statement, }, nameres::DefMap, path::{ModPath, Path}, @@ -362,7 +362,7 @@ impl ExpressionStore { for field in fields.iter() { f(field.expr); } - if let &Spread::Base(expr) = spread { + if let &Some(expr) = spread { f(expr); } } @@ -490,7 +490,7 @@ impl ExpressionStore { for field in fields.iter() { f(field.expr); } - if let &Spread::Base(expr) = spread { + if let &Some(expr) = spread { f(expr); } } diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index 811fecf91f49..2cabd0f9795d 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -45,7 +45,7 @@ use crate::{ }, Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind, Expr, ExprId, Item, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability, - OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Spread, Statement, + OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement, }, item_scope::BuiltinShadowMode, lang_item::LangItem, @@ -602,13 +602,11 @@ impl ExprCollector<'_> { Some(RecordLitField { name, expr }) }) .collect(); - let spread = nfl.spread().map(|s| self.collect_expr(s)).map_or_else( - || if nfl.dotdot_token().is_some() { Spread::Yes } else { Spread::No }, - Spread::Base, - ); - Expr::RecordLit { path, fields, spread } + let spread = nfl.spread().map(|s| self.collect_expr(s)); + let ellipsis = nfl.dotdot_token().is_some(); + Expr::RecordLit { path, fields, spread, ellipsis } } else { - Expr::RecordLit { path, fields: Box::default(), spread: Spread::No } + Expr::RecordLit { path, fields: Box::default(), spread: None, ellipsis: false } }; self.alloc_expr(record_lit, syntax_ptr) diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index 1b3a1bb4dc00..9a8a8c2cd057 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/crates/hir-def/src/expr_store/pretty.rs @@ -8,7 +8,7 @@ use span::Edition; use crate::{ hir::{ Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, LiteralOrConst, Movability, - Spread, Statement, + Statement, }, pretty::{print_generic_args, print_path, print_type_ref}, VariantId, @@ -398,7 +398,7 @@ impl Printer<'_> { self.print_expr(*expr); } } - Expr::RecordLit { path, fields, spread } => { + Expr::RecordLit { path, fields, spread, ellipsis: _ } => { match path { Some(path) => self.print_path(path), None => w!(self, "�"), @@ -412,16 +412,10 @@ impl Printer<'_> { p.print_expr(field.expr); wln!(p, ","); } - match spread { - Spread::No => {} - Spread::Yes => { - w!(p, ".."); - } - Spread::Base(expr) => { - w!(p, ".."); - p.print_expr(*expr); - wln!(p); - } + if let Some(spread) = spread { + w!(p, ".."); + p.print_expr(*spread); + wln!(p); } }); w!(self, "}}"); diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index e09ce67a897d..1e2417ecdf3a 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -251,7 +251,8 @@ pub enum Expr { RecordLit { path: Option>, fields: Box<[RecordLitField]>, - spread: Spread, + spread: Option, + ellipsis: bool, }, Field { expr: ExprId, @@ -478,13 +479,6 @@ pub struct RecordLitField { pub expr: ExprId, } -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Spread { - No, - Yes, - Base(ExprId), -} - #[derive(Debug, Clone, Eq, PartialEq)] pub enum Statement { Let { diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index dd55febbf042..d8700e277774 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -8,7 +8,6 @@ use base_db::CrateId; use chalk_solve::rust_ir::AdtKind; use either::Either; use hir_def::{ - hir::Spread, lang_item::LangItem, resolver::{HasResolver, ValueNs}, AdtId, AssocItemId, DefWithBodyId, HasModule, ItemContainerId, Lookup, @@ -547,11 +546,9 @@ pub fn record_literal_missing_fields( infer: &InferenceResult, id: ExprId, expr: &Expr, -) -> Option<(VariantId, Vec, /*has spread expr*/ bool)> { - let (fields, has_spread_expr, has_ellipsis) = match expr { - Expr::RecordLit { fields, spread, .. } => { - (fields, matches!(spread, Spread::Base(_)), matches!(spread, Spread::Yes)) - } +) -> Option<(VariantId, Vec, /*exhaustive*/ bool)> { + let (fields, exhaustive, ellipsis) = match expr { + Expr::RecordLit { fields, spread, ellipsis, .. } => (fields, spread.is_none(), *ellipsis), _ => return None, }; @@ -567,7 +564,7 @@ pub fn record_literal_missing_fields( .fields() .iter() .filter_map(|(f, d)| { - if (has_ellipsis && d.has_default) || specified_fields.contains(&d.name) { + if (ellipsis && d.has_default) || specified_fields.contains(&d.name) { None } else { Some(f) @@ -577,7 +574,7 @@ pub fn record_literal_missing_fields( if missed_fields.is_empty() { return None; } - Some((variant_def, missed_fields, has_spread_expr)) + Some((variant_def, missed_fields, exhaustive)) } pub fn record_pattern_missing_fields( diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 0e9aed416004..9283c46d0f61 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -12,7 +12,7 @@ use hir_def::{ data::adt::VariantData, hir::{ Array, AsmOperand, BinaryOp, BindingId, CaptureBy, Expr, ExprId, ExprOrPatId, Pat, PatId, - Spread, Statement, UnaryOp, + Statement, UnaryOp, }, lang_item::LangItem, path::Path, @@ -796,7 +796,7 @@ impl InferenceContext<'_> { self.consume_expr(expr); } Expr::RecordLit { fields, spread, .. } => { - if let &Spread::Base(expr) = spread { + if let &Some(expr) = spread { self.consume_expr(expr); } self.consume_exprs(fields.iter().map(|it| it.expr)); diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 8b3ec1ff2ad0..b951443897cb 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -10,7 +10,7 @@ use either::Either; use hir_def::{ hir::{ ArithOp, Array, AsmOperand, AsmOptions, BinaryOp, ClosureKind, Expr, ExprId, ExprOrPatId, - LabelId, Literal, Pat, PatId, Spread, Statement, UnaryOp, + LabelId, Literal, Pat, PatId, Statement, UnaryOp, }, lang_item::{LangItem, LangItemTarget}, path::{GenericArg, GenericArgs, Path}, @@ -775,7 +775,7 @@ impl InferenceContext<'_> { } } } - if let Spread::Base(expr) = spread { + if let Some(expr) = spread { self.infer_expr(*expr, &Expectation::has_type(ty.clone()), ExprIsRead::Yes); } ty diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs index e95a42549837..5b6c3cd15244 100644 --- a/crates/hir-ty/src/infer/mutability.rs +++ b/crates/hir-ty/src/infer/mutability.rs @@ -4,8 +4,8 @@ use chalk_ir::{cast::Cast, Mutability}; use hir_def::{ hir::{ - Array, AsmOperand, BinaryOp, BindingAnnotation, Expr, ExprId, Pat, PatId, Spread, - Statement, UnaryOp, + Array, AsmOperand, BinaryOp, BindingAnnotation, Expr, ExprId, Pat, PatId, Statement, + UnaryOp, }, lang_item::LangItem, }; @@ -121,12 +121,8 @@ impl InferenceContext<'_> { Expr::Become { expr } => { self.infer_mut_expr(*expr, Mutability::Not); } - Expr::RecordLit { path: _, fields, spread } => { - let spread_expr = match spread { - Spread::Base(expr) => Some(*expr), - _ => None, - }; - self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(spread_expr)) + Expr::RecordLit { path: _, fields, spread, ellipsis: _ } => { + self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread)) } &Expr::Index { base, index } => { if mutability == Mutability::Mut { diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 5d89ebd4ef40..85e8d1720310 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -9,7 +9,7 @@ use hir_def::{ expr_store::{Body, HygieneId}, hir::{ ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal, - LiteralOrConst, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField, Spread, + LiteralOrConst, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField, }, lang_item::{LangItem, LangItemTarget}, path::Path, @@ -823,16 +823,16 @@ impl<'ctx> MirLowerCtx<'ctx> { } Expr::Become { .. } => not_supported!("tail-calls"), Expr::Yield { .. } => not_supported!("yield"), - Expr::RecordLit { fields, path, spread } => { + Expr::RecordLit { fields, path, spread, ellipsis: _ } => { let spread_place = match spread { - &Spread::Base(it) => { + &Some(it) => { let Some((p, c)) = self.lower_expr_as_place(current, it, true)? else { return Ok(None); }; current = c; Some(p) } - _ => None, + None => None, }; let variant_id = self.infer.variant_resolution_for_expr(expr_id).ok_or_else(|| match path { diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 98c30540b497..ca239826d4fc 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -1023,7 +1023,7 @@ impl SourceAnalyzer { let expr_id = self.expr_id(db, &literal.clone().into())?; let substs = infer[expr_id].as_adt()?.1; - let (variant, missing_fields, _) = match expr_id { + let (variant, missing_fields, _exhaustive) = match expr_id { ExprOrPatId::ExprId(expr_id) => { record_literal_missing_fields(db, infer, expr_id, &body[expr_id])? } From 35f612305901f70a2fe177800c6b3d786b1d742d Mon Sep 17 00:00:00 2001 From: David Barsky Date: Mon, 27 Jan 2025 17:20:11 -0500 Subject: [PATCH 7/9] Back out "Handle missing fields diagnostics" This backs out commit e6a103ae50699db1dbb0676d075a4bcda2247939. --- crates/hir-def/src/data/adt.rs | 2 -- crates/hir-def/src/expr_store/lower.rs | 5 ++- crates/hir-def/src/expr_store/pretty.rs | 2 +- crates/hir-def/src/hir.rs | 1 - crates/hir-def/src/item_tree.rs | 1 - crates/hir-def/src/item_tree/lower.rs | 5 ++- crates/hir-def/src/item_tree/pretty.rs | 8 ++--- crates/hir-ty/src/diagnostics/expr.rs | 12 ++----- crates/hir-ty/src/infer/mutability.rs | 2 +- crates/hir-ty/src/mir/lower.rs | 2 +- .../src/handlers/missing_fields.rs | 31 ------------------- 11 files changed, 12 insertions(+), 59 deletions(-) diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index aaa260a358b6..8fc19854033c 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -85,7 +85,6 @@ pub struct FieldData { pub name: Name, pub type_ref: TypeRefId, pub visibility: RawVisibility, - pub has_default: bool, } fn repr_from_value( @@ -479,6 +478,5 @@ fn lower_field( name: field.name.clone(), type_ref: field.type_ref, visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), - has_default: field.has_default, } } diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index 2cabd0f9795d..35cd8f3c69f7 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -603,10 +603,9 @@ impl ExprCollector<'_> { }) .collect(); let spread = nfl.spread().map(|s| self.collect_expr(s)); - let ellipsis = nfl.dotdot_token().is_some(); - Expr::RecordLit { path, fields, spread, ellipsis } + Expr::RecordLit { path, fields, spread } } else { - Expr::RecordLit { path, fields: Box::default(), spread: None, ellipsis: false } + Expr::RecordLit { path, fields: Box::default(), spread: None } }; self.alloc_expr(record_lit, syntax_ptr) diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index 9a8a8c2cd057..6ba0bbd61c48 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/crates/hir-def/src/expr_store/pretty.rs @@ -398,7 +398,7 @@ impl Printer<'_> { self.print_expr(*expr); } } - Expr::RecordLit { path, fields, spread, ellipsis: _ } => { + Expr::RecordLit { path, fields, spread } => { match path { Some(path) => self.print_path(path), None => w!(self, "�"), diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index 1e2417ecdf3a..0dcddf162b2f 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -252,7 +252,6 @@ pub enum Expr { path: Option>, fields: Box<[RecordLitField]>, spread: Option, - ellipsis: bool, }, Field { expr: ExprId, diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 82e6ff821b76..8d5b3eeb28e1 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -1007,7 +1007,6 @@ pub struct Field { pub name: Name, pub type_ref: TypeRefId, pub visibility: RawVisibilityId, - pub has_default: bool, } #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 69a1933079ce..71848845a84d 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -319,9 +319,8 @@ impl<'a> Ctx<'a> { }; let visibility = self.lower_visibility(field); let type_ref = TypeRef::from_ast_opt(body_ctx, field.ty()); - let has_default = field.expr().is_some(); - Field { name, type_ref, visibility, has_default } + Field { name, type_ref, visibility } } fn lower_tuple_field( @@ -333,7 +332,7 @@ impl<'a> Ctx<'a> { let name = Name::new_tuple_field(idx); let visibility = self.lower_visibility(field); let type_ref = TypeRef::from_ast_opt(body_ctx, field.ty()); - Field { name, type_ref, visibility, has_default: false } + Field { name, type_ref, visibility } } fn lower_union(&mut self, union: &ast::Union) -> Option> { diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index 1e765ac78eb1..70bf2f13c88a 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -135,9 +135,7 @@ impl Printer<'_> { self.whitespace(); w!(self, "{{"); self.indented(|this| { - for (idx, Field { name, type_ref, visibility, has_default: _ }) in - fields.iter().enumerate() - { + for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() { this.print_attrs_of( AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))), "\n", @@ -153,9 +151,7 @@ impl Printer<'_> { FieldsShape::Tuple => { w!(self, "("); self.indented(|this| { - for (idx, Field { name, type_ref, visibility, has_default: _ }) in - fields.iter().enumerate() - { + for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() { this.print_attrs_of( AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))), "\n", diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index d8700e277774..0b5f1319243f 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -547,8 +547,8 @@ pub fn record_literal_missing_fields( id: ExprId, expr: &Expr, ) -> Option<(VariantId, Vec, /*exhaustive*/ bool)> { - let (fields, exhaustive, ellipsis) = match expr { - Expr::RecordLit { fields, spread, ellipsis, .. } => (fields, spread.is_none(), *ellipsis), + let (fields, exhaustive) = match expr { + Expr::RecordLit { fields, spread, .. } => (fields, spread.is_none()), _ => return None, }; @@ -563,13 +563,7 @@ pub fn record_literal_missing_fields( let missed_fields: Vec = variant_data .fields() .iter() - .filter_map(|(f, d)| { - if (ellipsis && d.has_default) || specified_fields.contains(&d.name) { - None - } else { - Some(f) - } - }) + .filter_map(|(f, d)| if specified_fields.contains(&d.name) { None } else { Some(f) }) .collect(); if missed_fields.is_empty() { return None; diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs index 5b6c3cd15244..d74a383f44ef 100644 --- a/crates/hir-ty/src/infer/mutability.rs +++ b/crates/hir-ty/src/infer/mutability.rs @@ -121,7 +121,7 @@ impl InferenceContext<'_> { Expr::Become { expr } => { self.infer_mut_expr(*expr, Mutability::Not); } - Expr::RecordLit { path: _, fields, spread, ellipsis: _ } => { + Expr::RecordLit { path: _, fields, spread } => { self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread)) } &Expr::Index { base, index } => { diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 85e8d1720310..23072011a7b3 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -823,7 +823,7 @@ impl<'ctx> MirLowerCtx<'ctx> { } Expr::Become { .. } => not_supported!("tail-calls"), Expr::Yield { .. } => not_supported!("yield"), - Expr::RecordLit { fields, path, spread, ellipsis: _ } => { + Expr::RecordLit { fields, path, spread } => { let spread_place = match spread { &Some(it) => { let Some((p, c)) = self.lower_expr_as_place(current, it, true)? else { diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs index c495df9daaaf..938b7182bc94 100644 --- a/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -846,35 +846,4 @@ pub struct Claims { "#, ); } - - #[test] - fn default_field_values() { - check_diagnostics( - r#" -struct F { - field1: i32 = 4, - field2: bool, -} - -fn f() { - let _f = F { - field2: true, - .. - }; - - let _f = F { - //^ 💡 error: missing structure fields: - //| - field1 - field2: true, - }; - - let _f = F { - //^ 💡 error: missing structure fields: - //| - field2 - .. - }; -} -"#, - ); - } } From be3307450f0309511be236b00f5e2c81e5842109 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Mon, 27 Jan 2025 17:20:11 -0500 Subject: [PATCH 8/9] Back out "feat: Implement `default-field-values`" This backs out commit 7de0b2e75a541b98f735ee6fcd12d326be38d23f. --- crates/hir-def/src/expr_store/body.rs | 3 - crates/hir-def/src/expr_store/lower.rs | 2 - crates/hir-def/src/expr_store/pretty.rs | 27 ------ crates/hir-def/src/lib.rs | 59 +------------ .../builtin_derive_macro.rs | 42 --------- crates/hir-def/src/resolver.rs | 10 --- crates/hir-expand/src/builtin/derive_macro.rs | 86 ++----------------- crates/hir-ty/src/diagnostics/unsafe_check.rs | 3 +- crates/hir-ty/src/infer.rs | 16 ---- crates/hir-ty/src/mir/lower.rs | 4 - crates/hir-ty/src/mir/pretty.rs | 34 +------- crates/hir-ty/src/tests.rs | 2 - crates/hir/src/from_id.rs | 2 - crates/hir/src/lib.rs | 64 +------------- crates/ide-db/src/defs.rs | 1 - crates/ide-db/src/search.rs | 6 -- .../src/handlers/type_mismatch.rs | 15 ---- crates/parser/src/grammar/expressions.rs | 18 +--- crates/parser/src/grammar/items/adt.rs | 5 -- crates/parser/test_data/generated/runner.rs | 12 --- .../comma_after_default_values_syntax.rast | 59 ------------- .../err/comma_after_default_values_syntax.rs | 4 - ...cord_literal_before_ellipsis_recovery.rast | 70 +++------------ ...record_literal_before_ellipsis_recovery.rs | 2 - .../ok/record_field_default_values.rast | 28 ------ .../inline/ok/record_field_default_values.rs | 1 - .../parser/inline/ok/record_lit.rast | 47 ---------- .../test_data/parser/inline/ok/record_lit.rs | 2 - .../ok/struct_initializer_with_defaults.rast | 39 --------- .../ok/struct_initializer_with_defaults.rs | 3 - .../rust-analyzer/src/cli/analysis_stats.rs | 6 -- crates/syntax/rust.ungram | 2 +- crates/syntax/src/ast/generated/nodes.rs | 4 - 33 files changed, 31 insertions(+), 647 deletions(-) delete mode 100644 crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast delete mode 100644 crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rs delete mode 100644 crates/parser/test_data/parser/inline/ok/record_field_default_values.rast delete mode 100644 crates/parser/test_data/parser/inline/ok/record_field_default_values.rs delete mode 100644 crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rast delete mode 100644 crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rs diff --git a/crates/hir-def/src/expr_store/body.rs b/crates/hir-def/src/expr_store/body.rs index 3177b2c74afe..a55fec4f8b1e 100644 --- a/crates/hir-def/src/expr_store/body.rs +++ b/crates/hir-def/src/expr_store/body.rs @@ -122,9 +122,6 @@ impl Body { src.map(|it| it.expr()) } DefWithBodyId::InTypeConstId(c) => c.lookup(db).id.map(|_| c.source(db).expr()), - DefWithBodyId::FieldId(f) => { - f.record_field_source(db).map(|it| it.and_then(|it| it.expr())) - } } }; let module = def.module(db); diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index 35cd8f3c69f7..88f770da02a4 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -90,7 +90,6 @@ pub(super) fn lower_body( DefWithBodyId::ConstId(it) => db.attrs(it.into()), DefWithBodyId::InTypeConstId(_) => Attrs::EMPTY, DefWithBodyId::VariantId(it) => db.attrs(it.into()), - DefWithBodyId::FieldId(it) => db.attrs(it.into()), } .rust_analyzer_tool() .any(|attr| *attr.path() == tool_path![skip]); @@ -169,7 +168,6 @@ pub(super) fn lower_body( Awaitable::No("constant") } DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"), - DefWithBodyId::FieldId(..) => Awaitable::No("field"), } }, ); diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index 6ba0bbd61c48..6a0b1e519790 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/crates/hir-def/src/expr_store/pretty.rs @@ -11,7 +11,6 @@ use crate::{ Statement, }, pretty::{print_generic_args, print_path, print_type_ref}, - VariantId, }; use super::*; @@ -57,32 +56,6 @@ pub(super) fn print_body_hir( loc.id.item_tree(db)[loc.id.value].name.display(db.upcast(), edition), ) } - DefWithBodyId::FieldId(it) => { - let parent_name: String = match it.parent { - VariantId::EnumVariantId(it) => { - let loc = it.lookup(db); - let enum_loc = loc.parent.lookup(db); - format!( - "{}::{}", - enum_loc.id.item_tree(db)[enum_loc.id.value] - .name - .display(db.upcast(), edition), - loc.id.item_tree(db)[loc.id.value].name.display(db.upcast(), edition), - ) - } - VariantId::StructId(it) => it - .lookup(db) - .id - .resolved(db, |it| it.name.display(db.upcast(), edition).to_string()), - VariantId::UnionId(it) => it - .lookup(db) - .id - .resolved(db, |it| it.name.display(db.upcast(), edition).to_string()), - }; - let variant_data = it.parent.variant_data(db); - let field_name = &variant_data.fields()[it.local_id].name; - format!("field {}.{}", parent_name, field_name.display(db.upcast(), edition),) - } }; let mut p = Printer { diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 95700b54db23..c8efd9043203 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -55,7 +55,6 @@ pub mod visibility; use intern::Interned; pub use rustc_abi as layout; -use src::HasSource; use triomphe::Arc; #[cfg(test)] @@ -78,7 +77,6 @@ use hir_expand::{ builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander}, db::ExpandDatabase, eager::expand_eager_macro_input, - files::InFileWrapper, impl_intern_lookup, name::Name, proc_macro::{CustomProcMacroExpander, ProcMacroKind}, @@ -521,41 +519,6 @@ pub struct FieldId { pub local_id: LocalFieldId, } -impl FieldId { - pub fn record_field_source( - &self, - db: &dyn DefDatabase, - ) -> InFileWrapper> { - let field_list = match self.parent { - crate::VariantId::EnumVariantId(it) => { - let s = it.lookup(db); - s.source(db).map(|it| { - it.field_list().and_then(|it| match it { - ast::FieldList::RecordFieldList(it) => Some(it), - _ => None, - }) - }) - } - crate::VariantId::StructId(it) => { - let s = it.lookup(db); - s.source(db).map(|it| { - it.field_list().and_then(|it| match it { - ast::FieldList::RecordFieldList(it) => Some(it), - _ => None, - }) - }) - } - crate::VariantId::UnionId(it) => { - let s = it.lookup(db); - s.source(db).map(|it| it.record_field_list()) - } - }; - field_list.map(|it| { - it.and_then(|it| it.fields().nth(self.local_id.into_raw().into_u32() as usize)) - }) - } -} - pub type LocalFieldId = Idx; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -723,7 +686,6 @@ pub enum TypeOwnerId { TypeAliasId(TypeAliasId), ImplId(ImplId), EnumVariantId(EnumVariantId), - FieldId(FieldId), } impl TypeOwnerId { @@ -741,11 +703,6 @@ impl TypeOwnerId { GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent)) } TypeOwnerId::InTypeConstId(_) => return None, - TypeOwnerId::FieldId(it) => GenericDefId::AdtId(match it.parent { - VariantId::EnumVariantId(it) => AdtId::EnumId(it.lookup(db).parent), - VariantId::StructId(it) => it.into(), - VariantId::UnionId(it) => it.into(), - }), }) } } @@ -760,8 +717,7 @@ impl_from!( TraitAliasId, TypeAliasId, ImplId, - EnumVariantId, - FieldId + EnumVariantId for TypeOwnerId ); @@ -774,7 +730,6 @@ impl From for TypeOwnerId { DefWithBodyId::ConstId(it) => it.into(), DefWithBodyId::InTypeConstId(it) => it.into(), DefWithBodyId::VariantId(it) => it.into(), - DefWithBodyId::FieldId(it) => it.into(), } } } @@ -930,7 +885,6 @@ pub enum DefWithBodyId { ConstId(ConstId), InTypeConstId(InTypeConstId), VariantId(EnumVariantId), - FieldId(FieldId), } impl_from!(FunctionId, ConstId, StaticId, InTypeConstId for DefWithBodyId); @@ -951,7 +905,6 @@ impl DefWithBodyId { // FIXME: stable rust doesn't allow generics in constants, but we should // use `TypeOwnerId::as_generic_def_id` when it does. DefWithBodyId::InTypeConstId(_) => None, - DefWithBodyId::FieldId(_) => None, } } } @@ -1379,11 +1332,6 @@ impl HasModule for TypeOwnerId { TypeOwnerId::ImplId(it) => it.module(db), TypeOwnerId::EnumVariantId(it) => it.module(db), TypeOwnerId::InTypeConstId(it) => it.lookup(db).owner.module(db), - TypeOwnerId::FieldId(it) => match it.parent { - VariantId::EnumVariantId(it) => it.module(db), - VariantId::StructId(it) => it.module(db), - VariantId::UnionId(it) => it.module(db), - }, } } } @@ -1396,11 +1344,6 @@ impl HasModule for DefWithBodyId { DefWithBodyId::ConstId(it) => it.module(db), DefWithBodyId::VariantId(it) => it.module(db), DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db), - DefWithBodyId::FieldId(it) => match it.parent { - VariantId::EnumVariantId(it) => it.module(db), - VariantId::StructId(it) => it.module(db), - VariantId::UnionId(it) => it.module(db), - }, } } } diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs index 25391c910eaf..c31d32213289 100644 --- a/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs +++ b/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs @@ -211,20 +211,6 @@ enum Bar { #[default] Bar, } -#[derive(Default)] -struct Baz { - field1: i32 = 2, - field2: bool = { false }, -} -#[derive(Default)] -enum Qux { - #[default] - Foo { - field1: i32, - field2: bool = true, - field3: (), - } -} "#, expect![[r#" #[derive(Default)] @@ -238,20 +224,6 @@ enum Bar { #[default] Bar, } -#[derive(Default)] -struct Baz { - field1: i32 = 2, - field2: bool = { false }, -} -#[derive(Default)] -enum Qux { - #[default] - Foo { - field1: i32, - field2: bool = true, - field3: (), - } -} impl <> $crate::default::Default for Foo< > where { fn default() -> Self { @@ -264,20 +236,6 @@ impl <> $crate::default::Default for Bar< > where { fn default() -> Self { Bar::Bar } -} -impl <> $crate::default::Default for Baz< > where { - fn default() -> Self { - Baz { - .. - } - } -} -impl <> $crate::default::Default for Qux< > where { - fn default() -> Self { - Qux::Foo { - field1: $crate::default::Default::default(), field3: $crate::default::Default::default(), .. - } - } }"#]], ); } diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 52998942965d..7e13ae2f7a1b 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -1227,11 +1227,6 @@ impl HasResolver for TypeOwnerId { TypeOwnerId::TypeAliasId(it) => it.resolver(db), TypeOwnerId::ImplId(it) => it.resolver(db), TypeOwnerId::EnumVariantId(it) => it.resolver(db), - TypeOwnerId::FieldId(it) => match it.parent { - VariantId::EnumVariantId(it) => it.resolver(db), - VariantId::StructId(it) => it.resolver(db), - VariantId::UnionId(it) => it.resolver(db), - }, } } } @@ -1244,11 +1239,6 @@ impl HasResolver for DefWithBodyId { DefWithBodyId::StaticId(s) => s.resolver(db), DefWithBodyId::VariantId(v) => v.resolver(db), DefWithBodyId::InTypeConstId(c) => c.lookup(db).owner.resolver(db), - DefWithBodyId::FieldId(f) => match f.parent { - VariantId::EnumVariantId(it) => it.resolver(db), - VariantId::StructId(it) => it.resolver(db), - VariantId::UnionId(it) => it.resolver(db), - }, } } } diff --git a/crates/hir-expand/src/builtin/derive_macro.rs b/crates/hir-expand/src/builtin/derive_macro.rs index f8fb700d55e7..28b681213944 100644 --- a/crates/hir-expand/src/builtin/derive_macro.rs +++ b/crates/hir-expand/src/builtin/derive_macro.rs @@ -80,15 +80,9 @@ pub fn find_builtin_derive(ident: &name::Name) -> Option BuiltinDeriveExpander::find_by_name(ident) } -#[derive(Clone, Copy)] -enum HasDefault { - Yes, - No, -} - #[derive(Clone)] enum VariantShape { - Struct(Vec<(tt::Ident, HasDefault)>), + Struct(Vec), Tuple(usize), Unit, } @@ -104,7 +98,7 @@ impl VariantShape { fn field_names(&self, span: Span) -> Vec { match self { - VariantShape::Struct(s) => s.iter().map(|(ident, _)| ident.clone()).collect(), + VariantShape::Struct(s) => s.clone(), VariantShape::Tuple(n) => tuple_field_iterator(span, *n).collect(), VariantShape::Unit => vec![], } @@ -118,7 +112,7 @@ impl VariantShape { ) -> tt::TopSubtree { match self { VariantShape::Struct(fields) => { - let fields = fields.iter().map(|(it, _)| { + let fields = fields.iter().map(|it| { let mapped = field_map(it); quote! {span => #it : #mapped , } }); @@ -141,63 +135,6 @@ impl VariantShape { } } - fn default_expand( - &self, - path: tt::TopSubtree, - span: Span, - field_map: impl Fn(&tt::Ident) -> tt::TopSubtree, - ) -> tt::TopSubtree { - match self { - VariantShape::Struct(fields) => { - let contains_default = fields.iter().any(|it| matches!(it.1, HasDefault::Yes)); - let fields = fields - .iter() - .filter_map(|(it, has_default)| match has_default { - HasDefault::Yes => None, - HasDefault::No => Some(it), - }) - .map(|it| { - let mapped = field_map(it); - quote! {span => #it : #mapped , } - }); - if contains_default { - let mut double_dots = - tt::TopSubtreeBuilder::new(tt::Delimiter::invisible_spanned(span)); - double_dots.push(tt::Leaf::Punct(tt::Punct { - char: '.', - spacing: tt::Spacing::Joint, - span, - })); - double_dots.push(tt::Leaf::Punct(tt::Punct { - char: '.', - spacing: tt::Spacing::Alone, - span, - })); - let double_dots = double_dots.build(); - quote! {span => - #path { ##fields #double_dots } - } - } else { - quote! {span => - #path { ##fields } - } - } - } - &VariantShape::Tuple(n) => { - let fields = tuple_field_iterator(span, n).map(|it| { - let mapped = field_map(&it); - quote! {span => - #mapped , - } - }); - quote! {span => - #path ( ##fields ) - } - } - VariantShape::Unit => path, - } - } - fn from( call_site: Span, tm: &ExpansionSpanMap, @@ -207,15 +144,8 @@ impl VariantShape { None => VariantShape::Unit, Some(FieldList::RecordFieldList(it)) => VariantShape::Struct( it.fields() - .map(|it| { - ( - it.name(), - if it.expr().is_some() { HasDefault::Yes } else { HasDefault::No }, - ) - }) - .map(|(it, has_default)| { - name_to_token(call_site, tm, it).map(|ident| (ident, has_default)) - }) + .map(|it| it.name()) + .map(|it| name_to_token(call_site, tm, it)) .collect::>()?, ), Some(FieldList::TupleFieldList(it)) => VariantShape::Tuple(it.fields().count()), @@ -671,7 +601,7 @@ fn default_expand( let body = match &adt.shape { AdtShape::Struct(fields) => { let name = &adt.name; - fields.default_expand( + fields.as_pattern_map( quote!(span =>#name), span, |_| quote!(span =>#krate::default::Default::default()), @@ -681,7 +611,7 @@ fn default_expand( if let Some(d) = default_variant { let (name, fields) = &variants[*d]; let adt_name = &adt.name; - fields.default_expand( + fields.as_pattern_map( quote!(span =>#adt_name :: #name), span, |_| quote!(span =>#krate::default::Default::default()), @@ -713,7 +643,7 @@ fn debug_expand( expand_simple_derive(db, span, tt, quote! {span => #krate::fmt::Debug }, |adt| { let for_variant = |name: String, v: &VariantShape| match v { VariantShape::Struct(fields) => { - let for_fields = fields.iter().map(|(it, _)| { + let for_fields = fields.iter().map(|it| { let x_string = it.to_string(); quote! {span => .field(#x_string, & #it) diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs index 2aca99c93bad..ac849b0762d7 100644 --- a/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -35,8 +35,7 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> MissingUnsafe DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) | DefWithBodyId::VariantId(_) - | DefWithBodyId::InTypeConstId(_) - | DefWithBodyId::FieldId(_) => false, + | DefWithBodyId::InTypeConstId(_) => false, }; let mut res = MissingUnsafeResult { fn_is_unsafe: is_unsafe, ..MissingUnsafeResult::default() }; diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 1b2ef2aef3ff..3c258e3c4cf4 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -134,9 +134,6 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc { - ctx.collect_field(f); - } } ctx.infer_body(); @@ -913,19 +910,6 @@ impl<'a> InferenceContext<'a> { self.return_ty = return_ty; } - fn collect_field(&mut self, field: FieldId) { - let variant_data = field.parent.variant_data(self.db.upcast()); - let field_data = &variant_data.fields()[field.local_id]; - let types_map = variant_data.types_map(); - let return_ty = - self.make_ty(field_data.type_ref, types_map, InferenceTyDiagnosticSource::Signature); - - // Field default value exprs might be defining usage sites of TAITs. - self.make_tait_coercion_table(iter::once(&return_ty)); - - self.return_ty = return_ty; - } - fn collect_fn(&mut self, func: FunctionId) { let data = self.db.function_data(func); let mut param_tys = diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 23072011a7b3..cc6ed122af4b 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -2130,10 +2130,6 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result format!("in type const {it:?}"), - DefWithBodyId::FieldId(it) => it.parent.variant_data(db.upcast()).fields()[it.local_id] - .name - .display(db.upcast(), edition) - .to_string(), }; let _p = tracing::info_span!("mir_body_query", ?detail).entered(); let body = db.body(def); diff --git a/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs index 193b7bcd97c2..2a26101ac439 100644 --- a/crates/hir-ty/src/mir/pretty.rs +++ b/crates/hir-ty/src/mir/pretty.rs @@ -6,7 +6,7 @@ use std::{ }; use either::Either; -use hir_def::{expr_store::Body, hir::BindingId, VariantId}; +use hir_def::{expr_store::Body, hir::BindingId}; use hir_expand::{name::Name, Lookup}; use la_arena::ArenaMap; use span::Edition; @@ -79,38 +79,6 @@ impl MirBody { hir_def::DefWithBodyId::InTypeConstId(id) => { w!(this, "in type const {id:?} = "); } - hir_def::DefWithBodyId::FieldId(id) => { - w!(this, "field "); - match id.parent { - VariantId::EnumVariantId(it) => { - let loc = it.lookup(db.upcast()); - let enum_loc = loc.parent.lookup(db.upcast()); - w!( - this, - "{}::{}", - enum_loc.id.item_tree(db.upcast())[enum_loc.id.value] - .name - .display(db.upcast(), Edition::LATEST), - loc.id.item_tree(db.upcast())[loc.id.value] - .name - .display(db.upcast(), Edition::LATEST), - ); - } - VariantId::StructId(id) => { - id.lookup(db.upcast()).id.resolved(db.upcast(), |it| { - w!(this, "{}", it.name.display(db.upcast(), Edition::LATEST)); - }); - } - VariantId::UnionId(id) => { - id.lookup(db.upcast()).id.resolved(db.upcast(), |it| { - w!(this, "{}", it.name.display(db.upcast(), Edition::LATEST)); - }); - } - }; - let variant_data = id.parent.variant_data(db.upcast()); - let field_name = &variant_data.fields()[id.local_id].name; - w!(this, ".{}: _ = ", field_name.display(db.upcast(), Edition::LATEST)); - } }); ctx.result } diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index a5af712b42f2..69ec35f406df 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -160,7 +160,6 @@ fn check_impl( loc.source(&db).value.syntax().text_range().start() } DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(), - DefWithBodyId::FieldId(_) => unreachable!(), }); let mut unexpected_type_mismatches = String::new(); for def in defs { @@ -416,7 +415,6 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { loc.source(&db).value.syntax().text_range().start() } DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(), - DefWithBodyId::FieldId(_) => unreachable!(), }); for def in defs { let (body, source_map) = db.body_with_source_map(def); diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index dd26e894d793..537401afdc34 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs @@ -147,7 +147,6 @@ impl From for DefWithBodyId { DefWithBody::Const(it) => DefWithBodyId::ConstId(it.id), DefWithBody::Variant(it) => DefWithBodyId::VariantId(it.into()), DefWithBody::InTypeConst(it) => DefWithBodyId::InTypeConstId(it.id), - DefWithBody::Field(it) => DefWithBodyId::FieldId(it.into()), } } } @@ -160,7 +159,6 @@ impl From for DefWithBody { DefWithBodyId::ConstId(it) => DefWithBody::Const(it.into()), DefWithBodyId::VariantId(it) => DefWithBody::Variant(it.into()), DefWithBodyId::InTypeConstId(it) => DefWithBody::InTypeConst(it.into()), - DefWithBodyId::FieldId(it) => DefWithBody::Field(it.into()), } } } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index ff9832d31019..56090bc6b605 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -415,19 +415,6 @@ impl ModuleDef { def.diagnostics(db, &mut acc); } - let fields = match self { - ModuleDef::Adt(Adt::Struct(it)) => Some(it.fields(db)), - ModuleDef::Adt(Adt::Union(it)) => Some(it.fields(db)), - ModuleDef::Variant(it) => Some(it.fields(db)), - _ => None, - }; - if let Some(fields) = fields { - for field in fields { - let def: DefWithBody = field.into(); - def.diagnostics(db, &mut acc, style_lints); - } - } - acc } @@ -1239,12 +1226,6 @@ impl HasVisibility for Module { } } -impl From<&Field> for DefWithBodyId { - fn from(&f: &Field) -> Self { - DefWithBodyId::FieldId(f.into()) - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Field { pub(crate) parent: VariantDef, @@ -1310,10 +1291,6 @@ impl AstNode for FieldSource { } impl Field { - pub fn module(self, db: &dyn HirDatabase) -> Module { - self.parent.module(db) - } - pub fn name(&self, db: &dyn HirDatabase) -> Name { self.parent.variant_data(db).fields()[self.id].name.clone() } @@ -1376,14 +1353,6 @@ impl Field { pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef { self.parent } - - pub fn default_value_source( - &self, - db: &dyn HirDatabase, - ) -> Option> { - let id: hir_def::FieldId = (*self).into(); - id.record_field_source(db.upcast()).map(|it| it.and_then(|it| it.expr())).transpose() - } } impl HasVisibility for Field { @@ -1820,9 +1789,8 @@ pub enum DefWithBody { Const(Const), Variant(Variant), InTypeConst(InTypeConst), - Field(Field), } -impl_from!(Function, Const, Static, Variant, InTypeConst, Field for DefWithBody); +impl_from!(Function, Const, Static, Variant, InTypeConst for DefWithBody); impl DefWithBody { pub fn module(self, db: &dyn HirDatabase) -> Module { @@ -1832,7 +1800,6 @@ impl DefWithBody { DefWithBody::Static(s) => s.module(db), DefWithBody::Variant(v) => v.module(db), DefWithBody::InTypeConst(c) => c.module(db), - DefWithBody::Field(f) => f.module(db), } } @@ -1843,7 +1810,6 @@ impl DefWithBody { DefWithBody::Const(c) => c.name(db), DefWithBody::Variant(v) => Some(v.name(db)), DefWithBody::InTypeConst(_) => None, - DefWithBody::Field(f) => Some(f.name(db)), } } @@ -1859,7 +1825,6 @@ impl DefWithBody { &DefWithBodyId::from(it.id).resolver(db.upcast()), TyKind::Error.intern(Interner), ), - DefWithBody::Field(it) => it.ty(db), } } @@ -1870,7 +1835,6 @@ impl DefWithBody { DefWithBody::Const(it) => it.id.into(), DefWithBody::Variant(it) => it.into(), DefWithBody::InTypeConst(it) => it.id.into(), - DefWithBody::Field(it) => it.into(), } } @@ -1916,23 +1880,6 @@ impl DefWithBody { item_tree_source_maps.konst(konst.value) } DefWithBody::Variant(_) | DefWithBody::InTypeConst(_) => &TypesSourceMap::EMPTY, - DefWithBody::Field(field) => match field.parent { - VariantDef::Struct(strukt) => { - let strukt = strukt.id.lookup(db.upcast()).id; - item_tree_source_maps = strukt.item_tree_with_source_map(db.upcast()).1; - item_tree_source_maps.strukt(strukt.value).item() - } - VariantDef::Union(union) => { - let union = union.id.lookup(db.upcast()).id; - item_tree_source_maps = union.item_tree_with_source_map(db.upcast()).1; - item_tree_source_maps.union(union.value).item() - } - VariantDef::Variant(variant) => { - let variant = variant.id.lookup(db.upcast()).id; - item_tree_source_maps = variant.item_tree_with_source_map(db.upcast()).1; - item_tree_source_maps.variant(variant.value) - } - }, }; for (_, def_map) in body.blocks(db.upcast()) { @@ -2188,8 +2135,8 @@ impl DefWithBody { DefWithBody::Static(it) => it.into(), DefWithBody::Const(it) => it.into(), DefWithBody::Variant(it) => it.into(), - // FIXME: don't ignore diagnostics for in type const and default field value exprs - DefWithBody::InTypeConst(_) | DefWithBody::Field(_) => return, + // FIXME: don't ignore diagnostics for in type const + DefWithBody::InTypeConst(_) => return, }; for diag in hir_ty::diagnostics::incorrect_case(db, def.into()) { acc.push(diag.into()) @@ -3322,10 +3269,7 @@ impl AsAssocItem for DefWithBody { match self { DefWithBody::Function(it) => it.as_assoc_item(db), DefWithBody::Const(it) => it.as_assoc_item(db), - DefWithBody::Static(_) - | DefWithBody::Variant(_) - | DefWithBody::InTypeConst(_) - | DefWithBody::Field(_) => None, + DefWithBody::Static(_) | DefWithBody::Variant(_) | DefWithBody::InTypeConst(_) => None, } } } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 6925880ba996..bad536080567 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -972,7 +972,6 @@ impl TryFrom for Definition { DefWithBody::Const(it) => Ok(it.into()), DefWithBody::Variant(it) => Ok(it.into()), DefWithBody::InTypeConst(_) => Err(()), - DefWithBody::Field(it) => Ok(it.into()), } } } diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index d2a237a5c003..7963e8ae4f78 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -310,9 +310,6 @@ impl Definition { DefWithBody::Variant(v) => v.source(db).map(|src| src.syntax().cloned()), // FIXME: implement DefWithBody::InTypeConst(_) => return SearchScope::empty(), - DefWithBody::Field(f) => { - f.default_value_source(db).map(|src| src.syntax().cloned()) - } }; return match def { Some(def) => SearchScope::file_range( @@ -330,9 +327,6 @@ impl Definition { DefWithBody::Variant(v) => v.source(db).map(|src| src.syntax().cloned()), // FIXME: implement DefWithBody::InTypeConst(_) => return SearchScope::empty(), - DefWithBody::Field(f) => { - f.default_value_source(db).map(|src| src.syntax().cloned()) - } }; return match def { Some(def) => SearchScope::file_range( diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 4080b5f12e59..73dcbc13b79a 100644 --- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -1232,21 +1232,6 @@ fn f() { let (_, _, _, ..) = (true, 42); // ^^^^^^^^^^^^^ error: expected (bool, i32), found (bool, i32, {unknown}) } -"#, - ); - } - - #[test] - fn diagnostics_inside_field_default_expr() { - check_diagnostics( - r#" -struct Foo { - foo: i32 = { - let x = false; - x - // ^ error: expected i32, found bool - }, -} "#, ); } diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs index fe1316c9bfde..389c01933c99 100644 --- a/crates/parser/src/grammar/expressions.rs +++ b/crates/parser/src/grammar/expressions.rs @@ -678,8 +678,6 @@ fn path_expr(p: &mut Parser<'_>, r: Restrictions) -> (CompletedMarker, BlockLike // S { x }; // S { x, y: 32, }; // S { x, y: 32, ..Default::default() }; -// S { x, y: 32, .. }; -// S { .. }; // S { x: ::default() }; // TupleStruct { 0: 1 }; // } @@ -711,8 +709,6 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) { // fn main() { // S { field ..S::default() } // S { 0 ..S::default() } - // S { field .. } - // S { 0 .. } // } name_ref_or_index(p); p.error("expected `:`"); @@ -743,13 +739,7 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) { // S { .. } = S {}; // } - // test struct_initializer_with_defaults - // fn foo() { - // let _s = S { .. }; - // } - - // We permit `.. }` on the left-hand side of a destructuring assignment - // or defaults values. + // We permit `.. }` on the left-hand side of a destructuring assignment. if !p.at(T!['}']) { expr(p); @@ -760,12 +750,6 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) { // S { ..x, a: 0 } // } - // test_err comma_after_default_values_syntax - // fn foo() { - // S { .., }; - // S { .., a: 0 } - // } - // Do not bump, so we can support additional fields after this comma. p.error("cannot use a comma after the base struct"); } diff --git a/crates/parser/src/grammar/items/adt.rs b/crates/parser/src/grammar/items/adt.rs index 9a16c9db6daf..21078175c0ec 100644 --- a/crates/parser/src/grammar/items/adt.rs +++ b/crates/parser/src/grammar/items/adt.rs @@ -135,11 +135,6 @@ pub(crate) fn record_field_list(p: &mut Parser<'_>) { name(p); p.expect(T![:]); types::type_(p); - // test record_field_default_values - // struct S { f: f32 = 0.0 } - if p.eat(T![=]) { - expressions::expr(p); - } m.complete(p, RECORD_FIELD); } else { m.abandon(p); diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs index c8ea8c547a98..b9f87b6af242 100644 --- a/crates/parser/test_data/generated/runner.rs +++ b/crates/parser/test_data/generated/runner.rs @@ -482,10 +482,6 @@ mod ok { run_and_expect_no_errors("test_data/parser/inline/ok/record_field_attrs.rs"); } #[test] - fn record_field_default_values() { - run_and_expect_no_errors("test_data/parser/inline/ok/record_field_default_values.rs"); - } - #[test] fn record_field_list() { run_and_expect_no_errors("test_data/parser/inline/ok/record_field_list.rs"); } @@ -548,10 +544,6 @@ mod ok { run_and_expect_no_errors("test_data/parser/inline/ok/stmt_postfix_expr_ambiguity.rs"); } #[test] - fn struct_initializer_with_defaults() { - run_and_expect_no_errors("test_data/parser/inline/ok/struct_initializer_with_defaults.rs"); - } - #[test] fn struct_item() { run_and_expect_no_errors("test_data/parser/inline/ok/struct_item.rs"); } #[test] fn trait_alias() { run_and_expect_no_errors("test_data/parser/inline/ok/trait_alias.rs"); } @@ -727,10 +719,6 @@ mod err { ); } #[test] - fn comma_after_default_values_syntax() { - run_and_expect_errors("test_data/parser/inline/err/comma_after_default_values_syntax.rs"); - } - #[test] fn crate_visibility_empty_recover() { run_and_expect_errors("test_data/parser/inline/err/crate_visibility_empty_recover.rs"); } diff --git a/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast b/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast deleted file mode 100644 index feb617e1aa2a..000000000000 --- a/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast +++ /dev/null @@ -1,59 +0,0 @@ -SOURCE_FILE - FN - FN_KW "fn" - WHITESPACE " " - NAME - IDENT "foo" - PARAM_LIST - L_PAREN "(" - R_PAREN ")" - WHITESPACE " " - BLOCK_EXPR - STMT_LIST - L_CURLY "{" - WHITESPACE "\n " - EXPR_STMT - RECORD_EXPR - PATH - PATH_SEGMENT - NAME_REF - IDENT "S" - WHITESPACE " " - RECORD_EXPR_FIELD_LIST - L_CURLY "{" - WHITESPACE " " - DOT2 ".." - ERROR - COMMA "," - WHITESPACE " " - R_CURLY "}" - SEMICOLON ";" - WHITESPACE "\n " - RECORD_EXPR - PATH - PATH_SEGMENT - NAME_REF - IDENT "S" - WHITESPACE " " - RECORD_EXPR_FIELD_LIST - L_CURLY "{" - WHITESPACE " " - DOT2 ".." - ERROR - COMMA "," - WHITESPACE " " - RECORD_EXPR_FIELD - NAME_REF - IDENT "a" - COLON ":" - WHITESPACE " " - LITERAL - INT_NUMBER "0" - WHITESPACE " " - R_CURLY "}" - WHITESPACE "\n" - R_CURLY "}" - WHITESPACE "\n" -error 21: expected expression -error 36: expected expression -error 37: expected COMMA diff --git a/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rs b/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rs deleted file mode 100644 index f1ecdf89fab1..000000000000 --- a/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn foo() { - S { .., }; - S { .., a: 0 } -} diff --git a/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast b/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast index 12b4e233e304..08ae906421c3 100644 --- a/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast +++ b/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast @@ -44,56 +44,6 @@ SOURCE_FILE WHITESPACE " " R_CURLY "}" WHITESPACE "\n " - EXPR_STMT - RECORD_EXPR - PATH - PATH_SEGMENT - NAME_REF - IDENT "S" - WHITESPACE " " - RECORD_EXPR_FIELD_LIST - L_CURLY "{" - WHITESPACE " " - RECORD_EXPR_FIELD - NAME_REF - INT_NUMBER "0" - WHITESPACE " " - DOT2 ".." - CALL_EXPR - PATH_EXPR - PATH - PATH - PATH_SEGMENT - NAME_REF - IDENT "S" - COLON2 "::" - PATH_SEGMENT - NAME_REF - IDENT "default" - ARG_LIST - L_PAREN "(" - R_PAREN ")" - WHITESPACE " " - R_CURLY "}" - WHITESPACE "\n " - EXPR_STMT - RECORD_EXPR - PATH - PATH_SEGMENT - NAME_REF - IDENT "S" - WHITESPACE " " - RECORD_EXPR_FIELD_LIST - L_CURLY "{" - WHITESPACE " " - RECORD_EXPR_FIELD - NAME_REF - IDENT "field" - WHITESPACE " " - DOT2 ".." - WHITESPACE " " - R_CURLY "}" - WHITESPACE "\n " RECORD_EXPR PATH PATH_SEGMENT @@ -108,6 +58,20 @@ SOURCE_FILE INT_NUMBER "0" WHITESPACE " " DOT2 ".." + CALL_EXPR + PATH_EXPR + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "default" + ARG_LIST + L_PAREN "(" + R_PAREN ")" WHITESPACE " " R_CURLY "}" WHITESPACE "\n" @@ -118,9 +82,3 @@ error 25: expected COMMA error 42: expected SEMICOLON error 52: expected `:` error 52: expected COMMA -error 69: expected SEMICOLON -error 83: expected `:` -error 83: expected COMMA -error 88: expected SEMICOLON -error 98: expected `:` -error 98: expected COMMA diff --git a/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs b/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs index 416cd763fdb5..65398ccb88e5 100644 --- a/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs +++ b/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs @@ -1,6 +1,4 @@ fn main() { S { field ..S::default() } S { 0 ..S::default() } - S { field .. } - S { 0 .. } } diff --git a/crates/parser/test_data/parser/inline/ok/record_field_default_values.rast b/crates/parser/test_data/parser/inline/ok/record_field_default_values.rast deleted file mode 100644 index 33088f2cabf3..000000000000 --- a/crates/parser/test_data/parser/inline/ok/record_field_default_values.rast +++ /dev/null @@ -1,28 +0,0 @@ -SOURCE_FILE - STRUCT - STRUCT_KW "struct" - WHITESPACE " " - NAME - IDENT "S" - WHITESPACE " " - RECORD_FIELD_LIST - L_CURLY "{" - WHITESPACE " " - RECORD_FIELD - NAME - IDENT "f" - COLON ":" - WHITESPACE " " - PATH_TYPE - PATH - PATH_SEGMENT - NAME_REF - IDENT "f32" - WHITESPACE " " - EQ "=" - WHITESPACE " " - LITERAL - FLOAT_NUMBER "0.0" - WHITESPACE " " - R_CURLY "}" - WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/record_field_default_values.rs b/crates/parser/test_data/parser/inline/ok/record_field_default_values.rs deleted file mode 100644 index d7b38944a8aa..000000000000 --- a/crates/parser/test_data/parser/inline/ok/record_field_default_values.rs +++ /dev/null @@ -1 +0,0 @@ -struct S { f: f32 = 0.0 } diff --git a/crates/parser/test_data/parser/inline/ok/record_lit.rast b/crates/parser/test_data/parser/inline/ok/record_lit.rast index b868da55bcea..00948c322f4c 100644 --- a/crates/parser/test_data/parser/inline/ok/record_lit.rast +++ b/crates/parser/test_data/parser/inline/ok/record_lit.rast @@ -120,53 +120,6 @@ SOURCE_FILE R_CURLY "}" SEMICOLON ";" WHITESPACE "\n " - EXPR_STMT - RECORD_EXPR - PATH - PATH_SEGMENT - NAME_REF - IDENT "S" - WHITESPACE " " - RECORD_EXPR_FIELD_LIST - L_CURLY "{" - WHITESPACE " " - RECORD_EXPR_FIELD - PATH_EXPR - PATH - PATH_SEGMENT - NAME_REF - IDENT "x" - COMMA "," - WHITESPACE " " - RECORD_EXPR_FIELD - NAME_REF - IDENT "y" - COLON ":" - WHITESPACE " " - LITERAL - INT_NUMBER "32" - COMMA "," - WHITESPACE " " - DOT2 ".." - WHITESPACE " " - R_CURLY "}" - SEMICOLON ";" - WHITESPACE "\n " - EXPR_STMT - RECORD_EXPR - PATH - PATH_SEGMENT - NAME_REF - IDENT "S" - WHITESPACE " " - RECORD_EXPR_FIELD_LIST - L_CURLY "{" - WHITESPACE " " - DOT2 ".." - WHITESPACE " " - R_CURLY "}" - SEMICOLON ";" - WHITESPACE "\n " EXPR_STMT RECORD_EXPR PATH diff --git a/crates/parser/test_data/parser/inline/ok/record_lit.rs b/crates/parser/test_data/parser/inline/ok/record_lit.rs index 42895f759b2b..86411fbb7dc0 100644 --- a/crates/parser/test_data/parser/inline/ok/record_lit.rs +++ b/crates/parser/test_data/parser/inline/ok/record_lit.rs @@ -3,8 +3,6 @@ fn foo() { S { x }; S { x, y: 32, }; S { x, y: 32, ..Default::default() }; - S { x, y: 32, .. }; - S { .. }; S { x: ::default() }; TupleStruct { 0: 1 }; } diff --git a/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rast b/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rast deleted file mode 100644 index 987e219ae822..000000000000 --- a/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rast +++ /dev/null @@ -1,39 +0,0 @@ -SOURCE_FILE - FN - FN_KW "fn" - WHITESPACE " " - NAME - IDENT "foo" - PARAM_LIST - L_PAREN "(" - R_PAREN ")" - WHITESPACE " " - BLOCK_EXPR - STMT_LIST - L_CURLY "{" - WHITESPACE "\n " - LET_STMT - LET_KW "let" - WHITESPACE " " - IDENT_PAT - NAME - IDENT "_s" - WHITESPACE " " - EQ "=" - WHITESPACE " " - RECORD_EXPR - PATH - PATH_SEGMENT - NAME_REF - IDENT "S" - WHITESPACE " " - RECORD_EXPR_FIELD_LIST - L_CURLY "{" - WHITESPACE " " - DOT2 ".." - WHITESPACE " " - R_CURLY "}" - SEMICOLON ";" - WHITESPACE "\n" - R_CURLY "}" - WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rs b/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rs deleted file mode 100644 index e08204f94c4b..000000000000 --- a/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn foo() { - let _s = S { .. }; -} diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 824f262ca363..cd709afe091f 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -673,9 +673,6 @@ impl flags::AnalysisStats { DefWithBody::Const(it) => it.source(db).map(|it| it.syntax().cloned()), DefWithBody::Variant(it) => it.source(db).map(|it| it.syntax().cloned()), DefWithBody::InTypeConst(_) => unimplemented!(), - DefWithBody::Field(it) => { - it.default_value_source(db).map(|it| it.syntax().cloned()) - } }; if let Some(src) = source { let original_file = src.file_id.original_file(db); @@ -990,9 +987,6 @@ impl flags::AnalysisStats { DefWithBody::Const(it) => it.source(db).map(|it| it.syntax().cloned()), DefWithBody::Variant(it) => it.source(db).map(|it| it.syntax().cloned()), DefWithBody::InTypeConst(_) => unimplemented!(), - DefWithBody::Field(it) => { - it.default_value_source(db).map(|it| it.syntax().cloned()) - } }; if let Some(src) = source { let original_file = src.file_id.original_file(db); diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index bbb8413cbc08..4e2a70d6cd91 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -241,7 +241,7 @@ RecordFieldList = RecordField = Attr* Visibility? - Name ':' Type ('=' Expr)? + Name ':' Type TupleFieldList = '(' fields:(TupleField (',' TupleField)* ','?)? ')' diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 8f10ea94645d..69e2a9f9c1b2 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -1538,14 +1538,10 @@ impl ast::HasDocComments for RecordField {} impl ast::HasName for RecordField {} impl ast::HasVisibility for RecordField {} impl RecordField { - #[inline] - pub fn expr(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn ty(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) } - #[inline] - pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] From 461ee092bf61a3dcf66d64f182a0adf943e9eaae Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Tue, 28 Jan 2025 11:30:47 -0500 Subject: [PATCH 9/9] feat: Implement `default-field-values` only in parser --- crates/parser/src/grammar/expressions.rs | 18 ++++- crates/parser/src/grammar/items/adt.rs | 5 ++ crates/parser/test_data/generated/runner.rs | 12 ++++ .../comma_after_default_values_syntax.rast | 59 ++++++++++++++++ .../err/comma_after_default_values_syntax.rs | 4 ++ ...cord_literal_before_ellipsis_recovery.rast | 70 +++++++++++++++---- ...record_literal_before_ellipsis_recovery.rs | 2 + .../ok/record_field_default_values.rast | 28 ++++++++ .../inline/ok/record_field_default_values.rs | 1 + .../parser/inline/ok/record_lit.rast | 47 +++++++++++++ .../test_data/parser/inline/ok/record_lit.rs | 2 + .../ok/struct_initializer_with_defaults.rast | 39 +++++++++++ .../ok/struct_initializer_with_defaults.rs | 3 + crates/syntax/rust.ungram | 2 +- crates/syntax/src/ast/generated/nodes.rs | 4 ++ 15 files changed, 280 insertions(+), 16 deletions(-) create mode 100644 crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast create mode 100644 crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rs create mode 100644 crates/parser/test_data/parser/inline/ok/record_field_default_values.rast create mode 100644 crates/parser/test_data/parser/inline/ok/record_field_default_values.rs create mode 100644 crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rast create mode 100644 crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rs diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs index 389c01933c99..fe1316c9bfde 100644 --- a/crates/parser/src/grammar/expressions.rs +++ b/crates/parser/src/grammar/expressions.rs @@ -678,6 +678,8 @@ fn path_expr(p: &mut Parser<'_>, r: Restrictions) -> (CompletedMarker, BlockLike // S { x }; // S { x, y: 32, }; // S { x, y: 32, ..Default::default() }; +// S { x, y: 32, .. }; +// S { .. }; // S { x: ::default() }; // TupleStruct { 0: 1 }; // } @@ -709,6 +711,8 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) { // fn main() { // S { field ..S::default() } // S { 0 ..S::default() } + // S { field .. } + // S { 0 .. } // } name_ref_or_index(p); p.error("expected `:`"); @@ -739,7 +743,13 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) { // S { .. } = S {}; // } - // We permit `.. }` on the left-hand side of a destructuring assignment. + // test struct_initializer_with_defaults + // fn foo() { + // let _s = S { .. }; + // } + + // We permit `.. }` on the left-hand side of a destructuring assignment + // or defaults values. if !p.at(T!['}']) { expr(p); @@ -750,6 +760,12 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) { // S { ..x, a: 0 } // } + // test_err comma_after_default_values_syntax + // fn foo() { + // S { .., }; + // S { .., a: 0 } + // } + // Do not bump, so we can support additional fields after this comma. p.error("cannot use a comma after the base struct"); } diff --git a/crates/parser/src/grammar/items/adt.rs b/crates/parser/src/grammar/items/adt.rs index 21078175c0ec..9a16c9db6daf 100644 --- a/crates/parser/src/grammar/items/adt.rs +++ b/crates/parser/src/grammar/items/adt.rs @@ -135,6 +135,11 @@ pub(crate) fn record_field_list(p: &mut Parser<'_>) { name(p); p.expect(T![:]); types::type_(p); + // test record_field_default_values + // struct S { f: f32 = 0.0 } + if p.eat(T![=]) { + expressions::expr(p); + } m.complete(p, RECORD_FIELD); } else { m.abandon(p); diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs index b9f87b6af242..c8ea8c547a98 100644 --- a/crates/parser/test_data/generated/runner.rs +++ b/crates/parser/test_data/generated/runner.rs @@ -482,6 +482,10 @@ mod ok { run_and_expect_no_errors("test_data/parser/inline/ok/record_field_attrs.rs"); } #[test] + fn record_field_default_values() { + run_and_expect_no_errors("test_data/parser/inline/ok/record_field_default_values.rs"); + } + #[test] fn record_field_list() { run_and_expect_no_errors("test_data/parser/inline/ok/record_field_list.rs"); } @@ -544,6 +548,10 @@ mod ok { run_and_expect_no_errors("test_data/parser/inline/ok/stmt_postfix_expr_ambiguity.rs"); } #[test] + fn struct_initializer_with_defaults() { + run_and_expect_no_errors("test_data/parser/inline/ok/struct_initializer_with_defaults.rs"); + } + #[test] fn struct_item() { run_and_expect_no_errors("test_data/parser/inline/ok/struct_item.rs"); } #[test] fn trait_alias() { run_and_expect_no_errors("test_data/parser/inline/ok/trait_alias.rs"); } @@ -719,6 +727,10 @@ mod err { ); } #[test] + fn comma_after_default_values_syntax() { + run_and_expect_errors("test_data/parser/inline/err/comma_after_default_values_syntax.rs"); + } + #[test] fn crate_visibility_empty_recover() { run_and_expect_errors("test_data/parser/inline/err/crate_visibility_empty_recover.rs"); } diff --git a/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast b/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast new file mode 100644 index 000000000000..feb617e1aa2a --- /dev/null +++ b/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast @@ -0,0 +1,59 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + DOT2 ".." + ERROR + COMMA "," + WHITESPACE " " + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n " + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + DOT2 ".." + ERROR + COMMA "," + WHITESPACE " " + RECORD_EXPR_FIELD + NAME_REF + IDENT "a" + COLON ":" + WHITESPACE " " + LITERAL + INT_NUMBER "0" + WHITESPACE " " + R_CURLY "}" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" +error 21: expected expression +error 36: expected expression +error 37: expected COMMA diff --git a/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rs b/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rs new file mode 100644 index 000000000000..f1ecdf89fab1 --- /dev/null +++ b/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rs @@ -0,0 +1,4 @@ +fn foo() { + S { .., }; + S { .., a: 0 } +} diff --git a/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast b/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast index 08ae906421c3..12b4e233e304 100644 --- a/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast +++ b/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast @@ -44,6 +44,56 @@ SOURCE_FILE WHITESPACE " " R_CURLY "}" WHITESPACE "\n " + EXPR_STMT + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + RECORD_EXPR_FIELD + NAME_REF + INT_NUMBER "0" + WHITESPACE " " + DOT2 ".." + CALL_EXPR + PATH_EXPR + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "default" + ARG_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + R_CURLY "}" + WHITESPACE "\n " + EXPR_STMT + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + RECORD_EXPR_FIELD + NAME_REF + IDENT "field" + WHITESPACE " " + DOT2 ".." + WHITESPACE " " + R_CURLY "}" + WHITESPACE "\n " RECORD_EXPR PATH PATH_SEGMENT @@ -58,20 +108,6 @@ SOURCE_FILE INT_NUMBER "0" WHITESPACE " " DOT2 ".." - CALL_EXPR - PATH_EXPR - PATH - PATH - PATH_SEGMENT - NAME_REF - IDENT "S" - COLON2 "::" - PATH_SEGMENT - NAME_REF - IDENT "default" - ARG_LIST - L_PAREN "(" - R_PAREN ")" WHITESPACE " " R_CURLY "}" WHITESPACE "\n" @@ -82,3 +118,9 @@ error 25: expected COMMA error 42: expected SEMICOLON error 52: expected `:` error 52: expected COMMA +error 69: expected SEMICOLON +error 83: expected `:` +error 83: expected COMMA +error 88: expected SEMICOLON +error 98: expected `:` +error 98: expected COMMA diff --git a/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs b/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs index 65398ccb88e5..416cd763fdb5 100644 --- a/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs +++ b/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs @@ -1,4 +1,6 @@ fn main() { S { field ..S::default() } S { 0 ..S::default() } + S { field .. } + S { 0 .. } } diff --git a/crates/parser/test_data/parser/inline/ok/record_field_default_values.rast b/crates/parser/test_data/parser/inline/ok/record_field_default_values.rast new file mode 100644 index 000000000000..33088f2cabf3 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/record_field_default_values.rast @@ -0,0 +1,28 @@ +SOURCE_FILE + STRUCT + STRUCT_KW "struct" + WHITESPACE " " + NAME + IDENT "S" + WHITESPACE " " + RECORD_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + RECORD_FIELD + NAME + IDENT "f" + COLON ":" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "f32" + WHITESPACE " " + EQ "=" + WHITESPACE " " + LITERAL + FLOAT_NUMBER "0.0" + WHITESPACE " " + R_CURLY "}" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/record_field_default_values.rs b/crates/parser/test_data/parser/inline/ok/record_field_default_values.rs new file mode 100644 index 000000000000..d7b38944a8aa --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/record_field_default_values.rs @@ -0,0 +1 @@ +struct S { f: f32 = 0.0 } diff --git a/crates/parser/test_data/parser/inline/ok/record_lit.rast b/crates/parser/test_data/parser/inline/ok/record_lit.rast index 00948c322f4c..b868da55bcea 100644 --- a/crates/parser/test_data/parser/inline/ok/record_lit.rast +++ b/crates/parser/test_data/parser/inline/ok/record_lit.rast @@ -120,6 +120,53 @@ SOURCE_FILE R_CURLY "}" SEMICOLON ";" WHITESPACE "\n " + EXPR_STMT + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + RECORD_EXPR_FIELD + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "x" + COMMA "," + WHITESPACE " " + RECORD_EXPR_FIELD + NAME_REF + IDENT "y" + COLON ":" + WHITESPACE " " + LITERAL + INT_NUMBER "32" + COMMA "," + WHITESPACE " " + DOT2 ".." + WHITESPACE " " + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + DOT2 ".." + WHITESPACE " " + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n " EXPR_STMT RECORD_EXPR PATH diff --git a/crates/parser/test_data/parser/inline/ok/record_lit.rs b/crates/parser/test_data/parser/inline/ok/record_lit.rs index 86411fbb7dc0..42895f759b2b 100644 --- a/crates/parser/test_data/parser/inline/ok/record_lit.rs +++ b/crates/parser/test_data/parser/inline/ok/record_lit.rs @@ -3,6 +3,8 @@ fn foo() { S { x }; S { x, y: 32, }; S { x, y: 32, ..Default::default() }; + S { x, y: 32, .. }; + S { .. }; S { x: ::default() }; TupleStruct { 0: 1 }; } diff --git a/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rast b/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rast new file mode 100644 index 000000000000..987e219ae822 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rast @@ -0,0 +1,39 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + LET_STMT + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "_s" + WHITESPACE " " + EQ "=" + WHITESPACE " " + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + DOT2 ".." + WHITESPACE " " + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rs b/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rs new file mode 100644 index 000000000000..e08204f94c4b --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/struct_initializer_with_defaults.rs @@ -0,0 +1,3 @@ +fn foo() { + let _s = S { .. }; +} diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index 4e2a70d6cd91..bbb8413cbc08 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -241,7 +241,7 @@ RecordFieldList = RecordField = Attr* Visibility? - Name ':' Type + Name ':' Type ('=' Expr)? TupleFieldList = '(' fields:(TupleField (',' TupleField)* ','?)? ')' diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 69e2a9f9c1b2..8f10ea94645d 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -1538,10 +1538,14 @@ impl ast::HasDocComments for RecordField {} impl ast::HasName for RecordField {} impl ast::HasVisibility for RecordField {} impl RecordField { + #[inline] + pub fn expr(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn ty(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) } + #[inline] + pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)]