Introduce dedicated AST node for union

Although structs and unions have the same syntax and differ only in
the keyword, re-using the single syntax node for both of them leads to
confusion in practice, and propagates further down the hir in an
upleasent way.

Moreover, static and consts also share syntax, but we use different
nodes for them.
This commit is contained in:
Aleksey Kladov 2019-11-25 16:55:09 +03:00
parent be00d74c7b
commit e1c0bdaf75
7 changed files with 63 additions and 15 deletions

View File

@ -1,13 +1,13 @@
//! FIXME: write short doc here
mod consts;
mod nominal;
mod adt;
mod traits;
mod use_item;
pub(crate) use self::{
expressions::{match_arm_list, record_field_list},
nominal::{enum_variant_list, record_field_def_list},
adt::{enum_variant_list, record_field_def_list},
traits::{impl_item_list, trait_item_list},
use_item::use_tree_list,
};
@ -247,7 +247,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
// a: i32,
// b: f32,
// }
nominal::struct_def(p, m, T![struct]);
adt::struct_def(p, m);
}
IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
// test union_items
@ -256,9 +256,9 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
// a: i32,
// b: f32,
// }
nominal::struct_def(p, m, T![union]);
adt::union_def(p, m);
}
T![enum] => nominal::enum_def(p, m),
T![enum] => adt::enum_def(p, m),
T![use] => use_item::use_item(p, m),
T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::const_def(p, m),
T![static] => consts::static_def(p, m),

View File

@ -2,10 +2,19 @@
use super::*;
pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
assert!(p.at(T![struct]) || p.at_contextual_kw("union"));
p.bump_remap(kind);
pub(super) fn struct_def(p: &mut Parser, m: Marker) {
assert!(p.at(T![struct]));
p.bump(T![struct]);
struct_or_union(p, m, T![struct], STRUCT_DEF);
}
pub(super) fn union_def(p: &mut Parser, m: Marker) {
assert!(p.at_contextual_kw("union"));
p.bump_remap(T![union]);
struct_or_union(p, m, T![union], UNION_DEF);
}
fn struct_or_union(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
name_r(p, ITEM_RECOVERY_SET);
type_params::opt_type_param_list(p);
match p.current() {
@ -22,11 +31,11 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
}
}
}
T![;] if kind == T![struct] => {
T![;] if kw == T![struct] => {
p.bump(T![;]);
}
T!['{'] => record_field_def_list(p),
T!['('] if kind == T![struct] => {
T!['('] if kw == T![struct] => {
tuple_field_def_list(p);
// test tuple_struct_where
// struct Test<T>(T) where T: Clone;
@ -34,14 +43,14 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
type_params::opt_where_clause(p);
p.expect(T![;]);
}
_ if kind == T![struct] => {
_ if kw == T![struct] => {
p.error("expected `;`, `{`, or `(`");
}
_ => {
p.error("expected `{`");
}
}
m.complete(p, STRUCT_DEF);
m.complete(p, def);
}
pub(super) fn enum_def(p: &mut Parser, m: Marker) {

View File

@ -122,6 +122,7 @@ pub enum SyntaxKind {
R_DOLLAR,
SOURCE_FILE,
STRUCT_DEF,
UNION_DEF,
ENUM_DEF,
FN_DEF,
RET_TYPE,

View File

@ -3789,6 +3789,34 @@ fn syntax(&self) -> &SyntaxNode {
}
impl TypeRef {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UnionDef {
pub(crate) syntax: SyntaxNode,
}
impl AstNode for UnionDef {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
UNION_DEF => true,
_ => false,
}
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl ast::VisibilityOwner for UnionDef {}
impl ast::NameOwner for UnionDef {}
impl ast::TypeParamsOwner for UnionDef {}
impl ast::AttrsOwner for UnionDef {}
impl ast::DocCommentsOwner for UnionDef {}
impl UnionDef {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UseItem {
pub(crate) syntax: SyntaxNode,
}

View File

@ -126,6 +126,7 @@ Grammar(
"SOURCE_FILE",
"STRUCT_DEF",
"UNION_DEF",
"ENUM_DEF",
"FN_DEF",
"RET_TYPE",
@ -285,6 +286,15 @@ Grammar(
"DocCommentsOwner"
]
),
"UnionDef": (
traits: [
"VisibilityOwner",
"NameOwner",
"TypeParamsOwner",
"AttrsOwner",
"DocCommentsOwner"
]
),
"RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]),
"RecordFieldDef": (
traits: [

View File

@ -1,5 +1,5 @@
SOURCE_FILE@[0; 51)
STRUCT_DEF@[0; 12)
UNION_DEF@[0; 12)
UNION_KW@[0; 5) "union"
WHITESPACE@[5; 6) " "
NAME@[6; 9)
@ -9,7 +9,7 @@ SOURCE_FILE@[0; 51)
L_CURLY@[10; 11) "{"
R_CURLY@[11; 12) "}"
WHITESPACE@[12; 13) "\n"
STRUCT_DEF@[13; 50)
UNION_DEF@[13; 50)
UNION_KW@[13; 18) "union"
WHITESPACE@[18; 19) " "
NAME@[19; 22)

View File

@ -1592,7 +1592,7 @@ SOURCE_FILE@[0; 3813)
BLOCK@[2845; 2906)
L_CURLY@[2845; 2846) "{"
WHITESPACE@[2846; 2851) "\n "
STRUCT_DEF@[2851; 2904)
UNION_DEF@[2851; 2904)
UNION_KW@[2851; 2856) "union"
WHITESPACE@[2856; 2857) " "
NAME@[2857; 2862)