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.rs369
1 files changed, 144 insertions, 225 deletions
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
index bf8f5024c2..9db66d6e91 100644
--- a/crates/hir-def/src/data/adt.rs
+++ b/crates/hir-def/src/data/adt.rs
@@ -3,18 +3,14 @@
use base_db::Crate;
use bitflags::bitflags;
use cfg::CfgOptions;
-use either::Either;
use hir_expand::name::Name;
use intern::sym;
use la_arena::Arena;
-use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
-use rustc_hashes::Hash64;
+use rustc_abi::{IntegerType, ReprOptions};
use triomphe::Arc;
-use tt::iter::TtElement;
use crate::{
- builtin_type::{BuiltinInt, BuiltinUint},
db::DefDatabase,
hir::Expr,
item_tree::{
@@ -22,7 +18,6 @@ use crate::{
},
lang_item::LangItem,
nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
- tt::{Delimiter, DelimiterKind, Leaf, TopSubtree},
type_ref::{TypeRefId, TypesMap},
visibility::RawVisibility,
EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId,
@@ -32,7 +27,6 @@ use crate::{
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructData {
pub name: Name,
- pub variant_data: Arc<VariantData>,
pub repr: Option<ReprOptions>,
pub visibility: RawVisibility,
pub flags: StructFlags,
@@ -61,16 +55,19 @@ bitflags! {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumData {
pub name: Name,
- pub variants: Box<[(EnumVariantId, 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,
- pub variant_data: Arc<VariantData>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -80,6 +77,94 @@ pub enum VariantData {
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 {
@@ -94,104 +179,12 @@ fn repr_from_value(
item_tree: &ItemTree,
of: AttrOwner,
) -> Option<ReprOptions> {
- item_tree.attrs(db, krate, of).by_key(&sym::repr).tt_values().find_map(parse_repr_tt)
-}
-
-fn parse_repr_tt(tt: &TopSubtree) -> Option<ReprOptions> {
- match tt.top_subtree().delimiter {
- Delimiter { kind: DelimiterKind::Parenthesis, .. } => {}
- _ => return None,
- }
-
- let mut flags = ReprFlags::empty();
- let mut int = None;
- let mut max_align: Option<Align> = None;
- let mut min_pack: Option<Align> = None;
-
- let mut tts = tt.iter();
- while let Some(tt) = tts.next() {
- if let TtElement::Leaf(Leaf::Ident(ident)) = tt {
- flags.insert(match &ident.sym {
- s if *s == sym::packed => {
- let pack = if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() {
- tts.next();
- if let Some(TtElement::Leaf(Leaf::Literal(lit))) = tt_iter.next() {
- lit.symbol.as_str().parse().unwrap_or_default()
- } else {
- 0
- }
- } else {
- 0
- };
- let pack = Align::from_bytes(pack).unwrap_or(Align::ONE);
- min_pack =
- Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack });
- ReprFlags::empty()
- }
- s if *s == sym::align => {
- if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() {
- tts.next();
- if let Some(TtElement::Leaf(Leaf::Literal(lit))) = tt_iter.next() {
- if let Ok(align) = lit.symbol.as_str().parse() {
- let align = Align::from_bytes(align).ok();
- max_align = max_align.max(align);
- }
- }
- }
- ReprFlags::empty()
- }
- s if *s == sym::C => ReprFlags::IS_C,
- s if *s == sym::transparent => ReprFlags::IS_TRANSPARENT,
- s if *s == sym::simd => ReprFlags::IS_SIMD,
- repr => {
- if let Some(builtin) = BuiltinInt::from_suffix_sym(repr)
- .map(Either::Left)
- .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right))
- {
- int = Some(match builtin {
- Either::Left(bi) => match bi {
- BuiltinInt::Isize => IntegerType::Pointer(true),
- BuiltinInt::I8 => IntegerType::Fixed(Integer::I8, true),
- BuiltinInt::I16 => IntegerType::Fixed(Integer::I16, true),
- BuiltinInt::I32 => IntegerType::Fixed(Integer::I32, true),
- BuiltinInt::I64 => IntegerType::Fixed(Integer::I64, true),
- BuiltinInt::I128 => IntegerType::Fixed(Integer::I128, true),
- },
- Either::Right(bu) => match bu {
- BuiltinUint::Usize => IntegerType::Pointer(false),
- BuiltinUint::U8 => IntegerType::Fixed(Integer::I8, false),
- BuiltinUint::U16 => IntegerType::Fixed(Integer::I16, false),
- BuiltinUint::U32 => IntegerType::Fixed(Integer::I32, false),
- BuiltinUint::U64 => IntegerType::Fixed(Integer::I64, false),
- BuiltinUint::U128 => IntegerType::Fixed(Integer::I128, false),
- },
- });
- }
- ReprFlags::empty()
- }
- })
- }
- }
-
- Some(ReprOptions {
- int,
- align: max_align,
- pack: min_pack,
- flags,
- field_shuffle_seed: Hash64::ZERO,
- })
+ item_tree.attrs(db, krate, of).repr()
}
impl StructData {
#[inline]
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
- db.struct_data_with_diagnostics(id).0
- }
-
- pub(crate) fn struct_data_with_diagnostics_query(
- db: &dyn DefDatabase,
- id: StructId,
- ) -> (Arc<StructData>, DefDiagnostics) {
let loc = id.lookup(db);
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
@@ -216,44 +209,16 @@ impl StructData {
}
let strukt = &item_tree[loc.id.value];
- let (fields, diagnostics) = 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,
- );
- let types_map = strukt.types_map.clone();
-
- (
- Arc::new(StructData {
- name: strukt.name.clone(),
- variant_data: Arc::new(match strukt.shape {
- FieldsShape::Record => VariantData::Record { fields, types_map },
- FieldsShape::Tuple => VariantData::Tuple { fields, types_map },
- FieldsShape::Unit => VariantData::Unit,
- }),
- repr,
- visibility: item_tree[strukt.visibility].clone(),
- flags,
- }),
- DefDiagnostics::new(diagnostics),
- )
+ 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> {
- db.union_data_with_diagnostics(id).0
- }
-
- pub(crate) fn union_data_with_diagnostics_query(
- db: &dyn DefDatabase,
- id: UnionId,
- ) -> (Arc<StructData>, DefDiagnostics) {
let loc = id.lookup(db);
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
@@ -268,53 +233,26 @@ impl StructData {
}
let union = &item_tree[loc.id.value];
- let (fields, diagnostics) = 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,
- );
- let types_map = union.types_map.clone();
- (
- Arc::new(StructData {
- name: union.name.clone(),
- variant_data: Arc::new(VariantData::Record { fields, types_map }),
- repr,
- visibility: item_tree[union.visibility].clone(),
- flags,
- }),
- DefDiagnostics::new(diagnostics),
- )
+
+ Arc::new(StructData {
+ name: union.name.clone(),
+ repr,
+ visibility: item_tree[union.visibility].clone(),
+ flags,
+ })
}
}
-impl EnumData {
- pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
+impl EnumVariants {
+ pub(crate) fn enum_variants_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumVariants> {
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 rustc_has_incoherent_inherent_impls = item_tree
- .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
- .by_key(&sym::rustc_has_incoherent_inherent_impls)
- .exists();
-
- let enum_ = &item_tree[loc.id.value];
- Arc::new(EnumData {
- name: enum_.name.clone(),
+ 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(),
- repr,
- visibility: item_tree[enum_.visibility].clone(),
- rustc_has_incoherent_inherent_impls,
})
}
@@ -323,25 +261,18 @@ impl EnumData {
Some(id)
}
- pub fn variant_body_type(&self) -> IntegerType {
- match self.repr {
- Some(ReprOptions { int: Some(builtin), .. }) => builtin,
- _ => IntegerType::Pointer(true),
- }
- }
-
// [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, _)| {
+ 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.enum_variant_data(*v).variant_data;
+ 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());
+ let body = db.body(v.into());
// A variant with explicit discriminant
if body.exprs[body.body_expr] != Expr::Missing {
return false;
@@ -352,49 +283,46 @@ impl EnumData {
}
}
+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 rustc_has_incoherent_inherent_impls = item_tree
+ .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
+ .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> {
- db.enum_variant_data_with_diagnostics(e).0
- }
-
- pub(crate) fn enum_variant_data_with_diagnostics_query(
- db: &dyn DefDatabase,
- e: EnumVariantId,
- ) -> (Arc<EnumVariantData>, DefDiagnostics) {
let loc = e.lookup(db);
- let container = loc.parent.lookup(db).container;
- let krate = container.krate;
let item_tree = loc.id.item_tree(db);
let variant = &item_tree[loc.id.value];
- let (fields, diagnostics) = lower_fields(
- db,
- krate,
- container.local_id,
- loc.id.tree_id(),
- &item_tree,
- krate.cfg_options(db),
- FieldParent::Variant(loc.id.value),
- &variant.fields,
- Some(item_tree[loc.parent.lookup(db).id.value].visibility),
- );
- let types_map = variant.types_map.clone();
-
- (
- Arc::new(EnumVariantData {
- name: variant.name.clone(),
- variant_data: Arc::new(match variant.shape {
- FieldsShape::Record => VariantData::Record { fields, types_map },
- FieldsShape::Tuple => VariantData::Tuple { fields, types_map },
- FieldsShape::Unit => VariantData::Unit,
- }),
- }),
- DefDiagnostics::new(diagnostics),
- )
+ Arc::new(EnumVariantData { name: variant.name.clone() })
}
}
@@ -428,15 +356,6 @@ impl VariantData {
VariantData::Unit => StructKind::Unit,
}
}
-
- #[allow(clippy::self_named_constructors)]
- pub(crate) fn variant_data(db: &dyn DefDatabase, id: VariantId) -> Arc<VariantData> {
- match id {
- VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
- VariantId::EnumVariantId(it) => db.enum_variant_data(it).variant_data.clone(),
- VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
- }
- }
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]