mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-10 07:04:22 +00:00
Merge #2403
2403: Fixme for union fields r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
ecd1204804
27 changed files with 190 additions and 98 deletions
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()?;
|
||||
|
|
|
@ -263,6 +263,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
.clone()
|
||||
.subst(&a_ty.parameters)
|
||||
}),
|
||||
// FIXME:
|
||||
TypeCtor::Adt(Adt::Union(_)) => None,
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
"###)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ")
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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) {
|
|
@ -122,6 +122,7 @@ pub enum SyntaxKind {
|
|||
R_DOLLAR,
|
||||
SOURCE_FILE,
|
||||
STRUCT_DEF,
|
||||
UNION_DEF,
|
||||
ENUM_DEF,
|
||||
FN_DEF,
|
||||
RET_TYPE,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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"],
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue