Skip to content

Commit f10b622

Browse files
committed
feat: Implement default-field-values only in parser
1 parent 0f9cdeb commit f10b622

15 files changed

+280
-16
lines changed

src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,8 @@ fn path_expr(p: &mut Parser<'_>, r: Restrictions) -> (CompletedMarker, BlockLike
678678
// S { x };
679679
// S { x, y: 32, };
680680
// S { x, y: 32, ..Default::default() };
681+
// S { x, y: 32, .. };
682+
// S { .. };
681683
// S { x: ::default() };
682684
// TupleStruct { 0: 1 };
683685
// }
@@ -709,6 +711,8 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
709711
// fn main() {
710712
// S { field ..S::default() }
711713
// S { 0 ..S::default() }
714+
// S { field .. }
715+
// S { 0 .. }
712716
// }
713717
name_ref_or_index(p);
714718
p.error("expected `:`");
@@ -739,7 +743,13 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
739743
// S { .. } = S {};
740744
// }
741745

742-
// We permit `.. }` on the left-hand side of a destructuring assignment.
746+
// test struct_initializer_with_defaults
747+
// fn foo() {
748+
// let _s = S { .. };
749+
// }
750+
751+
// We permit `.. }` on the left-hand side of a destructuring assignment
752+
// or defaults values.
743753
if !p.at(T!['}']) {
744754
expr(p);
745755

@@ -750,6 +760,12 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
750760
// S { ..x, a: 0 }
751761
// }
752762

763+
// test_err comma_after_default_values_syntax
764+
// fn foo() {
765+
// S { .., };
766+
// S { .., a: 0 }
767+
// }
768+
753769
// Do not bump, so we can support additional fields after this comma.
754770
p.error("cannot use a comma after the base struct");
755771
}

src/tools/rust-analyzer/crates/parser/src/grammar/items/adt.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ pub(crate) fn record_field_list(p: &mut Parser<'_>) {
135135
name(p);
136136
p.expect(T![:]);
137137
types::type_(p);
138+
// test record_field_default_values
139+
// struct S { f: f32 = 0.0 }
140+
if p.eat(T![=]) {
141+
expressions::expr(p);
142+
}
138143
m.complete(p, RECORD_FIELD);
139144
} else {
140145
m.abandon(p);

src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,10 @@ mod ok {
482482
run_and_expect_no_errors("test_data/parser/inline/ok/record_field_attrs.rs");
483483
}
484484
#[test]
485+
fn record_field_default_values() {
486+
run_and_expect_no_errors("test_data/parser/inline/ok/record_field_default_values.rs");
487+
}
488+
#[test]
485489
fn record_field_list() {
486490
run_and_expect_no_errors("test_data/parser/inline/ok/record_field_list.rs");
487491
}
@@ -544,6 +548,10 @@ mod ok {
544548
run_and_expect_no_errors("test_data/parser/inline/ok/stmt_postfix_expr_ambiguity.rs");
545549
}
546550
#[test]
551+
fn struct_initializer_with_defaults() {
552+
run_and_expect_no_errors("test_data/parser/inline/ok/struct_initializer_with_defaults.rs");
553+
}
554+
#[test]
547555
fn struct_item() { run_and_expect_no_errors("test_data/parser/inline/ok/struct_item.rs"); }
548556
#[test]
549557
fn trait_alias() { run_and_expect_no_errors("test_data/parser/inline/ok/trait_alias.rs"); }
@@ -719,6 +727,10 @@ mod err {
719727
);
720728
}
721729
#[test]
730+
fn comma_after_default_values_syntax() {
731+
run_and_expect_errors("test_data/parser/inline/err/comma_after_default_values_syntax.rs");
732+
}
733+
#[test]
722734
fn crate_visibility_empty_recover() {
723735
run_and_expect_errors("test_data/parser/inline/err/crate_visibility_empty_recover.rs");
724736
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "foo"
7+
PARAM_LIST
8+
L_PAREN "("
9+
R_PAREN ")"
10+
WHITESPACE " "
11+
BLOCK_EXPR
12+
STMT_LIST
13+
L_CURLY "{"
14+
WHITESPACE "\n "
15+
EXPR_STMT
16+
RECORD_EXPR
17+
PATH
18+
PATH_SEGMENT
19+
NAME_REF
20+
IDENT "S"
21+
WHITESPACE " "
22+
RECORD_EXPR_FIELD_LIST
23+
L_CURLY "{"
24+
WHITESPACE " "
25+
DOT2 ".."
26+
ERROR
27+
COMMA ","
28+
WHITESPACE " "
29+
R_CURLY "}"
30+
SEMICOLON ";"
31+
WHITESPACE "\n "
32+
RECORD_EXPR
33+
PATH
34+
PATH_SEGMENT
35+
NAME_REF
36+
IDENT "S"
37+
WHITESPACE " "
38+
RECORD_EXPR_FIELD_LIST
39+
L_CURLY "{"
40+
WHITESPACE " "
41+
DOT2 ".."
42+
ERROR
43+
COMMA ","
44+
WHITESPACE " "
45+
RECORD_EXPR_FIELD
46+
NAME_REF
47+
IDENT "a"
48+
COLON ":"
49+
WHITESPACE " "
50+
LITERAL
51+
INT_NUMBER "0"
52+
WHITESPACE " "
53+
R_CURLY "}"
54+
WHITESPACE "\n"
55+
R_CURLY "}"
56+
WHITESPACE "\n"
57+
error 21: expected expression
58+
error 36: expected expression
59+
error 37: expected COMMA
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn foo() {
2+
S { .., };
3+
S { .., a: 0 }
4+
}

src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,56 @@ SOURCE_FILE
4444
WHITESPACE " "
4545
R_CURLY "}"
4646
WHITESPACE "\n "
47+
EXPR_STMT
48+
RECORD_EXPR
49+
PATH
50+
PATH_SEGMENT
51+
NAME_REF
52+
IDENT "S"
53+
WHITESPACE " "
54+
RECORD_EXPR_FIELD_LIST
55+
L_CURLY "{"
56+
WHITESPACE " "
57+
RECORD_EXPR_FIELD
58+
NAME_REF
59+
INT_NUMBER "0"
60+
WHITESPACE " "
61+
DOT2 ".."
62+
CALL_EXPR
63+
PATH_EXPR
64+
PATH
65+
PATH
66+
PATH_SEGMENT
67+
NAME_REF
68+
IDENT "S"
69+
COLON2 "::"
70+
PATH_SEGMENT
71+
NAME_REF
72+
IDENT "default"
73+
ARG_LIST
74+
L_PAREN "("
75+
R_PAREN ")"
76+
WHITESPACE " "
77+
R_CURLY "}"
78+
WHITESPACE "\n "
79+
EXPR_STMT
80+
RECORD_EXPR
81+
PATH
82+
PATH_SEGMENT
83+
NAME_REF
84+
IDENT "S"
85+
WHITESPACE " "
86+
RECORD_EXPR_FIELD_LIST
87+
L_CURLY "{"
88+
WHITESPACE " "
89+
RECORD_EXPR_FIELD
90+
NAME_REF
91+
IDENT "field"
92+
WHITESPACE " "
93+
DOT2 ".."
94+
WHITESPACE " "
95+
R_CURLY "}"
96+
WHITESPACE "\n "
4797
RECORD_EXPR
4898
PATH
4999
PATH_SEGMENT
@@ -58,20 +108,6 @@ SOURCE_FILE
58108
INT_NUMBER "0"
59109
WHITESPACE " "
60110
DOT2 ".."
61-
CALL_EXPR
62-
PATH_EXPR
63-
PATH
64-
PATH
65-
PATH_SEGMENT
66-
NAME_REF
67-
IDENT "S"
68-
COLON2 "::"
69-
PATH_SEGMENT
70-
NAME_REF
71-
IDENT "default"
72-
ARG_LIST
73-
L_PAREN "("
74-
R_PAREN ")"
75111
WHITESPACE " "
76112
R_CURLY "}"
77113
WHITESPACE "\n"
@@ -82,3 +118,9 @@ error 25: expected COMMA
82118
error 42: expected SEMICOLON
83119
error 52: expected `:`
84120
error 52: expected COMMA
121+
error 69: expected SEMICOLON
122+
error 83: expected `:`
123+
error 83: expected COMMA
124+
error 88: expected SEMICOLON
125+
error 98: expected `:`
126+
error 98: expected COMMA
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
fn main() {
22
S { field ..S::default() }
33
S { 0 ..S::default() }
4+
S { field .. }
5+
S { 0 .. }
46
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
SOURCE_FILE
2+
STRUCT
3+
STRUCT_KW "struct"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "S"
7+
WHITESPACE " "
8+
RECORD_FIELD_LIST
9+
L_CURLY "{"
10+
WHITESPACE " "
11+
RECORD_FIELD
12+
NAME
13+
IDENT "f"
14+
COLON ":"
15+
WHITESPACE " "
16+
PATH_TYPE
17+
PATH
18+
PATH_SEGMENT
19+
NAME_REF
20+
IDENT "f32"
21+
WHITESPACE " "
22+
EQ "="
23+
WHITESPACE " "
24+
LITERAL
25+
FLOAT_NUMBER "0.0"
26+
WHITESPACE " "
27+
R_CURLY "}"
28+
WHITESPACE "\n"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
struct S { f: f32 = 0.0 }

src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_lit.rast

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,53 @@ SOURCE_FILE
120120
R_CURLY "}"
121121
SEMICOLON ";"
122122
WHITESPACE "\n "
123+
EXPR_STMT
124+
RECORD_EXPR
125+
PATH
126+
PATH_SEGMENT
127+
NAME_REF
128+
IDENT "S"
129+
WHITESPACE " "
130+
RECORD_EXPR_FIELD_LIST
131+
L_CURLY "{"
132+
WHITESPACE " "
133+
RECORD_EXPR_FIELD
134+
PATH_EXPR
135+
PATH
136+
PATH_SEGMENT
137+
NAME_REF
138+
IDENT "x"
139+
COMMA ","
140+
WHITESPACE " "
141+
RECORD_EXPR_FIELD
142+
NAME_REF
143+
IDENT "y"
144+
COLON ":"
145+
WHITESPACE " "
146+
LITERAL
147+
INT_NUMBER "32"
148+
COMMA ","
149+
WHITESPACE " "
150+
DOT2 ".."
151+
WHITESPACE " "
152+
R_CURLY "}"
153+
SEMICOLON ";"
154+
WHITESPACE "\n "
155+
EXPR_STMT
156+
RECORD_EXPR
157+
PATH
158+
PATH_SEGMENT
159+
NAME_REF
160+
IDENT "S"
161+
WHITESPACE " "
162+
RECORD_EXPR_FIELD_LIST
163+
L_CURLY "{"
164+
WHITESPACE " "
165+
DOT2 ".."
166+
WHITESPACE " "
167+
R_CURLY "}"
168+
SEMICOLON ";"
169+
WHITESPACE "\n "
123170
EXPR_STMT
124171
RECORD_EXPR
125172
PATH

src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_lit.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ fn foo() {
33
S { x };
44
S { x, y: 32, };
55
S { x, y: 32, ..Default::default() };
6+
S { x, y: 32, .. };
7+
S { .. };
68
S { x: ::default() };
79
TupleStruct { 0: 1 };
810
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "foo"
7+
PARAM_LIST
8+
L_PAREN "("
9+
R_PAREN ")"
10+
WHITESPACE " "
11+
BLOCK_EXPR
12+
STMT_LIST
13+
L_CURLY "{"
14+
WHITESPACE "\n "
15+
LET_STMT
16+
LET_KW "let"
17+
WHITESPACE " "
18+
IDENT_PAT
19+
NAME
20+
IDENT "_s"
21+
WHITESPACE " "
22+
EQ "="
23+
WHITESPACE " "
24+
RECORD_EXPR
25+
PATH
26+
PATH_SEGMENT
27+
NAME_REF
28+
IDENT "S"
29+
WHITESPACE " "
30+
RECORD_EXPR_FIELD_LIST
31+
L_CURLY "{"
32+
WHITESPACE " "
33+
DOT2 ".."
34+
WHITESPACE " "
35+
R_CURLY "}"
36+
SEMICOLON ";"
37+
WHITESPACE "\n"
38+
R_CURLY "}"
39+
WHITESPACE "\n"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn foo() {
2+
let _s = S { .. };
3+
}

src/tools/rust-analyzer/crates/syntax/rust.ungram

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ RecordFieldList =
241241

242242
RecordField =
243243
Attr* Visibility?
244-
Name ':' Type
244+
Name ':' Type ('=' Expr)?
245245

246246
TupleFieldList =
247247
'(' fields:(TupleField (',' TupleField)* ','?)? ')'

0 commit comments

Comments
 (0)