diff options
author | Zac Pullar-Strecker <[email protected]> | 2020-08-24 10:19:53 +0100 |
---|---|---|
committer | Zac Pullar-Strecker <[email protected]> | 2020-08-24 10:20:13 +0100 |
commit | 7bbca7a1b3f9293d2f5cc5745199bc5f8396f2f0 (patch) | |
tree | bdb47765991cb973b2cd5481a088fac636bd326c /xtask/src/codegen | |
parent | ca464650eeaca6195891199a93f4f76cf3e7e697 (diff) | |
parent | e65d48d1fb3d4d91d9dc1148a7a836ff5c9a3c87 (diff) |
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
Diffstat (limited to 'xtask/src/codegen')
-rw-r--r-- | xtask/src/codegen/gen_assists_docs.rs | 10 | ||||
-rw-r--r-- | xtask/src/codegen/gen_feature_docs.rs | 4 | ||||
-rw-r--r-- | xtask/src/codegen/gen_features.rs | 50 | ||||
-rw-r--r-- | xtask/src/codegen/gen_parser_tests.rs | 8 | ||||
-rw-r--r-- | xtask/src/codegen/gen_syntax.rs | 104 | ||||
-rw-r--r-- | xtask/src/codegen/rust.ungram | 621 |
6 files changed, 459 insertions, 338 deletions
diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index 526941f73..f0ded8b87 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::{fmt, fs, path::Path}; | 3 | use std::{fmt, fs, path::Path}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | codegen::{self, extract_comment_blocks_with_empty_lines, Location, Mode}, | 6 | codegen::{self, extract_comment_blocks_with_empty_lines, reformat, Location, Mode, PREAMBLE}, |
7 | project_root, rust_files, Result, | 7 | project_root, rust_files, Result, |
8 | }; | 8 | }; |
9 | 9 | ||
@@ -15,7 +15,7 @@ pub fn generate_assists_tests(mode: Mode) -> Result<()> { | |||
15 | pub fn generate_assists_docs(mode: Mode) -> Result<()> { | 15 | pub fn generate_assists_docs(mode: Mode) -> Result<()> { |
16 | let assists = Assist::collect()?; | 16 | let assists = Assist::collect()?; |
17 | let contents = assists.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); | 17 | let contents = assists.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); |
18 | let contents = contents.trim().to_string() + "\n"; | 18 | let contents = format!("//{}\n{}\n", PREAMBLE, contents.trim()); |
19 | let dst = project_root().join("docs/user/generated_assists.adoc"); | 19 | let dst = project_root().join("docs/user/generated_assists.adoc"); |
20 | codegen::update(&dst, &contents, mode) | 20 | codegen::update(&dst, &contents, mode) |
21 | } | 21 | } |
@@ -32,7 +32,7 @@ struct Assist { | |||
32 | impl Assist { | 32 | impl Assist { |
33 | fn collect() -> Result<Vec<Assist>> { | 33 | fn collect() -> Result<Vec<Assist>> { |
34 | let mut res = Vec::new(); | 34 | let mut res = Vec::new(); |
35 | for path in rust_files(&project_root().join(codegen::ASSISTS_DIR)) { | 35 | for path in rust_files(&project_root().join("crates/assists/src/handlers")) { |
36 | collect_file(&mut res, path.as_path())?; | 36 | collect_file(&mut res, path.as_path())?; |
37 | } | 37 | } |
38 | res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id)); | 38 | res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id)); |
@@ -134,8 +134,8 @@ r#####" | |||
134 | 134 | ||
135 | buf.push_str(&test) | 135 | buf.push_str(&test) |
136 | } | 136 | } |
137 | let buf = crate::reformat(buf)?; | 137 | let buf = reformat(buf)?; |
138 | codegen::update(&project_root().join(codegen::ASSISTS_TESTS), &buf, mode) | 138 | codegen::update(&project_root().join("crates/assists/src/tests/generated.rs"), &buf, mode) |
139 | } | 139 | } |
140 | 140 | ||
141 | fn hide_hash_comments(text: &str) -> String { | 141 | fn hide_hash_comments(text: &str) -> String { |
diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs index 31bc3839d..3f0013e82 100644 --- a/xtask/src/codegen/gen_feature_docs.rs +++ b/xtask/src/codegen/gen_feature_docs.rs | |||
@@ -3,14 +3,14 @@ | |||
3 | use std::{fmt, fs, path::PathBuf}; | 3 | use std::{fmt, fs, path::PathBuf}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | codegen::{self, extract_comment_blocks_with_empty_lines, Location, Mode}, | 6 | codegen::{self, extract_comment_blocks_with_empty_lines, Location, Mode, PREAMBLE}, |
7 | project_root, rust_files, Result, | 7 | project_root, rust_files, Result, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | pub fn generate_feature_docs(mode: Mode) -> Result<()> { | 10 | pub fn generate_feature_docs(mode: Mode) -> Result<()> { |
11 | let features = Feature::collect()?; | 11 | let features = Feature::collect()?; |
12 | let contents = features.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); | 12 | let contents = features.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); |
13 | let contents = contents.trim().to_string() + "\n"; | 13 | let contents = format!("//{}\n{}\n", PREAMBLE, contents.trim()); |
14 | let dst = project_root().join("docs/user/generated_features.adoc"); | 14 | let dst = project_root().join("docs/user/generated_features.adoc"); |
15 | codegen::update(&dst, &contents, mode)?; | 15 | codegen::update(&dst, &contents, mode)?; |
16 | Ok(()) | 16 | Ok(()) |
diff --git a/xtask/src/codegen/gen_features.rs b/xtask/src/codegen/gen_features.rs new file mode 100644 index 000000000..78268308b --- /dev/null +++ b/xtask/src/codegen/gen_features.rs | |||
@@ -0,0 +1,50 @@ | |||
1 | //! Generates descriptors structure for unstable feature from Unstable Book | ||
2 | use std::path::{Path, PathBuf}; | ||
3 | |||
4 | use quote::quote; | ||
5 | use walkdir::WalkDir; | ||
6 | |||
7 | use crate::{ | ||
8 | codegen::{project_root, reformat, update, Mode, Result}, | ||
9 | not_bash::{fs2, run}, | ||
10 | }; | ||
11 | |||
12 | pub fn generate_features(mode: Mode) -> Result<()> { | ||
13 | if !Path::new("./target/rust").exists() { | ||
14 | run!("git clone https://github.com/rust-lang/rust ./target/rust")?; | ||
15 | } | ||
16 | |||
17 | let contents = generate_descriptor("./target/rust/src/doc/unstable-book/src".into())?; | ||
18 | |||
19 | let destination = project_root().join("crates/ide/src/completion/generated_features.rs"); | ||
20 | update(destination.as_path(), &contents, mode)?; | ||
21 | |||
22 | Ok(()) | ||
23 | } | ||
24 | |||
25 | fn generate_descriptor(src_dir: PathBuf) -> Result<String> { | ||
26 | let definitions = ["language-features", "library-features"] | ||
27 | .iter() | ||
28 | .flat_map(|it| WalkDir::new(src_dir.join(it))) | ||
29 | .filter_map(|e| e.ok()) | ||
30 | .filter(|entry| { | ||
31 | // Get all `.md ` files | ||
32 | entry.file_type().is_file() && entry.path().extension().unwrap_or_default() == "md" | ||
33 | }) | ||
34 | .map(|entry| { | ||
35 | let path = entry.path(); | ||
36 | let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace("-", "_"); | ||
37 | let doc = fs2::read_to_string(path).unwrap(); | ||
38 | |||
39 | quote! { LintCompletion { label: #feature_ident, description: #doc } } | ||
40 | }); | ||
41 | |||
42 | let ts = quote! { | ||
43 | use crate::completion::complete_attribute::LintCompletion; | ||
44 | |||
45 | pub(super) const FEATURES: &[LintCompletion] = &[ | ||
46 | #(#definitions),* | ||
47 | ]; | ||
48 | }; | ||
49 | reformat(ts) | ||
50 | } | ||
diff --git a/xtask/src/codegen/gen_parser_tests.rs b/xtask/src/codegen/gen_parser_tests.rs index 2977da2fa..96fdd9216 100644 --- a/xtask/src/codegen/gen_parser_tests.rs +++ b/xtask/src/codegen/gen_parser_tests.rs | |||
@@ -8,12 +8,12 @@ use std::{ | |||
8 | }; | 8 | }; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | codegen::{self, extract_comment_blocks, update, Mode}, | 11 | codegen::{extract_comment_blocks, update, Mode}, |
12 | project_root, Result, | 12 | project_root, Result, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | pub fn generate_parser_tests(mode: Mode) -> Result<()> { | 15 | pub fn generate_parser_tests(mode: Mode) -> Result<()> { |
16 | let tests = tests_from_dir(&project_root().join(Path::new(codegen::GRAMMAR_DIR)))?; | 16 | let tests = tests_from_dir(&project_root().join(Path::new("crates/parser/src/grammar")))?; |
17 | fn install_tests(tests: &HashMap<String, Test>, into: &str, mode: Mode) -> Result<()> { | 17 | fn install_tests(tests: &HashMap<String, Test>, into: &str, mode: Mode) -> Result<()> { |
18 | let tests_dir = project_root().join(into); | 18 | let tests_dir = project_root().join(into); |
19 | if !tests_dir.is_dir() { | 19 | if !tests_dir.is_dir() { |
@@ -39,8 +39,8 @@ pub fn generate_parser_tests(mode: Mode) -> Result<()> { | |||
39 | } | 39 | } |
40 | Ok(()) | 40 | Ok(()) |
41 | } | 41 | } |
42 | install_tests(&tests.ok, codegen::OK_INLINE_TESTS_DIR, mode)?; | 42 | install_tests(&tests.ok, "crates/syntax/test_data/parser/inline/ok", mode)?; |
43 | install_tests(&tests.err, codegen::ERR_INLINE_TESTS_DIR, mode) | 43 | install_tests(&tests.err, "crates/syntax/test_data/parser/inline/err", mode) |
44 | } | 44 | } |
45 | 45 | ||
46 | #[derive(Debug)] | 46 | #[derive(Debug)] |
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 45b788bdb..200e8aa50 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! This module generates AST datatype used by rust-analyzer. | 1 | //! This module generates AST datatype used by rust-analyzer. |
2 | //! | 2 | //! |
3 | //! Specifically, it generates the `SyntaxKind` enum and a number of newtype | 3 | //! Specifically, it generates the `SyntaxKind` enum and a number of newtype |
4 | //! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`. | 4 | //! wrappers around `SyntaxNode` which implement `syntax::AstNode`. |
5 | 5 | ||
6 | use std::{ | 6 | use std::{ |
7 | collections::{BTreeSet, HashSet}, | 7 | collections::{BTreeSet, HashSet}, |
@@ -10,29 +10,27 @@ use std::{ | |||
10 | 10 | ||
11 | use proc_macro2::{Punct, Spacing}; | 11 | use proc_macro2::{Punct, Spacing}; |
12 | use quote::{format_ident, quote}; | 12 | use quote::{format_ident, quote}; |
13 | use ungrammar::{Grammar, Rule}; | 13 | use ungrammar::{rust_grammar, Grammar, Rule}; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC}, | 16 | ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC}, |
17 | codegen::{self, update, Mode}, | 17 | codegen::{reformat, update, Mode}, |
18 | project_root, Result, | 18 | project_root, Result, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | pub fn generate_syntax(mode: Mode) -> Result<()> { | 21 | pub fn generate_syntax(mode: Mode) -> Result<()> { |
22 | let grammar = include_str!("rust.ungram") | 22 | let grammar = rust_grammar(); |
23 | .parse::<Grammar>() | ||
24 | .unwrap_or_else(|err| panic!("\n \x1b[91merror\x1b[0m: {}\n", err)); | ||
25 | let ast = lower(&grammar); | 23 | let ast = lower(&grammar); |
26 | 24 | ||
27 | let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); | 25 | let syntax_kinds_file = project_root().join("crates/parser/src/syntax_kind/generated.rs"); |
28 | let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; | 26 | let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; |
29 | update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; | 27 | update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; |
30 | 28 | ||
31 | let ast_tokens_file = project_root().join(codegen::AST_TOKENS); | 29 | let ast_tokens_file = project_root().join("crates/syntax/src/ast/generated/tokens.rs"); |
32 | let contents = generate_tokens(&ast)?; | 30 | let contents = generate_tokens(&ast)?; |
33 | update(ast_tokens_file.as_path(), &contents, mode)?; | 31 | update(ast_tokens_file.as_path(), &contents, mode)?; |
34 | 32 | ||
35 | let ast_nodes_file = project_root().join(codegen::AST_NODES); | 33 | let ast_nodes_file = project_root().join("crates/syntax/src/ast/generated/nodes.rs"); |
36 | let contents = generate_nodes(KINDS_SRC, &ast)?; | 34 | let contents = generate_nodes(KINDS_SRC, &ast)?; |
37 | update(ast_nodes_file.as_path(), &contents, mode)?; | 35 | update(ast_nodes_file.as_path(), &contents, mode)?; |
38 | 36 | ||
@@ -63,7 +61,7 @@ fn generate_tokens(grammar: &AstSrc) -> Result<String> { | |||
63 | } | 61 | } |
64 | }); | 62 | }); |
65 | 63 | ||
66 | let pretty = crate::reformat(quote! { | 64 | let pretty = reformat(quote! { |
67 | use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken}; | 65 | use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken}; |
68 | #(#tokens)* | 66 | #(#tokens)* |
69 | })? | 67 | })? |
@@ -153,25 +151,10 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> { | |||
153 | quote!(impl ast::#trait_name for #name {}) | 151 | quote!(impl ast::#trait_name for #name {}) |
154 | }); | 152 | }); |
155 | 153 | ||
156 | ( | 154 | let ast_node = if en.name == "Stmt" { |
155 | quote! {} | ||
156 | } else { | ||
157 | quote! { | 157 | quote! { |
158 | #[pretty_doc_comment_placeholder_workaround] | ||
159 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
160 | pub enum #name { | ||
161 | #(#variants(#variants),)* | ||
162 | } | ||
163 | |||
164 | #(#traits)* | ||
165 | }, | ||
166 | quote! { | ||
167 | #( | ||
168 | impl From<#variants> for #name { | ||
169 | fn from(node: #variants) -> #name { | ||
170 | #name::#variants(node) | ||
171 | } | ||
172 | } | ||
173 | )* | ||
174 | |||
175 | impl AstNode for #name { | 158 | impl AstNode for #name { |
176 | fn can_cast(kind: SyntaxKind) -> bool { | 159 | fn can_cast(kind: SyntaxKind) -> bool { |
177 | match kind { | 160 | match kind { |
@@ -196,6 +179,28 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> { | |||
196 | } | 179 | } |
197 | } | 180 | } |
198 | } | 181 | } |
182 | } | ||
183 | }; | ||
184 | |||
185 | ( | ||
186 | quote! { | ||
187 | #[pretty_doc_comment_placeholder_workaround] | ||
188 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
189 | pub enum #name { | ||
190 | #(#variants(#variants),)* | ||
191 | } | ||
192 | |||
193 | #(#traits)* | ||
194 | }, | ||
195 | quote! { | ||
196 | #( | ||
197 | impl From<#variants> for #name { | ||
198 | fn from(node: #variants) -> #name { | ||
199 | #name::#variants(node) | ||
200 | } | ||
201 | } | ||
202 | )* | ||
203 | #ast_node | ||
199 | }, | 204 | }, |
200 | ) | 205 | ) |
201 | }) | 206 | }) |
@@ -256,7 +261,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> { | |||
256 | } | 261 | } |
257 | } | 262 | } |
258 | 263 | ||
259 | let pretty = crate::reformat(res)?; | 264 | let pretty = reformat(res)?; |
260 | Ok(pretty) | 265 | Ok(pretty) |
261 | } | 266 | } |
262 | 267 | ||
@@ -378,7 +383,7 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> { | |||
378 | } | 383 | } |
379 | }; | 384 | }; |
380 | 385 | ||
381 | crate::reformat(ast) | 386 | reformat(ast) |
382 | } | 387 | } |
383 | 388 | ||
384 | fn to_upper_snake_case(s: &str) -> String { | 389 | fn to_upper_snake_case(s: &str) -> String { |
@@ -472,11 +477,18 @@ impl Field { | |||
472 | "#" => "pound", | 477 | "#" => "pound", |
473 | "?" => "question_mark", | 478 | "?" => "question_mark", |
474 | "," => "comma", | 479 | "," => "comma", |
480 | "|" => "pipe", | ||
475 | _ => name, | 481 | _ => name, |
476 | }; | 482 | }; |
477 | format_ident!("{}_token", name) | 483 | format_ident!("{}_token", name) |
478 | } | 484 | } |
479 | Field::Node { name, .. } => format_ident!("{}", name), | 485 | Field::Node { name, .. } => { |
486 | if name == "type" { | ||
487 | format_ident!("ty") | ||
488 | } else { | ||
489 | format_ident!("{}", name) | ||
490 | } | ||
491 | } | ||
480 | } | 492 | } |
481 | } | 493 | } |
482 | fn ty(&self) -> proc_macro2::Ident { | 494 | fn ty(&self) -> proc_macro2::Ident { |
@@ -491,13 +503,7 @@ fn lower(grammar: &Grammar) -> AstSrc { | |||
491 | let mut res = AstSrc::default(); | 503 | let mut res = AstSrc::default(); |
492 | res.tokens = vec!["Whitespace".into(), "Comment".into(), "String".into(), "RawString".into()]; | 504 | res.tokens = vec!["Whitespace".into(), "Comment".into(), "String".into(), "RawString".into()]; |
493 | 505 | ||
494 | let nodes = grammar | 506 | let nodes = grammar.iter().collect::<Vec<_>>(); |
495 | .iter() | ||
496 | .filter(|&node| match grammar[node].rule { | ||
497 | Rule::Node(it) if it == node => false, | ||
498 | _ => true, | ||
499 | }) | ||
500 | .collect::<Vec<_>>(); | ||
501 | 507 | ||
502 | for &node in &nodes { | 508 | for &node in &nodes { |
503 | let name = grammar[node].name.clone(); | 509 | let name = grammar[node].name.clone(); |
@@ -531,6 +537,7 @@ fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> { | |||
531 | for alternative in alternatives { | 537 | for alternative in alternatives { |
532 | match alternative { | 538 | match alternative { |
533 | Rule::Node(it) => variants.push(grammar[*it].name.clone()), | 539 | Rule::Node(it) => variants.push(grammar[*it].name.clone()), |
540 | Rule::Token(it) if grammar[*it].name == ";" => (), | ||
534 | _ => return None, | 541 | _ => return None, |
535 | } | 542 | } |
536 | } | 543 | } |
@@ -572,6 +579,24 @@ fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, label: Option<&String>, r | |||
572 | } | 579 | } |
573 | Rule::Labeled { label: l, rule } => { | 580 | Rule::Labeled { label: l, rule } => { |
574 | assert!(label.is_none()); | 581 | assert!(label.is_none()); |
582 | let manually_implemented = matches!( | ||
583 | l.as_str(), | ||
584 | "lhs" | ||
585 | | "rhs" | ||
586 | | "then_branch" | ||
587 | | "else_branch" | ||
588 | | "start" | ||
589 | | "end" | ||
590 | | "op" | ||
591 | | "index" | ||
592 | | "base" | ||
593 | | "value" | ||
594 | | "trait" | ||
595 | | "self_ty" | ||
596 | ); | ||
597 | if manually_implemented { | ||
598 | return; | ||
599 | } | ||
575 | lower_rule(acc, grammar, Some(l), rule); | 600 | lower_rule(acc, grammar, Some(l), rule); |
576 | } | 601 | } |
577 | Rule::Seq(rules) | Rule::Alt(rules) => { | 602 | Rule::Seq(rules) | Rule::Alt(rules) => { |
@@ -687,6 +712,9 @@ fn extract_struct_trait(node: &mut AstNodeSrc, trait_name: &str, methods: &[&str | |||
687 | 712 | ||
688 | fn extract_enum_traits(ast: &mut AstSrc) { | 713 | fn extract_enum_traits(ast: &mut AstSrc) { |
689 | for enm in &mut ast.enums { | 714 | for enm in &mut ast.enums { |
715 | if enm.name == "Stmt" { | ||
716 | continue; | ||
717 | } | ||
690 | let nodes = &ast.nodes; | 718 | let nodes = &ast.nodes; |
691 | let mut variant_traits = enm | 719 | let mut variant_traits = enm |
692 | .variants | 720 | .variants |
diff --git a/xtask/src/codegen/rust.ungram b/xtask/src/codegen/rust.ungram index 375df301f..aca23890c 100644 --- a/xtask/src/codegen/rust.ungram +++ b/xtask/src/codegen/rust.ungram | |||
@@ -1,3 +1,63 @@ | |||
1 | //*************************// | ||
2 | // Names, Paths and Macros // | ||
3 | //*************************// | ||
4 | |||
5 | Name = | ||
6 | 'ident' | ||
7 | |||
8 | NameRef = | ||
9 | 'ident' | 'int_number' | ||
10 | |||
11 | Path = | ||
12 | (qualifier:Path '::')? segment:PathSegment | ||
13 | |||
14 | PathSegment = | ||
15 | 'crate' | 'self' | 'super' | ||
16 | | '::' NameRef | ||
17 | | NameRef GenericArgList? | ||
18 | | NameRef ParamList RetType? | ||
19 | | '<' PathType ('as' PathType)? '>' | ||
20 | |||
21 | GenericArgList = | ||
22 | '::'? '<' (GenericArg (',' GenericArg)* ','?)? '>' | ||
23 | |||
24 | GenericArg = | ||
25 | TypeArg | ||
26 | | AssocTypeArg | ||
27 | | LifetimeArg | ||
28 | | ConstArg | ||
29 | |||
30 | TypeArg = | ||
31 | Type | ||
32 | |||
33 | AssocTypeArg = | ||
34 | NameRef (':' TypeBoundList | '=' Type) | ||
35 | |||
36 | LifetimeArg = | ||
37 | 'lifetime' | ||
38 | |||
39 | ConstArg = | ||
40 | Expr | ||
41 | |||
42 | MacroCall = | ||
43 | Attr* Path '!' Name? TokenTree ';'? | ||
44 | |||
45 | TokenTree = | ||
46 | '(' ')' | ||
47 | | '{' '}' | ||
48 | | '[' ']' | ||
49 | |||
50 | MacroItems = | ||
51 | Item* | ||
52 | |||
53 | MacroStmts = | ||
54 | statements:Stmt* | ||
55 | Expr? | ||
56 | |||
57 | //*************************// | ||
58 | // Items // | ||
59 | //*************************// | ||
60 | |||
1 | SourceFile = | 61 | SourceFile = |
2 | 'shebang'? | 62 | 'shebang'? |
3 | Attr* | 63 | Attr* |
@@ -61,22 +121,22 @@ ParamList = | |||
61 | SelfParam = | 121 | SelfParam = |
62 | Attr* ( | 122 | Attr* ( |
63 | ('&' 'lifetime'?)? 'mut'? 'self' | 123 | ('&' 'lifetime'?)? 'mut'? 'self' |
64 | | 'mut'? 'self' ':' ty:TypeRef | 124 | | 'mut'? 'self' ':' Type |
65 | ) | 125 | ) |
66 | 126 | ||
67 | Param = | 127 | Param = |
68 | Attr* ( | 128 | Attr* ( |
69 | Pat (':' ty:TypeRef) | 129 | Pat (':' Type) |
70 | | ty:TypeRef | 130 | | Type |
71 | | '...' | 131 | | '...' |
72 | ) | 132 | ) |
73 | 133 | ||
74 | RetType = | 134 | RetType = |
75 | '->' ty:TypeRef | 135 | '->' Type |
76 | 136 | ||
77 | TypeAlias = | 137 | TypeAlias = |
78 | Attr* Visibility? 'default'? 'type' Name GenericParamList? (':' TypeBoundList?)? WhereClause? | 138 | Attr* Visibility? 'default'? 'type' Name GenericParamList? (':' TypeBoundList?)? WhereClause? |
79 | '=' ty:TypeRef ';' | 139 | '=' Type ';' |
80 | 140 | ||
81 | Struct = | 141 | Struct = |
82 | Attr* Visibility? 'struct' Name GenericParamList? ( | 142 | Attr* Visibility? 'struct' Name GenericParamList? ( |
@@ -88,13 +148,13 @@ RecordFieldList = | |||
88 | '{' fields:(RecordField (',' RecordField)* ','?)? '}' | 148 | '{' fields:(RecordField (',' RecordField)* ','?)? '}' |
89 | 149 | ||
90 | RecordField = | 150 | RecordField = |
91 | Attr* Visibility? Name ':' ty:TypeRef | 151 | Attr* Visibility? Name ':' Type |
92 | 152 | ||
93 | TupleFieldList = | 153 | TupleFieldList = |
94 | '(' fields:(TupleField (',' TupleField)* ','?)? ')' | 154 | '(' fields:(TupleField (',' TupleField)* ','?)? ')' |
95 | 155 | ||
96 | TupleField = | 156 | TupleField = |
97 | Attr* Visibility? ty:TypeRef | 157 | Attr* Visibility? Type |
98 | 158 | ||
99 | FieldList = | 159 | FieldList = |
100 | RecordFieldList | 160 | RecordFieldList |
@@ -114,12 +174,17 @@ Union = | |||
114 | Attr* Visibility? 'union' Name GenericParamList? WhereClause? | 174 | Attr* Visibility? 'union' Name GenericParamList? WhereClause? |
115 | RecordFieldList | 175 | RecordFieldList |
116 | 176 | ||
177 | AdtDef = | ||
178 | Enum | ||
179 | | Struct | ||
180 | | Union | ||
181 | |||
117 | Const = | 182 | Const = |
118 | Attr* Visibility? 'default'? 'const' (Name | '_') ':' ty:TypeRef | 183 | Attr* Visibility? 'default'? 'const' (Name | '_') ':' Type |
119 | '=' body:Expr ';' | 184 | '=' body:Expr ';' |
120 | 185 | ||
121 | Static = | 186 | Static = |
122 | Attr* Visibility? 'static'? 'mut'? Name ':' ty:TypeRef | 187 | Attr* Visibility? 'static'? 'mut'? Name ':' Type |
123 | '=' body:Expr ';' | 188 | '=' body:Expr ';' |
124 | 189 | ||
125 | Trait = | 190 | Trait = |
@@ -131,18 +196,17 @@ AssocItemList = | |||
131 | '{' Attr* AssocItem* '}' | 196 | '{' Attr* AssocItem* '}' |
132 | 197 | ||
133 | AssocItem = | 198 | AssocItem = |
134 | Fn | 199 | Const |
135 | | TypeAlias | 200 | | Fn |
136 | | Const | ||
137 | | MacroCall | 201 | | MacroCall |
202 | | TypeAlias | ||
138 | 203 | ||
139 | Impl = | 204 | Impl = |
140 | Attr* Visibility? | 205 | Attr* Visibility? |
141 | 'default'? 'unsafe'? 'impl' 'const'? GenericParamList? ( | 206 | 'default'? 'unsafe'? 'impl' 'const'? GenericParamList? |
142 | TypeRef | 207 | ('!'? target_trait:Type 'for')? target_type:Type |
143 | | '!'? TypeRef 'for' TypeRef | 208 | WhereClause? |
144 | ) WhereClause? | 209 | AssocItemList |
145 | AssocItemList | ||
146 | 210 | ||
147 | ExternBlock = | 211 | ExternBlock = |
148 | Attr* Abi ExternItemList | 212 | Attr* Abi ExternItemList |
@@ -157,20 +221,26 @@ GenericParamList = | |||
157 | '<' (GenericParam (',' GenericParam)* ','?)? '>' | 221 | '<' (GenericParam (',' GenericParam)* ','?)? '>' |
158 | 222 | ||
159 | GenericParam = | 223 | GenericParam = |
160 | LifetimeParam | 224 | ConstParam |
225 | | LifetimeParam | ||
161 | | TypeParam | 226 | | TypeParam |
162 | | ConstParam | ||
163 | 227 | ||
164 | TypeParam = | 228 | TypeParam = |
165 | Attr* Name (':' TypeBoundList?)? | 229 | Attr* Name (':' TypeBoundList?)? |
166 | ('=' default_type:TypeRef)? | 230 | ('=' default_type:Type)? |
167 | 231 | ||
168 | ConstParam = | 232 | ConstParam = |
169 | Attr* 'const' Name ':' ty:TypeRef | 233 | Attr* 'const' Name ':' Type |
170 | ('=' default_val:Expr)? | 234 | ('=' default_val:Expr)? |
171 | 235 | ||
172 | LifetimeParam = | 236 | LifetimeParam = |
173 | Attr* 'lifetime' | 237 | Attr* 'lifetime' (':' TypeBoundList?)? |
238 | |||
239 | WhereClause = | ||
240 | 'where' predicates:(WherePred (',' WherePred)* ','?) | ||
241 | |||
242 | WherePred = | ||
243 | ('for' GenericParamList)? ('lifetime' | Type) ':' TypeBoundList | ||
174 | 244 | ||
175 | Visibility = | 245 | Visibility = |
176 | 'pub' ('(' | 246 | 'pub' ('(' |
@@ -183,362 +253,335 @@ Visibility = | |||
183 | Attr = | 253 | Attr = |
184 | '#' '!'? '[' Path ('=' Literal | TokenTree)? ']' | 254 | '#' '!'? '[' Path ('=' Literal | TokenTree)? ']' |
185 | 255 | ||
186 | ParenType = | 256 | //****************************// |
187 | '(' ty:TypeRef ')' | 257 | // Statements and Expressions // |
258 | //****************************// | ||
188 | 259 | ||
189 | TupleType = | 260 | Stmt = |
190 | '(' fields:TypeRef* ')' | 261 | ExprStmt |
262 | | Item | ||
263 | | LetStmt | ||
191 | 264 | ||
192 | NeverType = | 265 | LetStmt = |
193 | '!' | 266 | Attr* 'let' Pat (':' Type)? |
267 | '=' initializer:Expr ';' | ||
194 | 268 | ||
195 | PathType = | 269 | ExprStmt = |
196 | Path | 270 | Attr* Expr ';'? |
197 | 271 | ||
198 | PointerType = | 272 | Expr = |
199 | '*' ('const' | 'mut') ty:TypeRef | 273 | ArrayExpr |
274 | | AwaitExpr | ||
275 | | BinExpr | ||
276 | | BlockExpr | ||
277 | | BoxExpr | ||
278 | | BreakExpr | ||
279 | | CallExpr | ||
280 | | CastExpr | ||
281 | | ClosureExpr | ||
282 | | ContinueExpr | ||
283 | | EffectExpr | ||
284 | | FieldExpr | ||
285 | | ForExpr | ||
286 | | IfExpr | ||
287 | | IndexExpr | ||
288 | | Literal | ||
289 | | LoopExpr | ||
290 | | MacroCall | ||
291 | | MatchExpr | ||
292 | | MethodCallExpr | ||
293 | | ParenExpr | ||
294 | | PathExpr | ||
295 | | PrefixExpr | ||
296 | | RangeExpr | ||
297 | | RecordExpr | ||
298 | | RefExpr | ||
299 | | ReturnExpr | ||
300 | | TryExpr | ||
301 | | TupleExpr | ||
302 | | WhileExpr | ||
200 | 303 | ||
201 | ArrayType = | 304 | Literal = |
202 | '[' ty:TypeRef ';' Expr ']' | 305 | Attr* value:( |
306 | 'int_number' | 'float_number' | ||
307 | | 'string' | 'raw_string' | ||
308 | | 'byte_string' | 'raw_byte_string' | ||
309 | | 'true' | 'false' | ||
310 | | 'char' | 'byte' | ||
311 | ) | ||
203 | 312 | ||
204 | SliceType = | 313 | PathExpr = |
205 | '[' ty:TypeRef ']' | 314 | Attr* Path |
206 | 315 | ||
207 | ReferenceType = | 316 | BlockExpr = |
208 | '&' 'lifetime'? 'mut'? ty:TypeRef | 317 | '{' |
318 | Attr* | ||
319 | statements:Stmt* | ||
320 | Expr? | ||
321 | '}' | ||
209 | 322 | ||
210 | PlaceholderType = | 323 | RefExpr = |
211 | '_' | 324 | Attr* '&' ('raw' |'mut' | 'const') Expr |
212 | 325 | ||
213 | FnPointerType = | 326 | TryExpr = |
214 | Abi 'unsafe'? 'fn' ParamList RetType? | 327 | Attr* Expr '?' |
215 | 328 | ||
216 | ForType = | 329 | EffectExpr = |
217 | 'for' GenericParamList ty:TypeRef | 330 | Attr* Label? ('try' | 'unsafe' | 'async') BlockExpr |
218 | 331 | ||
219 | ImplTraitType = | 332 | PrefixExpr = |
220 | 'impl' TypeBoundList | 333 | Attr* op:('-' | '!' | '*') Expr |
221 | 334 | ||
222 | DynTraitType = | 335 | BinExpr = |
223 | 'dyn' TypeBoundList | 336 | Attr* |
337 | lhs:Expr | ||
338 | op:( | ||
339 | '||' | '&&' | ||
340 | | '==' | '!=' | '<=' | '>=' | '<' | '>' | ||
341 | | '+' | '*' | '-' | '/' | '%' | '<<' | '>>' | '^' | '|' | '&' | ||
342 | | '=' | '+=' | '/=' | '*=' | '%=' | '>>=' | '<<=' | '-=' | '|=' | '&=' | '^=' | ||
343 | ) | ||
344 | rhs:Expr | ||
224 | 345 | ||
225 | TupleExpr = | 346 | CastExpr = |
226 | Attr* '(' Expr* ')' | 347 | Attr* Expr 'as' Type |
348 | |||
349 | ParenExpr = | ||
350 | Attr* '(' Attr* Expr ')' | ||
227 | 351 | ||
228 | ArrayExpr = | 352 | ArrayExpr = |
229 | Attr* '[' (Expr* | Expr ';' Expr) ']' | 353 | Attr* '[' Attr* ( |
354 | (Expr (',' Expr)* ','?)? | ||
355 | | Expr ';' Expr | ||
356 | ) ']' | ||
230 | 357 | ||
231 | ParenExpr = | 358 | IndexExpr = |
232 | Attr* '(' Expr ')' | 359 | Attr* base:Expr '[' index:Expr ']' |
233 | 360 | ||
234 | PathExpr = | 361 | TupleExpr = |
235 | Path | 362 | Attr* '(' Attr* fields:(Expr (',' Expr)* ','?)? ')' |
363 | |||
364 | RecordExpr = | ||
365 | Path RecordExprFieldList | ||
366 | |||
367 | RecordExprFieldList = | ||
368 | '{' | ||
369 | Attr* | ||
370 | fields:(RecordExprField (',' RecordExprField)* ','?) | ||
371 | ('..' spread:Expr)? | ||
372 | '}' | ||
373 | |||
374 | RecordExprField = | ||
375 | Attr* NameRef (':' Expr)? | ||
376 | |||
377 | CallExpr = | ||
378 | Attr* Expr ArgList | ||
379 | |||
380 | ArgList = | ||
381 | '(' args:(Expr (',' Expr)* ','?)? ')' | ||
382 | |||
383 | MethodCallExpr = | ||
384 | Attr* Expr '.' NameRef GenericArgList? ArgList | ||
385 | |||
386 | FieldExpr = | ||
387 | Attr* Expr '.' NameRef | ||
236 | 388 | ||
237 | LambdaExpr = | 389 | ClosureExpr = |
238 | Attr* 'static'? 'async'? 'move'? ParamList RetType? | 390 | Attr* 'static'? 'async'? 'move'? ParamList RetType? |
239 | body:Expr | 391 | body:Expr |
240 | 392 | ||
241 | IfExpr = | 393 | IfExpr = |
242 | Attr* 'if' Condition | 394 | Attr* 'if' Condition then_branch:BlockExpr |
395 | ('else' else_branch:(IfExpr | BlockExpr))? | ||
243 | 396 | ||
244 | Condition = | 397 | Condition = |
245 | 'let' Pat '=' Expr | 398 | 'let' Pat '=' Expr |
246 | | Expr | 399 | | Expr |
247 | 400 | ||
248 | EffectExpr = | ||
249 | Attr* Label? ('try' | 'unsafe' | 'async') BlockExpr | ||
250 | |||
251 | LoopExpr = | 401 | LoopExpr = |
252 | Attr* Label? 'loop' | 402 | Attr* Label? 'loop' |
253 | loop_body:BlockExpr? | 403 | loop_body:BlockExpr |
254 | 404 | ||
255 | ForExpr = | 405 | ForExpr = |
256 | Attr* Label? 'for' Pat 'in' iterable:Expr | 406 | Attr* Label? 'for' Pat 'in' iterable:Expr |
257 | loop_body:BlockExpr? | 407 | loop_body:BlockExpr |
258 | 408 | ||
259 | WhileExpr = | 409 | WhileExpr = |
260 | Attr* Label? 'while' Condition | 410 | Attr* Label? 'while' Condition |
261 | loop_body:BlockExpr? | 411 | loop_body:BlockExpr |
262 | 412 | ||
263 | ContinueExpr = | 413 | Label = |
264 | Attr* 'continue' 'lifetime'? | 414 | 'lifetime' |
265 | 415 | ||
266 | BreakExpr = | 416 | BreakExpr = |
267 | Attr* 'break' 'lifetime'? Expr? | 417 | Attr* 'break' 'lifetime'? Expr? |
268 | 418 | ||
269 | Label = | 419 | ContinueExpr = |
270 | 'lifetime' | 420 | Attr* 'continue' 'lifetime'? |
271 | |||
272 | BlockExpr = | ||
273 | Attr* Label | ||
274 | '{' | ||
275 | Item* | ||
276 | statements:Stmt* | ||
277 | Expr? | ||
278 | '}' | ||
279 | 421 | ||
280 | ReturnExpr = | 422 | RangeExpr = |
281 | Attr* 'return' Expr | 423 | Attr* start:Expr? op:('..' | '..=') end:Expr? |
282 | 424 | ||
283 | CallExpr = | 425 | MatchExpr = |
284 | Attr* Expr ArgList | 426 | Attr* 'match' Expr MatchArmList |
285 | 427 | ||
286 | MethodCallExpr = | 428 | MatchArmList = |
287 | Attr* Expr '.' NameRef TypeArgList? ArgList | 429 | '{' |
430 | Attr* | ||
431 | arms:MatchArm* | ||
432 | '}' | ||
288 | 433 | ||
289 | ArgList = | 434 | MatchArm = |
290 | '(' args:Expr* ')' | 435 | Attr* Pat guard:MatchGuard? '=>' Expr ','? |
291 | 436 | ||
292 | FieldExpr = | 437 | MatchGuard = |
293 | Attr* Expr '.' NameRef | 438 | 'if' Expr |
294 | 439 | ||
295 | IndexExpr = | 440 | ReturnExpr = |
296 | Attr* '[' ']' | 441 | Attr* 'return' Expr? |
297 | 442 | ||
298 | AwaitExpr = | 443 | AwaitExpr = |
299 | Attr* Expr '.' 'await' | 444 | Attr* Expr '.' 'await' |
300 | 445 | ||
301 | TryExpr = | ||
302 | Attr* Expr '?' | ||
303 | |||
304 | CastExpr = | ||
305 | Attr* Expr 'as' ty:TypeRef | ||
306 | |||
307 | RefExpr = | ||
308 | Attr* '&' ('raw' | 'mut' | 'const') Expr | ||
309 | |||
310 | PrefixExpr = | ||
311 | Attr* Expr | ||
312 | |||
313 | BoxExpr = | 446 | BoxExpr = |
314 | Attr* 'box' Expr | 447 | Attr* 'box' Expr |
315 | 448 | ||
316 | RangeExpr = | 449 | //*************************// |
317 | Attr* | 450 | // Types // |
451 | //*************************// | ||
318 | 452 | ||
319 | BinExpr = | 453 | Type = |
320 | Attr* | 454 | ArrayType |
321 | 455 | | DynTraitType | |
322 | Literal = | 456 | | FnPointerType |
323 | 'int_number' | 457 | | ForType |
458 | | ImplTraitType | ||
459 | | InferType | ||
460 | | NeverType | ||
461 | | ParenType | ||
462 | | PathType | ||
463 | | PointerType | ||
464 | | ReferenceType | ||
465 | | SliceType | ||
466 | | TupleType | ||
324 | 467 | ||
325 | MatchExpr = | 468 | ParenType = |
326 | Attr* 'match' Expr MatchArmList | 469 | '(' Type ')' |
327 | 470 | ||
328 | MatchArmList = | 471 | NeverType = |
329 | '{' arms:MatchArm* '}' | 472 | '!' |
330 | 473 | ||
331 | MatchArm = | 474 | PathType = |
332 | Attr* Pat guard:MatchGuard? '=>' Expr | 475 | Path |
333 | 476 | ||
334 | MatchGuard = | 477 | TupleType = |
335 | 'if' Expr | 478 | '(' fields:(Type (',' Type)* ','?)? ')' |
336 | 479 | ||
337 | RecordExpr = | 480 | PointerType = |
338 | Path RecordExprFieldList | 481 | '*' ('const' | 'mut') Type |
339 | 482 | ||
340 | RecordExprFieldList = | 483 | ReferenceType = |
341 | '{' | 484 | '&' 'lifetime'? 'mut'? Type |
342 | fields:RecordExprField* | ||
343 | ('..' spread:Expr)? | ||
344 | '}' | ||
345 | 485 | ||
346 | RecordExprField = | 486 | ArrayType = |
347 | Attr* NameRef (':' Expr)? | 487 | '[' Type ';' Expr ']' |
348 | 488 | ||
349 | OrPat = | 489 | SliceType = |
350 | Pat* | 490 | '[' Type ']' |
351 | 491 | ||
352 | ParenPat = | 492 | InferType = |
353 | '(' Pat ')' | 493 | '_' |
354 | 494 | ||
355 | RefPat = | 495 | FnPointerType = |
356 | '&' 'mut'? Pat | 496 | 'const'? 'async'? 'unsafe'? Abi? 'fn' ParamList RetType? |
357 | 497 | ||
358 | BoxPat = | 498 | ForType = |
359 | 'box' Path | 499 | 'for' GenericParamList Type |
360 | 500 | ||
361 | BindPat = | 501 | ImplTraitType = |
362 | Attr* 'ref'? 'mut'? Name ('@' Pat)? | 502 | 'impl' TypeBoundList |
363 | 503 | ||
364 | PlaceholderPat = | 504 | DynTraitType = |
365 | '_' | 505 | 'dyn' TypeBoundList |
366 | 506 | ||
367 | DotDotPat = | 507 | TypeBoundList = |
368 | '..' | 508 | bounds:(TypeBound ('+' TypeBound)* '+'?) |
369 | 509 | ||
370 | PathPat = | 510 | TypeBound = |
371 | Path | 511 | 'lifetime' |
512 | | '?'? Type | ||
372 | 513 | ||
373 | SlicePat = | 514 | //************************// |
374 | '[' args:Pat* ']' | 515 | // Patterns // |
516 | //************************// | ||
375 | 517 | ||
376 | RangePat = | 518 | Pat = |
377 | '..' | '..=' | 519 | IdentPat |
520 | | BoxPat | ||
521 | | RestPat | ||
522 | | LiteralPat | ||
523 | | MacroPat | ||
524 | | OrPat | ||
525 | | ParenPat | ||
526 | | PathPat | ||
527 | | WildcardPat | ||
528 | | RangePat | ||
529 | | RecordPat | ||
530 | | RefPat | ||
531 | | SlicePat | ||
532 | | TuplePat | ||
533 | | TupleStructPat | ||
378 | 534 | ||
379 | LiteralPat = | 535 | LiteralPat = |
380 | Literal | 536 | Literal |
381 | 537 | ||
382 | MacroPat = | 538 | IdentPat = |
383 | MacroCall | 539 | Attr* 'ref'? 'mut'? Name ('@' Pat)? |
540 | |||
541 | WildcardPat = | ||
542 | '_' | ||
543 | |||
544 | RangePat = | ||
545 | start:Pat op:('..' | '..=') end:Pat | ||
546 | |||
547 | RefPat = | ||
548 | '&' 'mut'? Pat | ||
384 | 549 | ||
385 | RecordPat = | 550 | RecordPat = |
386 | Path RecordFieldPatList | 551 | Path RecordPatFieldList |
387 | 552 | ||
388 | RecordFieldPatList = | 553 | RecordPatFieldList = |
389 | '{' | 554 | '{' |
390 | record_field_pats:RecordFieldPat* | 555 | fields:(RecordPatField (',' RecordPatField)* ','?) |
391 | BindPat* | ||
392 | '..'? | 556 | '..'? |
393 | '}' | 557 | '}' |
394 | 558 | ||
395 | RecordFieldPat = | 559 | RecordPatField = |
396 | Attr* NameRef ':' Pat | 560 | Attr* (NameRef ':')? Pat |
397 | 561 | ||
398 | TupleStructPat = | 562 | TupleStructPat = |
399 | Path '(' args:Pat* ')' | 563 | Path '(' fields:(Pat (',' Pat)* ','?)? ')' |
400 | 564 | ||
401 | TuplePat = | 565 | TuplePat = |
402 | '(' args:Pat* ')' | 566 | '(' fields:(Pat (',' Pat)* ','?)? ')' |
403 | |||
404 | Name = | ||
405 | 'ident' | ||
406 | |||
407 | NameRef = | ||
408 | 'ident' | 'int_number' | ||
409 | |||
410 | MacroCall = | ||
411 | Attr* Path '!' Name? TokenTree ';'? | ||
412 | |||
413 | MacroDef = | ||
414 | Name TokenTree | ||
415 | |||
416 | TokenTree = | ||
417 | '(' ')' | '{' '}' | '[' ']' | ||
418 | |||
419 | MacroItems = | ||
420 | Item* | ||
421 | |||
422 | MacroStmts = | ||
423 | statements:Stmt* | ||
424 | Expr? | ||
425 | |||
426 | TypeBound = | ||
427 | 'lifetime' | 'const'? TypeRef | ||
428 | |||
429 | TypeBoundList = | ||
430 | bounds:TypeBound* | ||
431 | |||
432 | WherePred = | ||
433 | ('for' GenericParamList)? ('lifetime' | TypeRef) ':' TypeBoundList | ||
434 | |||
435 | WhereClause = | ||
436 | 'where' predicates:WherePred* | ||
437 | |||
438 | ExprStmt = | ||
439 | Attr* Expr ';' | ||
440 | |||
441 | LetStmt = | ||
442 | Attr* 'let' Pat (':' ty:TypeRef) | ||
443 | '=' initializer:Expr ';' | ||
444 | |||
445 | Path = | ||
446 | (qualifier:Path '::')? segment:PathSegment | ||
447 | |||
448 | PathSegment = | ||
449 | '::' | 'crate' | 'self' | 'super' | ||
450 | | '<' NameRef TypeArgList ParamList RetType PathType '>' | ||
451 | |||
452 | TypeArgList = | ||
453 | '::'? '<' | ||
454 | TypeArg* | ||
455 | LifetimeArg* | ||
456 | AssocTypeArg* | ||
457 | ConstArg* | ||
458 | '>' | ||
459 | 567 | ||
460 | TypeArg = | 568 | ParenPat = |
461 | TypeRef | 569 | '(' Pat ')' |
462 | |||
463 | AssocTypeArg = | ||
464 | NameRef (':' TypeBoundList | '=' TypeRef) | ||
465 | |||
466 | LifetimeArg = | ||
467 | 'lifetime' | ||
468 | 570 | ||
469 | ConstArg = | 571 | SlicePat = |
470 | Literal | BlockExpr BlockExpr | 572 | '[' (Pat (',' Pat)* ','?)? ']' |
471 | 573 | ||
472 | AdtDef = | 574 | PathPat = |
473 | Struct | 575 | Path |
474 | | Enum | ||
475 | | Union | ||
476 | 576 | ||
477 | TypeRef = | 577 | OrPat = |
478 | ParenType | 578 | (Pat ('|' Pat)* '|'?) |
479 | | TupleType | ||
480 | | NeverType | ||
481 | | PathType | ||
482 | | PointerType | ||
483 | | ArrayType | ||
484 | | SliceType | ||
485 | | ReferenceType | ||
486 | | PlaceholderType | ||
487 | | FnPointerType | ||
488 | | ForType | ||
489 | | ImplTraitType | ||
490 | | DynTraitType | ||
491 | 579 | ||
492 | Stmt = | 580 | BoxPat = |
493 | LetStmt | 581 | 'box' Pat |
494 | | ExprStmt | ||
495 | 582 | ||
496 | Pat = | 583 | RestPat = |
497 | OrPat | 584 | '..' |
498 | | ParenPat | ||
499 | | RefPat | ||
500 | | BoxPat | ||
501 | | BindPat | ||
502 | | PlaceholderPat | ||
503 | | DotDotPat | ||
504 | | PathPat | ||
505 | | RecordPat | ||
506 | | TupleStructPat | ||
507 | | TuplePat | ||
508 | | SlicePat | ||
509 | | RangePat | ||
510 | | LiteralPat | ||
511 | | MacroPat | ||
512 | 585 | ||
513 | Expr = | 586 | MacroPat = |
514 | TupleExpr | 587 | MacroCall |
515 | | ArrayExpr | ||
516 | | ParenExpr | ||
517 | | PathExpr | ||
518 | | LambdaExpr | ||
519 | | IfExpr | ||
520 | | LoopExpr | ||
521 | | ForExpr | ||
522 | | WhileExpr | ||
523 | | ContinueExpr | ||
524 | | BreakExpr | ||
525 | | Label | ||
526 | | BlockExpr | ||
527 | | ReturnExpr | ||
528 | | MatchExpr | ||
529 | | RecordExpr | ||
530 | | CallExpr | ||
531 | | IndexExpr | ||
532 | | MethodCallExpr | ||
533 | | FieldExpr | ||
534 | | AwaitExpr | ||
535 | | TryExpr | ||
536 | | EffectExpr | ||
537 | | CastExpr | ||
538 | | RefExpr | ||
539 | | PrefixExpr | ||
540 | | RangeExpr | ||
541 | | BinExpr | ||
542 | | Literal | ||
543 | | MacroCall | ||
544 | | BoxExpr | ||