Skip to content

Commit ad0aea4

Browse files
authored
Merge pull request rust-lang#19001 from ShoyuVanilla/default-field-values
feat: Implement `default-field-values`
2 parents 1711a19 + c093db0 commit ad0aea4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+905
-94
lines changed

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

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

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

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::{
2525
db::DefDatabase,
2626
hir::{
2727
Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label, LabelId, Pat,
28-
PatId, RecordFieldPat, Statement,
28+
PatId, RecordFieldPat, Spread, Statement,
2929
},
3030
nameres::DefMap,
3131
path::{ModPath, Path},
@@ -362,7 +362,7 @@ impl ExpressionStore {
362362
for field in fields.iter() {
363363
f(field.expr);
364364
}
365-
if let &Some(expr) = spread {
365+
if let &Spread::Base(expr) = spread {
366366
f(expr);
367367
}
368368
}
@@ -490,7 +490,7 @@ impl ExpressionStore {
490490
for field in fields.iter() {
491491
f(field.expr);
492492
}
493-
if let &Some(expr) = spread {
493+
if let &Spread::Base(expr) = spread {
494494
f(expr);
495495
}
496496
}

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: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use crate::{
4545
},
4646
Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind,
4747
Expr, ExprId, Item, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability,
48-
OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
48+
OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Spread, Statement,
4949
},
5050
item_scope::BuiltinShadowMode,
5151
lang_item::LangItem,
@@ -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
);
@@ -600,10 +602,13 @@ impl ExprCollector<'_> {
600602
Some(RecordLitField { name, expr })
601603
})
602604
.collect();
603-
let spread = nfl.spread().map(|s| self.collect_expr(s));
605+
let spread = nfl.spread().map(|s| self.collect_expr(s)).map_or_else(
606+
|| if nfl.dotdot_token().is_some() { Spread::Yes } else { Spread::No },
607+
Spread::Base,
608+
);
604609
Expr::RecordLit { path, fields, spread }
605610
} else {
606-
Expr::RecordLit { path, fields: Box::default(), spread: None }
611+
Expr::RecordLit { path, fields: Box::default(), spread: Spread::No }
607612
};
608613

609614
self.alloc_expr(record_lit, syntax_ptr)

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

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ use span::Edition;
88
use crate::{
99
hir::{
1010
Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, LiteralOrConst, Movability,
11-
Statement,
11+
Spread, 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 {
@@ -385,10 +412,16 @@ impl Printer<'_> {
385412
p.print_expr(field.expr);
386413
wln!(p, ",");
387414
}
388-
if let Some(spread) = spread {
389-
w!(p, "..");
390-
p.print_expr(*spread);
391-
wln!(p);
415+
match spread {
416+
Spread::No => {}
417+
Spread::Yes => {
418+
w!(p, "..");
419+
}
420+
Spread::Base(expr) => {
421+
w!(p, "..");
422+
p.print_expr(*expr);
423+
wln!(p);
424+
}
392425
}
393426
});
394427
w!(self, "}}");

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ pub enum Expr {
251251
RecordLit {
252252
path: Option<Box<Path>>,
253253
fields: Box<[RecordLitField]>,
254-
spread: Option<ExprId>,
254+
spread: Spread,
255255
},
256256
Field {
257257
expr: ExprId,
@@ -478,6 +478,13 @@ pub struct RecordLitField {
478478
pub expr: ExprId,
479479
}
480480

481+
#[derive(Debug, Clone, Eq, PartialEq)]
482+
pub enum Spread {
483+
No,
484+
Yes,
485+
Base(ExprId),
486+
}
487+
481488
#[derive(Debug, Clone, Eq, PartialEq)]
482489
pub enum Statement {
483490
Let {

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

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

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

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

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

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

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

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

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

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

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

Lines changed: 56 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
}
@@ -1309,6 +1356,12 @@ impl HasModule for VariantId {
13091356
}
13101357
}
13111358

1359+
impl HasModule for FieldId {
1360+
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1361+
self.parent.module(db)
1362+
}
1363+
}
1364+
13121365
impl HasModule for MacroId {
13131366
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
13141367
match *self {
@@ -1332,6 +1385,7 @@ impl HasModule for TypeOwnerId {
13321385
TypeOwnerId::ImplId(it) => it.module(db),
13331386
TypeOwnerId::EnumVariantId(it) => it.module(db),
13341387
TypeOwnerId::InTypeConstId(it) => it.lookup(db).owner.module(db),
1388+
TypeOwnerId::FieldId(it) => it.module(db),
13351389
}
13361390
}
13371391
}
@@ -1344,6 +1398,7 @@ impl HasModule for DefWithBodyId {
13441398
DefWithBodyId::ConstId(it) => it.module(db),
13451399
DefWithBodyId::VariantId(it) => it.module(db),
13461400
DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db),
1401+
DefWithBodyId::FieldId(it) => it.module(db),
13471402
}
13481403
}
13491404
}

0 commit comments

Comments
 (0)