aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-11-25 14:51:17 +0000
committerGitHub <[email protected]>2019-11-25 14:51:17 +0000
commitecd1204804a2a3c8b9b98e4b9d18feef06ab51c7 (patch)
treed051e9bb71631cca33a1b4c23bf3f2576d1c0f56
parentbe00d74c7b61fb82bdade482e95035a21f9dd736 (diff)
parent1455663ea15ecbfbe87b4b5be6919aa35dd0b260 (diff)
Merge #2403
2403: Fixme for union fields r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r--crates/ra_assists/src/assists/add_new.rs4
-rw-r--r--crates/ra_hir/src/code_model.rs6
-rw-r--r--crates/ra_hir/src/code_model/src.rs8
-rw-r--r--crates/ra_hir/src/from_source.rs13
-rw-r--r--crates/ra_hir/src/ty.rs2
-rw-r--r--crates/ra_hir/src/ty/infer/coerce.rs2
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs2
-rw-r--r--crates/ra_hir/src/ty/lower.rs5
-rw-r--r--crates/ra_hir_def/src/adt.rs23
-rw-r--r--crates/ra_hir_def/src/attr.rs4
-rw-r--r--crates/ra_hir_def/src/db.rs12
-rw-r--r--crates/ra_hir_def/src/docs.rs4
-rw-r--r--crates/ra_hir_def/src/generics.rs6
-rw-r--r--crates/ra_hir_def/src/lib.rs33
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs12
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs13
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs7
-rw-r--r--crates/ra_ide_api/src/display/short_label.rs6
-rw-r--r--crates/ra_ide_api/src/impls.rs4
-rw-r--r--crates/ra_parser/src/grammar/items.rs10
-rw-r--r--crates/ra_parser/src/grammar/items/adt.rs (renamed from crates/ra_parser/src/grammar/items/nominal.rs)23
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs1
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs11
-rw-r--r--crates/ra_syntax/src/ast/generated.rs54
-rw-r--r--crates/ra_syntax/src/grammar.ron17
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt2
27 files changed, 190 insertions, 98 deletions
diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs
index ee8bff346..8f68bd5fb 100644
--- a/crates/ra_assists/src/assists/add_new.rs
+++ b/crates/ra_assists/src/assists/add_new.rs
@@ -35,8 +35,8 @@ pub(crate) fn add_new(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
35 let strukt = ctx.find_node_at_offset::<ast::StructDef>()?; 35 let strukt = ctx.find_node_at_offset::<ast::StructDef>()?;
36 36
37 // We want to only apply this to non-union structs with named fields 37 // We want to only apply this to non-union structs with named fields
38 let field_list = match (strukt.kind(), strukt.is_union()) { 38 let field_list = match strukt.kind() {
39 (StructKind::Record(named), false) => named, 39 StructKind::Record(named) => named,
40 _ => return None, 40 _ => return None,
41 }; 41 };
42 42
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 534f1f8e9..ae730beb5 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -320,7 +320,7 @@ pub struct Struct {
320 320
321impl Struct { 321impl Struct {
322 pub fn module(self, db: &impl DefDatabase) -> Module { 322 pub fn module(self, db: &impl DefDatabase) -> Module {
323 Module { id: self.id.0.module(db) } 323 Module { id: self.id.module(db) }
324 } 324 }
325 325
326 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 326 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
@@ -369,11 +369,11 @@ pub struct Union {
369 369
370impl Union { 370impl Union {
371 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 371 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
372 db.struct_data(self.id.into()).name.clone() 372 db.union_data(self.id).name.clone()
373 } 373 }
374 374
375 pub fn module(self, db: &impl DefDatabase) -> Module { 375 pub fn module(self, db: &impl DefDatabase) -> Module {
376 Module { id: self.id.0.module(db) } 376 Module { id: self.id.module(db) }
377 } 377 }
378 378
379 pub fn ty(self, db: &impl HirDatabase) -> Ty { 379 pub fn ty(self, db: &impl HirDatabase) -> Ty {
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index a4e317c20..076d86f2b 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -51,13 +51,13 @@ impl HasSource for StructField {
51impl HasSource for Struct { 51impl HasSource for Struct {
52 type Ast = ast::StructDef; 52 type Ast = ast::StructDef;
53 fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> { 53 fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> {
54 self.id.0.source(db) 54 self.id.source(db)
55 } 55 }
56} 56}
57impl HasSource for Union { 57impl HasSource for Union {
58 type Ast = ast::StructDef; 58 type Ast = ast::UnionDef;
59 fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> { 59 fn source(self, db: &impl DefDatabase) -> Source<ast::UnionDef> {
60 self.id.0.source(db) 60 self.id.source(db)
61 } 61 }
62} 62}
63impl HasSource for Enum { 63impl HasSource for Enum {
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 1e7c22774..95db7161b 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{AstItemDef, LocationCtx, ModuleId, StructId, StructOrUnionId, UnionId}; 3use hir_def::{AstItemDef, LocationCtx, ModuleId};
4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
5use ra_syntax::{ 5use ra_syntax::{
6 ast::{self, AstNode, NameOwner}, 6 ast::{self, AstNode, NameOwner},
@@ -19,19 +19,18 @@ pub trait FromSource: Sized {
19 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>; 19 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>;
20} 20}
21 21
22// FIXIME: these two impls are wrong, `ast::StructDef` might produce either a struct or a union
23impl FromSource for Struct { 22impl FromSource for Struct {
24 type Ast = ast::StructDef; 23 type Ast = ast::StructDef;
25 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 24 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
26 let id: StructOrUnionId = from_source(db, src)?; 25 let id = from_source(db, src)?;
27 Some(Struct { id: StructId(id) }) 26 Some(Struct { id })
28 } 27 }
29} 28}
30impl FromSource for Union { 29impl FromSource for Union {
31 type Ast = ast::StructDef; 30 type Ast = ast::UnionDef;
32 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 31 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
33 let id: StructOrUnionId = from_source(db, src)?; 32 let id = from_source(db, src)?;
34 Some(Union { id: UnionId(id) }) 33 Some(Union { id })
35 } 34 }
36} 35}
37impl FromSource for Enum { 36impl FromSource for Enum {
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 8c045aaef..3cbcbd1d0 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -858,7 +858,7 @@ impl HirDisplay for ApplicationTy {
858 let name = match def { 858 let name = match def {
859 CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(), 859 CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(),
860 CallableDef::StructId(s) => { 860 CallableDef::StructId(s) => {
861 f.db.struct_data(s.0).name.clone().unwrap_or_else(Name::missing) 861 f.db.struct_data(s).name.clone().unwrap_or_else(Name::missing)
862 } 862 }
863 CallableDef::EnumVariantId(e) => { 863 CallableDef::EnumVariantId(e) => {
864 let enum_data = f.db.enum_data(e.parent); 864 let enum_data = f.db.enum_data(e.parent);
diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs
index 4b53bba73..bb9a2e427 100644
--- a/crates/ra_hir/src/ty/infer/coerce.rs
+++ b/crates/ra_hir/src/ty/infer/coerce.rs
@@ -246,7 +246,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
246 ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), 246 ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2),
247 ) if struct1 == struct2 => { 247 ) if struct1 == struct2 => {
248 let field_tys = self.db.field_types(struct1.id.into()); 248 let field_tys = self.db.field_types(struct1.id.into());
249 let struct_data = self.db.struct_data(struct1.id.0); 249 let struct_data = self.db.struct_data(struct1.id);
250 250
251 let mut fields = struct_data.variant_data.fields().iter(); 251 let mut fields = struct_data.variant_data.fields().iter();
252 let (last_field_id, _data) = fields.next_back()?; 252 let (last_field_id, _data) = fields.next_back()?;
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index 1d6df2b7a..994a6d7e9 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -263,6 +263,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
263 .clone() 263 .clone()
264 .subst(&a_ty.parameters) 264 .subst(&a_ty.parameters)
265 }), 265 }),
266 // FIXME:
267 TypeCtor::Adt(Adt::Union(_)) => None,
266 _ => None, 268 _ => None,
267 }, 269 },
268 _ => None, 270 _ => None,
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 27cfe00c1..eb51d31bd 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -560,7 +560,8 @@ pub(crate) fn field_types_query(
560 variant_id: VariantId, 560 variant_id: VariantId,
561) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { 561) -> Arc<ArenaMap<LocalStructFieldId, Ty>> {
562 let (resolver, var_data) = match variant_id { 562 let (resolver, var_data) = match variant_id {
563 VariantId::StructId(it) => (it.resolver(db), db.struct_data(it.0).variant_data.clone()), 563 VariantId::StructId(it) => (it.resolver(db), db.struct_data(it).variant_data.clone()),
564 VariantId::UnionId(it) => (it.resolver(db), db.union_data(it).variant_data.clone()),
564 VariantId::EnumVariantId(it) => ( 565 VariantId::EnumVariantId(it) => (
565 it.parent.resolver(db), 566 it.parent.resolver(db),
566 db.enum_data(it.parent).variants[it.local_id].variant_data.clone(), 567 db.enum_data(it.parent).variants[it.local_id].variant_data.clone(),
@@ -818,7 +819,7 @@ impl CallableDef {
818 pub fn krate(self, db: &impl HirDatabase) -> CrateId { 819 pub fn krate(self, db: &impl HirDatabase) -> CrateId {
819 match self { 820 match self {
820 CallableDef::FunctionId(f) => f.lookup(db).module(db).krate, 821 CallableDef::FunctionId(f) => f.lookup(db).module(db).krate,
821 CallableDef::StructId(s) => s.0.module(db).krate, 822 CallableDef::StructId(s) => s.module(db).krate,
822 CallableDef::EnumVariantId(e) => e.parent.module(db).krate, 823 CallableDef::EnumVariantId(e) => e.parent.module(db).krate,
823 } 824 }
824 } 825 }
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index c9f30923e..0091bfbc3 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -12,7 +12,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
12 12
13use crate::{ 13use crate::{
14 db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource, 14 db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource,
15 LocalEnumVariantId, LocalStructFieldId, StructOrUnionId, VariantId, 15 LocalEnumVariantId, LocalStructFieldId, StructId, UnionId, VariantId,
16}; 16};
17 17
18/// Note that we use `StructData` for unions as well! 18/// Note that we use `StructData` for unions as well!
@@ -49,13 +49,25 @@ pub struct StructFieldData {
49} 49}
50 50
51impl StructData { 51impl StructData {
52 pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructOrUnionId) -> Arc<StructData> { 52 pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> {
53 let src = id.source(db); 53 let src = id.source(db);
54 let name = src.value.name().map(|n| n.as_name()); 54 let name = src.value.name().map(|n| n.as_name());
55 let variant_data = VariantData::new(src.value.kind()); 55 let variant_data = VariantData::new(src.value.kind());
56 let variant_data = Arc::new(variant_data); 56 let variant_data = Arc::new(variant_data);
57 Arc::new(StructData { name, variant_data }) 57 Arc::new(StructData { name, variant_data })
58 } 58 }
59 pub(crate) fn union_data_query(db: &impl DefDatabase, id: UnionId) -> Arc<StructData> {
60 let src = id.source(db);
61 let name = src.value.name().map(|n| n.as_name());
62 let variant_data = VariantData::new(
63 src.value
64 .record_field_def_list()
65 .map(ast::StructKind::Record)
66 .unwrap_or(ast::StructKind::Unit),
67 );
68 let variant_data = Arc::new(variant_data);
69 Arc::new(StructData { name, variant_data })
70 }
59} 71}
60 72
61impl EnumData { 73impl EnumData {
@@ -137,7 +149,12 @@ impl HasChildSource for VariantId {
137 let src = it.parent.child_source(db); 149 let src = it.parent.child_source(db);
138 src.map(|map| map[it.local_id].kind()) 150 src.map(|map| map[it.local_id].kind())
139 } 151 }
140 VariantId::StructId(it) => it.0.source(db).map(|it| it.kind()), 152 VariantId::StructId(it) => it.source(db).map(|it| it.kind()),
153 VariantId::UnionId(it) => it.source(db).map(|it| {
154 it.record_field_def_list()
155 .map(ast::StructKind::Record)
156 .unwrap_or(ast::StructKind::Unit)
157 }),
141 }; 158 };
142 let mut trace = Trace::new_for_map(); 159 let mut trace = Trace::new_for_map();
143 lower_struct(&mut trace, &src.value); 160 lower_struct(&mut trace, &src.value);
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 53456fc08..298608e27 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -54,9 +54,9 @@ impl Attrs {
54 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) 54 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
55 } 55 }
56 AttrDefId::AdtId(it) => match it { 56 AttrDefId::AdtId(it) => match it {
57 AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), 57 AdtId::StructId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
58 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 58 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
59 AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), 59 AdtId::UnionId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
60 }, 60 },
61 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 61 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
62 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db), 62 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db),
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 32adb11bd..ef5611ffc 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -18,8 +18,8 @@ use crate::{
18 CrateDefMap, 18 CrateDefMap,
19 }, 19 },
20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId, 20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId,
21 ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructOrUnionId, TraitId, TypeAliasId, 21 ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TypeAliasId, TypeAliasLoc,
22 TypeAliasLoc, 22 UnionId,
23}; 23};
24 24
25#[salsa::query_group(InternDatabaseStorage)] 25#[salsa::query_group(InternDatabaseStorage)]
@@ -27,7 +27,9 @@ pub trait InternDatabase: SourceDatabase {
27 #[salsa::interned] 27 #[salsa::interned]
28 fn intern_function(&self, loc: FunctionLoc) -> FunctionId; 28 fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
29 #[salsa::interned] 29 #[salsa::interned]
30 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> StructOrUnionId; 30 fn intern_struct(&self, loc: ItemLoc<ast::StructDef>) -> StructId;
31 #[salsa::interned]
32 fn intern_union(&self, loc: ItemLoc<ast::UnionDef>) -> UnionId;
31 #[salsa::interned] 33 #[salsa::interned]
32 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> EnumId; 34 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> EnumId;
33 #[salsa::interned] 35 #[salsa::interned]
@@ -57,7 +59,9 @@ pub trait DefDatabase: InternDatabase + AstDatabase {
57 fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>; 59 fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>;
58 60
59 #[salsa::invoke(StructData::struct_data_query)] 61 #[salsa::invoke(StructData::struct_data_query)]
60 fn struct_data(&self, id: StructOrUnionId) -> Arc<StructData>; 62 fn struct_data(&self, id: StructId) -> Arc<StructData>;
63 #[salsa::invoke(StructData::union_data_query)]
64 fn union_data(&self, id: UnionId) -> Arc<StructData>;
61 65
62 #[salsa::invoke(EnumData::enum_data_query)] 66 #[salsa::invoke(EnumData::enum_data_query)]
63 fn enum_data(&self, e: EnumId) -> Arc<EnumData>; 67 fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index 90a8627bc..4749b642f 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -47,9 +47,9 @@ impl Documentation {
47 } 47 }
48 } 48 }
49 AttrDefId::AdtId(it) => match it { 49 AttrDefId::AdtId(it) => match it {
50 AdtId::StructId(it) => docs_from_ast(&it.0.source(db).value), 50 AdtId::StructId(it) => docs_from_ast(&it.source(db).value),
51 AdtId::EnumId(it) => docs_from_ast(&it.source(db).value), 51 AdtId::EnumId(it) => docs_from_ast(&it.source(db).value),
52 AdtId::UnionId(it) => docs_from_ast(&it.0.source(db).value), 52 AdtId::UnionId(it) => docs_from_ast(&it.source(db).value),
53 }, 53 },
54 AttrDefId::EnumVariantId(it) => { 54 AttrDefId::EnumVariantId(it) => {
55 let src = it.parent.child_source(db); 55 let src = it.parent.child_source(db);
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 015fe772e..3f94e40e4 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -60,10 +60,8 @@ impl GenericParams {
60 // FIXME: add `: Sized` bound for everything except for `Self` in traits 60 // FIXME: add `: Sized` bound for everything except for `Self` in traits
61 match def { 61 match def {
62 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), 62 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start),
63 GenericDefId::AdtId(AdtId::StructId(it)) => { 63 GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start),
64 generics.fill(&it.0.source(db).value, start) 64 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start),
65 }
66 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.0.source(db).value, start),
67 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), 65 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start),
68 GenericDefId::TraitId(it) => { 66 GenericDefId::TraitId(it) => {
69 // traits get the Self type as an implicit first type parameter 67 // traits get the Self type as an implicit first type parameter
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 8e8c2d749..a88a78b38 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -141,30 +141,26 @@ impl Lookup for FunctionId {
141} 141}
142 142
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 143#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
144pub struct StructOrUnionId(salsa::InternId); 144pub struct StructId(salsa::InternId);
145impl_intern_key!(StructOrUnionId); 145impl_intern_key!(StructId);
146impl AstItemDef<ast::StructDef> for StructOrUnionId { 146impl AstItemDef<ast::StructDef> for StructId {
147 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self { 147 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self {
148 db.intern_struct_or_union(loc) 148 db.intern_struct(loc)
149 } 149 }
150 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> { 150 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> {
151 db.lookup_intern_struct_or_union(self) 151 db.lookup_intern_struct(self)
152 } 152 }
153} 153}
154 154
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 155#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
156pub struct StructId(pub StructOrUnionId); 156pub struct UnionId(salsa::InternId);
157impl From<StructId> for StructOrUnionId { 157impl_intern_key!(UnionId);
158 fn from(id: StructId) -> StructOrUnionId { 158impl AstItemDef<ast::UnionDef> for UnionId {
159 id.0 159 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::UnionDef>) -> Self {
160 db.intern_union(loc)
160 } 161 }
161} 162 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::UnionDef> {
162 163 db.lookup_intern_union(self)
163#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
164pub struct UnionId(pub StructOrUnionId);
165impl From<UnionId> for StructOrUnionId {
166 fn from(id: UnionId) -> StructOrUnionId {
167 id.0
168 } 164 }
169} 165}
170 166
@@ -435,6 +431,7 @@ impl_froms!(
435pub enum VariantId { 431pub enum VariantId {
436 EnumVariantId(EnumVariantId), 432 EnumVariantId(EnumVariantId),
437 StructId(StructId), 433 StructId(StructId),
434 UnionId(UnionId),
438} 435}
439impl_froms!(VariantId: EnumVariantId, StructId); 436impl_froms!(VariantId: EnumVariantId, StructId);
440 437
@@ -485,8 +482,8 @@ impl HasModule for ConstLoc {
485impl HasModule for AdtId { 482impl HasModule for AdtId {
486 fn module(&self, db: &impl db::DefDatabase) -> ModuleId { 483 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
487 match self { 484 match self {
488 AdtId::StructId(it) => it.0.module(db), 485 AdtId::StructId(it) => it.module(db),
489 AdtId::UnionId(it) => it.0.module(db), 486 AdtId::UnionId(it) => it.module(db),
490 AdtId::EnumId(it) => it.module(db), 487 AdtId::EnumId(it) => it.module(db),
491 } 488 }
492 } 489 }
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 41becf8df..4ff6f72cf 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -25,7 +25,7 @@ use crate::{
25 per_ns::PerNs, 25 per_ns::PerNs,
26 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId, 26 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId,
27 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId, 27 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId,
28 StructOrUnionId, TraitId, TypeAliasLoc, UnionId, 28 TraitId, TypeAliasLoc, UnionId,
29}; 29};
30 30
31pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { 31pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
@@ -698,14 +698,12 @@ where
698 PerNs::values(def.into()) 698 PerNs::values(def.into())
699 } 699 }
700 raw::DefKind::Struct(ast_id) => { 700 raw::DefKind::Struct(ast_id) => {
701 let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); 701 let id = StructId::from_ast_id(ctx, ast_id).into();
702 let s = StructId(id).into(); 702 PerNs::both(id, id)
703 PerNs::both(s, s)
704 } 703 }
705 raw::DefKind::Union(ast_id) => { 704 raw::DefKind::Union(ast_id) => {
706 let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); 705 let id = UnionId::from_ast_id(ctx, ast_id).into();
707 let u = UnionId(id).into(); 706 PerNs::both(id, id)
708 PerNs::both(u, u)
709 } 707 }
710 raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()), 708 raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()),
711 raw::DefKind::Const(ast_id) => { 709 raw::DefKind::Const(ast_id) => {
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 401af031c..6eb106094 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -176,7 +176,7 @@ pub(super) struct DefData {
176pub(super) enum DefKind { 176pub(super) enum DefKind {
177 Function(FileAstId<ast::FnDef>), 177 Function(FileAstId<ast::FnDef>),
178 Struct(FileAstId<ast::StructDef>), 178 Struct(FileAstId<ast::StructDef>),
179 Union(FileAstId<ast::StructDef>), 179 Union(FileAstId<ast::UnionDef>),
180 Enum(FileAstId<ast::EnumDef>), 180 Enum(FileAstId<ast::EnumDef>),
181 Const(FileAstId<ast::ConstDef>), 181 Const(FileAstId<ast::ConstDef>),
182 Static(FileAstId<ast::StaticDef>), 182 Static(FileAstId<ast::StaticDef>),
@@ -246,11 +246,12 @@ impl RawItemsCollector {
246 ast::ModuleItem::StructDef(it) => { 246 ast::ModuleItem::StructDef(it) => {
247 let id = self.source_ast_id_map.ast_id(&it); 247 let id = self.source_ast_id_map.ast_id(&it);
248 let name = it.name(); 248 let name = it.name();
249 if it.is_union() { 249 (DefKind::Struct(id), name)
250 (DefKind::Union(id), name) 250 }
251 } else { 251 ast::ModuleItem::UnionDef(it) => {
252 (DefKind::Struct(id), name) 252 let id = self.source_ast_id_map.ast_id(&it);
253 } 253 let name = it.name();
254 (DefKind::Union(id), name)
254 } 255 }
255 ast::ModuleItem::EnumDef(it) => { 256 ast::ModuleItem::EnumDef(it) => {
256 (DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name()) 257 (DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name())
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index f502f1cb3..87fcd617c 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -82,6 +82,12 @@ fn crate_def_map_smoke_test() {
82 82
83 //- /foo/bar.rs 83 //- /foo/bar.rs
84 pub struct Baz; 84 pub struct Baz;
85
86 union U {
87 to_be: bool,
88 not_to_be: u8,
89 }
90
85 enum E { V } 91 enum E { V }
86 ", 92 ",
87 ); 93 );
@@ -99,6 +105,7 @@ fn crate_def_map_smoke_test() {
99 â‹®crate::foo::bar 105 â‹®crate::foo::bar
100 â‹®Baz: t v 106 â‹®Baz: t v
101 â‹®E: t 107 â‹®E: t
108 â‹®U: t v
102 "###) 109 "###)
103} 110}
104 111
diff --git a/crates/ra_ide_api/src/display/short_label.rs b/crates/ra_ide_api/src/display/short_label.rs
index 5d2bce3d2..9ffc9b980 100644
--- a/crates/ra_ide_api/src/display/short_label.rs
+++ b/crates/ra_ide_api/src/display/short_label.rs
@@ -19,6 +19,12 @@ impl ShortLabel for ast::StructDef {
19 } 19 }
20} 20}
21 21
22impl ShortLabel for ast::UnionDef {
23 fn short_label(&self) -> Option<String> {
24 short_label_from_node(self, "union ")
25 }
26}
27
22impl ShortLabel for ast::EnumDef { 28impl ShortLabel for ast::EnumDef {
23 fn short_label(&self) -> Option<String> { 29 fn short_label(&self) -> Option<String> {
24 short_label_from_node(self, "enum ") 30 short_label_from_node(self, "enum ")
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs
index 3e3012559..2b3100fc3 100644
--- a/crates/ra_ide_api/src/impls.rs
+++ b/crates/ra_ide_api/src/impls.rs
@@ -49,6 +49,10 @@ fn impls_for_def(
49 let src = hir::Source { file_id: position.file_id.into(), value: def.clone() }; 49 let src = hir::Source { file_id: position.file_id.into(), value: def.clone() };
50 hir::Enum::from_source(db, src)?.ty(db) 50 hir::Enum::from_source(db, src)?.ty(db)
51 } 51 }
52 ast::NominalDef::UnionDef(def) => {
53 let src = hir::Source { file_id: position.file_id.into(), value: def.clone() };
54 hir::Union::from_source(db, src)?.ty(db)
55 }
52 }; 56 };
53 57
54 let krate = module.krate(); 58 let krate = module.krate();
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 85f7eeb00..370990e21 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -1,13 +1,13 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3mod consts; 3mod consts;
4mod nominal; 4mod adt;
5mod traits; 5mod traits;
6mod use_item; 6mod use_item;
7 7
8pub(crate) use self::{ 8pub(crate) use self::{
9 adt::{enum_variant_list, record_field_def_list},
9 expressions::{match_arm_list, record_field_list}, 10 expressions::{match_arm_list, record_field_list},
10 nominal::{enum_variant_list, record_field_def_list},
11 traits::{impl_item_list, trait_item_list}, 11 traits::{impl_item_list, trait_item_list},
12 use_item::use_tree_list, 12 use_item::use_tree_list,
13}; 13};
@@ -247,7 +247,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
247 // a: i32, 247 // a: i32,
248 // b: f32, 248 // b: f32,
249 // } 249 // }
250 nominal::struct_def(p, m, T![struct]); 250 adt::struct_def(p, m);
251 } 251 }
252 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { 252 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
253 // test union_items 253 // test union_items
@@ -256,9 +256,9 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
256 // a: i32, 256 // a: i32,
257 // b: f32, 257 // b: f32,
258 // } 258 // }
259 nominal::struct_def(p, m, T![union]); 259 adt::union_def(p, m);
260 } 260 }
261 T![enum] => nominal::enum_def(p, m), 261 T![enum] => adt::enum_def(p, m),
262 T![use] => use_item::use_item(p, m), 262 T![use] => use_item::use_item(p, m),
263 T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::const_def(p, m), 263 T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::const_def(p, m),
264 T![static] => consts::static_def(p, m), 264 T![static] => consts::static_def(p, m),
diff --git a/crates/ra_parser/src/grammar/items/nominal.rs b/crates/ra_parser/src/grammar/items/adt.rs
index 9d8fb8486..c777bc9d0 100644
--- a/crates/ra_parser/src/grammar/items/nominal.rs
+++ b/crates/ra_parser/src/grammar/items/adt.rs
@@ -2,10 +2,19 @@
2 2
3use super::*; 3use super::*;
4 4
5pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) { 5pub(super) fn struct_def(p: &mut Parser, m: Marker) {
6 assert!(p.at(T![struct]) || p.at_contextual_kw("union")); 6 assert!(p.at(T![struct]));
7 p.bump_remap(kind); 7 p.bump(T![struct]);
8 struct_or_union(p, m, T![struct], STRUCT_DEF);
9}
10
11pub(super) fn union_def(p: &mut Parser, m: Marker) {
12 assert!(p.at_contextual_kw("union"));
13 p.bump_remap(T![union]);
14 struct_or_union(p, m, T![union], UNION_DEF);
15}
8 16
17fn struct_or_union(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
9 name_r(p, ITEM_RECOVERY_SET); 18 name_r(p, ITEM_RECOVERY_SET);
10 type_params::opt_type_param_list(p); 19 type_params::opt_type_param_list(p);
11 match p.current() { 20 match p.current() {
@@ -22,11 +31,11 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
22 } 31 }
23 } 32 }
24 } 33 }
25 T![;] if kind == T![struct] => { 34 T![;] if kw == T![struct] => {
26 p.bump(T![;]); 35 p.bump(T![;]);
27 } 36 }
28 T!['{'] => record_field_def_list(p), 37 T!['{'] => record_field_def_list(p),
29 T!['('] if kind == T![struct] => { 38 T!['('] if kw == T![struct] => {
30 tuple_field_def_list(p); 39 tuple_field_def_list(p);
31 // test tuple_struct_where 40 // test tuple_struct_where
32 // struct Test<T>(T) where T: Clone; 41 // struct Test<T>(T) where T: Clone;
@@ -34,14 +43,14 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
34 type_params::opt_where_clause(p); 43 type_params::opt_where_clause(p);
35 p.expect(T![;]); 44 p.expect(T![;]);
36 } 45 }
37 _ if kind == T![struct] => { 46 _ if kw == T![struct] => {
38 p.error("expected `;`, `{`, or `(`"); 47 p.error("expected `;`, `{`, or `(`");
39 } 48 }
40 _ => { 49 _ => {
41 p.error("expected `{`"); 50 p.error("expected `{`");
42 } 51 }
43 } 52 }
44 m.complete(p, STRUCT_DEF); 53 m.complete(p, def);
45} 54}
46 55
47pub(super) fn enum_def(p: &mut Parser, m: Marker) { 56pub(super) fn enum_def(p: &mut Parser, m: Marker) {
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 96b5bce88..fe0fcdb33 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -122,6 +122,7 @@ pub enum SyntaxKind {
122 R_DOLLAR, 122 R_DOLLAR,
123 SOURCE_FILE, 123 SOURCE_FILE,
124 STRUCT_DEF, 124 STRUCT_DEF,
125 UNION_DEF,
125 ENUM_DEF, 126 ENUM_DEF,
126 FN_DEF, 127 FN_DEF,
127 RET_TYPE, 128 RET_TYPE,
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 513ed7920..a8f625176 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -196,17 +196,6 @@ impl StructKind {
196} 196}
197 197
198impl ast::StructDef { 198impl ast::StructDef {
199 pub fn is_union(&self) -> bool {
200 for child in self.syntax().children_with_tokens() {
201 match child.kind() {
202 T![struct] => return false,
203 T![union] => return true,
204 _ => (),
205 }
206 }
207 false
208 }
209
210 pub fn kind(&self) -> StructKind { 199 pub fn kind(&self) -> StructKind {
211 StructKind::from_node(self) 200 StructKind::from_node(self)
212 } 201 }
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index de506d7cd..c06076e3d 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1856,6 +1856,7 @@ impl Module {
1856#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1856#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1857pub enum ModuleItem { 1857pub enum ModuleItem {
1858 StructDef(StructDef), 1858 StructDef(StructDef),
1859 UnionDef(UnionDef),
1859 EnumDef(EnumDef), 1860 EnumDef(EnumDef),
1860 FnDef(FnDef), 1861 FnDef(FnDef),
1861 TraitDef(TraitDef), 1862 TraitDef(TraitDef),
@@ -1872,6 +1873,11 @@ impl From<StructDef> for ModuleItem {
1872 ModuleItem::StructDef(node) 1873 ModuleItem::StructDef(node)
1873 } 1874 }
1874} 1875}
1876impl From<UnionDef> for ModuleItem {
1877 fn from(node: UnionDef) -> ModuleItem {
1878 ModuleItem::UnionDef(node)
1879 }
1880}
1875impl From<EnumDef> for ModuleItem { 1881impl From<EnumDef> for ModuleItem {
1876 fn from(node: EnumDef) -> ModuleItem { 1882 fn from(node: EnumDef) -> ModuleItem {
1877 ModuleItem::EnumDef(node) 1883 ModuleItem::EnumDef(node)
@@ -1925,14 +1931,15 @@ impl From<Module> for ModuleItem {
1925impl AstNode for ModuleItem { 1931impl AstNode for ModuleItem {
1926 fn can_cast(kind: SyntaxKind) -> bool { 1932 fn can_cast(kind: SyntaxKind) -> bool {
1927 match kind { 1933 match kind {
1928 STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | TYPE_ALIAS_DEF | IMPL_BLOCK | USE_ITEM 1934 STRUCT_DEF | UNION_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | TYPE_ALIAS_DEF
1929 | EXTERN_CRATE_ITEM | CONST_DEF | STATIC_DEF | MODULE => true, 1935 | IMPL_BLOCK | USE_ITEM | EXTERN_CRATE_ITEM | CONST_DEF | STATIC_DEF | MODULE => true,
1930 _ => false, 1936 _ => false,
1931 } 1937 }
1932 } 1938 }
1933 fn cast(syntax: SyntaxNode) -> Option<Self> { 1939 fn cast(syntax: SyntaxNode) -> Option<Self> {
1934 let res = match syntax.kind() { 1940 let res = match syntax.kind() {
1935 STRUCT_DEF => ModuleItem::StructDef(StructDef { syntax }), 1941 STRUCT_DEF => ModuleItem::StructDef(StructDef { syntax }),
1942 UNION_DEF => ModuleItem::UnionDef(UnionDef { syntax }),
1936 ENUM_DEF => ModuleItem::EnumDef(EnumDef { syntax }), 1943 ENUM_DEF => ModuleItem::EnumDef(EnumDef { syntax }),
1937 FN_DEF => ModuleItem::FnDef(FnDef { syntax }), 1944 FN_DEF => ModuleItem::FnDef(FnDef { syntax }),
1938 TRAIT_DEF => ModuleItem::TraitDef(TraitDef { syntax }), 1945 TRAIT_DEF => ModuleItem::TraitDef(TraitDef { syntax }),
@@ -1950,6 +1957,7 @@ impl AstNode for ModuleItem {
1950 fn syntax(&self) -> &SyntaxNode { 1957 fn syntax(&self) -> &SyntaxNode {
1951 match self { 1958 match self {
1952 ModuleItem::StructDef(it) => &it.syntax, 1959 ModuleItem::StructDef(it) => &it.syntax,
1960 ModuleItem::UnionDef(it) => &it.syntax,
1953 ModuleItem::EnumDef(it) => &it.syntax, 1961 ModuleItem::EnumDef(it) => &it.syntax,
1954 ModuleItem::FnDef(it) => &it.syntax, 1962 ModuleItem::FnDef(it) => &it.syntax,
1955 ModuleItem::TraitDef(it) => &it.syntax, 1963 ModuleItem::TraitDef(it) => &it.syntax,
@@ -2038,6 +2046,7 @@ impl NeverType {}
2038pub enum NominalDef { 2046pub enum NominalDef {
2039 StructDef(StructDef), 2047 StructDef(StructDef),
2040 EnumDef(EnumDef), 2048 EnumDef(EnumDef),
2049 UnionDef(UnionDef),
2041} 2050}
2042impl From<StructDef> for NominalDef { 2051impl From<StructDef> for NominalDef {
2043 fn from(node: StructDef) -> NominalDef { 2052 fn from(node: StructDef) -> NominalDef {
@@ -2049,10 +2058,15 @@ impl From<EnumDef> for NominalDef {
2049 NominalDef::EnumDef(node) 2058 NominalDef::EnumDef(node)
2050 } 2059 }
2051} 2060}
2061impl From<UnionDef> for NominalDef {
2062 fn from(node: UnionDef) -> NominalDef {
2063 NominalDef::UnionDef(node)
2064 }
2065}
2052impl AstNode for NominalDef { 2066impl AstNode for NominalDef {
2053 fn can_cast(kind: SyntaxKind) -> bool { 2067 fn can_cast(kind: SyntaxKind) -> bool {
2054 match kind { 2068 match kind {
2055 STRUCT_DEF | ENUM_DEF => true, 2069 STRUCT_DEF | ENUM_DEF | UNION_DEF => true,
2056 _ => false, 2070 _ => false,
2057 } 2071 }
2058 } 2072 }
@@ -2060,6 +2074,7 @@ impl AstNode for NominalDef {
2060 let res = match syntax.kind() { 2074 let res = match syntax.kind() {
2061 STRUCT_DEF => NominalDef::StructDef(StructDef { syntax }), 2075 STRUCT_DEF => NominalDef::StructDef(StructDef { syntax }),
2062 ENUM_DEF => NominalDef::EnumDef(EnumDef { syntax }), 2076 ENUM_DEF => NominalDef::EnumDef(EnumDef { syntax }),
2077 UNION_DEF => NominalDef::UnionDef(UnionDef { syntax }),
2063 _ => return None, 2078 _ => return None,
2064 }; 2079 };
2065 Some(res) 2080 Some(res)
@@ -2068,6 +2083,7 @@ impl AstNode for NominalDef {
2068 match self { 2083 match self {
2069 NominalDef::StructDef(it) => &it.syntax, 2084 NominalDef::StructDef(it) => &it.syntax,
2070 NominalDef::EnumDef(it) => &it.syntax, 2085 NominalDef::EnumDef(it) => &it.syntax,
2086 NominalDef::UnionDef(it) => &it.syntax,
2071 } 2087 }
2072 } 2088 }
2073} 2089}
@@ -3789,6 +3805,38 @@ impl AstNode for TypeRef {
3789} 3805}
3790impl TypeRef {} 3806impl TypeRef {}
3791#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3807#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3808pub struct UnionDef {
3809 pub(crate) syntax: SyntaxNode,
3810}
3811impl AstNode for UnionDef {
3812 fn can_cast(kind: SyntaxKind) -> bool {
3813 match kind {
3814 UNION_DEF => true,
3815 _ => false,
3816 }
3817 }
3818 fn cast(syntax: SyntaxNode) -> Option<Self> {
3819 if Self::can_cast(syntax.kind()) {
3820 Some(Self { syntax })
3821 } else {
3822 None
3823 }
3824 }
3825 fn syntax(&self) -> &SyntaxNode {
3826 &self.syntax
3827 }
3828}
3829impl ast::VisibilityOwner for UnionDef {}
3830impl ast::NameOwner for UnionDef {}
3831impl ast::TypeParamsOwner for UnionDef {}
3832impl ast::AttrsOwner for UnionDef {}
3833impl ast::DocCommentsOwner for UnionDef {}
3834impl UnionDef {
3835 pub fn record_field_def_list(&self) -> Option<RecordFieldDefList> {
3836 AstChildren::new(&self.syntax).next()
3837 }
3838}
3839#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3792pub struct UseItem { 3840pub struct UseItem {
3793 pub(crate) syntax: SyntaxNode, 3841 pub(crate) syntax: SyntaxNode,
3794} 3842}
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 88d1dc109..d1be40abe 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -126,6 +126,7 @@ Grammar(
126 "SOURCE_FILE", 126 "SOURCE_FILE",
127 127
128 "STRUCT_DEF", 128 "STRUCT_DEF",
129 "UNION_DEF",
129 "ENUM_DEF", 130 "ENUM_DEF",
130 "FN_DEF", 131 "FN_DEF",
131 "RET_TYPE", 132 "RET_TYPE",
@@ -285,6 +286,16 @@ Grammar(
285 "DocCommentsOwner" 286 "DocCommentsOwner"
286 ] 287 ]
287 ), 288 ),
289 "UnionDef": (
290 traits: [
291 "VisibilityOwner",
292 "NameOwner",
293 "TypeParamsOwner",
294 "AttrsOwner",
295 "DocCommentsOwner"
296 ],
297 options: ["RecordFieldDefList"],
298 ),
288 "RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]), 299 "RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]),
289 "RecordFieldDef": ( 300 "RecordFieldDef": (
290 traits: [ 301 traits: [
@@ -388,7 +399,7 @@ Grammar(
388 ]), 399 ]),
389 400
390 "NominalDef": ( 401 "NominalDef": (
391 enum: ["StructDef", "EnumDef"], 402 enum: ["StructDef", "EnumDef", "UnionDef"],
392 traits: [ 403 traits: [
393 "NameOwner", 404 "NameOwner",
394 "TypeParamsOwner", 405 "TypeParamsOwner",
@@ -396,9 +407,9 @@ Grammar(
396 ], 407 ],
397 ), 408 ),
398 "ModuleItem": ( 409 "ModuleItem": (
399 enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock", 410 enum: ["StructDef", "UnionDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock",
400 "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ], 411 "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ],
401 traits: ["AttrsOwner"] 412 traits: ["AttrsOwner"],
402 ), 413 ),
403 "ImplItem": ( 414 "ImplItem": (
404 enum: ["FnDef", "TypeAliasDef", "ConstDef"], 415 enum: ["FnDef", "TypeAliasDef", "ConstDef"],
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt b/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
index f9ace02ee..9d7982684 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 51) 1SOURCE_FILE@[0; 51)
2 STRUCT_DEF@[0; 12) 2 UNION_DEF@[0; 12)
3 UNION_KW@[0; 5) "union" 3 UNION_KW@[0; 5) "union"
4 WHITESPACE@[5; 6) " " 4 WHITESPACE@[5; 6) " "
5 NAME@[6; 9) 5 NAME@[6; 9)
@@ -9,7 +9,7 @@ SOURCE_FILE@[0; 51)
9 L_CURLY@[10; 11) "{" 9 L_CURLY@[10; 11) "{"
10 R_CURLY@[11; 12) "}" 10 R_CURLY@[11; 12) "}"
11 WHITESPACE@[12; 13) "\n" 11 WHITESPACE@[12; 13) "\n"
12 STRUCT_DEF@[13; 50) 12 UNION_DEF@[13; 50)
13 UNION_KW@[13; 18) "union" 13 UNION_KW@[13; 18) "union"
14 WHITESPACE@[18; 19) " " 14 WHITESPACE@[18; 19) " "
15 NAME@[19; 22) 15 NAME@[19; 22)
diff --git a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
index 3260cc589..90538b90d 100644
--- a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
@@ -1592,7 +1592,7 @@ SOURCE_FILE@[0; 3813)
1592 BLOCK@[2845; 2906) 1592 BLOCK@[2845; 2906)
1593 L_CURLY@[2845; 2846) "{" 1593 L_CURLY@[2845; 2846) "{"
1594 WHITESPACE@[2846; 2851) "\n " 1594 WHITESPACE@[2846; 2851) "\n "
1595 STRUCT_DEF@[2851; 2904) 1595 UNION_DEF@[2851; 2904)
1596 UNION_KW@[2851; 2856) "union" 1596 UNION_KW@[2851; 2856) "union"
1597 WHITESPACE@[2856; 2857) " " 1597 WHITESPACE@[2856; 2857) " "
1598 NAME@[2857; 2862) 1598 NAME@[2857; 2862)