]> git.lizzy.rs Git - rust.git/commitdiff
Fix hir for ast::UnionDef
authorAleksey Kladov <aleksey.kladov@gmail.com>
Mon, 25 Nov 2019 14:30:50 +0000 (17:30 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Mon, 25 Nov 2019 14:50:49 +0000 (17:50 +0300)
22 files changed:
crates/ra_assists/src/assists/add_new.rs
crates/ra_hir/src/code_model.rs
crates/ra_hir/src/code_model/src.rs
crates/ra_hir/src/from_source.rs
crates/ra_hir/src/ty.rs
crates/ra_hir/src/ty/infer/coerce.rs
crates/ra_hir/src/ty/lower.rs
crates/ra_hir_def/src/adt.rs
crates/ra_hir_def/src/attr.rs
crates/ra_hir_def/src/db.rs
crates/ra_hir_def/src/docs.rs
crates/ra_hir_def/src/generics.rs
crates/ra_hir_def/src/lib.rs
crates/ra_hir_def/src/nameres/collector.rs
crates/ra_hir_def/src/nameres/raw.rs
crates/ra_hir_def/src/nameres/tests.rs
crates/ra_ide_api/src/display/short_label.rs
crates/ra_ide_api/src/impls.rs
crates/ra_parser/src/grammar/items.rs
crates/ra_syntax/src/ast/extensions.rs
crates/ra_syntax/src/ast/generated.rs
crates/ra_syntax/src/grammar.ron

index ee8bff34678b5a1bbb9cf888cba5460b31d8c876..8f68bd5fb13061dbbffd82c2df455d780a8d382c 100644 (file)
@@ -35,8 +35,8 @@ pub(crate) fn add_new(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let strukt = ctx.find_node_at_offset::<ast::StructDef>()?;
 
     // We want to only apply this to non-union structs with named fields
-    let field_list = match (strukt.kind(), strukt.is_union()) {
-        (StructKind::Record(named), false) => named,
+    let field_list = match strukt.kind() {
+        StructKind::Record(named) => named,
         _ => return None,
     };
 
index 534f1f8e982f31713c42d289043d39c10ce7ac0b..ae730beb51a8a9dfab561248b87298099ff3f2c7 100644 (file)
@@ -320,7 +320,7 @@ pub struct Struct {
 
 impl Struct {
     pub fn module(self, db: &impl DefDatabase) -> Module {
-        Module { id: self.id.0.module(db) }
+        Module { id: self.id.module(db) }
     }
 
     pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
@@ -369,11 +369,11 @@ pub struct Union {
 
 impl Union {
     pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
-        db.struct_data(self.id.into()).name.clone()
+        db.union_data(self.id).name.clone()
     }
 
     pub fn module(self, db: &impl DefDatabase) -> Module {
-        Module { id: self.id.0.module(db) }
+        Module { id: self.id.module(db) }
     }
 
     pub fn ty(self, db: &impl HirDatabase) -> Ty {
index a4e317c203c69cc3cfacbf85abb00be49ea97a8b..076d86f2b9c71faaabaaa4181c79e4e3bbb6815d 100644 (file)
@@ -51,13 +51,13 @@ fn source(self, db: &impl DefDatabase) -> Source<FieldSource> {
 impl HasSource for Struct {
     type Ast = ast::StructDef;
     fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> {
-        self.id.0.source(db)
+        self.id.source(db)
     }
 }
 impl HasSource for Union {
-    type Ast = ast::StructDef;
-    fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> {
-        self.id.0.source(db)
+    type Ast = ast::UnionDef;
+    fn source(self, db: &impl DefDatabase) -> Source<ast::UnionDef> {
+        self.id.source(db)
     }
 }
 impl HasSource for Enum {
index 1e7c22774d1cd55f8c6b3e82b0c83015eadc98c6..95db7161bf808ced07f59672b27220e37eece5ad 100644 (file)
@@ -1,6 +1,6 @@
 //! FIXME: write short doc here
 
-use hir_def::{AstItemDef, LocationCtx, ModuleId, StructId, StructOrUnionId, UnionId};
+use hir_def::{AstItemDef, LocationCtx, ModuleId};
 use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
 use ra_syntax::{
     ast::{self, AstNode, NameOwner},
@@ -19,19 +19,18 @@ pub trait FromSource: Sized {
     fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>;
 }
 
-// FIXIME: these two impls are wrong, `ast::StructDef` might produce either a struct or a union
 impl FromSource for Struct {
     type Ast = ast::StructDef;
     fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id: StructOrUnionId = from_source(db, src)?;
-        Some(Struct { id: StructId(id) })
+        let id = from_source(db, src)?;
+        Some(Struct { id })
     }
 }
 impl FromSource for Union {
-    type Ast = ast::StructDef;
+    type Ast = ast::UnionDef;
     fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id: StructOrUnionId = from_source(db, src)?;
-        Some(Union { id: UnionId(id) })
+        let id = from_source(db, src)?;
+        Some(Union { id })
     }
 }
 impl FromSource for Enum {
index 8c045aaef297542ca42094d04e881b2c50aa2ccb..3cbcbd1d01bc54d9faaba58fb47ce81e6ec4e37e 100644 (file)
@@ -858,7 +858,7 @@ fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
                 let name = match def {
                     CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(),
                     CallableDef::StructId(s) => {
-                        f.db.struct_data(s.0).name.clone().unwrap_or_else(Name::missing)
+                        f.db.struct_data(s).name.clone().unwrap_or_else(Name::missing)
                     }
                     CallableDef::EnumVariantId(e) => {
                         let enum_data = f.db.enum_data(e.parent);
index 4b53bba73b466ec5b89cd986cc9488b0cf2ed809..bb9a2e427eff4369b20151e13d8d779a9edbe5cc 100644 (file)
@@ -246,7 +246,7 @@ fn check_unsize_and_coerce(&mut self, from_ty: &Ty, to_ty: &Ty, depth: usize) ->
                 ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2),
             ) if struct1 == struct2 => {
                 let field_tys = self.db.field_types(struct1.id.into());
-                let struct_data = self.db.struct_data(struct1.id.0);
+                let struct_data = self.db.struct_data(struct1.id);
 
                 let mut fields = struct_data.variant_data.fields().iter();
                 let (last_field_id, _data) = fields.next_back()?;
index 27cfe00c11a9e81cc7ce49d2b3a8b0c7ab228628..89bc4b9aebb52d2f904d45fddecba9311f9bdcec 100644 (file)
@@ -560,7 +560,7 @@ pub(crate) fn field_types_query(
     variant_id: VariantId,
 ) -> Arc<ArenaMap<LocalStructFieldId, Ty>> {
     let (resolver, var_data) = match variant_id {
-        VariantId::StructId(it) => (it.resolver(db), db.struct_data(it.0).variant_data.clone()),
+        VariantId::StructId(it) => (it.resolver(db), db.struct_data(it).variant_data.clone()),
         VariantId::EnumVariantId(it) => (
             it.parent.resolver(db),
             db.enum_data(it.parent).variants[it.local_id].variant_data.clone(),
@@ -818,7 +818,7 @@ impl CallableDef {
     pub fn krate(self, db: &impl HirDatabase) -> CrateId {
         match self {
             CallableDef::FunctionId(f) => f.lookup(db).module(db).krate,
-            CallableDef::StructId(s) => s.0.module(db).krate,
+            CallableDef::StructId(s) => s.module(db).krate,
             CallableDef::EnumVariantId(e) => e.parent.module(db).krate,
         }
     }
index c9f30923ee69701a0d631d4ec43d35c9c90aa091..71014826ef7a97f218d4bd31d759fda7c5010229 100644 (file)
@@ -12,7 +12,7 @@
 
 use crate::{
     db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource,
-    LocalEnumVariantId, LocalStructFieldId, StructOrUnionId, VariantId,
+    LocalEnumVariantId, LocalStructFieldId, StructId, UnionId, VariantId,
 };
 
 /// Note that we use `StructData` for unions as well!
@@ -49,13 +49,25 @@ pub struct StructFieldData {
 }
 
 impl StructData {
-    pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructOrUnionId) -> Arc<StructData> {
+    pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> {
         let src = id.source(db);
         let name = src.value.name().map(|n| n.as_name());
         let variant_data = VariantData::new(src.value.kind());
         let variant_data = Arc::new(variant_data);
         Arc::new(StructData { name, variant_data })
     }
+    pub(crate) fn union_data_query(db: &impl DefDatabase, id: UnionId) -> Arc<StructData> {
+        let src = id.source(db);
+        let name = src.value.name().map(|n| n.as_name());
+        let variant_data = VariantData::new(
+            src.value
+                .record_field_def_list()
+                .map(ast::StructKind::Record)
+                .unwrap_or(ast::StructKind::Unit),
+        );
+        let variant_data = Arc::new(variant_data);
+        Arc::new(StructData { name, variant_data })
+    }
 }
 
 impl EnumData {
@@ -137,7 +149,7 @@ fn child_source(&self, db: &impl DefDatabase) -> Source<ArenaMap<Self::ChildId,
                 let src = it.parent.child_source(db);
                 src.map(|map| map[it.local_id].kind())
             }
-            VariantId::StructId(it) => it.0.source(db).map(|it| it.kind()),
+            VariantId::StructId(it) => it.source(db).map(|it| it.kind()),
         };
         let mut trace = Trace::new_for_map();
         lower_struct(&mut trace, &src.value);
index 53456fc08508a57a27a65589adce88dc02a5f3eb..298608e27cdb3692d3f60aa4a4c8b53e617c7e99 100644 (file)
@@ -54,9 +54,9 @@ pub(crate) fn attrs_query(db: &impl DefDatabase, def: AttrDefId) -> Attrs {
                 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
             }
             AttrDefId::AdtId(it) => match it {
-                AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
+                AdtId::StructId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
                 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
-                AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
+                AdtId::UnionId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
             },
             AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
             AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db),
index 32adb11bdc4d39e3f6103e7f213b402283878ef7..ef5611ffc0da75b467e079ac5e58cbe31a95d941 100644 (file)
@@ -18,8 +18,8 @@
         CrateDefMap,
     },
     AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId,
-    ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructOrUnionId, TraitId, TypeAliasId,
-    TypeAliasLoc,
+    ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TypeAliasId, TypeAliasLoc,
+    UnionId,
 };
 
 #[salsa::query_group(InternDatabaseStorage)]
@@ -27,7 +27,9 @@ pub trait InternDatabase: SourceDatabase {
     #[salsa::interned]
     fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
     #[salsa::interned]
-    fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> StructOrUnionId;
+    fn intern_struct(&self, loc: ItemLoc<ast::StructDef>) -> StructId;
+    #[salsa::interned]
+    fn intern_union(&self, loc: ItemLoc<ast::UnionDef>) -> UnionId;
     #[salsa::interned]
     fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> EnumId;
     #[salsa::interned]
@@ -57,7 +59,9 @@ fn raw_items_with_source_map(
     fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>;
 
     #[salsa::invoke(StructData::struct_data_query)]
-    fn struct_data(&self, id: StructOrUnionId) -> Arc<StructData>;
+    fn struct_data(&self, id: StructId) -> Arc<StructData>;
+    #[salsa::invoke(StructData::union_data_query)]
+    fn union_data(&self, id: UnionId) -> Arc<StructData>;
 
     #[salsa::invoke(EnumData::enum_data_query)]
     fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
index 90a8627bc6911990d1211d0c2fc5e685fa0cf02d..4749b642f0d5fa3ae43e54b856760d8a87623448 100644 (file)
@@ -47,9 +47,9 @@ pub(crate) fn documentation_query(
                 }
             }
             AttrDefId::AdtId(it) => match it {
-                AdtId::StructId(it) => docs_from_ast(&it.0.source(db).value),
+                AdtId::StructId(it) => docs_from_ast(&it.source(db).value),
                 AdtId::EnumId(it) => docs_from_ast(&it.source(db).value),
-                AdtId::UnionId(it) => docs_from_ast(&it.0.source(db).value),
+                AdtId::UnionId(it) => docs_from_ast(&it.source(db).value),
             },
             AttrDefId::EnumVariantId(it) => {
                 let src = it.parent.child_source(db);
index 015fe772e54b38fdfcda032421173d824422e928..3f94e40e4f4bedc2dd0e76084ffc4eaba9e3e812 100644 (file)
@@ -60,10 +60,8 @@ fn new(
         // FIXME: add `: Sized` bound for everything except for `Self` in traits
         match def {
             GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start),
-            GenericDefId::AdtId(AdtId::StructId(it)) => {
-                generics.fill(&it.0.source(db).value, start)
-            }
-            GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.0.source(db).value, start),
+            GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start),
+            GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start),
             GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start),
             GenericDefId::TraitId(it) => {
                 // traits get the Self type as an implicit first type parameter
index 8e8c2d74908fec8e162e25ca18173bd3ae6cf449..5f11be1143a7c0c11f3e161cd6ea2a1da61d3bb0 100644 (file)
@@ -141,30 +141,26 @@ fn lookup(&self, db: &impl db::DefDatabase) -> FunctionLoc {
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct StructOrUnionId(salsa::InternId);
-impl_intern_key!(StructOrUnionId);
-impl AstItemDef<ast::StructDef> for StructOrUnionId {
+pub struct StructId(salsa::InternId);
+impl_intern_key!(StructId);
+impl AstItemDef<ast::StructDef> for StructId {
     fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self {
-        db.intern_struct_or_union(loc)
+        db.intern_struct(loc)
     }
     fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> {
-        db.lookup_intern_struct_or_union(self)
+        db.lookup_intern_struct(self)
     }
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct StructId(pub StructOrUnionId);
-impl From<StructId> for StructOrUnionId {
-    fn from(id: StructId) -> StructOrUnionId {
-        id.0
+pub struct UnionId(salsa::InternId);
+impl_intern_key!(UnionId);
+impl AstItemDef<ast::UnionDef> for UnionId {
+    fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::UnionDef>) -> Self {
+        db.intern_union(loc)
     }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct UnionId(pub StructOrUnionId);
-impl From<UnionId> for StructOrUnionId {
-    fn from(id: UnionId) -> StructOrUnionId {
-        id.0
+    fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::UnionDef> {
+        db.lookup_intern_union(self)
     }
 }
 
@@ -485,8 +481,8 @@ fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
 impl HasModule for AdtId {
     fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
         match self {
-            AdtId::StructId(it) => it.0.module(db),
-            AdtId::UnionId(it) => it.0.module(db),
+            AdtId::StructId(it) => it.module(db),
+            AdtId::UnionId(it) => it.module(db),
             AdtId::EnumId(it) => it.module(db),
         }
     }
index 41becf8dffd22bab59f4f1563a7721f32a33c01a..4ff6f72cfbae3802f61a052a5b13e81cbf2c1e4a 100644 (file)
@@ -25,7 +25,7 @@
     per_ns::PerNs,
     AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId,
     Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId,
-    StructOrUnionId, TraitId, TypeAliasLoc, UnionId,
+    TraitId, TypeAliasLoc, UnionId,
 };
 
 pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
@@ -698,14 +698,12 @@ fn define_def(&mut self, def: &raw::DefData) {
                 PerNs::values(def.into())
             }
             raw::DefKind::Struct(ast_id) => {
-                let id = StructOrUnionId::from_ast_id(ctx, ast_id).into();
-                let s = StructId(id).into();
-                PerNs::both(s, s)
+                let id = StructId::from_ast_id(ctx, ast_id).into();
+                PerNs::both(id, id)
             }
             raw::DefKind::Union(ast_id) => {
-                let id = StructOrUnionId::from_ast_id(ctx, ast_id).into();
-                let u = UnionId(id).into();
-                PerNs::both(u, u)
+                let id = UnionId::from_ast_id(ctx, ast_id).into();
+                PerNs::both(id, id)
             }
             raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()),
             raw::DefKind::Const(ast_id) => {
index 401af031cc8feeaf38434b38561840b7e34f4a2e..6eb106094cf4ed239d5be7bdb6088a6d4a8fc0e7 100644 (file)
@@ -176,7 +176,7 @@ pub(super) struct DefData {
 pub(super) enum DefKind {
     Function(FileAstId<ast::FnDef>),
     Struct(FileAstId<ast::StructDef>),
-    Union(FileAstId<ast::StructDef>),
+    Union(FileAstId<ast::UnionDef>),
     Enum(FileAstId<ast::EnumDef>),
     Const(FileAstId<ast::ConstDef>),
     Static(FileAstId<ast::StaticDef>),
@@ -246,11 +246,12 @@ fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) {
             ast::ModuleItem::StructDef(it) => {
                 let id = self.source_ast_id_map.ast_id(&it);
                 let name = it.name();
-                if it.is_union() {
-                    (DefKind::Union(id), name)
-                } else {
-                    (DefKind::Struct(id), name)
-                }
+                (DefKind::Struct(id), name)
+            }
+            ast::ModuleItem::UnionDef(it) => {
+                let id = self.source_ast_id_map.ast_id(&it);
+                let name = it.name();
+                (DefKind::Union(id), name)
             }
             ast::ModuleItem::EnumDef(it) => {
                 (DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name())
index f502f1cb30e1eb11a0b999c2463e06fac4045c9c..87fcd617c523a9daa9d00bd40419bfefc0dee384 100644 (file)
@@ -82,6 +82,12 @@ fn f() {}
 
         //- /foo/bar.rs
         pub struct Baz;
+
+        union U {
+            to_be: bool,
+            not_to_be: u8,
+        }
+
         enum E { V }
         ",
     );
@@ -99,6 +105,7 @@ enum E { V }
         ⋮crate::foo::bar
         ⋮Baz: t v
         ⋮E: t
+        ⋮U: t v
     "###)
 }
 
index 5d2bce3d292030a4b288d99b16dbc2eef75b235b..9ffc9b980140d586e1bb4f3547bc77165d6e8447 100644 (file)
@@ -19,6 +19,12 @@ fn short_label(&self) -> Option<String> {
     }
 }
 
+impl ShortLabel for ast::UnionDef {
+    fn short_label(&self) -> Option<String> {
+        short_label_from_node(self, "union ")
+    }
+}
+
 impl ShortLabel for ast::EnumDef {
     fn short_label(&self) -> Option<String> {
         short_label_from_node(self, "enum ")
index 3e3012559bb5292253c8e01b96be710f73db1776..2b3100fc366f3bb81edfd6e42515d4d1aeff7e33 100644 (file)
@@ -49,6 +49,10 @@ fn impls_for_def(
             let src = hir::Source { file_id: position.file_id.into(), value: def.clone() };
             hir::Enum::from_source(db, src)?.ty(db)
         }
+        ast::NominalDef::UnionDef(def) => {
+            let src = hir::Source { file_id: position.file_id.into(), value: def.clone() };
+            hir::Union::from_source(db, src)?.ty(db)
+        }
     };
 
     let krate = module.krate();
index 630e6ce64fbc166b1ae7234cfcf2f5233690a117..370990e21fd357b0c5b767cb08a30069f77114e2 100644 (file)
@@ -6,8 +6,8 @@
 mod use_item;
 
 pub(crate) use self::{
-    expressions::{match_arm_list, record_field_list},
     adt::{enum_variant_list, record_field_def_list},
+    expressions::{match_arm_list, record_field_list},
     traits::{impl_item_list, trait_item_list},
     use_item::use_tree_list,
 };
index 513ed7920f983674579f675fda7d3b021f345dca..a8f6251762921f95970f1297cb50ee3f071aa19d 100644 (file)
@@ -196,17 +196,6 @@ fn from_node<N: AstNode>(node: &N) -> StructKind {
 }
 
 impl ast::StructDef {
-    pub fn is_union(&self) -> bool {
-        for child in self.syntax().children_with_tokens() {
-            match child.kind() {
-                T![struct] => return false,
-                T![union] => return true,
-                _ => (),
-            }
-        }
-        false
-    }
-
     pub fn kind(&self) -> StructKind {
         StructKind::from_node(self)
     }
index 1a03ae56c4baf87531ec52dc17cc7941f84031ab..c06076e3d7acbef3ae28ea7a35d4ce8bb4903095 100644 (file)
@@ -1856,6 +1856,7 @@ pub fn item_list(&self) -> Option<ItemList> {
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum ModuleItem {
     StructDef(StructDef),
+    UnionDef(UnionDef),
     EnumDef(EnumDef),
     FnDef(FnDef),
     TraitDef(TraitDef),
@@ -1872,6 +1873,11 @@ fn from(node: StructDef) -> ModuleItem {
         ModuleItem::StructDef(node)
     }
 }
+impl From<UnionDef> for ModuleItem {
+    fn from(node: UnionDef) -> ModuleItem {
+        ModuleItem::UnionDef(node)
+    }
+}
 impl From<EnumDef> for ModuleItem {
     fn from(node: EnumDef) -> ModuleItem {
         ModuleItem::EnumDef(node)
@@ -1925,14 +1931,15 @@ fn from(node: Module) -> ModuleItem {
 impl AstNode for ModuleItem {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | TYPE_ALIAS_DEF | IMPL_BLOCK | USE_ITEM
-            | EXTERN_CRATE_ITEM | CONST_DEF | STATIC_DEF | MODULE => true,
+            STRUCT_DEF | UNION_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | TYPE_ALIAS_DEF
+            | IMPL_BLOCK | USE_ITEM | EXTERN_CRATE_ITEM | CONST_DEF | STATIC_DEF | MODULE => true,
             _ => false,
         }
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         let res = match syntax.kind() {
             STRUCT_DEF => ModuleItem::StructDef(StructDef { syntax }),
+            UNION_DEF => ModuleItem::UnionDef(UnionDef { syntax }),
             ENUM_DEF => ModuleItem::EnumDef(EnumDef { syntax }),
             FN_DEF => ModuleItem::FnDef(FnDef { syntax }),
             TRAIT_DEF => ModuleItem::TraitDef(TraitDef { syntax }),
@@ -1950,6 +1957,7 @@ fn cast(syntax: SyntaxNode) -> Option<Self> {
     fn syntax(&self) -> &SyntaxNode {
         match self {
             ModuleItem::StructDef(it) => &it.syntax,
+            ModuleItem::UnionDef(it) => &it.syntax,
             ModuleItem::EnumDef(it) => &it.syntax,
             ModuleItem::FnDef(it) => &it.syntax,
             ModuleItem::TraitDef(it) => &it.syntax,
@@ -2038,6 +2046,7 @@ impl NeverType {}
 pub enum NominalDef {
     StructDef(StructDef),
     EnumDef(EnumDef),
+    UnionDef(UnionDef),
 }
 impl From<StructDef> for NominalDef {
     fn from(node: StructDef) -> NominalDef {
@@ -2049,10 +2058,15 @@ fn from(node: EnumDef) -> NominalDef {
         NominalDef::EnumDef(node)
     }
 }
+impl From<UnionDef> for NominalDef {
+    fn from(node: UnionDef) -> NominalDef {
+        NominalDef::UnionDef(node)
+    }
+}
 impl AstNode for NominalDef {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            STRUCT_DEF | ENUM_DEF => true,
+            STRUCT_DEF | ENUM_DEF | UNION_DEF => true,
             _ => false,
         }
     }
@@ -2060,6 +2074,7 @@ fn cast(syntax: SyntaxNode) -> Option<Self> {
         let res = match syntax.kind() {
             STRUCT_DEF => NominalDef::StructDef(StructDef { syntax }),
             ENUM_DEF => NominalDef::EnumDef(EnumDef { syntax }),
+            UNION_DEF => NominalDef::UnionDef(UnionDef { syntax }),
             _ => return None,
         };
         Some(res)
@@ -2068,6 +2083,7 @@ fn syntax(&self) -> &SyntaxNode {
         match self {
             NominalDef::StructDef(it) => &it.syntax,
             NominalDef::EnumDef(it) => &it.syntax,
+            NominalDef::UnionDef(it) => &it.syntax,
         }
     }
 }
@@ -3815,7 +3831,11 @@ impl ast::NameOwner for UnionDef {}
 impl ast::TypeParamsOwner for UnionDef {}
 impl ast::AttrsOwner for UnionDef {}
 impl ast::DocCommentsOwner for UnionDef {}
-impl UnionDef {}
+impl UnionDef {
+    pub fn record_field_def_list(&self) -> Option<RecordFieldDefList> {
+        AstChildren::new(&self.syntax).next()
+    }
+}
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct UseItem {
     pub(crate) syntax: SyntaxNode,
index c16bed891564257d6bc410025752386dc1794274..d1be40abeb9690a54d8f90a3f50765cd9dfeccdf 100644 (file)
@@ -293,7 +293,8 @@ Grammar(
                 "TypeParamsOwner",
                 "AttrsOwner",
                 "DocCommentsOwner"
-            ]
+            ],
+            options: ["RecordFieldDefList"],
         ),
         "RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]),
         "RecordFieldDef": (
@@ -398,7 +399,7 @@ Grammar(
         ]),
 
         "NominalDef": (
-            enum: ["StructDef", "EnumDef"],
+            enum: ["StructDef", "EnumDef", "UnionDef"],
             traits: [
                 "NameOwner",
                 "TypeParamsOwner",
@@ -406,9 +407,9 @@ Grammar(
             ],
         ),
         "ModuleItem": (
-            enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock",
+            enum: ["StructDef", "UnionDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock",
                    "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ],
-            traits: ["AttrsOwner"]
+            traits: ["AttrsOwner"],
         ),
         "ImplItem": (
             enum: ["FnDef", "TypeAliasDef", "ConstDef"],