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,
};
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> {
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 {
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 {
//! 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},
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 {
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);
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()?;
variant_id: VariantId,
) -> Arc<ArenaMap<LocalStructFieldId, Ty>> {
let (resolver, var_data) = match variant_id {
- VariantId::StructId(it) => (it.resolver(db), db.struct_data(it.0).variant_data.clone()),
+ VariantId::StructId(it) => (it.resolver(db), db.struct_data(it).variant_data.clone()),
VariantId::EnumVariantId(it) => (
it.parent.resolver(db),
db.enum_data(it.parent).variants[it.local_id].variant_data.clone(),
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,
}
}
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!
}
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 {
let src = it.parent.child_source(db);
src.map(|map| map[it.local_id].kind())
}
- VariantId::StructId(it) => it.0.source(db).map(|it| it.kind()),
+ VariantId::StructId(it) => it.source(db).map(|it| it.kind()),
};
let mut trace = Trace::new_for_map();
lower_struct(&mut trace, &src.value);
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),
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)]
#[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]
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>;
}
}
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);
// 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
}
#[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)
}
}
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),
}
}
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 {
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) => {
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>),
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())
//- /foo/bar.rs
pub struct Baz;
+
+ union U {
+ to_be: bool,
+ not_to_be: u8,
+ }
+
enum E { V }
",
);
⋮crate::foo::bar
⋮Baz: t v
⋮E: t
+ ⋮U: t v
"###)
}
}
}
+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 ")
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();
mod use_item;
pub(crate) use self::{
- expressions::{match_arm_list, record_field_list},
adt::{enum_variant_list, record_field_def_list},
+ expressions::{match_arm_list, record_field_list},
traits::{impl_item_list, trait_item_list},
use_item::use_tree_list,
};
}
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)
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ModuleItem {
StructDef(StructDef),
+ UnionDef(UnionDef),
EnumDef(EnumDef),
FnDef(FnDef),
TraitDef(TraitDef),
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)
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 }),
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,
pub enum NominalDef {
StructDef(StructDef),
EnumDef(EnumDef),
+ UnionDef(UnionDef),
}
impl From<StructDef> for NominalDef {
fn from(node: StructDef) -> 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,
}
}
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)
match self {
NominalDef::StructDef(it) => &it.syntax,
NominalDef::EnumDef(it) => &it.syntax,
+ NominalDef::UnionDef(it) => &it.syntax,
}
}
}
impl ast::TypeParamsOwner for UnionDef {}
impl ast::AttrsOwner for UnionDef {}
impl ast::DocCommentsOwner for UnionDef {}
-impl UnionDef {}
+impl UnionDef {
+ pub fn record_field_def_list(&self) -> Option<RecordFieldDefList> {
+ AstChildren::new(&self.syntax).next()
+ }
+}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UseItem {
pub(crate) syntax: SyntaxNode,
"TypeParamsOwner",
"AttrsOwner",
"DocCommentsOwner"
- ]
+ ],
+ options: ["RecordFieldDefList"],
),
"RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]),
"RecordFieldDef": (
]),
"NominalDef": (
- enum: ["StructDef", "EnumDef"],
+ enum: ["StructDef", "EnumDef", "UnionDef"],
traits: [
"NameOwner",
"TypeParamsOwner",
],
),
"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"],