Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/data/adt.rs')
-rw-r--r--crates/hir-def/src/data/adt.rs412
1 files changed, 0 insertions, 412 deletions
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
deleted file mode 100644
index a54d7663cc..0000000000
--- a/crates/hir-def/src/data/adt.rs
+++ /dev/null
@@ -1,412 +0,0 @@
-//! Defines hir-level representation of structs, enums and unions
-
-use base_db::Crate;
-use bitflags::bitflags;
-use cfg::CfgOptions;
-
-use hir_expand::name::Name;
-use intern::sym;
-use la_arena::Arena;
-use rustc_abi::{IntegerType, ReprOptions};
-use triomphe::Arc;
-
-use crate::{
- EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId,
- db::DefDatabase,
- hir::Expr,
- item_tree::{
- AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId,
- },
- lang_item::LangItem,
- nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
- type_ref::{TypeRefId, TypesMap},
- visibility::RawVisibility,
-};
-
-/// Note that we use `StructData` for unions as well!
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct StructData {
- pub name: Name,
- pub repr: Option<ReprOptions>,
- pub visibility: RawVisibility,
- pub flags: StructFlags,
-}
-
-bitflags! {
- #[derive(Debug, Copy, Clone, PartialEq, Eq)]
- pub struct StructFlags: u8 {
- const NO_FLAGS = 0;
- /// Indicates whether the struct is `PhantomData`.
- const IS_PHANTOM_DATA = 1 << 2;
- /// Indicates whether the struct has a `#[fundamental]` attribute.
- const IS_FUNDAMENTAL = 1 << 3;
- // FIXME: should this be a flag?
- /// Indicates whether the struct has a `#[rustc_has_incoherent_inherent_impls]` attribute.
- const IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL = 1 << 4;
- /// Indicates whether this struct is `Box`.
- const IS_BOX = 1 << 5;
- /// Indicates whether this struct is `ManuallyDrop`.
- const IS_MANUALLY_DROP = 1 << 6;
- /// Indicates whether this struct is `UnsafeCell`.
- const IS_UNSAFE_CELL = 1 << 7;
- }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct EnumData {
- pub name: Name,
- pub repr: Option<ReprOptions>,
- pub visibility: RawVisibility,
- pub rustc_has_incoherent_inherent_impls: bool,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct EnumVariants {
- pub variants: Box<[(EnumVariantId, Name)]>,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct EnumVariantData {
- pub name: Name,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum VariantData {
- Record { fields: Arena<FieldData>, types_map: Arc<TypesMap> },
- Tuple { fields: Arena<FieldData>, types_map: Arc<TypesMap> },
- Unit,
-}
-
-impl VariantData {
- #[inline]
- pub(crate) fn variant_data_query(db: &dyn DefDatabase, id: VariantId) -> Arc<VariantData> {
- db.variant_data_with_diagnostics(id).0
- }
-
- pub(crate) fn variant_data_with_diagnostics_query(
- db: &dyn DefDatabase,
- id: VariantId,
- ) -> (Arc<VariantData>, DefDiagnostics) {
- let (shape, types_map, (fields, diagnostics)) = match id {
- VariantId::EnumVariantId(id) => {
- let loc = id.lookup(db);
- let item_tree = loc.id.item_tree(db);
- let parent = loc.parent.lookup(db);
- let krate = parent.container.krate;
- let variant = &item_tree[loc.id.value];
- (
- variant.shape,
- variant.types_map.clone(),
- lower_fields(
- db,
- krate,
- parent.container.local_id,
- loc.id.tree_id(),
- &item_tree,
- krate.cfg_options(db),
- FieldParent::EnumVariant(loc.id.value),
- &variant.fields,
- Some(item_tree[parent.id.value].visibility),
- ),
- )
- }
- VariantId::StructId(id) => {
- let loc = id.lookup(db);
- let item_tree = loc.id.item_tree(db);
- let krate = loc.container.krate;
- let strukt = &item_tree[loc.id.value];
- (
- strukt.shape,
- strukt.types_map.clone(),
- lower_fields(
- db,
- krate,
- loc.container.local_id,
- loc.id.tree_id(),
- &item_tree,
- krate.cfg_options(db),
- FieldParent::Struct(loc.id.value),
- &strukt.fields,
- None,
- ),
- )
- }
- VariantId::UnionId(id) => {
- let loc = id.lookup(db);
- let item_tree = loc.id.item_tree(db);
- let krate = loc.container.krate;
- let union = &item_tree[loc.id.value];
- (
- FieldsShape::Record,
- union.types_map.clone(),
- lower_fields(
- db,
- krate,
- loc.container.local_id,
- loc.id.tree_id(),
- &item_tree,
- krate.cfg_options(db),
- FieldParent::Union(loc.id.value),
- &union.fields,
- None,
- ),
- )
- }
- };
-
- (
- Arc::new(match shape {
- FieldsShape::Record => VariantData::Record { fields, types_map },
- FieldsShape::Tuple => VariantData::Tuple { fields, types_map },
- FieldsShape::Unit => VariantData::Unit,
- }),
- DefDiagnostics::new(diagnostics),
- )
- }
-}
-
-/// A single field of an enum variant or struct
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct FieldData {
- pub name: Name,
- pub type_ref: TypeRefId,
- pub visibility: RawVisibility,
- pub is_unsafe: bool,
-}
-
-fn repr_from_value(
- db: &dyn DefDatabase,
- krate: Crate,
- item_tree: &ItemTree,
- of: AttrOwner,
-) -> Option<ReprOptions> {
- item_tree.attrs(db, krate, of).repr()
-}
-
-impl StructData {
- #[inline]
- pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
- let loc = id.lookup(db);
- let krate = loc.container.krate;
- let item_tree = loc.id.item_tree(db);
- let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
- let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
-
- let mut flags = StructFlags::NO_FLAGS;
- if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
- flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
- }
- if attrs.by_key(&sym::fundamental).exists() {
- flags |= StructFlags::IS_FUNDAMENTAL;
- }
- if let Some(lang) = attrs.lang_item() {
- match lang {
- LangItem::PhantomData => flags |= StructFlags::IS_PHANTOM_DATA,
- LangItem::OwnedBox => flags |= StructFlags::IS_BOX,
- LangItem::ManuallyDrop => flags |= StructFlags::IS_MANUALLY_DROP,
- LangItem::UnsafeCell => flags |= StructFlags::IS_UNSAFE_CELL,
- _ => (),
- }
- }
-
- let strukt = &item_tree[loc.id.value];
- Arc::new(StructData {
- name: strukt.name.clone(),
- repr,
- visibility: item_tree[strukt.visibility].clone(),
- flags,
- })
- }
-
- #[inline]
- pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
- let loc = id.lookup(db);
- let krate = loc.container.krate;
- let item_tree = loc.id.item_tree(db);
- let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
- let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
- let mut flags = StructFlags::NO_FLAGS;
-
- if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
- flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
- }
- if attrs.by_key(&sym::fundamental).exists() {
- flags |= StructFlags::IS_FUNDAMENTAL;
- }
-
- let union = &item_tree[loc.id.value];
-
- Arc::new(StructData {
- name: union.name.clone(),
- repr,
- visibility: item_tree[union.visibility].clone(),
- flags,
- })
- }
-}
-
-impl EnumVariants {
- pub(crate) fn enum_variants_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumVariants> {
- let loc = e.lookup(db);
- let item_tree = loc.id.item_tree(db);
-
- Arc::new(EnumVariants {
- variants: loc.container.def_map(db).enum_definitions[&e]
- .iter()
- .map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone()))
- .collect(),
- })
- }
-
- pub fn variant(&self, name: &Name) -> Option<EnumVariantId> {
- let &(id, _) = self.variants.iter().find(|(_id, n)| n == name)?;
- Some(id)
- }
-
- // [Adopted from rustc](https://github.com/rust-lang/rust/blob/bd53aa3bf7a24a70d763182303bd75e5fc51a9af/compiler/rustc_middle/src/ty/adt.rs#L446-L448)
- pub fn is_payload_free(&self, db: &dyn DefDatabase) -> bool {
- self.variants.iter().all(|&(v, _)| {
- // The condition check order is slightly modified from rustc
- // to improve performance by early returning with relatively fast checks
- let variant = &db.variant_data(v.into());
- if !variant.fields().is_empty() {
- return false;
- }
- // The outer if condition is whether this variant has const ctor or not
- if !matches!(variant.kind(), StructKind::Unit) {
- let body = db.body(v.into());
- // A variant with explicit discriminant
- if body.exprs[body.body_expr] != Expr::Missing {
- return false;
- }
- }
- true
- })
- }
-}
-
-impl EnumData {
- pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
- let loc = e.lookup(db);
- let krate = loc.container.krate;
- let item_tree = loc.id.item_tree(db);
- let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
- let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
-
- let rustc_has_incoherent_inherent_impls =
- attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
-
- let enum_ = &item_tree[loc.id.value];
-
- Arc::new(EnumData {
- name: enum_.name.clone(),
- repr,
- visibility: item_tree[enum_.visibility].clone(),
- rustc_has_incoherent_inherent_impls,
- })
- }
-
- pub fn variant_body_type(&self) -> IntegerType {
- match self.repr {
- Some(ReprOptions { int: Some(builtin), .. }) => builtin,
- _ => IntegerType::Pointer(true),
- }
- }
-}
-
-impl EnumVariantData {
- #[inline]
- pub(crate) fn enum_variant_data_query(
- db: &dyn DefDatabase,
- e: EnumVariantId,
- ) -> Arc<EnumVariantData> {
- let loc = e.lookup(db);
- let item_tree = loc.id.item_tree(db);
- let variant = &item_tree[loc.id.value];
-
- Arc::new(EnumVariantData { name: variant.name.clone() })
- }
-}
-
-impl VariantData {
- pub fn fields(&self) -> &Arena<FieldData> {
- const EMPTY: &Arena<FieldData> = &Arena::new();
- match self {
- VariantData::Record { fields, .. } | VariantData::Tuple { fields, .. } => fields,
- _ => EMPTY,
- }
- }
-
- pub fn types_map(&self) -> &TypesMap {
- match self {
- VariantData::Record { types_map, .. } | VariantData::Tuple { types_map, .. } => {
- types_map
- }
- VariantData::Unit => TypesMap::EMPTY,
- }
- }
-
- // FIXME: Linear lookup
- pub fn field(&self, name: &Name) -> Option<LocalFieldId> {
- self.fields().iter().find_map(|(id, data)| if &data.name == name { Some(id) } else { None })
- }
-
- pub fn kind(&self) -> StructKind {
- match self {
- VariantData::Record { .. } => StructKind::Record,
- VariantData::Tuple { .. } => StructKind::Tuple,
- VariantData::Unit => StructKind::Unit,
- }
- }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum StructKind {
- Tuple,
- Record,
- Unit,
-}
-
-fn lower_fields(
- db: &dyn DefDatabase,
- krate: Crate,
- container: LocalModuleId,
- tree_id: TreeId,
- item_tree: &ItemTree,
- cfg_options: &CfgOptions,
- parent: FieldParent,
- fields: &[Field],
- override_visibility: Option<RawVisibilityId>,
-) -> (Arena<FieldData>, Vec<DefDiagnostic>) {
- let mut diagnostics = Vec::new();
- let mut arena = Arena::new();
- for (idx, field) in fields.iter().enumerate() {
- let attr_owner = AttrOwner::make_field_indexed(parent, idx);
- let attrs = item_tree.attrs(db, krate, attr_owner);
- if attrs.is_cfg_enabled(cfg_options) {
- arena.alloc(lower_field(item_tree, field, override_visibility));
- } else {
- diagnostics.push(DefDiagnostic::unconfigured_code(
- container,
- tree_id,
- attr_owner,
- attrs.cfg().unwrap(),
- cfg_options.clone(),
- ))
- }
- }
- (arena, diagnostics)
-}
-
-fn lower_field(
- item_tree: &ItemTree,
- field: &Field,
- override_visibility: Option<RawVisibilityId>,
-) -> FieldData {
- FieldData {
- name: field.name.clone(),
- type_ref: field.type_ref,
- visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
- is_unsafe: field.is_unsafe,
- }
-}