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

Commit d18afd3

Browse files
committed
feat: Implement default-field-values
1 parent 1711a19 commit d18afd3

33 files changed

+647
-31
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ impl Body {
122122
src.map(|it| it.expr())
123123
}
124124
DefWithBodyId::InTypeConstId(c) => c.lookup(db).id.map(|_| c.source(db).expr()),
125+
DefWithBodyId::FieldId(f) => {
126+
f.record_field_source(db).map(|it| it.and_then(|it| it.expr()))
127+
}
125128
}
126129
};
127130
let module = def.module(db);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub(super) fn lower_body(
9090
DefWithBodyId::ConstId(it) => db.attrs(it.into()),
9191
DefWithBodyId::InTypeConstId(_) => Attrs::EMPTY,
9292
DefWithBodyId::VariantId(it) => db.attrs(it.into()),
93+
DefWithBodyId::FieldId(it) => db.attrs(it.into()),
9394
}
9495
.rust_analyzer_tool()
9596
.any(|attr| *attr.path() == tool_path![skip]);
@@ -168,6 +169,7 @@ pub(super) fn lower_body(
168169
Awaitable::No("constant")
169170
}
170171
DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"),
172+
DefWithBodyId::FieldId(..) => Awaitable::No("field"),
171173
}
172174
},
173175
);

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::{
1111
Statement,
1212
},
1313
pretty::{print_generic_args, print_path, print_type_ref},
14+
VariantId,
1415
};
1516

1617
use super::*;
@@ -56,6 +57,32 @@ pub(super) fn print_body_hir(
5657
loc.id.item_tree(db)[loc.id.value].name.display(db.upcast(), edition),
5758
)
5859
}
60+
DefWithBodyId::FieldId(it) => {
61+
let parent_name: String = match it.parent {
62+
VariantId::EnumVariantId(it) => {
63+
let loc = it.lookup(db);
64+
let enum_loc = loc.parent.lookup(db);
65+
format!(
66+
"{}::{}",
67+
enum_loc.id.item_tree(db)[enum_loc.id.value]
68+
.name
69+
.display(db.upcast(), edition),
70+
loc.id.item_tree(db)[loc.id.value].name.display(db.upcast(), edition),
71+
)
72+
}
73+
VariantId::StructId(it) => it
74+
.lookup(db)
75+
.id
76+
.resolved(db, |it| it.name.display(db.upcast(), edition).to_string()),
77+
VariantId::UnionId(it) => it
78+
.lookup(db)
79+
.id
80+
.resolved(db, |it| it.name.display(db.upcast(), edition).to_string()),
81+
};
82+
let variant_data = it.parent.variant_data(db);
83+
let field_name = &variant_data.fields()[it.local_id].name;
84+
format!("field {}.{}", parent_name, field_name.display(db.upcast(), edition),)
85+
}
5986
};
6087

6188
let mut p = Printer {

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

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub mod visibility;
5555

5656
use intern::Interned;
5757
pub use rustc_abi as layout;
58+
use src::HasSource;
5859
use triomphe::Arc;
5960

6061
#[cfg(test)]
@@ -77,6 +78,7 @@ use hir_expand::{
7778
builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander},
7879
db::ExpandDatabase,
7980
eager::expand_eager_macro_input,
81+
files::InFileWrapper,
8082
impl_intern_lookup,
8183
name::Name,
8284
proc_macro::{CustomProcMacroExpander, ProcMacroKind},
@@ -519,6 +521,41 @@ pub struct FieldId {
519521
pub local_id: LocalFieldId,
520522
}
521523

524+
impl FieldId {
525+
pub fn record_field_source(
526+
&self,
527+
db: &dyn DefDatabase,
528+
) -> InFileWrapper<HirFileId, Option<ast::RecordField>> {
529+
let field_list = match self.parent {
530+
crate::VariantId::EnumVariantId(it) => {
531+
let s = it.lookup(db);
532+
s.source(db).map(|it| {
533+
it.field_list().and_then(|it| match it {
534+
ast::FieldList::RecordFieldList(it) => Some(it),
535+
_ => None,
536+
})
537+
})
538+
}
539+
crate::VariantId::StructId(it) => {
540+
let s = it.lookup(db);
541+
s.source(db).map(|it| {
542+
it.field_list().and_then(|it| match it {
543+
ast::FieldList::RecordFieldList(it) => Some(it),
544+
_ => None,
545+
})
546+
})
547+
}
548+
crate::VariantId::UnionId(it) => {
549+
let s = it.lookup(db);
550+
s.source(db).map(|it| it.record_field_list())
551+
}
552+
};
553+
field_list.map(|it| {
554+
it.and_then(|it| it.fields().nth(self.local_id.into_raw().into_u32() as usize))
555+
})
556+
}
557+
}
558+
522559
pub type LocalFieldId = Idx<data::adt::FieldData>;
523560

524561
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -686,6 +723,7 @@ pub enum TypeOwnerId {
686723
TypeAliasId(TypeAliasId),
687724
ImplId(ImplId),
688725
EnumVariantId(EnumVariantId),
726+
FieldId(FieldId),
689727
}
690728

691729
impl TypeOwnerId {
@@ -703,6 +741,11 @@ impl TypeOwnerId {
703741
GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent))
704742
}
705743
TypeOwnerId::InTypeConstId(_) => return None,
744+
TypeOwnerId::FieldId(it) => GenericDefId::AdtId(match it.parent {
745+
VariantId::EnumVariantId(it) => AdtId::EnumId(it.lookup(db).parent),
746+
VariantId::StructId(it) => it.into(),
747+
VariantId::UnionId(it) => it.into(),
748+
}),
706749
})
707750
}
708751
}
@@ -717,7 +760,8 @@ impl_from!(
717760
TraitAliasId,
718761
TypeAliasId,
719762
ImplId,
720-
EnumVariantId
763+
EnumVariantId,
764+
FieldId
721765
for TypeOwnerId
722766
);
723767

@@ -730,6 +774,7 @@ impl From<DefWithBodyId> for TypeOwnerId {
730774
DefWithBodyId::ConstId(it) => it.into(),
731775
DefWithBodyId::InTypeConstId(it) => it.into(),
732776
DefWithBodyId::VariantId(it) => it.into(),
777+
DefWithBodyId::FieldId(it) => it.into(),
733778
}
734779
}
735780
}
@@ -885,6 +930,7 @@ pub enum DefWithBodyId {
885930
ConstId(ConstId),
886931
InTypeConstId(InTypeConstId),
887932
VariantId(EnumVariantId),
933+
FieldId(FieldId),
888934
}
889935

890936
impl_from!(FunctionId, ConstId, StaticId, InTypeConstId for DefWithBodyId);
@@ -905,6 +951,7 @@ impl DefWithBodyId {
905951
// FIXME: stable rust doesn't allow generics in constants, but we should
906952
// use `TypeOwnerId::as_generic_def_id` when it does.
907953
DefWithBodyId::InTypeConstId(_) => None,
954+
DefWithBodyId::FieldId(_) => None,
908955
}
909956
}
910957
}
@@ -1332,6 +1379,11 @@ impl HasModule for TypeOwnerId {
13321379
TypeOwnerId::ImplId(it) => it.module(db),
13331380
TypeOwnerId::EnumVariantId(it) => it.module(db),
13341381
TypeOwnerId::InTypeConstId(it) => it.lookup(db).owner.module(db),
1382+
TypeOwnerId::FieldId(it) => match it.parent {
1383+
VariantId::EnumVariantId(it) => it.module(db),
1384+
VariantId::StructId(it) => it.module(db),
1385+
VariantId::UnionId(it) => it.module(db),
1386+
},
13351387
}
13361388
}
13371389
}
@@ -1344,6 +1396,11 @@ impl HasModule for DefWithBodyId {
13441396
DefWithBodyId::ConstId(it) => it.module(db),
13451397
DefWithBodyId::VariantId(it) => it.module(db),
13461398
DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db),
1399+
DefWithBodyId::FieldId(it) => match it.parent {
1400+
VariantId::EnumVariantId(it) => it.module(db),
1401+
VariantId::StructId(it) => it.module(db),
1402+
VariantId::UnionId(it) => it.module(db),
1403+
},
13471404
}
13481405
}
13491406
}

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,20 @@ enum Bar {
211211
#[default]
212212
Bar,
213213
}
214+
#[derive(Default)]
215+
struct Baz {
216+
field1: i32 = 2,
217+
field2: bool = { false },
218+
}
219+
#[derive(Default)]
220+
enum Qux {
221+
#[default]
222+
Foo {
223+
field1: i32,
224+
field2: bool = true,
225+
field3: (),
226+
}
227+
}
214228
"#,
215229
expect![[r#"
216230
#[derive(Default)]
@@ -224,6 +238,20 @@ enum Bar {
224238
#[default]
225239
Bar,
226240
}
241+
#[derive(Default)]
242+
struct Baz {
243+
field1: i32 = 2,
244+
field2: bool = { false },
245+
}
246+
#[derive(Default)]
247+
enum Qux {
248+
#[default]
249+
Foo {
250+
field1: i32,
251+
field2: bool = true,
252+
field3: (),
253+
}
254+
}
227255
228256
impl <> $crate::default::Default for Foo< > where {
229257
fn default() -> Self {
@@ -236,6 +264,20 @@ impl <> $crate::default::Default for Bar< > where {
236264
fn default() -> Self {
237265
Bar::Bar
238266
}
267+
}
268+
impl <> $crate::default::Default for Baz< > where {
269+
fn default() -> Self {
270+
Baz {
271+
..
272+
}
273+
}
274+
}
275+
impl <> $crate::default::Default for Qux< > where {
276+
fn default() -> Self {
277+
Qux::Foo {
278+
field1: $crate::default::Default::default(), field3: $crate::default::Default::default(), ..
279+
}
280+
}
239281
}"#]],
240282
);
241283
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,11 @@ impl HasResolver for TypeOwnerId {
12271227
TypeOwnerId::TypeAliasId(it) => it.resolver(db),
12281228
TypeOwnerId::ImplId(it) => it.resolver(db),
12291229
TypeOwnerId::EnumVariantId(it) => it.resolver(db),
1230+
TypeOwnerId::FieldId(it) => match it.parent {
1231+
VariantId::EnumVariantId(it) => it.resolver(db),
1232+
VariantId::StructId(it) => it.resolver(db),
1233+
VariantId::UnionId(it) => it.resolver(db),
1234+
},
12301235
}
12311236
}
12321237
}
@@ -1239,6 +1244,11 @@ impl HasResolver for DefWithBodyId {
12391244
DefWithBodyId::StaticId(s) => s.resolver(db),
12401245
DefWithBodyId::VariantId(v) => v.resolver(db),
12411246
DefWithBodyId::InTypeConstId(c) => c.lookup(db).owner.resolver(db),
1247+
DefWithBodyId::FieldId(f) => match f.parent {
1248+
VariantId::EnumVariantId(it) => it.resolver(db),
1249+
VariantId::StructId(it) => it.resolver(db),
1250+
VariantId::UnionId(it) => it.resolver(db),
1251+
},
12421252
}
12431253
}
12441254
}

0 commit comments

Comments
 (0)