feat: Implement default-field-values

This commit is contained in:
Shoyu Vanilla 2025-01-23 00:27:31 +09:00
parent 35b55fd67f
commit 7de0b2e75a
33 changed files with 647 additions and 31 deletions

View file

@ -122,6 +122,9 @@ 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);

View file

@ -90,6 +90,7 @@ 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]);
@ -168,6 +169,7 @@ pub(super) fn lower_body(
Awaitable::No("constant")
}
DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"),
DefWithBodyId::FieldId(..) => Awaitable::No("field"),
}
},
);

View file

@ -11,6 +11,7 @@ use crate::{
Statement,
},
pretty::{print_generic_args, print_path, print_type_ref},
VariantId,
};
use super::*;
@ -56,6 +57,32 @@ 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 {

View file

@ -55,6 +55,7 @@ pub mod visibility;
use intern::Interned;
pub use rustc_abi as layout;
use src::HasSource;
use triomphe::Arc;
#[cfg(test)]
@ -77,6 +78,7 @@ 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},
@ -519,6 +521,41 @@ pub struct FieldId {
pub local_id: LocalFieldId,
}
impl FieldId {
pub fn record_field_source(
&self,
db: &dyn DefDatabase,
) -> InFileWrapper<HirFileId, Option<ast::RecordField>> {
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<data::adt::FieldData>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -686,6 +723,7 @@ pub enum TypeOwnerId {
TypeAliasId(TypeAliasId),
ImplId(ImplId),
EnumVariantId(EnumVariantId),
FieldId(FieldId),
}
impl TypeOwnerId {
@ -703,6 +741,11 @@ 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(),
}),
})
}
}
@ -717,7 +760,8 @@ impl_from!(
TraitAliasId,
TypeAliasId,
ImplId,
EnumVariantId
EnumVariantId,
FieldId
for TypeOwnerId
);
@ -730,6 +774,7 @@ impl From<DefWithBodyId> for TypeOwnerId {
DefWithBodyId::ConstId(it) => it.into(),
DefWithBodyId::InTypeConstId(it) => it.into(),
DefWithBodyId::VariantId(it) => it.into(),
DefWithBodyId::FieldId(it) => it.into(),
}
}
}
@ -885,6 +930,7 @@ pub enum DefWithBodyId {
ConstId(ConstId),
InTypeConstId(InTypeConstId),
VariantId(EnumVariantId),
FieldId(FieldId),
}
impl_from!(FunctionId, ConstId, StaticId, InTypeConstId for DefWithBodyId);
@ -905,6 +951,7 @@ 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,
}
}
}
@ -1332,6 +1379,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) => match it.parent {
VariantId::EnumVariantId(it) => it.module(db),
VariantId::StructId(it) => it.module(db),
VariantId::UnionId(it) => it.module(db),
},
}
}
}
@ -1344,6 +1396,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) => match it.parent {
VariantId::EnumVariantId(it) => it.module(db),
VariantId::StructId(it) => it.module(db),
VariantId::UnionId(it) => it.module(db),
},
}
}
}

View file

@ -211,6 +211,20 @@ 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)]
@ -224,6 +238,20 @@ 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 {
@ -236,6 +264,20 @@ 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(), ..
}
}
}"#]],
);
}

View file

@ -1227,6 +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) => match it.parent {
VariantId::EnumVariantId(it) => it.resolver(db),
VariantId::StructId(it) => it.resolver(db),
VariantId::UnionId(it) => it.resolver(db),
},
}
}
}
@ -1239,6 +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) => match f.parent {
VariantId::EnumVariantId(it) => it.resolver(db),
VariantId::StructId(it) => it.resolver(db),
VariantId::UnionId(it) => it.resolver(db),
},
}
}
}