aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--crates/completion/src/completions/qualified_path.rs29
-rw-r--r--crates/completion/src/completions/unqualified_path.rs27
-rw-r--r--crates/hir_def/src/body/lower.rs4
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs9
-rw-r--r--crates/parser/src/grammar/items.rs7
-rw-r--r--crates/parser/src/grammar/patterns.rs14
-rw-r--r--crates/parser/src/syntax_kind/generated.rs1
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs33
-rw-r--r--crates/syntax/src/ast/make.rs8
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rast76
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0157_const_block.rast23
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0157_const_block.rs1
-rw-r--r--xtask/Cargo.toml2
-rw-r--r--xtask/src/ast_src.rs1
16 files changed, 234 insertions, 9 deletions
diff --git a/Cargo.lock b/Cargo.lock
index fbb79e01f..891cff55e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1827,9 +1827,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
1827 1827
1828[[package]] 1828[[package]]
1829name = "ungrammar" 1829name = "ungrammar"
1830version = "1.4.0" 1830version = "1.5.0"
1831source = "registry+https://github.com/rust-lang/crates.io-index" 1831source = "registry+https://github.com/rust-lang/crates.io-index"
1832checksum = "68951379f3ced25754472ca5addbf74d7dab58c9818f49290a3d8caa3ab44fb7" 1832checksum = "c11bffada52edc8f2a56160b286ea4640acf90ffcb21bded361ccb8ed43a1457"
1833 1833
1834[[package]] 1834[[package]]
1835name = "unicase" 1835name = "unicase"
diff --git a/crates/completion/src/completions/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs
index 1300f00b2..882c4dcbc 100644
--- a/crates/completion/src/completions/qualified_path.rs
+++ b/crates/completion/src/completions/qualified_path.rs
@@ -118,6 +118,12 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
118 _ => return, 118 _ => return,
119 }; 119 };
120 120
121 if let Some(Adt::Enum(e)) = ty.as_adt() {
122 for variant in e.variants(ctx.db) {
123 acc.add_enum_variant(ctx, variant, None);
124 }
125 }
126
121 let traits_in_scope = ctx.scope.traits_in_scope(); 127 let traits_in_scope = ctx.scope.traits_in_scope();
122 let mut seen = FxHashSet::default(); 128 let mut seen = FxHashSet::default();
123 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { 129 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
@@ -752,4 +758,27 @@ fn main() {
752 "#]], 758 "#]],
753 ); 759 );
754 } 760 }
761
762 #[test]
763 fn completes_self_enum() {
764 check(
765 r#"
766enum Foo {
767 Bar,
768 Baz,
769}
770
771impl Foo {
772 fn foo(self) {
773 Self::<|>
774 }
775}
776"#,
777 expect![[r#"
778 ev Bar ()
779 ev Baz ()
780 me foo(…) fn foo(self)
781 "#]],
782 );
783 }
755} 784}
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index 099ffb4d4..d09849752 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -1,5 +1,7 @@
1//! Completion of names from the current scope, e.g. locals and imported items. 1//! Completion of names from the current scope, e.g. locals and imported items.
2 2
3use std::iter;
4
3use either::Either; 5use either::Either;
4use hir::{Adt, ModPath, ModuleDef, ScopeDef, Type}; 6use hir::{Adt, ModPath, ModuleDef, ScopeDef, Type};
5use ide_db::helpers::insert_use::ImportScope; 7use ide_db::helpers::insert_use::ImportScope;
@@ -50,7 +52,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
50} 52}
51 53
52fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { 54fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) {
53 if let Some(Adt::Enum(enum_data)) = ty.as_adt() { 55 if let Some(Adt::Enum(enum_data)) =
56 iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt())
57 {
54 let variants = enum_data.variants(ctx.db); 58 let variants = enum_data.variants(ctx.db);
55 59
56 let module = if let Some(module) = ctx.scope.module() { 60 let module = if let Some(module) = ctx.scope.module() {
@@ -701,6 +705,7 @@ fn main() { <|> }
701 "#]], 705 "#]],
702 ); 706 );
703 } 707 }
708
704 #[test] 709 #[test]
705 fn completes_enum_variant_matcharm() { 710 fn completes_enum_variant_matcharm() {
706 check( 711 check(
@@ -722,6 +727,26 @@ fn main() {
722 } 727 }
723 728
724 #[test] 729 #[test]
730 fn completes_enum_variant_matcharm_ref() {
731 check(
732 r#"
733enum Foo { Bar, Baz, Quux }
734
735fn main() {
736 let foo = Foo::Quux;
737 match &foo { Qu<|> }
738}
739"#,
740 expect![[r#"
741 ev Foo::Bar ()
742 ev Foo::Baz ()
743 ev Foo::Quux ()
744 en Foo
745 "#]],
746 )
747 }
748
749 #[test]
725 fn completes_enum_variant_iflet() { 750 fn completes_enum_variant_iflet() {
726 check( 751 check(
727 r#" 752 r#"
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 0f404be1b..978c3a324 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -933,7 +933,9 @@ impl ExprCollector<'_> {
933 Pat::Box { inner } 933 Pat::Box { inner }
934 } 934 }
935 // FIXME: implement 935 // FIXME: implement
936 ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, 936 ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) | ast::Pat::ConstBlockPat(_) => {
937 Pat::Missing
938 }
937 }; 939 };
938 let ptr = AstPtr::new(&pat); 940 let ptr = AstPtr::new(&pat);
939 self.alloc_pat(pattern, Either::Left(ptr)) 941 self.alloc_pat(pattern, Either::Left(ptr))
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index e897d5a52..c7a3556a7 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -46,6 +46,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
46 T![continue], 46 T![continue],
47 T![async], 47 T![async],
48 T![try], 48 T![try],
49 T![const],
49 T![loop], 50 T![loop],
50 T![for], 51 T![for],
51 LIFETIME_IDENT, 52 LIFETIME_IDENT,
@@ -115,6 +116,14 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
115 block_expr(p); 116 block_expr(p);
116 m.complete(p, EFFECT_EXPR) 117 m.complete(p, EFFECT_EXPR)
117 } 118 }
119 // test const_block
120 // fn f() { const { } }
121 T![const] if la == T!['{'] => {
122 let m = p.start();
123 p.bump(T![const]);
124 block_expr(p);
125 m.complete(p, EFFECT_EXPR)
126 }
118 T!['{'] => { 127 T!['{'] => {
119 // test for_range_from 128 // test for_range_from
120 // fn foo() { 129 // fn foo() {
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index 8999829b4..72b73f891 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -96,7 +96,10 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
96 let mut has_mods = false; 96 let mut has_mods = false;
97 97
98 // modifiers 98 // modifiers
99 has_mods |= p.eat(T![const]); 99 if p.at(T![const]) && p.nth(1) != T!['{'] {
100 p.eat(T![const]);
101 has_mods = true;
102 }
100 103
101 // test_err async_without_semicolon 104 // test_err async_without_semicolon
102 // fn foo() { let _ = async {} } 105 // fn foo() { let _ = async {} }
@@ -167,7 +170,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
167 m.complete(p, TRAIT); 170 m.complete(p, TRAIT);
168 } 171 }
169 172
170 T![const] => { 173 T![const] if p.nth(1) != T!['{'] => {
171 consts::konst(p, m); 174 consts::konst(p, m);
172 } 175 }
173 176
diff --git a/crates/parser/src/grammar/patterns.rs b/crates/parser/src/grammar/patterns.rs
index 7e7f73dee..b53d5749f 100644
--- a/crates/parser/src/grammar/patterns.rs
+++ b/crates/parser/src/grammar/patterns.rs
@@ -89,6 +89,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
89 let m = match p.nth(0) { 89 let m = match p.nth(0) {
90 T![box] => box_pat(p), 90 T![box] => box_pat(p),
91 T![ref] | T![mut] => ident_pat(p, true), 91 T![ref] | T![mut] => ident_pat(p, true),
92 T![const] => const_block_pat(p),
92 IDENT => match p.nth(1) { 93 IDENT => match p.nth(1) {
93 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro 94 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
94 // (T![x]). 95 // (T![x]).
@@ -386,3 +387,16 @@ fn box_pat(p: &mut Parser) -> CompletedMarker {
386 pattern_single(p); 387 pattern_single(p);
387 m.complete(p, BOX_PAT) 388 m.complete(p, BOX_PAT)
388} 389}
390
391// test const_block_pat
392// fn main() {
393// let const { 15 } = ();
394// let const { foo(); bar() } = ();
395// }
396fn const_block_pat(p: &mut Parser) -> CompletedMarker {
397 assert!(p.at(T![const]));
398 let m = p.start();
399 p.bump(T![const]);
400 expressions::block_expr(p);
401 m.complete(p, CONST_BLOCK_PAT)
402}
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index 980aa5979..f69e71bdb 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -170,6 +170,7 @@ pub enum SyntaxKind {
170 RANGE_PAT, 170 RANGE_PAT,
171 LITERAL_PAT, 171 LITERAL_PAT,
172 MACRO_PAT, 172 MACRO_PAT,
173 CONST_BLOCK_PAT,
173 TUPLE_EXPR, 174 TUPLE_EXPR,
174 ARRAY_EXPR, 175 ARRAY_EXPR,
175 PAREN_EXPR, 176 PAREN_EXPR,
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 1588ba93e..c5b80bffe 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -763,6 +763,7 @@ impl EffectExpr {
763 pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) } 763 pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
764 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } 764 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
765 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } 765 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
766 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
766 pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) } 767 pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
767} 768}
768#[derive(Debug, Clone, PartialEq, Eq, Hash)] 769#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1251,6 +1252,14 @@ impl TupleStructPat {
1251 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 1252 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
1252} 1253}
1253#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1254#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1255pub struct ConstBlockPat {
1256 pub(crate) syntax: SyntaxNode,
1257}
1258impl ConstBlockPat {
1259 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
1260 pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
1261}
1262#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1254pub struct RecordPatFieldList { 1263pub struct RecordPatFieldList {
1255 pub(crate) syntax: SyntaxNode, 1264 pub(crate) syntax: SyntaxNode,
1256} 1265}
@@ -1369,6 +1378,7 @@ pub enum Pat {
1369 SlicePat(SlicePat), 1378 SlicePat(SlicePat),
1370 TuplePat(TuplePat), 1379 TuplePat(TuplePat),
1371 TupleStructPat(TupleStructPat), 1380 TupleStructPat(TupleStructPat),
1381 ConstBlockPat(ConstBlockPat),
1372} 1382}
1373#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1383#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1374pub enum FieldList { 1384pub enum FieldList {
@@ -2772,6 +2782,17 @@ impl AstNode for TupleStructPat {
2772 } 2782 }
2773 fn syntax(&self) -> &SyntaxNode { &self.syntax } 2783 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2774} 2784}
2785impl AstNode for ConstBlockPat {
2786 fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_BLOCK_PAT }
2787 fn cast(syntax: SyntaxNode) -> Option<Self> {
2788 if Self::can_cast(syntax.kind()) {
2789 Some(Self { syntax })
2790 } else {
2791 None
2792 }
2793 }
2794 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2795}
2775impl AstNode for RecordPatFieldList { 2796impl AstNode for RecordPatFieldList {
2776 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST } 2797 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST }
2777 fn cast(syntax: SyntaxNode) -> Option<Self> { 2798 fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3242,12 +3263,15 @@ impl From<TuplePat> for Pat {
3242impl From<TupleStructPat> for Pat { 3263impl From<TupleStructPat> for Pat {
3243 fn from(node: TupleStructPat) -> Pat { Pat::TupleStructPat(node) } 3264 fn from(node: TupleStructPat) -> Pat { Pat::TupleStructPat(node) }
3244} 3265}
3266impl From<ConstBlockPat> for Pat {
3267 fn from(node: ConstBlockPat) -> Pat { Pat::ConstBlockPat(node) }
3268}
3245impl AstNode for Pat { 3269impl AstNode for Pat {
3246 fn can_cast(kind: SyntaxKind) -> bool { 3270 fn can_cast(kind: SyntaxKind) -> bool {
3247 match kind { 3271 match kind {
3248 IDENT_PAT | BOX_PAT | REST_PAT | LITERAL_PAT | MACRO_PAT | OR_PAT | PAREN_PAT 3272 IDENT_PAT | BOX_PAT | REST_PAT | LITERAL_PAT | MACRO_PAT | OR_PAT | PAREN_PAT
3249 | PATH_PAT | WILDCARD_PAT | RANGE_PAT | RECORD_PAT | REF_PAT | SLICE_PAT 3273 | PATH_PAT | WILDCARD_PAT | RANGE_PAT | RECORD_PAT | REF_PAT | SLICE_PAT
3250 | TUPLE_PAT | TUPLE_STRUCT_PAT => true, 3274 | TUPLE_PAT | TUPLE_STRUCT_PAT | CONST_BLOCK_PAT => true,
3251 _ => false, 3275 _ => false,
3252 } 3276 }
3253 } 3277 }
@@ -3268,6 +3292,7 @@ impl AstNode for Pat {
3268 SLICE_PAT => Pat::SlicePat(SlicePat { syntax }), 3292 SLICE_PAT => Pat::SlicePat(SlicePat { syntax }),
3269 TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }), 3293 TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }),
3270 TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }), 3294 TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }),
3295 CONST_BLOCK_PAT => Pat::ConstBlockPat(ConstBlockPat { syntax }),
3271 _ => return None, 3296 _ => return None,
3272 }; 3297 };
3273 Some(res) 3298 Some(res)
@@ -3289,6 +3314,7 @@ impl AstNode for Pat {
3289 Pat::SlicePat(it) => &it.syntax, 3314 Pat::SlicePat(it) => &it.syntax,
3290 Pat::TuplePat(it) => &it.syntax, 3315 Pat::TuplePat(it) => &it.syntax,
3291 Pat::TupleStructPat(it) => &it.syntax, 3316 Pat::TupleStructPat(it) => &it.syntax,
3317 Pat::ConstBlockPat(it) => &it.syntax,
3292 } 3318 }
3293 } 3319 }
3294} 3320}
@@ -4137,6 +4163,11 @@ impl std::fmt::Display for TupleStructPat {
4137 std::fmt::Display::fmt(self.syntax(), f) 4163 std::fmt::Display::fmt(self.syntax(), f)
4138 } 4164 }
4139} 4165}
4166impl std::fmt::Display for ConstBlockPat {
4167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4168 std::fmt::Display::fmt(self.syntax(), f)
4169 }
4170}
4140impl std::fmt::Display for RecordPatFieldList { 4171impl std::fmt::Display for RecordPatFieldList {
4141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 4172 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4142 std::fmt::Display::fmt(self.syntax(), f) 4173 std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index ba7e5d2fb..cafa4c198 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -4,6 +4,11 @@
4//! Note that all functions here intended to be stupid constructors, which just 4//! Note that all functions here intended to be stupid constructors, which just
5//! assemble a finish node from immediate children. If you want to do something 5//! assemble a finish node from immediate children. If you want to do something
6//! smarter than that, it probably doesn't belong in this module. 6//! smarter than that, it probably doesn't belong in this module.
7//!
8//! Keep in mind that `from_text` functions should be kept private. The public
9//! API should require to assemble every node piecewise. The trick of
10//! `parse(format!())` we use internally is an implementation detail -- long
11//! term, it will be replaced with direct tree manipulation.
7use itertools::Itertools; 12use itertools::Itertools;
8use stdx::format_to; 13use stdx::format_to;
9 14
@@ -16,7 +21,8 @@ pub fn name(text: &str) -> ast::Name {
16pub fn name_ref(text: &str) -> ast::NameRef { 21pub fn name_ref(text: &str) -> ast::NameRef {
17 ast_from_text(&format!("fn f() {{ {}; }}", text)) 22 ast_from_text(&format!("fn f() {{ {}; }}", text))
18} 23}
19 24// FIXME: replace stringly-typed constructor with a family of typed ctors, a-la
25// `expr_xxx`.
20pub fn ty(text: &str) -> ast::Type { 26pub fn ty(text: &str) -> ast::Type {
21 ast_from_text(&format!("impl {} for D {{}};", text)) 27 ast_from_text(&format!("impl {} for D {{}};", text))
22} 28}
diff --git a/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rast b/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rast
new file mode 100644
index 000000000..8ff4822c4
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rast
@@ -0,0 +1,76 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "main"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] "\n "
14 [email protected]
15 [email protected] "let"
16 [email protected] " "
17 [email protected]
18 [email protected] "const"
19 [email protected] " "
20 [email protected]
21 [email protected] "{"
22 [email protected] " "
23 [email protected]
24 [email protected] "15"
25 [email protected] " "
26 [email protected] "}"
27 [email protected] " "
28 [email protected] "="
29 [email protected] " "
30 [email protected]
31 [email protected] "("
32 [email protected] ")"
33 [email protected] ";"
34 [email protected] "\n "
35 [email protected]
36 [email protected] "let"
37 [email protected] " "
38 [email protected]
39 [email protected] "const"
40 [email protected] " "
41 [email protected]
42 [email protected] "{"
43 [email protected] " "
44 [email protected]
45 [email protected]
46 [email protected]
47 [email protected]
48 [email protected]
49 [email protected]
50 [email protected] "foo"
51 [email protected]
52 [email protected] "("
53 [email protected] ")"
54 [email protected] ";"
55 [email protected] " "
56 [email protected]
57 [email protected]
58 [email protected]
59 [email protected]
60 [email protected]
61 [email protected] "bar"
62 [email protected]
63 [email protected] "("
64 [email protected] ")"
65 [email protected] " "
66 [email protected] "}"
67 [email protected] " "
68 [email protected] "="
69 [email protected] " "
70 [email protected]
71 [email protected] "("
72 [email protected] ")"
73 [email protected] ";"
74 [email protected] "\n"
75 [email protected] "}"
76 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rs b/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rs
new file mode 100644
index 000000000..dce9defac
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rs
@@ -0,0 +1,4 @@
1fn main() {
2 let const { 15 } = ();
3 let const { foo(); bar() } = ();
4}
diff --git a/crates/syntax/test_data/parser/inline/ok/0157_const_block.rast b/crates/syntax/test_data/parser/inline/ok/0157_const_block.rast
new file mode 100644
index 000000000..d5d2c8fe3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0157_const_block.rast
@@ -0,0 +1,23 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "f"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] " "
14 [email protected]
15 [email protected] "const"
16 [email protected] " "
17 [email protected]
18 [email protected] "{"
19 [email protected] " "
20 [email protected] "}"
21 [email protected] " "
22 [email protected] "}"
23 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0157_const_block.rs b/crates/syntax/test_data/parser/inline/ok/0157_const_block.rs
new file mode 100644
index 000000000..a2e3565a3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0157_const_block.rs
@@ -0,0 +1 @@
fn f() { const { } }
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index 78a0b54ba..96b4ea448 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -15,7 +15,7 @@ flate2 = "1.0"
15pico-args = "0.3.1" 15pico-args = "0.3.1"
16proc-macro2 = "1.0.8" 16proc-macro2 = "1.0.8"
17quote = "1.0.2" 17quote = "1.0.2"
18ungrammar = "1.4" 18ungrammar = "1.5"
19walkdir = "2.3.1" 19walkdir = "2.3.1"
20write-json = "0.1.0" 20write-json = "0.1.0"
21xshell = "0.1" 21xshell = "0.1"
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index a69ced5cc..2b8012bdd 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -132,6 +132,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
132 "RANGE_PAT", 132 "RANGE_PAT",
133 "LITERAL_PAT", 133 "LITERAL_PAT",
134 "MACRO_PAT", 134 "MACRO_PAT",
135 "CONST_BLOCK_PAT",
135 // atoms 136 // atoms
136 "TUPLE_EXPR", 137 "TUPLE_EXPR",
137 "ARRAY_EXPR", 138 "ARRAY_EXPR",