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.rs205
1 files changed, 63 insertions, 142 deletions
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
index 8772c34f02..5986b7df3d 100644
--- a/crates/hir-def/src/data/adt.rs
+++ b/crates/hir-def/src/data/adt.rs
@@ -21,15 +21,14 @@ use crate::{
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
lang_item::LangItem,
lower::LowerCtx,
- nameres::diagnostics::DefDiagnostic,
+ nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
src::HasChildSource,
src::HasSource,
trace::Trace,
tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
type_ref::TypeRef,
visibility::RawVisibility,
- EnumId, EnumLoc, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId,
- UnionId, VariantId,
+ EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId,
};
/// Note that we use `StructData` for unions as well!
@@ -43,7 +42,7 @@ pub struct StructData {
}
bitflags! {
-#[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructFlags: u8 {
const NO_FLAGS = 0;
/// Indicates whether the struct is `PhantomData`.
@@ -65,7 +64,7 @@ bitflags! {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumData {
pub name: Name,
- pub variants: Arena<EnumVariantData>,
+ pub variants: Box<[(EnumVariantId, Name)]>,
pub repr: Option<ReprOptions>,
pub visibility: RawVisibility,
pub rustc_has_incoherent_inherent_impls: bool,
@@ -75,7 +74,6 @@ pub struct EnumData {
pub struct EnumVariantData {
pub name: Name,
pub variant_data: Arc<VariantData>,
- pub tree_id: la_arena::Idx<crate::item_tree::Variant>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -182,6 +180,7 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
}
impl StructData {
+ #[inline]
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
db.struct_data_with_diagnostics(id).0
}
@@ -189,7 +188,7 @@ impl StructData {
pub(crate) fn struct_data_with_diagnostics_query(
db: &dyn DefDatabase,
id: StructId,
- ) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
+ ) -> (Arc<StructData>, DefDiagnostics) {
let loc = id.lookup(db);
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
@@ -234,10 +233,11 @@ impl StructData {
visibility: item_tree[strukt.visibility].clone(),
flags,
}),
- diagnostics.into(),
+ DefDiagnostics::new(diagnostics),
)
}
+ #[inline]
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
db.union_data_with_diagnostics(id).0
}
@@ -245,7 +245,7 @@ impl StructData {
pub(crate) fn union_data_with_diagnostics_query(
db: &dyn DefDatabase,
id: UnionId,
- ) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
+ ) -> (Arc<StructData>, DefDiagnostics) {
let loc = id.lookup(db);
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
@@ -280,24 +280,16 @@ impl StructData {
visibility: item_tree[union.visibility].clone(),
flags,
}),
- diagnostics.into(),
+ DefDiagnostics::new(diagnostics),
)
}
}
impl EnumData {
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
- db.enum_data_with_diagnostics(e).0
- }
-
- pub(crate) fn enum_data_with_diagnostics_query(
- db: &dyn DefDatabase,
- e: EnumId,
- ) -> (Arc<EnumData>, Arc<[DefDiagnostic]>) {
let loc = e.lookup(db);
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
- let cfg_options = db.crate_graph()[krate].cfg_options.clone();
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())
@@ -305,53 +297,21 @@ impl EnumData {
.exists();
let enum_ = &item_tree[loc.id.value];
- let mut variants = Arena::new();
- let mut diagnostics = Vec::new();
- for tree_id in enum_.variants.clone() {
- let attrs = item_tree.attrs(db, krate, tree_id.into());
- let var = &item_tree[tree_id];
- if attrs.is_cfg_enabled(&cfg_options) {
- let (var_data, field_diagnostics) = lower_fields(
- db,
- krate,
- loc.id.file_id(),
- loc.container.local_id,
- &item_tree,
- &cfg_options,
- &var.fields,
- Some(enum_.visibility),
- );
- diagnostics.extend(field_diagnostics);
-
- variants.alloc(EnumVariantData {
- name: var.name.clone(),
- variant_data: Arc::new(var_data),
- tree_id,
- });
- } else {
- diagnostics.push(DefDiagnostic::unconfigured_code(
- loc.container.local_id,
- InFile::new(loc.id.file_id(), var.ast_id.erase()),
- attrs.cfg().unwrap(),
- cfg_options.clone(),
- ))
- }
- }
- (
- Arc::new(EnumData {
- name: enum_.name.clone(),
- variants,
- repr,
- visibility: item_tree[enum_.visibility].clone(),
- rustc_has_incoherent_inherent_impls,
- }),
- diagnostics.into(),
- )
+ Arc::new(EnumData {
+ name: enum_.name.clone(),
+ 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,
+ })
}
- pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
- let (id, _) = self.variants.iter().find(|(_id, data)| &data.name == name)?;
+ pub fn variant(&self, name: &Name) -> Option<EnumVariantId> {
+ let &(id, _) = self.variants.iter().find(|(_id, n)| n == name)?;
Some(id)
}
@@ -363,82 +323,48 @@ impl EnumData {
}
}
-impl HasChildSource<LocalEnumVariantId> for EnumId {
- type Value = ast::Variant;
- fn child_source(
- &self,
+impl EnumVariantData {
+ #[inline]
+ pub(crate) fn enum_variant_data_query(
db: &dyn DefDatabase,
- ) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> {
- let loc = &self.lookup(db);
- let src = loc.source(db);
- let mut trace = Trace::new_for_map();
- lower_enum(db, &mut trace, &src, loc);
- src.with_value(trace.into_map())
+ e: EnumVariantId,
+ ) -> Arc<EnumVariantData> {
+ db.enum_variant_data_with_diagnostics(e).0
}
-}
-fn lower_enum(
- db: &dyn DefDatabase,
- trace: &mut Trace<EnumVariantData, ast::Variant>,
- ast: &InFile<ast::Enum>,
- loc: &EnumLoc,
-) {
- let item_tree = loc.id.item_tree(db);
- let krate = loc.container.krate;
-
- let item_tree_variants = item_tree[loc.id.value].variants.clone();
-
- let cfg_options = &db.crate_graph()[krate].cfg_options;
- let variants = ast
- .value
- .variant_list()
- .into_iter()
- .flat_map(|it| it.variants())
- .zip(item_tree_variants)
- .filter(|&(_, item_tree_id)| {
- item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options)
- });
- for (var, item_tree_id) in variants {
- trace.alloc(
- || var.clone(),
- || EnumVariantData {
- name: var.name().map_or_else(Name::missing, |it| it.as_name()),
- variant_data: Arc::new(VariantData::new(
- db,
- ast.with_value(var.kind()),
- loc.container,
- &item_tree,
- item_tree_id,
- )),
- tree_id: item_tree_id,
- },
+ 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 cfg_options = db.crate_graph()[krate].cfg_options.clone();
+ let variant = &item_tree[loc.id.value];
+
+ let (var_data, diagnostics) = lower_fields(
+ db,
+ krate,
+ loc.id.file_id(),
+ container.local_id,
+ &item_tree,
+ &cfg_options,
+ &variant.fields,
+ Some(item_tree[loc.parent.lookup(db).id.value].visibility),
);
+
+ (
+ Arc::new(EnumVariantData {
+ name: variant.name.clone(),
+ variant_data: Arc::new(var_data),
+ }),
+ DefDiagnostics::new(diagnostics),
+ )
}
}
impl VariantData {
- fn new(
- db: &dyn DefDatabase,
- flavor: InFile<ast::StructKind>,
- module_id: ModuleId,
- item_tree: &ItemTree,
- variant: la_arena::Idx<crate::item_tree::Variant>,
- ) -> Self {
- let mut trace = Trace::new_for_arena();
- match lower_struct(
- db,
- &mut trace,
- &flavor,
- module_id.krate,
- item_tree,
- &item_tree[variant].fields,
- ) {
- StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
- StructKind::Record => VariantData::Record(trace.into_arena()),
- StructKind::Unit => VariantData::Unit,
- }
- }
-
pub fn fields(&self) -> &Arena<FieldData> {
const EMPTY: &Arena<FieldData> = &Arena::new();
match &self {
@@ -468,14 +394,13 @@ impl HasChildSource<LocalFieldId> for VariantId {
let item_tree;
let (src, fields, container) = match *self {
VariantId::EnumVariantId(it) => {
- // I don't really like the fact that we call into parent source
- // here, this might add to more queries then necessary.
- let lookup = it.parent.lookup(db);
+ let lookup = it.lookup(db);
item_tree = lookup.id.item_tree(db);
- let src = it.parent.child_source(db);
- let tree_id = db.enum_data(it.parent).variants[it.local_id].tree_id;
- let fields = &item_tree[tree_id].fields;
- (src.map(|map| map[it.local_id].kind()), fields, lookup.container)
+ (
+ lookup.source(db).map(|it| it.kind()),
+ &item_tree[lookup.id.value].fields,
+ lookup.parent.lookup(db).container,
+ )
}
VariantId::StructId(it) => {
let lookup = it.lookup(db);
@@ -490,11 +415,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
let lookup = it.lookup(db);
item_tree = lookup.id.item_tree(db);
(
- lookup.source(db).map(|it| {
- it.record_field_list()
- .map(ast::StructKind::Record)
- .unwrap_or(ast::StructKind::Unit)
- }),
+ lookup.source(db).map(|it| it.kind()),
&item_tree[lookup.id.value].fields,
lookup.container,
)