Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.lock4
-rw-r--r--crates/hir_def/src/body/lower.rs1
-rw-r--r--crates/ide_assists/src/handlers/extract_module.rs29
-rw-r--r--crates/ide_db/src/helpers.rs1
-rw-r--r--crates/mbe/src/expander/matcher.rs12
-rw-r--r--crates/parser/src/grammar/expressions.rs11
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs11
-rw-r--r--crates/parser/src/syntax_kind/generated.rs1
-rw-r--r--crates/parser/test_data/parser/err/0025_nope.rast204
-rw-r--r--crates/parser/test_data/parser/err/0025_nope.rs3
-rw-r--r--crates/parser/test_data/parser/err/0025_nope.txt21
-rw-r--r--crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rs3
-rw-r--r--crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.txt44
-rw-r--r--crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rs4
-rw-r--r--crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.txt50
-rw-r--r--crates/parser/test_data/parser/ok/0072_destructuring_assignment.rs14
-rw-r--r--crates/parser/test_data/parser/ok/0072_destructuring_assignment.txt352
-rw-r--r--crates/syntax/Cargo.toml2
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs35
-rw-r--r--crates/syntax/src/tests/ast_src.rs1
20 files changed, 582 insertions, 221 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3f2ee2c572..9cc5a73c96 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1833,9 +1833,9 @@ checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
[[package]]
name = "ungrammar"
-version = "1.15.0"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed01567101450f7d600508e7680df6005ae4fe97119d79b0364cc5910ff39732"
+checksum = "a62374cbbda72c1459ce5e7bfcdf1bd284c812a4faf2324aa083e5d9ea87880f"
[[package]]
name = "unicase"
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index a2b57cb5bd..f86f4f3c85 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -525,6 +525,7 @@ impl ExprCollector<'_> {
self.alloc_expr(Expr::MacroStmts { tail }, syntax_ptr)
}
+ ast::Expr::UnderscoreExpr(_) => return None,
})
}
diff --git a/crates/ide_assists/src/handlers/extract_module.rs b/crates/ide_assists/src/handlers/extract_module.rs
index 64875adfae..880617dd38 100644
--- a/crates/ide_assists/src/handlers/extract_module.rs
+++ b/crates/ide_assists/src/handlers/extract_module.rs
@@ -179,7 +179,7 @@ impl Module {
//Here impl is not included as each item inside impl will be tied to the parent of
//implementing block(a struct, enum, etc), if the parent is in selected module, it will
//get updated by ADT section given below or if it is not, then we dont need to do any operation
- self.body_items.clone().into_iter().for_each(|item| {
+ self.body_items.iter().cloned().for_each(|item| {
match_ast! {
match (item.syntax()) {
ast::Adt(it) => {
@@ -240,6 +240,11 @@ impl Module {
self.expand_and_group_usages_file_wise(ctx, node_def, &mut refs);
}
},
+ ast::Macro(it) => {
+ if let Some(nod) = ctx.sema.to_def(&it) {
+ self.expand_and_group_usages_file_wise(ctx, Definition::Macro(nod), &mut refs);
+ }
+ },
_ => (),
}
}
@@ -781,7 +786,6 @@ fn get_replacements_for_visibilty_change(
ast::Item::Fn(it) => replacements.push((it.visibility(), it.syntax().clone())),
//Associated item's visibility should not be changed
ast::Item::Impl(it) if it.for_token().is_none() => impls.push(it),
- ast::Item::MacroRules(it) => replacements.push((it.visibility(), it.syntax().clone())),
ast::Item::MacroDef(it) => replacements.push((it.visibility(), it.syntax().clone())),
ast::Item::Module(it) => replacements.push((it.visibility(), it.syntax().clone())),
ast::Item::Static(it) => replacements.push((it.visibility(), it.syntax().clone())),
@@ -1377,6 +1381,27 @@ mod modname {
}
#[test]
+ fn test_extract_module_macro_rules() {
+ check_assist(
+ extract_module,
+ r"
+$0macro_rules! m {
+ () => {};
+}$0
+m! {}
+ ",
+ r"
+mod modname {
+ macro_rules! m {
+ () => {};
+ }
+}
+modname::m! {}
+ ",
+ );
+ }
+
+ #[test]
fn test_do_not_apply_visibility_modifier_to_trait_impl_items() {
check_assist(
extract_module,
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
index fcad172984..4a14a7f849 100644
--- a/crates/ide_db/src/helpers.rs
+++ b/crates/ide_db/src/helpers.rs
@@ -187,6 +187,7 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
| ast::Expr::TupleExpr(_)
| ast::Expr::WhileExpr(_)
| ast::Expr::LetExpr(_)
+ | ast::Expr::UnderscoreExpr(_)
| ast::Expr::YieldExpr(_) => cb(expr),
}
}
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 944d3ef87d..aefb3d059f 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -690,9 +690,19 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragmen
"item" => parser::PrefixEntryPoint::Item,
"vis" => parser::PrefixEntryPoint::Vis,
"expr" => {
+ // `expr` should not match underscores.
+ // HACK: Macro expansion should not be done using "rollback and try another alternative".
+ // rustc [explicitly checks the next token][0].
+ // [0]: https://github.com/rust-lang/rust/blob/f0c4da499/compiler/rustc_expand/src/mbe/macro_parser.rs#L576
+ match input.peek_n(0) {
+ Some(tt::TokenTree::Leaf(tt::Leaf::Ident(it))) if it.text == "_" => {
+ return ExpandResult::only_err(ExpandError::NoMatchingRule)
+ }
+ _ => {}
+ };
return input
.expect_fragment(parser::PrefixEntryPoint::Expr)
- .map(|tt| tt.map(Fragment::Expr))
+ .map(|tt| tt.map(Fragment::Expr));
}
_ => {
let tt_result = match kind {
diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs
index a40db15049..5d652fb8dc 100644
--- a/crates/parser/src/grammar/expressions.rs
+++ b/crates/parser/src/grammar/expressions.rs
@@ -593,7 +593,16 @@ pub(crate) fn record_expr_field_list(p: &mut Parser) {
T![.] if p.at(T![..]) => {
m.abandon(p);
p.bump(T![..]);
- expr(p);
+
+ // test destructuring_assignment_struct_rest_pattern
+ // fn foo() {
+ // S { .. } = S {};
+ // }
+
+ // We permit `.. }` on the left-hand side of a destructuring assignment.
+ if !p.at(T!['}']) {
+ expr(p);
+ }
}
T!['{'] => {
error_block(p, "expected a field");
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index e2c1b1fec5..e5f8e8199e 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -81,6 +81,17 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
T![if] => if_expr(p),
T![let] => let_expr(p),
+ T![_] => {
+ // test destructuring_assignment_wildcard_pat
+ // fn foo() {
+ // _ = 1;
+ // Some(_) = None;
+ // }
+ let m = p.start();
+ p.bump(T![_]);
+ m.complete(p, UNDERSCORE_EXPR)
+ }
+
T![loop] => loop_expr(p, None),
T![box] => box_expr(p, None),
T![for] => for_expr(p, None),
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index d04b5dbf00..4e8a0cfe80 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -188,6 +188,7 @@ pub enum SyntaxKind {
RETURN_EXPR,
YIELD_EXPR,
LET_EXPR,
+ UNDERSCORE_EXPR,
MATCH_EXPR,
MATCH_ARM_LIST,
MATCH_ARM,
diff --git a/crates/parser/test_data/parser/err/0025_nope.rast b/crates/parser/test_data/parser/err/0025_nope.rast
deleted file mode 100644
index b48b4aed8d..0000000000
--- a/crates/parser/test_data/parser/err/0025_nope.rast
+++ /dev/null
@@ -1,204 +0,0 @@
- [email protected] "//~ ERROR: expected t ..."
- [email protected] "// recover..."
- [email protected] "StillFine"
- [email protected] "// fail again"
- [email protected] "//~ ERROR: found `{`"
- [email protected] "//~^ ERROR: found `{`"
- [email protected] "// still recover later"
- [email protected] "bad_syntax"
- [email protected] "//~ ERROR: expected e ..."
-error 95..95: expected type
-error 95..95: expected COMMA
-error 96..96: expected field
-error 98..98: expected field declaration
-error 371..371: expected COMMA
-error 372..372: expected a type
-error 372..372: expected R_PAREN
-error 372..372: expected COMMA
-error 372..372: expected enum variant
-error 374..374: expected enum variant
-error 508..508: expected expression
diff --git a/crates/parser/test_data/parser/err/0025_nope.rs b/crates/parser/test_data/parser/err/0025_nope.rs
index 28726ed513..c78abe80ab 100644
--- a/crates/parser/test_data/parser/err/0025_nope.rs
+++ b/crates/parser/test_data/parser/err/0025_nope.rs
@@ -27,5 +27,6 @@ fn main() {
}
}
// still recover later
- let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_`
+ let; //~ ERROR: expected pattern
+ let _ = 0;
}
diff --git a/crates/parser/test_data/parser/err/0025_nope.txt b/crates/parser/test_data/parser/err/0025_nope.txt
index aca57faf96..6b49724ec9 100644
--- a/crates/parser/test_data/parser/err/0025_nope.txt
+++ b/crates/parser/test_data/parser/err/0025_nope.txt
@@ -176,18 +176,22 @@ SOURCE_FILE
WHITESPACE "\n "
LET_STMT
LET_KW "let"
+ ERROR
+ SEMICOLON ";"
+ WHITESPACE " "
+ COMMENT "//~ ERROR: expected pattern"
+ WHITESPACE "\n "
+ LET_STMT
+ LET_KW "let"
WHITESPACE " "
- IDENT_PAT
- NAME
- IDENT "bad_syntax"
+ WILDCARD_PAT
+ UNDERSCORE "_"
WHITESPACE " "
EQ "="
WHITESPACE " "
- ERROR
- UNDERSCORE "_"
+ LITERAL
+ INT_NUMBER "0"
SEMICOLON ";"
- WHITESPACE " "
- COMMENT "//~ ERROR: expected expression, found reserved identifier `_`"
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"
@@ -201,4 +205,5 @@ error 372: expected R_PAREN
error 372: expected COMMA
error 372: expected enum variant
error 374: expected enum variant
-error 508: expected expression
+error 494: expected pattern
+error 495: expected SEMICOLON
diff --git a/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rs b/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rs
new file mode 100644
index 0000000000..22a5b5f3e3
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rs
@@ -0,0 +1,3 @@
+fn foo() {
+ S { .. } = S {};
+}
diff --git a/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.txt b/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.txt
new file mode 100644
index 0000000000..fb8aa5accb
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.txt
@@ -0,0 +1,44 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "foo"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ RECORD_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ WHITESPACE " "
+ RECORD_EXPR_FIELD_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ DOT2 ".."
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ RECORD_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ WHITESPACE " "
+ RECORD_EXPR_FIELD_LIST
+ L_CURLY "{"
+ R_CURLY "}"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ R_CURLY "}"
+ WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rs b/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rs
new file mode 100644
index 0000000000..91acfb3a0a
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rs
@@ -0,0 +1,4 @@
+fn foo() {
+ _ = 1;
+ Some(_) = None;
+}
diff --git a/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.txt b/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.txt
new file mode 100644
index 0000000000..5f53d34510
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.txt
@@ -0,0 +1,50 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "foo"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ UNDERSCORE_EXPR
+ UNDERSCORE "_"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "1"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ CALL_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Some"
+ ARG_LIST
+ L_PAREN "("
+ UNDERSCORE_EXPR
+ UNDERSCORE "_"
+ R_PAREN ")"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "None"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ R_CURLY "}"
+ WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/ok/0072_destructuring_assignment.rs b/crates/parser/test_data/parser/ok/0072_destructuring_assignment.rs
new file mode 100644
index 0000000000..9d3e86603f
--- /dev/null
+++ b/crates/parser/test_data/parser/ok/0072_destructuring_assignment.rs
@@ -0,0 +1,14 @@
+fn foo() {
+ let (mut a, mut b) = (0, 1);
+ (b, a, ..) = (a, b);
+ (_) = ..;
+ struct S { a: i32 }
+ S { .. } = S { ..S::default() };
+ Some(..) = Some(0).
+ Ok(_) = 0;
+ let (a, b);
+ [a, .., b] = [1, .., 2];
+ (_, _) = (a, b);
+ (_) = (a, b);
+ _ = (a, b);
+}
diff --git a/crates/parser/test_data/parser/ok/0072_destructuring_assignment.txt b/crates/parser/test_data/parser/ok/0072_destructuring_assignment.txt
new file mode 100644
index 0000000000..e8b836dfbd
--- /dev/null
+++ b/crates/parser/test_data/parser/ok/0072_destructuring_assignment.txt
@@ -0,0 +1,352 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "foo"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ LET_STMT
+ LET_KW "let"
+ WHITESPACE " "
+ TUPLE_PAT
+ L_PAREN "("
+ IDENT_PAT
+ MUT_KW "mut"
+ WHITESPACE " "
+ NAME
+ IDENT "a"
+ COMMA ","
+ WHITESPACE " "
+ IDENT_PAT
+ MUT_KW "mut"
+ WHITESPACE " "
+ NAME
+ IDENT "b"
+ R_PAREN ")"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ TUPLE_EXPR
+ L_PAREN "("
+ LITERAL
+ INT_NUMBER "0"
+ COMMA ","
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "1"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ TUPLE_EXPR
+ L_PAREN "("
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "b"
+ COMMA ","
+ WHITESPACE " "
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "a"
+ COMMA ","
+ WHITESPACE " "
+ RANGE_EXPR
+ DOT2 ".."
+ R_PAREN ")"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ TUPLE_EXPR
+ L_PAREN "("
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "a"
+ COMMA ","
+ WHITESPACE " "
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "b"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ PAREN_EXPR
+ L_PAREN "("
+ UNDERSCORE_EXPR
+ UNDERSCORE "_"
+ R_PAREN ")"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ RANGE_EXPR
+ DOT2 ".."
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ STRUCT
+ STRUCT_KW "struct"
+ WHITESPACE " "
+ NAME
+ IDENT "S"
+ WHITESPACE " "
+ RECORD_FIELD_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ RECORD_FIELD
+ NAME
+ IDENT "a"
+ COLON ":"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ RECORD_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ WHITESPACE " "
+ RECORD_EXPR_FIELD_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ DOT2 ".."
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ RECORD_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ WHITESPACE " "
+ RECORD_EXPR_FIELD_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ DOT2 ".."
+ CALL_EXPR
+ PATH_EXPR
+ PATH
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ COLON2 "::"
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "default"
+ ARG_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ R_CURLY "}"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ BIN_EXPR
+ CALL_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Some"
+ ARG_LIST
+ L_PAREN "("
+ RANGE_EXPR
+ DOT2 ".."
+ R_PAREN ")"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ METHOD_CALL_EXPR
+ CALL_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Some"
+ ARG_LIST
+ L_PAREN "("
+ LITERAL
+ INT_NUMBER "0"
+ R_PAREN ")"
+ DOT "."
+ WHITESPACE "\n "
+ NAME_REF
+ IDENT "Ok"
+ ARG_LIST
+ L_PAREN "("
+ UNDERSCORE_EXPR
+ UNDERSCORE "_"
+ R_PAREN ")"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "0"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ LET_STMT
+ LET_KW "let"
+ WHITESPACE " "
+ TUPLE_PAT
+ L_PAREN "("
+ IDENT_PAT
+ NAME
+ IDENT "a"
+ COMMA ","
+ WHITESPACE " "
+ IDENT_PAT
+ NAME
+ IDENT "b"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ ARRAY_EXPR
+ L_BRACK "["
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "a"
+ COMMA ","
+ WHITESPACE " "
+ RANGE_EXPR
+ DOT2 ".."
+ COMMA ","
+ WHITESPACE " "
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "b"
+ R_BRACK "]"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ ARRAY_EXPR
+ L_BRACK "["
+ LITERAL
+ INT_NUMBER "1"
+ COMMA ","
+ WHITESPACE " "
+ RANGE_EXPR
+ DOT2 ".."
+ COMMA ","
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "2"
+ R_BRACK "]"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ TUPLE_EXPR
+ L_PAREN "("
+ UNDERSCORE_EXPR
+ UNDERSCORE "_"
+ COMMA ","
+ WHITESPACE " "
+ UNDERSCORE_EXPR
+ UNDERSCORE "_"
+ R_PAREN ")"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ TUPLE_EXPR
+ L_PAREN "("
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "a"
+ COMMA ","
+ WHITESPACE " "
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "b"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ PAREN_EXPR
+ L_PAREN "("
+ UNDERSCORE_EXPR
+ UNDERSCORE "_"
+ R_PAREN ")"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ TUPLE_EXPR
+ L_PAREN "("
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "a"
+ COMMA ","
+ WHITESPACE " "
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "b"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ BIN_EXPR
+ UNDERSCORE_EXPR
+ UNDERSCORE "_"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ TUPLE_EXPR
+ L_PAREN "("
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "a"
+ COMMA ","
+ WHITESPACE " "
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "b"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ R_CURLY "}"
+ WHITESPACE "\n"
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index f59cd4f257..8baea77075 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -30,7 +30,7 @@ rayon = "1"
expect-test = "1.2.0-pre.1"
proc-macro2 = "1.0.8"
quote = "1.0.2"
-ungrammar = "=1.15.0"
+ungrammar = "=1.16.0"
test_utils = { path = "../test_utils" }
sourcegen = { path = "../sourcegen" }
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 11247fbf1c..fc1ee6f601 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -262,6 +262,7 @@ pub struct ExternBlock {
impl ast::HasAttrs for ExternBlock {}
impl ast::HasDocComments for ExternBlock {}
impl ExternBlock {
+ pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) }
}
@@ -1063,6 +1064,15 @@ impl LetExpr {
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct UnderscoreExpr {
+ pub(crate) syntax: SyntaxNode,
+}
+impl ast::HasAttrs for UnderscoreExpr {}
+impl UnderscoreExpr {
+ pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct StmtList {
pub(crate) syntax: SyntaxNode,
}
@@ -1522,6 +1532,7 @@ pub enum Expr {
WhileExpr(WhileExpr),
YieldExpr(YieldExpr),
LetExpr(LetExpr),
+ UnderscoreExpr(UnderscoreExpr),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -2673,6 +2684,17 @@ impl AstNode for LetExpr {
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
+impl AstNode for UnderscoreExpr {
+ fn can_cast(kind: SyntaxKind) -> bool { kind == UNDERSCORE_EXPR }
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ if Self::can_cast(syntax.kind()) {
+ Some(Self { syntax })
+ } else {
+ None
+ }
+ }
+ fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
impl AstNode for StmtList {
fn can_cast(kind: SyntaxKind) -> bool { kind == STMT_LIST }
fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3337,6 +3359,9 @@ impl From<YieldExpr> for Expr {
impl From<LetExpr> for Expr {
fn from(node: LetExpr) -> Expr { Expr::LetExpr(node) }
}
+impl From<UnderscoreExpr> for Expr {
+ fn from(node: UnderscoreExpr) -> Expr { Expr::UnderscoreExpr(node) }
+}
impl AstNode for Expr {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
@@ -3345,7 +3370,7 @@ impl AstNode for Expr {
| INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MACRO_STMTS | MATCH_EXPR
| METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR
| RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR
- | YIELD_EXPR | LET_EXPR => true,
+ | YIELD_EXPR | LET_EXPR | UNDERSCORE_EXPR => true,
_ => false,
}
}
@@ -3383,6 +3408,7 @@ impl AstNode for Expr {
WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }),
YIELD_EXPR => Expr::YieldExpr(YieldExpr { syntax }),
LET_EXPR => Expr::LetExpr(LetExpr { syntax }),
+ UNDERSCORE_EXPR => Expr::UnderscoreExpr(UnderscoreExpr { syntax }),
_ => return None,
};
Some(res)
@@ -3421,6 +3447,7 @@ impl AstNode for Expr {
Expr::WhileExpr(it) => &it.syntax,
Expr::YieldExpr(it) => &it.syntax,
Expr::LetExpr(it) => &it.syntax,
+ Expr::UnderscoreExpr(it) => &it.syntax,
}
}
}
@@ -3887,6 +3914,7 @@ impl AstNode for AnyHasAttrs {
| WHILE_EXPR
| YIELD_EXPR
| LET_EXPR
+ | UNDERSCORE_EXPR
| STMT_LIST
| RECORD_EXPR_FIELD_LIST
| RECORD_EXPR_FIELD
@@ -4546,6 +4574,11 @@ impl std::fmt::Display for LetExpr {
std::fmt::Display::fmt(self.syntax(), f)
}
}
+impl std::fmt::Display for UnderscoreExpr {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
impl std::fmt::Display for StmtList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/tests/ast_src.rs b/crates/syntax/src/tests/ast_src.rs
index aeff851ce4..3152137fb8 100644
--- a/crates/syntax/src/tests/ast_src.rs
+++ b/crates/syntax/src/tests/ast_src.rs
@@ -143,6 +143,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
"RETURN_EXPR",
"YIELD_EXPR",
"LET_EXPR",
+ "UNDERSCORE_EXPR",
"MATCH_EXPR",
"MATCH_ARM_LIST",
"MATCH_ARM",