2403: Fixme for union fields r=matklad a=matklad



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2019-11-25 14:51:17 +00:00 committed by GitHub
commit ecd1204804
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 190 additions and 98 deletions

View 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,
};

View 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 {

View file

@ -51,13 +51,13 @@ impl HasSource for StructField {
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 {

View 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 {

View file

@ -858,7 +858,7 @@ impl HirDisplay for ApplicationTy {
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);

View file

@ -246,7 +246,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
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()?;

View file

@ -263,6 +263,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
.clone()
.subst(&a_ty.parameters)
}),
// FIXME:
TypeCtor::Adt(Adt::Union(_)) => None,
_ => None,
},
_ => None,

View file

@ -560,7 +560,8 @@ 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::UnionId(it) => (it.resolver(db), db.union_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 +819,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,
}
}

View file

@ -12,7 +12,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
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,12 @@ impl HasChildSource for VariantId {
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()),
VariantId::UnionId(it) => it.source(db).map(|it| {
it.record_field_def_list()
.map(ast::StructKind::Record)
.unwrap_or(ast::StructKind::Unit)
}),
};
let mut trace = Trace::new_for_map();
lower_struct(&mut trace, &src.value);

View file

@ -54,9 +54,9 @@ impl 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),

View file

@ -18,8 +18,8 @@ use crate::{
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 @@ pub trait DefDatabase: InternDatabase + AstDatabase {
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>;

View file

@ -47,9 +47,9 @@ impl Documentation {
}
}
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);

View file

@ -60,10 +60,8 @@ impl GenericParams {
// 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

View file

@ -141,30 +141,26 @@ impl Lookup for FunctionId {
}
#[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)
}
}
@ -435,6 +431,7 @@ impl_froms!(
pub enum VariantId {
EnumVariantId(EnumVariantId),
StructId(StructId),
UnionId(UnionId),
}
impl_froms!(VariantId: EnumVariantId, StructId);
@ -485,8 +482,8 @@ impl HasModule for ConstLoc {
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),
}
}

View file

@ -25,7 +25,7 @@ use crate::{
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 @@ where
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) => {

View 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 @@ impl RawItemsCollector {
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())

View file

@ -82,6 +82,12 @@ fn crate_def_map_smoke_test() {
//- /foo/bar.rs
pub struct Baz;
union U {
to_be: bool,
not_to_be: u8,
}
enum E { V }
",
);
@ -99,6 +105,7 @@ fn crate_def_map_smoke_test() {
crate::foo::bar
Baz: t v
E: t
U: t v
"###)
}

View file

@ -19,6 +19,12 @@ impl ShortLabel for ast::StructDef {
}
}
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 ")

View 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();

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::{
adt::{enum_variant_list, record_field_def_list},
expressions::{match_arm_list, record_field_list},
nominal::{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

@ -196,17 +196,6 @@ impl 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)
}

View file

@ -1856,6 +1856,7 @@ impl Module {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ModuleItem {
StructDef(StructDef),
UnionDef(UnionDef),
EnumDef(EnumDef),
FnDef(FnDef),
TraitDef(TraitDef),
@ -1872,6 +1873,11 @@ impl From<StructDef> for 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 @@ impl From<Module> for 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 @@ impl AstNode for ModuleItem {
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 @@ impl From<EnumDef> for 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 @@ impl AstNode for NominalDef {
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 @@ impl AstNode for NominalDef {
match self {
NominalDef::StructDef(it) => &it.syntax,
NominalDef::EnumDef(it) => &it.syntax,
NominalDef::UnionDef(it) => &it.syntax,
}
}
}
@ -3789,6 +3805,38 @@ impl AstNode for TypeRef {
}
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 {
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,
}

View file

@ -126,6 +126,7 @@ Grammar(
"SOURCE_FILE",
"STRUCT_DEF",
"UNION_DEF",
"ENUM_DEF",
"FN_DEF",
"RET_TYPE",
@ -285,6 +286,16 @@ Grammar(
"DocCommentsOwner"
]
),
"UnionDef": (
traits: [
"VisibilityOwner",
"NameOwner",
"TypeParamsOwner",
"AttrsOwner",
"DocCommentsOwner"
],
options: ["RecordFieldDefList"],
),
"RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]),
"RecordFieldDef": (
traits: [
@ -388,7 +399,7 @@ Grammar(
]),
"NominalDef": (
enum: ["StructDef", "EnumDef"],
enum: ["StructDef", "EnumDef", "UnionDef"],
traits: [
"NameOwner",
"TypeParamsOwner",
@ -396,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"],

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)