From 627eddbc7e5eb13fc17c1c655ee1c3864c6dd4fe Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 29 Jul 2020 11:48:32 +0200 Subject: [PATCH] Owned AST IR --- xtask/src/ast_src.rs | 3942 ++++++++++++++++--------------- xtask/src/codegen/gen_syntax.rs | 29 +- 2 files changed, 1990 insertions(+), 1981 deletions(-) diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 392648d7133..425814d7328 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -223,35 +223,35 @@ pub(crate) struct KindsSrc<'a> { ], }; -pub(crate) struct AstSrc<'a> { - pub(crate) tokens: &'a [&'a str], - pub(crate) nodes: &'a [AstNodeSrc<'a>], - pub(crate) enums: &'a [AstEnumSrc<'a>], +pub(crate) struct AstSrc { + pub(crate) tokens: Vec, + pub(crate) nodes: Vec, + pub(crate) enums: Vec, } -pub(crate) struct AstNodeSrc<'a> { - pub(crate) doc: &'a [&'a str], - pub(crate) name: &'a str, - pub(crate) traits: &'a [&'a str], - pub(crate) fields: &'a [Field<'a>], +pub(crate) struct AstNodeSrc { + pub(crate) doc: Vec, + pub(crate) name: String, + pub(crate) traits: Vec, + pub(crate) fields: Vec, } -pub(crate) enum Field<'a> { - Token(&'a str), - Node { name: &'a str, src: FieldSrc<'a> }, +pub(crate) enum Field { + Token(String), + Node { name: String, src: FieldSrc }, } -pub(crate) enum FieldSrc<'a> { +pub(crate) enum FieldSrc { Shorthand, - Optional(&'a str), - Many(&'a str), + Optional(String), + Many(String), } -pub(crate) struct AstEnumSrc<'a> { - pub(crate) doc: &'a [&'a str], - pub(crate) name: &'a str, - pub(crate) traits: &'a [&'a str], - pub(crate) variants: &'a [&'a str], +pub(crate) struct AstEnumSrc { + pub(crate) doc: Vec, + pub(crate) name: String, + pub(crate) traits: Vec, + pub(crate) variants: Vec, } macro_rules! ast_nodes { @@ -261,12 +261,12 @@ struct $name:ident$(: $($trait:ident),*)? { $($field_name:ident $(![$token:tt])? $(: $ty:tt)?),*$(,)? } )*) => { - [$( + vec![$( AstNodeSrc { - doc: &[$($doc),*], - name: stringify!($name), - traits: &[$($(stringify!($trait)),*)?], - fields: &[ + doc: vec![$($doc.to_string()),*], + name: stringify!($name).to_string(), + traits: vec![$($(stringify!($trait).to_string()),*)?], + fields: vec![ $(field!($(T![$token])? $field_name $($ty)?)),* ], @@ -277,16 +277,22 @@ struct $name:ident$(: $($trait:ident),*)? { macro_rules! field { (T![$token:tt] T) => { - Field::Token(stringify!($token)) + Field::Token(stringify!($token).to_string()) }; ($field_name:ident) => { - Field::Node { name: stringify!($field_name), src: FieldSrc::Shorthand } + Field::Node { name: stringify!($field_name).to_string(), src: FieldSrc::Shorthand } }; ($field_name:ident [$ty:ident]) => { - Field::Node { name: stringify!($field_name), src: FieldSrc::Many(stringify!($ty)) } + Field::Node { + name: stringify!($field_name).to_string(), + src: FieldSrc::Many(stringify!($ty).to_string()), + } }; ($field_name:ident $ty:ident) => { - Field::Node { name: stringify!($field_name), src: FieldSrc::Optional(stringify!($ty)) } + Field::Node { + name: stringify!($field_name).to_string(), + src: FieldSrc::Optional(stringify!($ty).to_string()), + } }; } @@ -297,1947 +303,1949 @@ enum $name:ident $(: $($trait:ident),*)? { $($variant:ident),*$(,)? } )*) => { - [$( + vec![$( AstEnumSrc { - doc: &[$($doc),*], - name: stringify!($name), - traits: &[$($(stringify!($trait)),*)?], - variants: &[$(stringify!($variant)),*], + doc: vec![$($doc.to_string()),*], + name: stringify!($name).to_string(), + traits: vec![$($(stringify!($trait).to_string()),*)?], + variants: vec![$(stringify!($variant).to_string()),*], } ),*] }; } -pub(crate) const AST_SRC: AstSrc = AstSrc { - tokens: &["Whitespace", "Comment", "String", "RawString"], - nodes: &ast_nodes! { - /// The entire Rust source file. Includes all top-level inner attributes and module items. - /// - /// [Reference](https://doc.rust-lang.org/reference/crates-and-source-files.html) - struct SourceFile: ModuleItemOwner, AttrsOwner, DocCommentsOwner { - modules: [Module], - } - - /// Function definition either with body or not. - /// Includes all of its attributes and doc comments. - /// - /// ``` - /// ❰ - /// /// Docs - /// #[attr] - /// pub extern "C" fn foo(#[attr] Patern {p}: Pattern) -> u32 - /// where - /// T: Debug - /// { - /// 42 - /// } - /// ❱ - /// - /// extern "C" { - /// ❰ fn fn_decl(also_variadic_ffi: u32, ...) -> u32; ❱ - /// } - /// ``` - /// - /// - [Reference](https://doc.rust-lang.org/reference/items/functions.html) - /// - [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions) - struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner { - Abi, - T![const], - T![default], - T![async], - T![unsafe], - T![fn], - ParamList, - RetType, - body: BlockExpr, - T![;] - } - - /// Return type annotation. - /// - /// ``` - /// fn foo(a: u32) ❰ -> Option ❱ { Some(a) } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/functions.html) - struct RetType { T![->], TypeRef } - - /// Struct definition. - /// Includes all of its attributes and doc comments. - /// - /// ``` - /// ❰ - /// /// Docs - /// #[attr] - /// struct Foo where T: Debug { - /// /// Docs - /// #[attr] - /// pub a: u32, - /// b: T, - /// } - /// ❱ - /// - /// ❰ struct Foo; ❱ - /// ❰ struct Foo(#[attr] T) where T: Debug; ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) - struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { - T![struct], - FieldDefList, - T![;] - } - - /// Union definition. - /// Includes all of its attributes and doc comments. - /// - /// ``` - /// ❰ - /// /// Docs - /// #[attr] - /// pub union Foo where T: Debug { - /// /// Docs - /// #[attr] - /// a: T, - /// b: u32, - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/unions.html) - struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { - T![union], - RecordFieldDefList, - } - - /// Record field definition list including enclosing curly braces. - /// - /// ``` - /// struct Foo // same for union - /// ❰ - /// { - /// a: u32, - /// b: bool, - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) - struct RecordFieldDefList { T!['{'], fields: [RecordFieldDef], T!['}'] } - - /// Record field definition including its attributes and doc comments. - /// - /// ` `` - /// same for union - /// struct Foo { - /// ❰ - /// /// Docs - /// #[attr] - /// pub a: u32 - /// ❱ - /// - /// ❰ b: bool ❱ - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) - struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { } - - /// Tuple field definition list including enclosing parens. - /// - /// ``` - /// struct Foo ❰ (u32, String, Vec) ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) - struct TupleFieldDefList { T!['('], fields: [TupleFieldDef], T![')'] } - - /// Tuple field definition including its attributes. - /// - /// ``` - /// struct Foo(❰ #[attr] u32 ❱); - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) - struct TupleFieldDef: VisibilityOwner, AttrsOwner { - TypeRef, - } - - /// Enum definition. - /// Includes all of its attributes and doc comments. - /// - /// ``` - /// ❰ - /// /// Docs - /// #[attr] - /// pub enum Foo where T: Debug { - /// /// Docs - /// #[attr] - /// Bar, - /// Baz(#[attr] u32), - /// Bruh { - /// a: u32, - /// /// Docs - /// #[attr] - /// b: T, - /// } - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) - struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { - T![enum], - variant_list: EnumVariantList, - } - - /// Enum variant definition list including enclosing curly braces. - /// - /// ``` - /// enum Foo - /// ❰ - /// { - /// Bar, - /// Baz(u32), - /// Bruh { - /// a: u32 - /// } - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) - struct EnumVariantList { - T!['{'], - variants: [EnumVariant], - T!['}'] - } - - /// Enum variant definition including its attributes and discriminant value definition. - /// - /// ``` - /// enum Foo { - /// ❰ - /// /// Docs - /// #[attr] - /// Bar - /// ❱ - /// - /// // same for tuple and record variants - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) - struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner { - FieldDefList, - T![=], - Expr - } - - /// Trait definition. - /// Includes all of its attributes and doc comments. - /// - /// ``` - /// ❰ - /// /// Docs - /// #[attr] - /// pub unsafe trait Foo: Debug where T: Debug { - /// // ... - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/traits.html) - struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner { - T![unsafe], - T![auto], - T![trait], - ItemList, - } - - /// Module definition either with body or not. - /// Includes all of its inner and outer attributes, module items, doc comments. - /// - /// ``` - /// ❰ - /// /// Docs - /// #[attr] - /// pub mod foo; - /// ❱ - /// - /// ❰ - /// /// Docs - /// #[attr] - /// pub mod bar { - /// //! Inner docs - /// #![inner_attr] - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/modules.html) - struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner { - T![mod], - ItemList, - T![;] - } - - /// Item defintion list. - /// This is used for both top-level items and impl block items. - /// - /// ``` - /// ❰ - /// fn foo {} - /// struct Bar; - /// enum Baz; - /// trait Bruh; - /// const BRUUH: u32 = 42; - /// ❱ - /// - /// impl Foo - /// ❰ - /// { - /// fn bar() {} - /// const BAZ: u32 = 42; - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items.html) - struct ItemList: ModuleItemOwner { - T!['{'], - assoc_items: [AssocItem], - T!['}'] - } - - /// Constant variable definition. - /// Includes all of its attributes and doc comments. - /// - /// ``` - /// ❰ - /// /// Docs - /// #[attr] - /// pub const FOO: u32 = 42; - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/constant-items.html) - struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { - T![default], - T![const], - T![=], - body: Expr, - T![;] - } - - - /// Static variable definition. - /// Includes all of its attributes and doc comments. - /// - /// ``` - /// ❰ - /// /// Docs - /// #[attr] - /// pub static mut FOO: u32 = 42; - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/static-items.html) - struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { - T![static], - T![mut], - T![=], - body: Expr, - T![;] - } - - /// Type alias definition. - /// Includes associated type clauses with type bounds. - /// - /// ``` - /// ❰ - /// /// Docs - /// #[attr] - /// pub type Foo where T: Debug = T; - /// ❱ - /// - /// trait Bar { - /// ❰ type Baz: Debug; ❱ - /// ❰ type Bruh = String; ❱ - /// ❰ type Bruuh: Debug = u32; ❱ - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/type-aliases.html) - struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner { - T![default], - T![type], - T![=], - TypeRef, - T![;] - } - - /// Inherent and trait impl definition. - /// Includes all of its inner and outer attributes. - /// - /// ``` - /// ❰ - /// #[attr] - /// unsafe impl const !Foo for Bar where T: Debug { - /// #![inner_attr] - /// // ... - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/implementations.html) - struct ImplDef: TypeParamsOwner, AttrsOwner, DocCommentsOwner { - T![default], - T![const], - T![unsafe], - T![impl], - T![!], - T![for], - ItemList, - } - - - /// Parenthesized type reference. - /// Note: parens are only used for grouping, this is not a tuple type. - /// - /// ``` - /// // This is effectively just `u32`. - /// // Single-item tuple must be defined with a trailing comma: `(u32,)` - /// type Foo = ❰ (u32) ❱; - /// - /// let bar: &'static ❰ (dyn Debug) ❱ = "bruh"; - /// ``` - struct ParenType { T!['('], TypeRef, T![')'] } - - /// Unnamed tuple type. - /// - /// ``` - /// let foo: ❰ (u32, bool) ❱ = (42, true); - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/types/tuple.html) - struct TupleType { T!['('], fields: [TypeRef], T![')'] } - - /// The never type (i.e. the exclamation point). - /// - /// ``` - /// type T = ❰ ! ❱; - /// - /// fn no_return() -> ❰ ! ❱ { - /// loop {} - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/types/never.html) - struct NeverType { T![!] } - - /// Path to a type. - /// Includes single identifier type names and elaborate paths with - /// generic parameters. - /// - /// ``` - /// type Foo = ❰ String ❱; - /// type Bar = ❰ std::vec::Vec ❱; - /// type Baz = ❰ ::bruh::::Item ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/paths.html) - struct PathType { Path } - - /// Raw pointer type. - /// - /// ``` - /// type Foo = ❰ *const u32 ❱; - /// type Bar = ❰ *mut u32 ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html#raw-pointers-const-and-mut) - struct PointerType { T![*], T![const], T![mut], TypeRef } - - /// Array type. - /// - /// ``` - /// type Foo = ❰ [u32; 24 - 3] ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/types/array.html) - struct ArrayType { T!['['], TypeRef, T![;], Expr, T![']'] } - - /// Slice type. - /// - /// ``` - /// type Foo = ❰ [u8] ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/types/slice.html) - struct SliceType { T!['['], TypeRef, T![']'] } - - /// Reference type. - /// - /// ``` - /// type Foo = ❰ &'static str ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html) - struct ReferenceType { T![&], T![lifetime], T![mut], TypeRef } - - /// Placeholder type (i.e. the underscore). - /// - /// ``` - /// let foo: ❰ _ ❱ = 42_u32; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/types/inferred.html) - struct PlaceholderType { T![_] } - - /// Function pointer type (not to be confused with `Fn*` family of traits). - /// - /// ``` - /// type Foo = ❰ async fn(#[attr] u32, named: bool) -> u32 ❱; - /// - /// type Bar = ❰ extern "C" fn(variadic: u32, #[attr] ...) ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/types/function-pointer.html) - struct FnPointerType { Abi, T![unsafe], T![fn], ParamList, RetType } - - /// Higher order type. - /// - /// ``` - /// type Foo = ❰ for<'a> fn(&'a str) ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/nomicon/hrtb.html) - struct ForType { T![for], TypeParamList, TypeRef } - - /// Opaque `impl Trait` type. - /// - /// ``` - /// fn foo(bar: ❰ impl Debug + Eq ❱) {} - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/types/impl-trait.html) - struct ImplTraitType: TypeBoundsOwner { T![impl] } - - /// Trait object type. - /// - /// ``` - /// type Foo = ❰ dyn Debug ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/types/trait-object.html) - struct DynTraitType: TypeBoundsOwner { T![dyn] } - - /// Tuple literal. - /// - /// ``` - /// ❰ (42, true) ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/tuple-expr.html) - struct TupleExpr: AttrsOwner { T!['('], exprs: [Expr], T![')'] } - - /// Array literal. - /// - /// ``` - /// ❰ [#![inner_attr] true, false, true] ❱; - /// - /// ❰ ["baz"; 24] ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html) - struct ArrayExpr: AttrsOwner { T!['['], exprs: [Expr], T![;], T![']'] } - - /// Parenthesized expression. - /// Note: parens are only used for grouping, this is not a tuple literal. - /// - /// ``` - /// ❰ (#![inner_attr] 2 + 2) ❱ * 2; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/grouped-expr.html) - struct ParenExpr: AttrsOwner { T!['('], Expr, T![')'] } - - /// Path to a symbol in expression context. - /// Includes single identifier variable names and elaborate paths with - /// generic parameters. - /// - /// ``` - /// ❰ Some:: ❱; - /// ❰ foo ❱ + 42; - /// ❰ Vec::::push ❱; - /// ❰ <[i32]>::reverse ❱; - /// ❰ >::borrow ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/path-expr.html) - struct PathExpr { Path } - - /// Anonymous callable object literal a.k.a. closure, lambda or functor. - /// - /// ``` - /// ❰ || 42 ❱; - /// ❰ |a: u32| val + 1 ❱; - /// ❰ async |#[attr] Pattern(_): Pattern| { bar } ❱; - /// ❰ move || baz ❱; - /// ❰ || -> u32 { closure_with_ret_type_annotation_requires_block_expr } ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html) - struct LambdaExpr: AttrsOwner { - T![static], // Note(@matklad): I belive this is (used to be?) syntax for generators - T![async], - T![move], - ParamList, - RetType, - body: Expr, - } - - /// If expression. Includes both regular `if` and `if let` forms. - /// Beware that `else if` is a special case syntax sugar, because in general - /// there has to be block expression after `else`. - /// - /// ``` - /// ❰ if bool_cond { 42 } ❱ - /// ❰ if bool_cond { 42 } else { 24 } ❱ - /// ❰ if bool_cond { 42 } else if bool_cond2 { 42 } ❱ - /// - /// ❰ - /// if let Pattern(foo) = bar { - /// foo - /// } else { - /// panic!(); - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/if-expr.html) - struct IfExpr: AttrsOwner { T![if], Condition } - - /// Unconditional loop expression. - /// - /// ``` - /// ❰ - /// loop { - /// // yeah, it's that simple... - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html) - struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] } - - /// Block expression with an optional prefix (label, try ketword, - /// unsafe keyword, async keyword...). - /// - /// ``` - /// ❰ - /// 'label: try { - /// None? - /// } - /// ❱ - /// ``` - /// - /// - [try block](https://doc.rust-lang.org/unstable-book/language-features/try-blocks.html) - /// - [unsafe block](https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks) - /// - [async block](https://doc.rust-lang.org/reference/expressions/block-expr.html#async-blocks) - struct EffectExpr: AttrsOwner { Label, T![try], T![unsafe], T![async], BlockExpr } - - - /// For loop expression. - /// Note: record struct literals are not valid as iterable expression - /// due to ambiguity. - /// - /// ``` - /// ❰ - /// for i in (0..4) { - /// dbg!(i); - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops) - struct ForExpr: AttrsOwner, LoopBodyOwner { - T![for], - Pat, - T![in], - iterable: Expr, - } - - /// While loop expression. Includes both regular `while` and `while let` forms. - /// - /// ``` - /// ❰ - /// while bool_cond { - /// 42; - /// } - /// ❱ - /// ❰ - /// while let Pattern(foo) = bar { - /// bar += 1; - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops) - struct WhileExpr: AttrsOwner, LoopBodyOwner { T![while], Condition } - - /// Continue expression. - /// - /// ``` - /// while bool_cond { - /// ❰ continue ❱; - /// } - /// - /// 'outer: loop { - /// loop { - /// ❰ continue 'outer ❱; - /// } - /// } - /// - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions) - struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] } - - /// Break expression. - /// - /// ``` - /// while bool_cond { - /// ❰ break ❱; - /// } - /// 'outer: loop { - /// for foo in bar { - /// ❰ break 'outer ❱; - /// } - /// } - /// 'outer: loop { - /// loop { - /// ❰ break 'outer 42 ❱; - /// } - /// } - /// ``` - /// - /// [Refernce](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions) - struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr } - - /// Label. - /// - /// ``` - /// ❰ 'outer: ❱ loop {} - /// - /// let foo = ❰ 'bar: ❱ loop {} - /// - /// ❰ 'baz: ❱ { - /// break 'baz; - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html?highlight=label#loop-labels) - /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md) - struct Label { T![lifetime] } - - /// Block expression. Includes unsafe blocks and block labels. - /// - /// ``` - /// let foo = ❰ - /// { - /// #![inner_attr] - /// ❰ { } ❱ - /// - /// ❰ 'label: { break 'label } ❱ - /// } - /// ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/block-expr.html) - /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md) - struct BlockExpr: AttrsOwner, ModuleItemOwner { - Label, T!['{'], statements: [Stmt], Expr, T!['}'], - } - - /// Return expression. - /// - /// ``` - /// || ❰ return 42 ❱; - /// - /// fn bar() { - /// ❰ return ❱; - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/return-expr.html) - struct ReturnExpr: AttrsOwner { Expr } - - /// Call expression (not to be confused with method call expression, it is - /// a separate ast node). - /// - /// ``` - /// ❰ foo() ❱; - /// ❰ &str::len("bar") ❱; - /// ❰ <&str as PartialEq<&str>>::eq(&"", &"") ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html) - struct CallExpr: ArgListOwner { Expr } - - /// Method call expression. - /// - /// ``` - /// ❰ receiver_expr.method() ❱; - /// ❰ receiver_expr.method::(42, true) ❱; - /// - /// ❰ ❰ ❰ foo.bar() ❱ .baz() ❱ .bruh() ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/method-call-expr.html) - struct MethodCallExpr: AttrsOwner, ArgListOwner { - Expr, T![.], NameRef, TypeArgList, - } - - /// Index expression a.k.a. subscript operator call. - /// - /// ``` - /// ❰ foo[42] ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html) - struct IndexExpr: AttrsOwner { T!['['], T![']'] } - - /// Field access expression. - /// - /// ``` - /// ❰ expr.bar ❱; - /// - /// ❰ ❰ ❰ foo.bar ❱ .baz ❱ .bruh ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/field-expr.html) - struct FieldExpr: AttrsOwner { Expr, T![.], NameRef } - - /// Await operator call expression. - /// - /// ``` - /// ❰ expr.await ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/await-expr.html) - struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] } - - /// The question mark operator call. - /// - /// ``` - /// ❰ expr? ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator) - struct TryExpr: AttrsOwner { Expr, T![?] } - - /// Type cast expression. - /// - /// ``` - /// ❰ expr as T ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions) - struct CastExpr: AttrsOwner { Expr, T![as], TypeRef } - - - /// Borrow operator call. - /// - /// ``` - /// ❰ &foo ❱; - /// ❰ &mut bar ❱; - /// ❰ &raw const bar ❱; - /// ❰ &raw mut bar ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators) - struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], T![const], Expr } - - /// Prefix operator call. This is either `!` or `*` or `-`. - /// - /// ``` - /// ❰ !foo ❱; - /// ❰ *bar ❱; - /// ❰ -42 ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html) - struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr } - - /// Box operator call. - /// - /// ``` - /// ❰ box 42 ❱; - /// ``` - /// - /// [RFC](https://github.com/rust-lang/rfcs/blob/0806be4f282144cfcd55b1d20284b43f87cbe1c6/text/0809-box-and-in-for-stdlib.md) - struct BoxExpr: AttrsOwner { T![box], Expr } - - /// Range operator call. - /// - /// ``` - /// ❰ 0..42 ❱; - /// ❰ ..42 ❱; - /// ❰ 0.. ❱; - /// ❰ .. ❱; - /// ❰ 0..=42 ❱; - /// ❰ ..=42 ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/range-expr.html) - struct RangeExpr: AttrsOwner { /*RangeOp*/ } - - - /// Binary operator call. - /// Includes all arithmetic, logic, bitwise and assignment operators. - /// - /// ``` - /// ❰ 2 + ❰ 2 * 2 ❱ ❱; - /// ❰ ❰ true && false ❱ || true ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators) - struct BinExpr: AttrsOwner { /*BinOp*/ } - - - /// [Raw] string, [raw] byte string, char, byte, integer, float or bool literal. - /// - /// ``` - /// ❰ "str" ❱; - /// ❰ br##"raw byte str"## ❱; - /// ❰ 'c' ❱; - /// ❰ b'c' ❱; - /// ❰ 42 ❱; - /// ❰ 1e9 ❱; - /// ❰ true ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/literal-expr.html) - struct Literal { /*LiteralToken*/ } - - /// Match expression. - /// - /// ``` - /// ❰ - /// match expr { - /// Pat1 => {} - /// Pat2(_) => 42, - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html) - struct MatchExpr: AttrsOwner { T![match], Expr, MatchArmList } - - /// Match arm list part of match expression. Includes its inner attributes. - /// - /// ``` - /// match expr - /// ❰ - /// { - /// #![inner_attr] - /// Pat1 => {} - /// Pat2(_) => 42, - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html) - struct MatchArmList: AttrsOwner { T!['{'], arms: [MatchArm], T!['}'] } - - - /// Match arm. - /// Note: record struct literals are not valid as target match expression - /// due to ambiguity. - /// ``` - /// match expr { - /// ❰ #[attr] Pattern(it) if bool_cond => it ❱, - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html) - struct MatchArm: AttrsOwner { - pat: Pat, - guard: MatchGuard, - T![=>], - Expr, - } - - /// Match guard. - /// - /// ``` - /// match expr { - /// Pattern(it) ❰ if bool_cond ❱ => it, - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards) - struct MatchGuard { T![if], Expr } - - /// Record literal expression. The same syntax is used for structs, - /// unions and record enum variants. - /// - /// ``` - /// ❰ - /// foo::Bar { - /// #![inner_attr] - /// baz: 42, - /// bruh: true, - /// ..spread - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html) - struct RecordLit { Path, RecordFieldList} - - /// Record field list including enclosing curly braces. - /// - /// foo::Bar ❰ - /// { - /// baz: 42, - /// ..spread - /// } - /// ❱ - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html) - struct RecordFieldList { - T!['{'], - fields: [RecordField], - T![..], - spread: Expr, - T!['}'] - } - - /// Record field. - /// - /// ``` - /// foo::Bar { - /// ❰ #[attr] baz: 42 ❱ - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html) - struct RecordField: AttrsOwner { NameRef, T![:], Expr } - - /// Disjunction of patterns. - /// - /// ``` - /// let ❰ Foo(it) | Bar(it) | Baz(it) ❱ = bruh; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html) - struct OrPat { pats: [Pat] } - - /// Parenthesized pattern. - /// Note: parens are only used for grouping, this is not a tuple pattern. - /// - /// ``` - /// if let ❰ &(0..=42) ❱ = foo {} - /// ``` - /// - /// https://doc.rust-lang.org/reference/patterns.html#grouped-patterns - struct ParenPat { T!['('], Pat, T![')'] } - - /// Reference pattern. - /// Note: this has nothing to do with `ref` keyword, the latter is used in bind patterns. - /// - /// ``` - /// let ❰ &mut foo ❱ = bar; - /// - /// let ❰ & ❰ &mut ❰ &_ ❱ ❱ ❱ = baz; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#reference-patterns) - struct RefPat { T![&], T![mut], Pat } - - /// Box pattern. - /// - /// ``` - /// let ❰ box foo ❱ = box 42; - /// ``` - /// - /// [Unstable book](https://doc.rust-lang.org/unstable-book/language-features/box-patterns.html) - struct BoxPat { T![box], Pat } - - /// Bind pattern. - /// - /// ``` - /// match foo { - /// Some(❰ ref mut bar ❱) => {} - /// ❰ baz @ None ❱ => {} - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#identifier-patterns) - struct BindPat: AttrsOwner, NameOwner { T![ref], T![mut], T![@], Pat } - - /// Placeholder pattern a.k.a. the wildcard pattern or the underscore. - /// - /// ``` - /// let ❰ _ ❱ = foo; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#wildcard-pattern) - struct PlaceholderPat { T![_] } - - /// Rest-of-the record/tuple pattern. - /// Note: this is not the unbonded range pattern (even more: it doesn't exist). - /// - /// ``` - /// let Foo { bar, ❰ .. ❱ } = baz; - /// let (❰ .. ❱, bruh) = (42, 24, 42); - /// let Bruuh(❰ .. ❱) = bruuuh; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) - struct DotDotPat { T![..] } - - /// Path pattern. - /// Doesn't include the underscore pattern (it is a special case, namely `PlaceholderPat`). - /// - /// ``` - /// let ❰ foo::bar::Baz ❱ { .. } = bruh; - /// if let ❰ CONST ❱ = 42 {} - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#path-patterns) - struct PathPat { Path } - - /// Slice pattern. - /// - /// ``` - /// let ❰ [foo, bar, baz] ❱ = [1, 2, 3]; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#slice-patterns) - struct SlicePat { T!['['], args: [Pat], T![']'] } - - /// Range pattern. - /// - /// ``` - /// match foo { - /// ❰ 0..42 ❱ => {} - /// ❰ 0..=42 ❱ => {} - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#range-patterns) - struct RangePat { } // FIXME(@matklad): here should be T![..], T![..=] I think, if we don't already have an accessor in expresions_ext - - /// Literal pattern. - /// Includes only bool, number, char, and string literals. - /// - /// ``` - /// match foo { - /// Number(❰ 42 ❱) => {} - /// String(❰ "42" ❱) => {} - /// Bool(❰ true ❱) => {} - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#literal-patterns) - struct LiteralPat { Literal } - - /// Macro invocation in pattern position. - /// - /// ``` - /// let ❰ foo!(my custom syntax) ❱ = baz; - /// - /// ``` - /// [Reference](https://doc.rust-lang.org/reference/macros.html#macro-invocation) - struct MacroPat { MacroCall } - - /// Record literal pattern. - /// - /// ``` - /// let ❰ foo::Bar { baz, .. } ❱ = bruh; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) - struct RecordPat { RecordFieldPatList, Path } - - /// Record literal's field patterns list including enclosing curly braces. - /// - /// ``` - /// let foo::Bar ❰ { baz, bind @ bruh, .. } ❱ = bruuh; - /// `` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) - struct RecordFieldPatList { - T!['{'], - pats: [RecordInnerPat], - record_field_pats: [RecordFieldPat], - bind_pats: [BindPat], - T![..], - T!['}'] - } - - /// Record literal's field pattern. - /// Note: record literal can also match tuple structs. - /// - /// ``` - /// let Foo { ❰ bar: _ ❱ } = baz; - /// let TupleStruct { ❰ 0: _ ❱ } = bruh; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) - struct RecordFieldPat: AttrsOwner { NameRef, T![:], Pat } - - /// Tuple struct literal pattern. - /// - /// ``` - /// let ❰ foo::Bar(baz, bruh) ❱ = bruuh; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-struct-patterns) - struct TupleStructPat { Path, T!['('], args: [Pat], T![')'] } - - /// Tuple pattern. - /// Note: this doesn't include tuple structs (see `TupleStructPat`) - /// - /// ``` - /// let ❰ (foo, bar, .., baz) ❱ = bruh; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-patterns) - struct TuplePat { T!['('], args: [Pat], T![')'] } - - /// Visibility. - /// - /// ``` - /// ❰ pub mod ❱ foo; - /// ❰ pub(crate) ❱ struct Bar; - /// ❰ pub(self) ❱ enum Baz {} - /// ❰ pub(super) ❱ fn bruh() {} - /// ❰ pub(in bruuh::bruuuh) ❱ type T = u64; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html) - struct Visibility { T![pub], T![super], T![self], T![crate] } - - /// Single identifier. - /// Note(@matklad): `Name` is for things that install a new name into the scope, - /// `NameRef` is a usage of a name. Most of the time, this definition/reference - /// distinction can be determined purely syntactically, ie in - /// ``` - /// fn foo() { foo() } - /// ``` - /// the first foo is `Name`, the second one is `NameRef`. - /// The notable exception are patterns, where in - /// `` - /// let x = 92 - /// ``` - /// `x` can be semantically either a name or a name ref, depeding on - /// wether there's an `x` constant in scope. - /// We use `Name` for patterns, and disambiguate semantically (see `NameClass` in ide_db). - /// - /// ``` - /// let ❰ foo ❱ = bar; - /// struct ❰ Baz ❱; - /// fn ❰ bruh ❱() {} - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/identifiers.html) - struct Name { T![ident] } - - /// Reference to a name. - /// See the explanation on the difference between `Name` and `NameRef` - /// in `Name` ast node docs. - /// - /// ``` - /// let foo = ❰ bar ❱(❰ Baz(❰ bruh ❱) ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/identifiers.html) - struct NameRef { } - - /// Macro call. - /// Includes all of its attributes and doc comments. - /// - /// ``` - /// ❰ - /// /// Docs - /// #[attr] - /// macro_rules! foo { // macro rules is also a macro call - /// ($bar: tt) => {} - /// } - /// ❱ - /// - /// // semicolon is a part of `MacroCall` when it is used in item positions - /// ❰ foo!(); ❱ - /// - /// fn main() { - /// ❰ foo!() ❱; // macro call in expression positions doesn't include the semi - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/macros.html) - struct MacroCall: NameOwner, AttrsOwner, DocCommentsOwner { - Path, T![!], TokenTree, T![;] - } - - /// Attribute. - /// - /// ``` - /// ❰ #![inner_attr] ❱ - /// - /// ❰ #[attr] ❱ - /// ❰ #[foo = "bar"] ❱ - /// ❰ #[baz(bruh::bruuh = "42")] ❱ - /// struct Foo; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/attributes.html) - struct Attr { T![#], T![!], T!['['], Path, T![=], input: AttrInput, T![']'] } - - /// Stores a list of lexer tokens and other `TokenTree`s. - /// It appears in attributes, macro_rules and macro call (foo!) - /// - /// ``` - /// macro_call! ❰ { my syntax here } ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/macros.html) - struct TokenTree {} - - /// Generic lifetime, type and constants parameters list **declaration**. - /// - /// ``` - /// fn foo❰ <'a, 'b, T, U, const BAR: u64> ❱() {} - /// - /// struct Baz❰ ❱(T); - /// - /// impl❰ ❱ Bruh {} - /// - /// type Bruuh = for❰ <'a> ❱ fn(&'a str) -> &'a str; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/generics.html) - struct TypeParamList { - T![<], - generic_params: [GenericParam], - type_params: [TypeParam], - lifetime_params: [LifetimeParam], - const_params: [ConstParam], - T![>] - } - - /// Single type parameter **declaration**. - /// - /// ``` - /// fn foo<❰ K ❱, ❰ I ❱, ❰ E: Debug ❱, ❰ V = DefaultType ❱>() {} - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/generics.html) - struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner { - T![=], - default_type: TypeRef, - } - - /// Const generic parameter **declaration**. - /// ``` - /// fn foo() {} - /// ``` - /// - /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter) - struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner { - T![=], - default_val: Expr, - } - - /// Lifetime parameter **declaration**. - /// - /// ``` - /// fn foo<❰ 'a ❱, ❰ 'b ❱, V, G, D>(bar: &'a str, baz: &'b mut str) {} - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/generics.html) - struct LifetimeParam: AttrsOwner { T![lifetime] } - - /// Type bound declaration clause. - /// - /// ``` - /// fn foo() {} - /// - /// trait Bar - /// where - /// T: ❰ Send ❱ + ❰ Sync ❱ - /// { - /// type Baz: ❰ !Sync ❱ + ❰ Debug ❱ + ❰ ?const Add ❱; - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html) - struct TypeBound { T![lifetime], /* Question, */ T![const], /* Question, */ TypeRef } - - /// Type bounds list. - /// - /// ``` - /// - /// fn foo() {} - /// - /// trait Bar - /// where - /// T: ❰ Send + Sync ❱ - /// { - /// type Baz: ❰ !Sync + Debug ❱; - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html) - struct TypeBoundList { bounds: [TypeBound] } - - /// Single where predicate. - /// - /// ``` - /// trait Foo<'a, 'b, T> - /// where - /// ❰ 'a: 'b ❱, - /// ❰ T: IntoIterator ❱, - /// ❰ for<'c> ::Item: Bar<'c> ❱ - /// {} - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses) - struct WherePred: TypeBoundsOwner { T![for], TypeParamList, T![lifetime], TypeRef } - - /// Where clause. - /// - /// ``` - /// trait Foo<'a, T> ❰ where 'a: 'static, T: Debug ❱ {} - /// - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses) - struct WhereClause { T![where], predicates: [WherePred] } - - /// Abi declaration. - /// Note: the abi string is optional. - /// - /// ``` - /// ❰ extern "C" ❱ { - /// fn foo() {} - /// } - /// - /// type Bar = ❰ extern ❱ fn() -> u32; - /// - /// type Baz = ❰ extern r#"stdcall"# ❱ fn() -> bool; - /// ``` - /// - /// - [Extern blocks reference](https://doc.rust-lang.org/reference/items/external-blocks.html) - /// - [FFI function pointers reference](https://doc.rust-lang.org/reference/items/functions.html#functions) - struct Abi { /*String*/ } - - /// Expression statement. - /// - /// ``` - /// ❰ 42; ❱ - /// ❰ foo(); ❱ - /// ❰ (); ❱ - /// ❰ {}; ❱ - /// - /// // constructions with trailing curly brace can omit the semicolon - /// // but only when there are satements immediately after them (this is important!) - /// ❰ if bool_cond { } ❱ - /// ❰ loop {} ❱ - /// ❰ somestatment; ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/statements.html) - struct ExprStmt: AttrsOwner { Expr, T![;] } - - /// Let statement. - /// - /// ``` - /// ❰ #[attr] let foo; ❱ - /// ❰ let bar: u64; ❱ - /// ❰ let baz = 42; ❱ - /// ❰ let bruh: bool = true; ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/statements.html#let-statements) - struct LetStmt: AttrsOwner, TypeAscriptionOwner { - T![let], - Pat, - T![=], - initializer: Expr, - T![;], - } - - /// Condition of `if` or `while` expression. - /// - /// ``` - /// if ❰ true ❱ {} - /// if ❰ let Pat(foo) = bar ❱ {} - /// - /// while ❰ true ❱ {} - /// while ❰ let Pat(baz) = bruh ❱ {} - /// ``` - /// - /// [If expression reference](https://doc.rust-lang.org/reference/expressions/if-expr.html) - /// [While expression reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops) - struct Condition { T![let], Pat, T![=], Expr } - - /// Parameter list **declaration**. - /// - /// ``` - /// fn foo❰ (a: u32, b: bool) ❱ -> u32 {} - /// let bar = ❰ |a, b| ❱ {}; - /// - /// impl Baz { - /// fn bruh❰ (&self, a: u32) ❱ {} - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)ocs to codegen script - struct ParamList { // FIXME: this node is used by closure expressions too, but hey use pipes instead of parens... - T!['('], - SelfParam, - params: [Param], - T![')'] - } - - /// Self parameter **declaration**. - /// - /// ``` - /// impl Bruh { - /// fn foo(❰ self ❱) {} - /// fn bar(❰ &self ❱) {} - /// fn baz(❰ &mut self ❱) {} - /// fn blah<'a>(❰ &'a self ❱) {} - /// fn blin(❰ self: Box ❱) {} - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/functions.html) - struct SelfParam: TypeAscriptionOwner, AttrsOwner { T![&], T![mut], T![lifetime], T![self] } - - /// Parameter **declaration**. - /// - /// ``` - /// fn foo(❰ #[attr] Pat(bar): Pat(u32) ❱, ❰ #[attr] _: bool ❱) {} - /// - /// extern "C" { - /// fn bar(❰ baz: u32 ❱, ❰ ... ❱) -> u32; - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/functions.html) - struct Param: TypeAscriptionOwner, AttrsOwner { - Pat, - T![...] - } - - /// Use declaration. - /// - /// ``` - /// ❰ #[attr] pub use foo; ❱ - /// ❰ use bar as baz; ❱ - /// ❰ use bruh::{self, bruuh}; ❱ - /// ❰ use { blin::blen, blah::* }; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) - struct UseItem: AttrsOwner, VisibilityOwner { - T![use], - UseTree, - } - - /// Use tree. - /// - /// ``` - /// pub use ❰ foo::❰ * ❱ ❱; - /// use ❰ bar as baz ❱; - /// use ❰ bruh::bruuh::{ ❰ self ❱, ❰ blin ❱ } ❱; - /// use ❰ { ❰ blin::blen ❱ } ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) - struct UseTree { - Path, T![*], UseTreeList, Alias - } - - /// Item alias. - /// Note: this is not the type alias. - /// - /// ``` - /// use foo ❰ as bar ❱; - /// use baz::{bruh ❰ as _ ❱}; - /// extern crate bruuh ❰ as blin ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) - struct Alias: NameOwner { T![as] } - - /// Sublist of use trees. - /// - /// ``` - /// use bruh::bruuh::❰ { ❰ self ❱, ❰ blin ❱ } ❱; - /// use ❰ { blin::blen::❰ {} ❱ } ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) - struct UseTreeList { T!['{'], use_trees: [UseTree], T!['}'] } - - /// Extern crate item. - /// - /// ``` - /// ❰ #[attr] pub extern crate foo; ❱ - /// ❰ extern crate self as bar; ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/extern-crates.html) - struct ExternCrateItem: AttrsOwner, VisibilityOwner { - T![extern], T![crate], NameRef, Alias, - } - - /// Call site arguments list. - /// - /// ``` - /// foo::❰ (42, true) ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html) - struct ArgList { - T!['('], - args: [Expr], - T![')'] - } - - /// Path to a symbol. Includes single identifier names and elaborate paths with - /// generic parameters. - /// - /// ``` - /// (0..10).❰ ❰ collect ❱ ::> ❱(); - /// ❰ ❰ ❰ Vec ❱ :: ❱ ::with_capacity ❱(1024); - /// ❰ ❰ <❰ Foo ❱ as ❰ ❰ bar ❱ ::Bar ❱> ❱ ::baz ❱(); - /// ❰ ❰ <❰ bruh ❱> ❱ ::bruuh ❱(); - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/paths.html) - struct Path { - segment: PathSegment, - T![::], - qualifier: Path, - } - - /// Segment of the path to a symbol. - /// Only path segment of an absolute path holds the `::` token, - /// all other `::` tokens that connect path segments reside under `Path` itself.` - /// - /// ``` - /// (0..10).❰ collect ❱ :: ❰ > ❱(); - /// ❰ Vec ❱ :: ❰ ❱ :: ❰ with_capacity ❱(1024); - /// ❰ <❰ Foo ❱ as ❰ bar ❱ :: ❰ Bar ❱> ❱ :: ❰ baz ❱(); - /// ❰ <❰ bruh ❱> ❱ :: ❰ bruuh ❱(); - /// - /// // Note that only in this case `::` token is inlcuded: - /// ❰ ::foo ❱; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/paths.html) - struct PathSegment { - T![::], T![crate], T![self], T![super], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>] - } - - /// List of type arguments that are passed at generic instantiation site. - /// - /// ``` - /// type _ = Foo ❰ ::<'a, u64, Item = Bar, 42, {true}> ❱::Bar; - /// - /// Vec❰ :: ❱::(); - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions) - struct TypeArgList { - T![::], - T![<], - generic_args: [GenericArg], - type_args: [TypeArg], - lifetime_args: [LifetimeArg], - assoc_type_args: [AssocTypeArg], - const_args: [ConstArg], - T![>] - } - - /// Type argument that is passed at generic instantiation site. - /// - /// ``` - /// type _ = Foo::<'a, ❰ u64 ❱, ❰ bool ❱, Item = Bar, 42>::Baz; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions) - struct TypeArg { TypeRef } - - /// Associated type argument that is passed at generic instantiation site. - /// ``` - /// type Foo = Bar::<'a, u64, bool, ❰ Item = Baz ❱, 42>::Bruh; - /// - /// trait Bruh: Iterator<❰ Item: Debug ❱> {} - /// ``` - /// - struct AssocTypeArg : TypeBoundsOwner { NameRef, T![=], TypeRef } - - /// Lifetime argument that is passed at generic instantiation site. - /// - /// ``` - /// fn foo<'a>(s: &'a str) { - /// bar::<❰ 'a ❱>(s); - /// } - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions) - struct LifetimeArg { T![lifetime] } - - /// Constant value argument that is passed at generic instantiation site. - /// - /// ``` - /// foo::(); - /// - /// bar::<❰ { 2 + 2} ❱>(); - /// ``` - /// - /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter) - struct ConstArg { Literal, BlockExpr } - - - /// FIXME: (@edwin0cheng) Remove it to use ItemList instead - /// https://github.com/rust-analyzer/rust-analyzer/pull/4083#discussion_r422666243 - /// - /// [Reference](https://doc.rust-lang.org/reference/macros.html) - struct MacroItems: ModuleItemOwner { } - - /// FIXME: (@edwin0cheng) add some documentation here. As per the writing - /// of this comment this ast node is not used. - /// - /// ``` - /// // FIXME: example here - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/macros.html) - struct MacroStmts { - statements: [Stmt], - Expr, - } - - /// List of items in an extern block. - /// - /// ``` - /// extern "C" ❰ - /// { - /// fn foo(); - /// static var: u32; - /// } - /// ❱ - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html) - struct ExternItemList: ModuleItemOwner { - T!['{'], - extern_items: [ExternItem], - T!['}'] - } - - /// Extern block. - /// - /// ``` - /// ❰ - /// extern "C" { - /// fn foo(); - /// } - /// ❱ - /// - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html) - struct ExternBlock { - Abi, - ExternItemList - } - - /// Meta item in an attribute. - /// - /// ``` - /// #[❰ bar::baz = "42" ❱] - /// #[❰ bruh(bruuh("true")) ❱] - /// struct Foo; - /// ``` - /// - /// [Reference](https://doc.rust-lang.org/reference/attributes.html?highlight=meta,item#meta-item-attribute-syntax) - struct MetaItem { - Path, T![=], AttrInput, nested_meta_items: [MetaItem] - } - - /// Macro 2.0 definition. - /// Their syntax is still WIP by rustc team... - /// ``` - /// ❰ - /// macro foo { } - /// ❱ - /// ``` - /// - /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/1584-macros.md) - struct MacroDef { - Name, TokenTree - } - }, - enums: &ast_enums! { - /// Any kind of nominal type definition. - enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner { - StructDef, EnumDef, UnionDef, - } - - /// Any kind of **declared** generic parameter - enum GenericParam { - LifetimeParam, - TypeParam, - ConstParam - } - - /// Any kind of generic argument passed at instantiation site - enum GenericArg { - LifetimeArg, - TypeArg, - ConstArg, - AssocTypeArg - } - - /// Any kind of construct valid in type context - enum TypeRef { - ParenType, - TupleType, - NeverType, - PathType, - PointerType, - ArrayType, - SliceType, - ReferenceType, - PlaceholderType, - FnPointerType, - ForType, - ImplTraitType, - DynTraitType, - } - - /// Any kind of top-level item that may appear in a module - enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner { - StructDef, - UnionDef, - EnumDef, - FnDef, - TraitDef, - TypeAliasDef, - ImplDef, - UseItem, - ExternCrateItem, - ConstDef, - StaticDef, - Module, - MacroCall, - ExternBlock - } - - - - /// Any kind of item that may appear in an impl block - /// - /// // FIXME: impl blocks can also contain MacroCall - enum AssocItem: NameOwner, AttrsOwner { - FnDef, TypeAliasDef, ConstDef - } - - /// Any kind of item that may appear in an extern block - /// - /// // FIXME: extern blocks can also contain MacroCall - enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner { - FnDef, StaticDef - } - - /// Any kind of expression - enum Expr: AttrsOwner { - TupleExpr, - ArrayExpr, - ParenExpr, - PathExpr, - LambdaExpr, - IfExpr, - LoopExpr, - ForExpr, - WhileExpr, - ContinueExpr, - BreakExpr, - Label, - BlockExpr, - ReturnExpr, - MatchExpr, - RecordLit, - CallExpr, - IndexExpr, - MethodCallExpr, - FieldExpr, - AwaitExpr, - TryExpr, - EffectExpr, - CastExpr, - RefExpr, - PrefixExpr, - RangeExpr, - BinExpr, - Literal, - MacroCall, - BoxExpr, - } - - /// Any kind of pattern - enum Pat { - OrPat, - ParenPat, - RefPat, - BoxPat, - BindPat, - PlaceholderPat, - DotDotPat, - PathPat, - RecordPat, - TupleStructPat, - TuplePat, - SlicePat, - RangePat, - LiteralPat, - MacroPat, - } - - /// Any kind of pattern that appears directly inside of the curly - /// braces of a record pattern - enum RecordInnerPat { - RecordFieldPat, - BindPat - } - - /// Any kind of input to an attribute - enum AttrInput { Literal, TokenTree } - - /// Any kind of statement - /// Note: there are no empty statements, these are just represented as - /// bare semicolons without a dedicated statement ast node. - enum Stmt { - LetStmt, - ExprStmt, - // macro calls are parsed as expression statements - } - - /// Any kind of fields list (record or tuple field lists) - enum FieldDefList { - RecordFieldDefList, - TupleFieldDefList, - } - }, -}; +pub(crate) fn rust_ast() -> AstSrc { + AstSrc { + tokens: vec!["Whitespace".into(), "Comment".into(), "String".into(), "RawString".into()], + nodes: ast_nodes! { + /// The entire Rust source file. Includes all top-level inner attributes and module items. + /// + /// [Reference](https://doc.rust-lang.org/reference/crates-and-source-files.html) + struct SourceFile: ModuleItemOwner, AttrsOwner, DocCommentsOwner { + modules: [Module], + } + + /// Function definition either with body or not. + /// Includes all of its attributes and doc comments. + /// + /// ``` + /// ❰ + /// /// Docs + /// #[attr] + /// pub extern "C" fn foo(#[attr] Patern {p}: Pattern) -> u32 + /// where + /// T: Debug + /// { + /// 42 + /// } + /// ❱ + /// + /// extern "C" { + /// ❰ fn fn_decl(also_variadic_ffi: u32, ...) -> u32; ❱ + /// } + /// ``` + /// + /// - [Reference](https://doc.rust-lang.org/reference/items/functions.html) + /// - [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions) + struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner { + Abi, + T![const], + T![default], + T![async], + T![unsafe], + T![fn], + ParamList, + RetType, + body: BlockExpr, + T![;] + } + + /// Return type annotation. + /// + /// ``` + /// fn foo(a: u32) ❰ -> Option ❱ { Some(a) } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/functions.html) + struct RetType { T![->], TypeRef } + + /// Struct definition. + /// Includes all of its attributes and doc comments. + /// + /// ``` + /// ❰ + /// /// Docs + /// #[attr] + /// struct Foo where T: Debug { + /// /// Docs + /// #[attr] + /// pub a: u32, + /// b: T, + /// } + /// ❱ + /// + /// ❰ struct Foo; ❱ + /// ❰ struct Foo(#[attr] T) where T: Debug; ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) + struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { + T![struct], + FieldDefList, + T![;] + } + + /// Union definition. + /// Includes all of its attributes and doc comments. + /// + /// ``` + /// ❰ + /// /// Docs + /// #[attr] + /// pub union Foo where T: Debug { + /// /// Docs + /// #[attr] + /// a: T, + /// b: u32, + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/unions.html) + struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { + T![union], + RecordFieldDefList, + } + + /// Record field definition list including enclosing curly braces. + /// + /// ``` + /// struct Foo // same for union + /// ❰ + /// { + /// a: u32, + /// b: bool, + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) + struct RecordFieldDefList { T!['{'], fields: [RecordFieldDef], T!['}'] } + + /// Record field definition including its attributes and doc comments. + /// + /// ` `` + /// same for union + /// struct Foo { + /// ❰ + /// /// Docs + /// #[attr] + /// pub a: u32 + /// ❱ + /// + /// ❰ b: bool ❱ + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) + struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { } + + /// Tuple field definition list including enclosing parens. + /// + /// ``` + /// struct Foo ❰ (u32, String, Vec) ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) + struct TupleFieldDefList { T!['('], fields: [TupleFieldDef], T![')'] } + + /// Tuple field definition including its attributes. + /// + /// ``` + /// struct Foo(❰ #[attr] u32 ❱); + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) + struct TupleFieldDef: VisibilityOwner, AttrsOwner { + TypeRef, + } + + /// Enum definition. + /// Includes all of its attributes and doc comments. + /// + /// ``` + /// ❰ + /// /// Docs + /// #[attr] + /// pub enum Foo where T: Debug { + /// /// Docs + /// #[attr] + /// Bar, + /// Baz(#[attr] u32), + /// Bruh { + /// a: u32, + /// /// Docs + /// #[attr] + /// b: T, + /// } + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) + struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { + T![enum], + variant_list: EnumVariantList, + } + + /// Enum variant definition list including enclosing curly braces. + /// + /// ``` + /// enum Foo + /// ❰ + /// { + /// Bar, + /// Baz(u32), + /// Bruh { + /// a: u32 + /// } + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) + struct EnumVariantList { + T!['{'], + variants: [EnumVariant], + T!['}'] + } + + /// Enum variant definition including its attributes and discriminant value definition. + /// + /// ``` + /// enum Foo { + /// ❰ + /// /// Docs + /// #[attr] + /// Bar + /// ❱ + /// + /// // same for tuple and record variants + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) + struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner { + FieldDefList, + T![=], + Expr + } + + /// Trait definition. + /// Includes all of its attributes and doc comments. + /// + /// ``` + /// ❰ + /// /// Docs + /// #[attr] + /// pub unsafe trait Foo: Debug where T: Debug { + /// // ... + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/traits.html) + struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner { + T![unsafe], + T![auto], + T![trait], + ItemList, + } + + /// Module definition either with body or not. + /// Includes all of its inner and outer attributes, module items, doc comments. + /// + /// ``` + /// ❰ + /// /// Docs + /// #[attr] + /// pub mod foo; + /// ❱ + /// + /// ❰ + /// /// Docs + /// #[attr] + /// pub mod bar { + /// //! Inner docs + /// #![inner_attr] + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/modules.html) + struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner { + T![mod], + ItemList, + T![;] + } + + /// Item defintion list. + /// This is used for both top-level items and impl block items. + /// + /// ``` + /// ❰ + /// fn foo {} + /// struct Bar; + /// enum Baz; + /// trait Bruh; + /// const BRUUH: u32 = 42; + /// ❱ + /// + /// impl Foo + /// ❰ + /// { + /// fn bar() {} + /// const BAZ: u32 = 42; + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items.html) + struct ItemList: ModuleItemOwner { + T!['{'], + assoc_items: [AssocItem], + T!['}'] + } + + /// Constant variable definition. + /// Includes all of its attributes and doc comments. + /// + /// ``` + /// ❰ + /// /// Docs + /// #[attr] + /// pub const FOO: u32 = 42; + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/constant-items.html) + struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { + T![default], + T![const], + T![=], + body: Expr, + T![;] + } + + + /// Static variable definition. + /// Includes all of its attributes and doc comments. + /// + /// ``` + /// ❰ + /// /// Docs + /// #[attr] + /// pub static mut FOO: u32 = 42; + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/static-items.html) + struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { + T![static], + T![mut], + T![=], + body: Expr, + T![;] + } + + /// Type alias definition. + /// Includes associated type clauses with type bounds. + /// + /// ``` + /// ❰ + /// /// Docs + /// #[attr] + /// pub type Foo where T: Debug = T; + /// ❱ + /// + /// trait Bar { + /// ❰ type Baz: Debug; ❱ + /// ❰ type Bruh = String; ❱ + /// ❰ type Bruuh: Debug = u32; ❱ + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/type-aliases.html) + struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner { + T![default], + T![type], + T![=], + TypeRef, + T![;] + } + + /// Inherent and trait impl definition. + /// Includes all of its inner and outer attributes. + /// + /// ``` + /// ❰ + /// #[attr] + /// unsafe impl const !Foo for Bar where T: Debug { + /// #![inner_attr] + /// // ... + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/implementations.html) + struct ImplDef: TypeParamsOwner, AttrsOwner, DocCommentsOwner { + T![default], + T![const], + T![unsafe], + T![impl], + T![!], + T![for], + ItemList, + } + + + /// Parenthesized type reference. + /// Note: parens are only used for grouping, this is not a tuple type. + /// + /// ``` + /// // This is effectively just `u32`. + /// // Single-item tuple must be defined with a trailing comma: `(u32,)` + /// type Foo = ❰ (u32) ❱; + /// + /// let bar: &'static ❰ (dyn Debug) ❱ = "bruh"; + /// ``` + struct ParenType { T!['('], TypeRef, T![')'] } + + /// Unnamed tuple type. + /// + /// ``` + /// let foo: ❰ (u32, bool) ❱ = (42, true); + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/types/tuple.html) + struct TupleType { T!['('], fields: [TypeRef], T![')'] } + + /// The never type (i.e. the exclamation point). + /// + /// ``` + /// type T = ❰ ! ❱; + /// + /// fn no_return() -> ❰ ! ❱ { + /// loop {} + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/types/never.html) + struct NeverType { T![!] } + + /// Path to a type. + /// Includes single identifier type names and elaborate paths with + /// generic parameters. + /// + /// ``` + /// type Foo = ❰ String ❱; + /// type Bar = ❰ std::vec::Vec ❱; + /// type Baz = ❰ ::bruh::::Item ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/paths.html) + struct PathType { Path } + + /// Raw pointer type. + /// + /// ``` + /// type Foo = ❰ *const u32 ❱; + /// type Bar = ❰ *mut u32 ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html#raw-pointers-const-and-mut) + struct PointerType { T![*], T![const], T![mut], TypeRef } + + /// Array type. + /// + /// ``` + /// type Foo = ❰ [u32; 24 - 3] ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/types/array.html) + struct ArrayType { T!['['], TypeRef, T![;], Expr, T![']'] } + + /// Slice type. + /// + /// ``` + /// type Foo = ❰ [u8] ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/types/slice.html) + struct SliceType { T!['['], TypeRef, T![']'] } + + /// Reference type. + /// + /// ``` + /// type Foo = ❰ &'static str ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html) + struct ReferenceType { T![&], T![lifetime], T![mut], TypeRef } + + /// Placeholder type (i.e. the underscore). + /// + /// ``` + /// let foo: ❰ _ ❱ = 42_u32; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/types/inferred.html) + struct PlaceholderType { T![_] } + + /// Function pointer type (not to be confused with `Fn*` family of traits). + /// + /// ``` + /// type Foo = ❰ async fn(#[attr] u32, named: bool) -> u32 ❱; + /// + /// type Bar = ❰ extern "C" fn(variadic: u32, #[attr] ...) ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/types/function-pointer.html) + struct FnPointerType { Abi, T![unsafe], T![fn], ParamList, RetType } + + /// Higher order type. + /// + /// ``` + /// type Foo = ❰ for<'a> fn(&'a str) ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/nomicon/hrtb.html) + struct ForType { T![for], TypeParamList, TypeRef } + + /// Opaque `impl Trait` type. + /// + /// ``` + /// fn foo(bar: ❰ impl Debug + Eq ❱) {} + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/types/impl-trait.html) + struct ImplTraitType: TypeBoundsOwner { T![impl] } + + /// Trait object type. + /// + /// ``` + /// type Foo = ❰ dyn Debug ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/types/trait-object.html) + struct DynTraitType: TypeBoundsOwner { T![dyn] } + + /// Tuple literal. + /// + /// ``` + /// ❰ (42, true) ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/tuple-expr.html) + struct TupleExpr: AttrsOwner { T!['('], exprs: [Expr], T![')'] } + + /// Array literal. + /// + /// ``` + /// ❰ [#![inner_attr] true, false, true] ❱; + /// + /// ❰ ["baz"; 24] ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html) + struct ArrayExpr: AttrsOwner { T!['['], exprs: [Expr], T![;], T![']'] } + + /// Parenthesized expression. + /// Note: parens are only used for grouping, this is not a tuple literal. + /// + /// ``` + /// ❰ (#![inner_attr] 2 + 2) ❱ * 2; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/grouped-expr.html) + struct ParenExpr: AttrsOwner { T!['('], Expr, T![')'] } + + /// Path to a symbol in expression context. + /// Includes single identifier variable names and elaborate paths with + /// generic parameters. + /// + /// ``` + /// ❰ Some:: ❱; + /// ❰ foo ❱ + 42; + /// ❰ Vec::::push ❱; + /// ❰ <[i32]>::reverse ❱; + /// ❰ >::borrow ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/path-expr.html) + struct PathExpr { Path } + + /// Anonymous callable object literal a.k.a. closure, lambda or functor. + /// + /// ``` + /// ❰ || 42 ❱; + /// ❰ |a: u32| val + 1 ❱; + /// ❰ async |#[attr] Pattern(_): Pattern| { bar } ❱; + /// ❰ move || baz ❱; + /// ❰ || -> u32 { closure_with_ret_type_annotation_requires_block_expr } ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html) + struct LambdaExpr: AttrsOwner { + T![static], // Note(@matklad): I belive this is (used to be?) syntax for generators + T![async], + T![move], + ParamList, + RetType, + body: Expr, + } + + /// If expression. Includes both regular `if` and `if let` forms. + /// Beware that `else if` is a special case syntax sugar, because in general + /// there has to be block expression after `else`. + /// + /// ``` + /// ❰ if bool_cond { 42 } ❱ + /// ❰ if bool_cond { 42 } else { 24 } ❱ + /// ❰ if bool_cond { 42 } else if bool_cond2 { 42 } ❱ + /// + /// ❰ + /// if let Pattern(foo) = bar { + /// foo + /// } else { + /// panic!(); + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/if-expr.html) + struct IfExpr: AttrsOwner { T![if], Condition } + + /// Unconditional loop expression. + /// + /// ``` + /// ❰ + /// loop { + /// // yeah, it's that simple... + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html) + struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] } + + /// Block expression with an optional prefix (label, try ketword, + /// unsafe keyword, async keyword...). + /// + /// ``` + /// ❰ + /// 'label: try { + /// None? + /// } + /// ❱ + /// ``` + /// + /// - [try block](https://doc.rust-lang.org/unstable-book/language-features/try-blocks.html) + /// - [unsafe block](https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks) + /// - [async block](https://doc.rust-lang.org/reference/expressions/block-expr.html#async-blocks) + struct EffectExpr: AttrsOwner { Label, T![try], T![unsafe], T![async], BlockExpr } + + + /// For loop expression. + /// Note: record struct literals are not valid as iterable expression + /// due to ambiguity. + /// + /// ``` + /// ❰ + /// for i in (0..4) { + /// dbg!(i); + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops) + struct ForExpr: AttrsOwner, LoopBodyOwner { + T![for], + Pat, + T![in], + iterable: Expr, + } + + /// While loop expression. Includes both regular `while` and `while let` forms. + /// + /// ``` + /// ❰ + /// while bool_cond { + /// 42; + /// } + /// ❱ + /// ❰ + /// while let Pattern(foo) = bar { + /// bar += 1; + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops) + struct WhileExpr: AttrsOwner, LoopBodyOwner { T![while], Condition } + + /// Continue expression. + /// + /// ``` + /// while bool_cond { + /// ❰ continue ❱; + /// } + /// + /// 'outer: loop { + /// loop { + /// ❰ continue 'outer ❱; + /// } + /// } + /// + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions) + struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] } + + /// Break expression. + /// + /// ``` + /// while bool_cond { + /// ❰ break ❱; + /// } + /// 'outer: loop { + /// for foo in bar { + /// ❰ break 'outer ❱; + /// } + /// } + /// 'outer: loop { + /// loop { + /// ❰ break 'outer 42 ❱; + /// } + /// } + /// ``` + /// + /// [Refernce](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions) + struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr } + + /// Label. + /// + /// ``` + /// ❰ 'outer: ❱ loop {} + /// + /// let foo = ❰ 'bar: ❱ loop {} + /// + /// ❰ 'baz: ❱ { + /// break 'baz; + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html?highlight=label#loop-labels) + /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md) + struct Label { T![lifetime] } + + /// Block expression. Includes unsafe blocks and block labels. + /// + /// ``` + /// let foo = ❰ + /// { + /// #![inner_attr] + /// ❰ { } ❱ + /// + /// ❰ 'label: { break 'label } ❱ + /// } + /// ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/block-expr.html) + /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md) + struct BlockExpr: AttrsOwner, ModuleItemOwner { + Label, T!['{'], statements: [Stmt], Expr, T!['}'], + } + + /// Return expression. + /// + /// ``` + /// || ❰ return 42 ❱; + /// + /// fn bar() { + /// ❰ return ❱; + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/return-expr.html) + struct ReturnExpr: AttrsOwner { Expr } + + /// Call expression (not to be confused with method call expression, it is + /// a separate ast node). + /// + /// ``` + /// ❰ foo() ❱; + /// ❰ &str::len("bar") ❱; + /// ❰ <&str as PartialEq<&str>>::eq(&"", &"") ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html) + struct CallExpr: ArgListOwner { Expr } + + /// Method call expression. + /// + /// ``` + /// ❰ receiver_expr.method() ❱; + /// ❰ receiver_expr.method::(42, true) ❱; + /// + /// ❰ ❰ ❰ foo.bar() ❱ .baz() ❱ .bruh() ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/method-call-expr.html) + struct MethodCallExpr: AttrsOwner, ArgListOwner { + Expr, T![.], NameRef, TypeArgList, + } + + /// Index expression a.k.a. subscript operator call. + /// + /// ``` + /// ❰ foo[42] ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html) + struct IndexExpr: AttrsOwner { T!['['], T![']'] } + + /// Field access expression. + /// + /// ``` + /// ❰ expr.bar ❱; + /// + /// ❰ ❰ ❰ foo.bar ❱ .baz ❱ .bruh ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/field-expr.html) + struct FieldExpr: AttrsOwner { Expr, T![.], NameRef } + + /// Await operator call expression. + /// + /// ``` + /// ❰ expr.await ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/await-expr.html) + struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] } + + /// The question mark operator call. + /// + /// ``` + /// ❰ expr? ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator) + struct TryExpr: AttrsOwner { Expr, T![?] } + + /// Type cast expression. + /// + /// ``` + /// ❰ expr as T ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions) + struct CastExpr: AttrsOwner { Expr, T![as], TypeRef } + + + /// Borrow operator call. + /// + /// ``` + /// ❰ &foo ❱; + /// ❰ &mut bar ❱; + /// ❰ &raw const bar ❱; + /// ❰ &raw mut bar ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators) + struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], T![const], Expr } + + /// Prefix operator call. This is either `!` or `*` or `-`. + /// + /// ``` + /// ❰ !foo ❱; + /// ❰ *bar ❱; + /// ❰ -42 ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html) + struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr } + + /// Box operator call. + /// + /// ``` + /// ❰ box 42 ❱; + /// ``` + /// + /// [RFC](https://github.com/rust-lang/rfcs/blob/0806be4f282144cfcd55b1d20284b43f87cbe1c6/text/0809-box-and-in-for-stdlib.md) + struct BoxExpr: AttrsOwner { T![box], Expr } + + /// Range operator call. + /// + /// ``` + /// ❰ 0..42 ❱; + /// ❰ ..42 ❱; + /// ❰ 0.. ❱; + /// ❰ .. ❱; + /// ❰ 0..=42 ❱; + /// ❰ ..=42 ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/range-expr.html) + struct RangeExpr: AttrsOwner { /*RangeOp*/ } + + + /// Binary operator call. + /// Includes all arithmetic, logic, bitwise and assignment operators. + /// + /// ``` + /// ❰ 2 + ❰ 2 * 2 ❱ ❱; + /// ❰ ❰ true && false ❱ || true ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators) + struct BinExpr: AttrsOwner { /*BinOp*/ } + + + /// [Raw] string, [raw] byte string, char, byte, integer, float or bool literal. + /// + /// ``` + /// ❰ "str" ❱; + /// ❰ br##"raw byte str"## ❱; + /// ❰ 'c' ❱; + /// ❰ b'c' ❱; + /// ❰ 42 ❱; + /// ❰ 1e9 ❱; + /// ❰ true ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/literal-expr.html) + struct Literal { /*LiteralToken*/ } + + /// Match expression. + /// + /// ``` + /// ❰ + /// match expr { + /// Pat1 => {} + /// Pat2(_) => 42, + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html) + struct MatchExpr: AttrsOwner { T![match], Expr, MatchArmList } + + /// Match arm list part of match expression. Includes its inner attributes. + /// + /// ``` + /// match expr + /// ❰ + /// { + /// #![inner_attr] + /// Pat1 => {} + /// Pat2(_) => 42, + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html) + struct MatchArmList: AttrsOwner { T!['{'], arms: [MatchArm], T!['}'] } + + + /// Match arm. + /// Note: record struct literals are not valid as target match expression + /// due to ambiguity. + /// ``` + /// match expr { + /// ❰ #[attr] Pattern(it) if bool_cond => it ❱, + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html) + struct MatchArm: AttrsOwner { + pat: Pat, + guard: MatchGuard, + T![=>], + Expr, + } + + /// Match guard. + /// + /// ``` + /// match expr { + /// Pattern(it) ❰ if bool_cond ❱ => it, + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards) + struct MatchGuard { T![if], Expr } + + /// Record literal expression. The same syntax is used for structs, + /// unions and record enum variants. + /// + /// ``` + /// ❰ + /// foo::Bar { + /// #![inner_attr] + /// baz: 42, + /// bruh: true, + /// ..spread + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html) + struct RecordLit { Path, RecordFieldList} + + /// Record field list including enclosing curly braces. + /// + /// foo::Bar ❰ + /// { + /// baz: 42, + /// ..spread + /// } + /// ❱ + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html) + struct RecordFieldList { + T!['{'], + fields: [RecordField], + T![..], + spread: Expr, + T!['}'] + } + + /// Record field. + /// + /// ``` + /// foo::Bar { + /// ❰ #[attr] baz: 42 ❱ + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html) + struct RecordField: AttrsOwner { NameRef, T![:], Expr } + + /// Disjunction of patterns. + /// + /// ``` + /// let ❰ Foo(it) | Bar(it) | Baz(it) ❱ = bruh; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html) + struct OrPat { pats: [Pat] } + + /// Parenthesized pattern. + /// Note: parens are only used for grouping, this is not a tuple pattern. + /// + /// ``` + /// if let ❰ &(0..=42) ❱ = foo {} + /// ``` + /// + /// https://doc.rust-lang.org/reference/patterns.html#grouped-patterns + struct ParenPat { T!['('], Pat, T![')'] } + + /// Reference pattern. + /// Note: this has nothing to do with `ref` keyword, the latter is used in bind patterns. + /// + /// ``` + /// let ❰ &mut foo ❱ = bar; + /// + /// let ❰ & ❰ &mut ❰ &_ ❱ ❱ ❱ = baz; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#reference-patterns) + struct RefPat { T![&], T![mut], Pat } + + /// Box pattern. + /// + /// ``` + /// let ❰ box foo ❱ = box 42; + /// ``` + /// + /// [Unstable book](https://doc.rust-lang.org/unstable-book/language-features/box-patterns.html) + struct BoxPat { T![box], Pat } + + /// Bind pattern. + /// + /// ``` + /// match foo { + /// Some(❰ ref mut bar ❱) => {} + /// ❰ baz @ None ❱ => {} + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#identifier-patterns) + struct BindPat: AttrsOwner, NameOwner { T![ref], T![mut], T![@], Pat } + + /// Placeholder pattern a.k.a. the wildcard pattern or the underscore. + /// + /// ``` + /// let ❰ _ ❱ = foo; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#wildcard-pattern) + struct PlaceholderPat { T![_] } + + /// Rest-of-the record/tuple pattern. + /// Note: this is not the unbonded range pattern (even more: it doesn't exist). + /// + /// ``` + /// let Foo { bar, ❰ .. ❱ } = baz; + /// let (❰ .. ❱, bruh) = (42, 24, 42); + /// let Bruuh(❰ .. ❱) = bruuuh; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) + struct DotDotPat { T![..] } + + /// Path pattern. + /// Doesn't include the underscore pattern (it is a special case, namely `PlaceholderPat`). + /// + /// ``` + /// let ❰ foo::bar::Baz ❱ { .. } = bruh; + /// if let ❰ CONST ❱ = 42 {} + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#path-patterns) + struct PathPat { Path } + + /// Slice pattern. + /// + /// ``` + /// let ❰ [foo, bar, baz] ❱ = [1, 2, 3]; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#slice-patterns) + struct SlicePat { T!['['], args: [Pat], T![']'] } + + /// Range pattern. + /// + /// ``` + /// match foo { + /// ❰ 0..42 ❱ => {} + /// ❰ 0..=42 ❱ => {} + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#range-patterns) + struct RangePat { } // FIXME(@matklad): here should be T![..], T![..=] I think, if we don't already have an accessor in expresions_ext + + /// Literal pattern. + /// Includes only bool, number, char, and string literals. + /// + /// ``` + /// match foo { + /// Number(❰ 42 ❱) => {} + /// String(❰ "42" ❱) => {} + /// Bool(❰ true ❱) => {} + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#literal-patterns) + struct LiteralPat { Literal } + + /// Macro invocation in pattern position. + /// + /// ``` + /// let ❰ foo!(my custom syntax) ❱ = baz; + /// + /// ``` + /// [Reference](https://doc.rust-lang.org/reference/macros.html#macro-invocation) + struct MacroPat { MacroCall } + + /// Record literal pattern. + /// + /// ``` + /// let ❰ foo::Bar { baz, .. } ❱ = bruh; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) + struct RecordPat { RecordFieldPatList, Path } + + /// Record literal's field patterns list including enclosing curly braces. + /// + /// ``` + /// let foo::Bar ❰ { baz, bind @ bruh, .. } ❱ = bruuh; + /// `` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) + struct RecordFieldPatList { + T!['{'], + pats: [RecordInnerPat], + record_field_pats: [RecordFieldPat], + bind_pats: [BindPat], + T![..], + T!['}'] + } + + /// Record literal's field pattern. + /// Note: record literal can also match tuple structs. + /// + /// ``` + /// let Foo { ❰ bar: _ ❱ } = baz; + /// let TupleStruct { ❰ 0: _ ❱ } = bruh; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) + struct RecordFieldPat: AttrsOwner { NameRef, T![:], Pat } + + /// Tuple struct literal pattern. + /// + /// ``` + /// let ❰ foo::Bar(baz, bruh) ❱ = bruuh; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-struct-patterns) + struct TupleStructPat { Path, T!['('], args: [Pat], T![')'] } + + /// Tuple pattern. + /// Note: this doesn't include tuple structs (see `TupleStructPat`) + /// + /// ``` + /// let ❰ (foo, bar, .., baz) ❱ = bruh; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-patterns) + struct TuplePat { T!['('], args: [Pat], T![')'] } + + /// Visibility. + /// + /// ``` + /// ❰ pub mod ❱ foo; + /// ❰ pub(crate) ❱ struct Bar; + /// ❰ pub(self) ❱ enum Baz {} + /// ❰ pub(super) ❱ fn bruh() {} + /// ❰ pub(in bruuh::bruuuh) ❱ type T = u64; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html) + struct Visibility { T![pub], T![super], T![self], T![crate] } + + /// Single identifier. + /// Note(@matklad): `Name` is for things that install a new name into the scope, + /// `NameRef` is a usage of a name. Most of the time, this definition/reference + /// distinction can be determined purely syntactically, ie in + /// ``` + /// fn foo() { foo() } + /// ``` + /// the first foo is `Name`, the second one is `NameRef`. + /// The notable exception are patterns, where in + /// `` + /// let x = 92 + /// ``` + /// `x` can be semantically either a name or a name ref, depeding on + /// wether there's an `x` constant in scope. + /// We use `Name` for patterns, and disambiguate semantically (see `NameClass` in ide_db). + /// + /// ``` + /// let ❰ foo ❱ = bar; + /// struct ❰ Baz ❱; + /// fn ❰ bruh ❱() {} + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/identifiers.html) + struct Name { T![ident] } + + /// Reference to a name. + /// See the explanation on the difference between `Name` and `NameRef` + /// in `Name` ast node docs. + /// + /// ``` + /// let foo = ❰ bar ❱(❰ Baz(❰ bruh ❱) ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/identifiers.html) + struct NameRef { } + + /// Macro call. + /// Includes all of its attributes and doc comments. + /// + /// ``` + /// ❰ + /// /// Docs + /// #[attr] + /// macro_rules! foo { // macro rules is also a macro call + /// ($bar: tt) => {} + /// } + /// ❱ + /// + /// // semicolon is a part of `MacroCall` when it is used in item positions + /// ❰ foo!(); ❱ + /// + /// fn main() { + /// ❰ foo!() ❱; // macro call in expression positions doesn't include the semi + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/macros.html) + struct MacroCall: NameOwner, AttrsOwner, DocCommentsOwner { + Path, T![!], TokenTree, T![;] + } + + /// Attribute. + /// + /// ``` + /// ❰ #![inner_attr] ❱ + /// + /// ❰ #[attr] ❱ + /// ❰ #[foo = "bar"] ❱ + /// ❰ #[baz(bruh::bruuh = "42")] ❱ + /// struct Foo; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/attributes.html) + struct Attr { T![#], T![!], T!['['], Path, T![=], input: AttrInput, T![']'] } + + /// Stores a list of lexer tokens and other `TokenTree`s. + /// It appears in attributes, macro_rules and macro call (foo!) + /// + /// ``` + /// macro_call! ❰ { my syntax here } ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/macros.html) + struct TokenTree {} + + /// Generic lifetime, type and constants parameters list **declaration**. + /// + /// ``` + /// fn foo❰ <'a, 'b, T, U, const BAR: u64> ❱() {} + /// + /// struct Baz❰ ❱(T); + /// + /// impl❰ ❱ Bruh {} + /// + /// type Bruuh = for❰ <'a> ❱ fn(&'a str) -> &'a str; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/generics.html) + struct TypeParamList { + T![<], + generic_params: [GenericParam], + type_params: [TypeParam], + lifetime_params: [LifetimeParam], + const_params: [ConstParam], + T![>] + } + + /// Single type parameter **declaration**. + /// + /// ``` + /// fn foo<❰ K ❱, ❰ I ❱, ❰ E: Debug ❱, ❰ V = DefaultType ❱>() {} + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/generics.html) + struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner { + T![=], + default_type: TypeRef, + } + + /// Const generic parameter **declaration**. + /// ``` + /// fn foo() {} + /// ``` + /// + /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter) + struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner { + T![=], + default_val: Expr, + } + + /// Lifetime parameter **declaration**. + /// + /// ``` + /// fn foo<❰ 'a ❱, ❰ 'b ❱, V, G, D>(bar: &'a str, baz: &'b mut str) {} + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/generics.html) + struct LifetimeParam: AttrsOwner { T![lifetime] } + + /// Type bound declaration clause. + /// + /// ``` + /// fn foo() {} + /// + /// trait Bar + /// where + /// T: ❰ Send ❱ + ❰ Sync ❱ + /// { + /// type Baz: ❰ !Sync ❱ + ❰ Debug ❱ + ❰ ?const Add ❱; + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html) + struct TypeBound { T![lifetime], /* Question, */ T![const], /* Question, */ TypeRef } + + /// Type bounds list. + /// + /// ``` + /// + /// fn foo() {} + /// + /// trait Bar + /// where + /// T: ❰ Send + Sync ❱ + /// { + /// type Baz: ❰ !Sync + Debug ❱; + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html) + struct TypeBoundList { bounds: [TypeBound] } + + /// Single where predicate. + /// + /// ``` + /// trait Foo<'a, 'b, T> + /// where + /// ❰ 'a: 'b ❱, + /// ❰ T: IntoIterator ❱, + /// ❰ for<'c> ::Item: Bar<'c> ❱ + /// {} + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses) + struct WherePred: TypeBoundsOwner { T![for], TypeParamList, T![lifetime], TypeRef } + + /// Where clause. + /// + /// ``` + /// trait Foo<'a, T> ❰ where 'a: 'static, T: Debug ❱ {} + /// + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses) + struct WhereClause { T![where], predicates: [WherePred] } + + /// Abi declaration. + /// Note: the abi string is optional. + /// + /// ``` + /// ❰ extern "C" ❱ { + /// fn foo() {} + /// } + /// + /// type Bar = ❰ extern ❱ fn() -> u32; + /// + /// type Baz = ❰ extern r#"stdcall"# ❱ fn() -> bool; + /// ``` + /// + /// - [Extern blocks reference](https://doc.rust-lang.org/reference/items/external-blocks.html) + /// - [FFI function pointers reference](https://doc.rust-lang.org/reference/items/functions.html#functions) + struct Abi { /*String*/ } + + /// Expression statement. + /// + /// ``` + /// ❰ 42; ❱ + /// ❰ foo(); ❱ + /// ❰ (); ❱ + /// ❰ {}; ❱ + /// + /// // constructions with trailing curly brace can omit the semicolon + /// // but only when there are satements immediately after them (this is important!) + /// ❰ if bool_cond { } ❱ + /// ❰ loop {} ❱ + /// ❰ somestatment; ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/statements.html) + struct ExprStmt: AttrsOwner { Expr, T![;] } + + /// Let statement. + /// + /// ``` + /// ❰ #[attr] let foo; ❱ + /// ❰ let bar: u64; ❱ + /// ❰ let baz = 42; ❱ + /// ❰ let bruh: bool = true; ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/statements.html#let-statements) + struct LetStmt: AttrsOwner, TypeAscriptionOwner { + T![let], + Pat, + T![=], + initializer: Expr, + T![;], + } + + /// Condition of `if` or `while` expression. + /// + /// ``` + /// if ❰ true ❱ {} + /// if ❰ let Pat(foo) = bar ❱ {} + /// + /// while ❰ true ❱ {} + /// while ❰ let Pat(baz) = bruh ❱ {} + /// ``` + /// + /// [If expression reference](https://doc.rust-lang.org/reference/expressions/if-expr.html) + /// [While expression reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops) + struct Condition { T![let], Pat, T![=], Expr } + + /// Parameter list **declaration**. + /// + /// ``` + /// fn foo❰ (a: u32, b: bool) ❱ -> u32 {} + /// let bar = ❰ |a, b| ❱ {}; + /// + /// impl Baz { + /// fn bruh❰ (&self, a: u32) ❱ {} + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)ocs to codegen script + struct ParamList { // FIXME: this node is used by closure expressions too, but hey use pipes instead of parens... + T!['('], + SelfParam, + params: [Param], + T![')'] + } + + /// Self parameter **declaration**. + /// + /// ``` + /// impl Bruh { + /// fn foo(❰ self ❱) {} + /// fn bar(❰ &self ❱) {} + /// fn baz(❰ &mut self ❱) {} + /// fn blah<'a>(❰ &'a self ❱) {} + /// fn blin(❰ self: Box ❱) {} + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/functions.html) + struct SelfParam: TypeAscriptionOwner, AttrsOwner { T![&], T![mut], T![lifetime], T![self] } + + /// Parameter **declaration**. + /// + /// ``` + /// fn foo(❰ #[attr] Pat(bar): Pat(u32) ❱, ❰ #[attr] _: bool ❱) {} + /// + /// extern "C" { + /// fn bar(❰ baz: u32 ❱, ❰ ... ❱) -> u32; + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/functions.html) + struct Param: TypeAscriptionOwner, AttrsOwner { + Pat, + T![...] + } + + /// Use declaration. + /// + /// ``` + /// ❰ #[attr] pub use foo; ❱ + /// ❰ use bar as baz; ❱ + /// ❰ use bruh::{self, bruuh}; ❱ + /// ❰ use { blin::blen, blah::* }; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) + struct UseItem: AttrsOwner, VisibilityOwner { + T![use], + UseTree, + } + + /// Use tree. + /// + /// ``` + /// pub use ❰ foo::❰ * ❱ ❱; + /// use ❰ bar as baz ❱; + /// use ❰ bruh::bruuh::{ ❰ self ❱, ❰ blin ❱ } ❱; + /// use ❰ { ❰ blin::blen ❱ } ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) + struct UseTree { + Path, T![*], UseTreeList, Alias + } + + /// Item alias. + /// Note: this is not the type alias. + /// + /// ``` + /// use foo ❰ as bar ❱; + /// use baz::{bruh ❰ as _ ❱}; + /// extern crate bruuh ❰ as blin ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) + struct Alias: NameOwner { T![as] } + + /// Sublist of use trees. + /// + /// ``` + /// use bruh::bruuh::❰ { ❰ self ❱, ❰ blin ❱ } ❱; + /// use ❰ { blin::blen::❰ {} ❱ } ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) + struct UseTreeList { T!['{'], use_trees: [UseTree], T!['}'] } + + /// Extern crate item. + /// + /// ``` + /// ❰ #[attr] pub extern crate foo; ❱ + /// ❰ extern crate self as bar; ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/extern-crates.html) + struct ExternCrateItem: AttrsOwner, VisibilityOwner { + T![extern], T![crate], NameRef, Alias, + } + + /// Call site arguments list. + /// + /// ``` + /// foo::❰ (42, true) ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html) + struct ArgList { + T!['('], + args: [Expr], + T![')'] + } + + /// Path to a symbol. Includes single identifier names and elaborate paths with + /// generic parameters. + /// + /// ``` + /// (0..10).❰ ❰ collect ❱ ::> ❱(); + /// ❰ ❰ ❰ Vec ❱ :: ❱ ::with_capacity ❱(1024); + /// ❰ ❰ <❰ Foo ❱ as ❰ ❰ bar ❱ ::Bar ❱> ❱ ::baz ❱(); + /// ❰ ❰ <❰ bruh ❱> ❱ ::bruuh ❱(); + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/paths.html) + struct Path { + segment: PathSegment, + T![::], + qualifier: Path, + } + + /// Segment of the path to a symbol. + /// Only path segment of an absolute path holds the `::` token, + /// all other `::` tokens that connect path segments reside under `Path` itself.` + /// + /// ``` + /// (0..10).❰ collect ❱ :: ❰ > ❱(); + /// ❰ Vec ❱ :: ❰ ❱ :: ❰ with_capacity ❱(1024); + /// ❰ <❰ Foo ❱ as ❰ bar ❱ :: ❰ Bar ❱> ❱ :: ❰ baz ❱(); + /// ❰ <❰ bruh ❱> ❱ :: ❰ bruuh ❱(); + /// + /// // Note that only in this case `::` token is inlcuded: + /// ❰ ::foo ❱; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/paths.html) + struct PathSegment { + T![::], T![crate], T![self], T![super], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>] + } + + /// List of type arguments that are passed at generic instantiation site. + /// + /// ``` + /// type _ = Foo ❰ ::<'a, u64, Item = Bar, 42, {true}> ❱::Bar; + /// + /// Vec❰ :: ❱::(); + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions) + struct TypeArgList { + T![::], + T![<], + generic_args: [GenericArg], + type_args: [TypeArg], + lifetime_args: [LifetimeArg], + assoc_type_args: [AssocTypeArg], + const_args: [ConstArg], + T![>] + } + + /// Type argument that is passed at generic instantiation site. + /// + /// ``` + /// type _ = Foo::<'a, ❰ u64 ❱, ❰ bool ❱, Item = Bar, 42>::Baz; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions) + struct TypeArg { TypeRef } + + /// Associated type argument that is passed at generic instantiation site. + /// ``` + /// type Foo = Bar::<'a, u64, bool, ❰ Item = Baz ❱, 42>::Bruh; + /// + /// trait Bruh: Iterator<❰ Item: Debug ❱> {} + /// ``` + /// + struct AssocTypeArg : TypeBoundsOwner { NameRef, T![=], TypeRef } + + /// Lifetime argument that is passed at generic instantiation site. + /// + /// ``` + /// fn foo<'a>(s: &'a str) { + /// bar::<❰ 'a ❱>(s); + /// } + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions) + struct LifetimeArg { T![lifetime] } + + /// Constant value argument that is passed at generic instantiation site. + /// + /// ``` + /// foo::(); + /// + /// bar::<❰ { 2 + 2} ❱>(); + /// ``` + /// + /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter) + struct ConstArg { Literal, BlockExpr } + + + /// FIXME: (@edwin0cheng) Remove it to use ItemList instead + /// https://github.com/rust-analyzer/rust-analyzer/pull/4083#discussion_r422666243 + /// + /// [Reference](https://doc.rust-lang.org/reference/macros.html) + struct MacroItems: ModuleItemOwner { } + + /// FIXME: (@edwin0cheng) add some documentation here. As per the writing + /// of this comment this ast node is not used. + /// + /// ``` + /// // FIXME: example here + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/macros.html) + struct MacroStmts { + statements: [Stmt], + Expr, + } + + /// List of items in an extern block. + /// + /// ``` + /// extern "C" ❰ + /// { + /// fn foo(); + /// static var: u32; + /// } + /// ❱ + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html) + struct ExternItemList: ModuleItemOwner { + T!['{'], + extern_items: [ExternItem], + T!['}'] + } + + /// Extern block. + /// + /// ``` + /// ❰ + /// extern "C" { + /// fn foo(); + /// } + /// ❱ + /// + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html) + struct ExternBlock { + Abi, + ExternItemList + } + + /// Meta item in an attribute. + /// + /// ``` + /// #[❰ bar::baz = "42" ❱] + /// #[❰ bruh(bruuh("true")) ❱] + /// struct Foo; + /// ``` + /// + /// [Reference](https://doc.rust-lang.org/reference/attributes.html?highlight=meta,item#meta-item-attribute-syntax) + struct MetaItem { + Path, T![=], AttrInput, nested_meta_items: [MetaItem] + } + + /// Macro 2.0 definition. + /// Their syntax is still WIP by rustc team... + /// ``` + /// ❰ + /// macro foo { } + /// ❱ + /// ``` + /// + /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/1584-macros.md) + struct MacroDef { + Name, TokenTree + } + }, + enums: ast_enums! { + /// Any kind of nominal type definition. + enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner { + StructDef, EnumDef, UnionDef, + } + + /// Any kind of **declared** generic parameter + enum GenericParam { + LifetimeParam, + TypeParam, + ConstParam + } + + /// Any kind of generic argument passed at instantiation site + enum GenericArg { + LifetimeArg, + TypeArg, + ConstArg, + AssocTypeArg + } + + /// Any kind of construct valid in type context + enum TypeRef { + ParenType, + TupleType, + NeverType, + PathType, + PointerType, + ArrayType, + SliceType, + ReferenceType, + PlaceholderType, + FnPointerType, + ForType, + ImplTraitType, + DynTraitType, + } + + /// Any kind of top-level item that may appear in a module + enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner { + StructDef, + UnionDef, + EnumDef, + FnDef, + TraitDef, + TypeAliasDef, + ImplDef, + UseItem, + ExternCrateItem, + ConstDef, + StaticDef, + Module, + MacroCall, + ExternBlock + } + + + + /// Any kind of item that may appear in an impl block + /// + /// // FIXME: impl blocks can also contain MacroCall + enum AssocItem: NameOwner, AttrsOwner { + FnDef, TypeAliasDef, ConstDef + } + + /// Any kind of item that may appear in an extern block + /// + /// // FIXME: extern blocks can also contain MacroCall + enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner { + FnDef, StaticDef + } + + /// Any kind of expression + enum Expr: AttrsOwner { + TupleExpr, + ArrayExpr, + ParenExpr, + PathExpr, + LambdaExpr, + IfExpr, + LoopExpr, + ForExpr, + WhileExpr, + ContinueExpr, + BreakExpr, + Label, + BlockExpr, + ReturnExpr, + MatchExpr, + RecordLit, + CallExpr, + IndexExpr, + MethodCallExpr, + FieldExpr, + AwaitExpr, + TryExpr, + EffectExpr, + CastExpr, + RefExpr, + PrefixExpr, + RangeExpr, + BinExpr, + Literal, + MacroCall, + BoxExpr, + } + + /// Any kind of pattern + enum Pat { + OrPat, + ParenPat, + RefPat, + BoxPat, + BindPat, + PlaceholderPat, + DotDotPat, + PathPat, + RecordPat, + TupleStructPat, + TuplePat, + SlicePat, + RangePat, + LiteralPat, + MacroPat, + } + + /// Any kind of pattern that appears directly inside of the curly + /// braces of a record pattern + enum RecordInnerPat { + RecordFieldPat, + BindPat + } + + /// Any kind of input to an attribute + enum AttrInput { Literal, TokenTree } + + /// Any kind of statement + /// Note: there are no empty statements, these are just represented as + /// bare semicolons without a dedicated statement ast node. + enum Stmt { + LetStmt, + ExprStmt, + // macro calls are parsed as expression statements + } + + /// Any kind of fields list (record or tuple field lists) + enum FieldDefList { + RecordFieldDefList, + TupleFieldDefList, + } + }, + } +} diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 745a25862b6..5a18b3e2b36 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -9,28 +9,29 @@ use quote::{format_ident, quote}; use crate::{ - ast_src::{AstSrc, Field, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC}, + ast_src::{rust_ast, AstSrc, Field, FieldSrc, KindsSrc, KINDS_SRC}, codegen::{self, update, Mode}, project_root, Result, }; pub fn generate_syntax(mode: Mode) -> Result<()> { + let ast = rust_ast(); let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; let ast_tokens_file = project_root().join(codegen::AST_TOKENS); - let contents = generate_tokens(AST_SRC)?; + let contents = generate_tokens(&ast)?; update(ast_tokens_file.as_path(), &contents, mode)?; let ast_nodes_file = project_root().join(codegen::AST_NODES); - let contents = generate_nodes(KINDS_SRC, AST_SRC)?; + let contents = generate_nodes(KINDS_SRC, &ast)?; update(ast_nodes_file.as_path(), &contents, mode)?; Ok(()) } -fn generate_tokens(grammar: AstSrc<'_>) -> Result { +fn generate_tokens(grammar: &AstSrc) -> Result { let tokens = grammar.tokens.iter().map(|token| { let name = format_ident!("{}", token); let kind = format_ident!("{}", to_upper_snake_case(token)); @@ -62,13 +63,13 @@ fn syntax(&self) -> &SyntaxToken { &self.syntax } Ok(pretty) } -fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { +fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result { let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar .nodes .iter() .map(|node| { let name = format_ident!("{}", node.name); - let kind = format_ident!("{}", to_upper_snake_case(node.name)); + let kind = format_ident!("{}", to_upper_snake_case(&node.name)); let traits = node.traits.iter().map(|trait_name| { let trait_name = format_ident!("{}", trait_name); quote!(impl ast::#trait_name for #name {}) @@ -192,8 +193,8 @@ fn syntax(&self) -> &SyntaxNode { }) .unzip(); - let enum_names = grammar.enums.iter().map(|it| it.name); - let node_names = grammar.nodes.iter().map(|it| it.name); + let enum_names = grammar.enums.iter().map(|it| &it.name); + let node_names = grammar.nodes.iter().map(|it| &it.name); let display_impls = enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| { @@ -212,7 +213,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { .nodes .iter() .map(|kind| to_pascal_case(kind)) - .filter(|name| !defined_nodes.contains(name.as_str())) + .filter(|name| !defined_nodes.iter().any(|&it| it == name)) { eprintln!("Warning: node {} not defined in ast source", node); } @@ -236,12 +237,12 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut res = String::with_capacity(ast.len() * 2); let mut docs = - grammar.nodes.iter().map(|it| it.doc).chain(grammar.enums.iter().map(|it| it.doc)); + grammar.nodes.iter().map(|it| &it.doc).chain(grammar.enums.iter().map(|it| &it.doc)); for chunk in ast.split("# [ pretty_doc_comment_placeholder_workaround ]") { res.push_str(chunk); if let Some(doc) = docs.next() { - write_doc_comment(doc, &mut res); + write_doc_comment(&doc, &mut res); } } @@ -249,7 +250,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Ok(pretty) } -fn write_doc_comment(contents: &[&str], dest: &mut String) { +fn write_doc_comment(contents: &[String], dest: &mut String) { for line in contents { writeln!(dest, "///{}", line).unwrap(); } @@ -413,7 +414,7 @@ fn to_pascal_case(s: &str) -> String { buf } -impl Field<'_> { +impl Field { fn is_many(&self) -> bool { matches!(self, Field::Node { src: FieldSrc::Many(_), .. }) } @@ -429,7 +430,7 @@ fn token_kind(&self) -> Option { fn method_name(&self) -> proc_macro2::Ident { match self { Field::Token(name) => { - let name = match *name { + let name = match name.as_str() { ";" => "semicolon", "->" => "thin_arrow", "'{'" => "l_curly",