Unnamed repository; edit this file 'description' to name the repository.
Split enum variants out of `enum_data` query
Lukas Wirth 2025-03-14
parent dff1896 · commit 8e8d997
-rw-r--r--crates/hir-def/src/data/adt.rs60
-rw-r--r--crates/hir-def/src/db.rs5
-rw-r--r--crates/hir-ty/src/chalk_db.rs2
-rw-r--r--crates/hir-ty/src/consteval.rs2
-rw-r--r--crates/hir-ty/src/diagnostics/decl_check.rs2
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs2
-rw-r--r--crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs4
-rw-r--r--crates/hir-ty/src/drop.rs2
-rw-r--r--crates/hir-ty/src/infer.rs4
-rw-r--r--crates/hir-ty/src/infer/cast.rs2
-rw-r--r--crates/hir-ty/src/infer/closure.rs2
-rw-r--r--crates/hir-ty/src/infer/path.rs2
-rw-r--r--crates/hir-ty/src/inhabitedness.rs2
-rw-r--r--crates/hir-ty/src/layout/adt.rs8
-rw-r--r--crates/hir-ty/src/mir/eval.rs5
-rw-r--r--crates/hir-ty/src/tests.rs2
-rw-r--r--crates/hir-ty/src/utils.rs6
-rw-r--r--crates/hir-ty/src/variance.rs2
-rw-r--r--crates/hir/src/lib.rs6
-rw-r--r--crates/hir/src/semantics/child_by_source.rs2
-rw-r--r--crates/ide-completion/src/completions/pattern.rs4
21 files changed, 74 insertions, 52 deletions
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
index 161b205c80..c8429d8b68 100644
--- a/crates/hir-def/src/data/adt.rs
+++ b/crates/hir-def/src/data/adt.rs
@@ -56,13 +56,17 @@ 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>,
@@ -203,28 +207,16 @@ impl StructData {
}
}
-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,
})
}
@@ -233,13 +225,6 @@ 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, _)| {
@@ -262,6 +247,35 @@ 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(
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index ff33056538..bc9fc8e079 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -11,7 +11,7 @@ use triomphe::Arc;
use crate::{
attr::{Attrs, AttrsWithOwner},
data::{
- adt::{EnumData, EnumVariantData, StructData, VariantData},
+ adt::{EnumData, EnumVariantData, EnumVariants, StructData, VariantData},
ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData,
ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData,
},
@@ -167,6 +167,9 @@ pub trait DefDatabase:
#[salsa::invoke_actual(EnumData::enum_data_query)]
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
+ #[salsa::invoke_actual(EnumVariants::enum_variants_query)]
+ fn enum_variants(&self, e: EnumId) -> Arc<EnumVariants>;
+
#[salsa::transparent]
#[salsa::invoke_actual(EnumVariantData::enum_variant_data_query)]
fn enum_variant_data(&self, id: EnumVariantId) -> Arc<EnumVariantData>;
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index e5751a394d..ac4d1babd6 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -801,7 +801,7 @@ pub(crate) fn adt_datum_query(
}
hir_def::AdtId::EnumId(id) => {
let variants = db
- .enum_data(id)
+ .enum_variants(id)
.variants
.iter()
.map(|&(variant_id, _)| variant_id_to_fields(variant_id.into()))
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 525672bc39..ec8f9b7c31 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -309,7 +309,7 @@ pub(crate) fn const_eval_discriminant_variant(
let value = match prev_idx {
Some(prev_idx) => {
1 + db.const_eval_discriminant(
- db.enum_data(loc.parent).variants[prev_idx as usize].0,
+ db.enum_variants(loc.parent).variants[prev_idx as usize].0,
)?
}
_ => 0,
diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs
index a0b1fe32ce..0b21ae7ade 100644
--- a/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -394,7 +394,7 @@ impl<'a> DeclValidator<'a> {
/// Check incorrect names for enum variants.
fn validate_enum_variants(&mut self, enum_id: EnumId) {
- let data = self.db.enum_data(enum_id);
+ let data = self.db.enum_variants(enum_id);
for (variant_id, _) in data.variants.iter() {
self.validate_enum_variant_fields(*variant_id);
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index 1035651692..6096439565 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -642,7 +642,7 @@ fn missing_match_arms<'p>(
}
let non_empty_enum = match scrut_ty.as_adt() {
- Some((AdtId::EnumId(e), _)) => !cx.db.enum_data(e).variants.is_empty(),
+ Some((AdtId::EnumId(e), _)) => !cx.db.enum_variants(e).variants.is_empty(),
_ => false,
};
let display_target = DisplayTarget::from_crate(cx.db, krate);
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 91eb59fb31..b7f8a0c610 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -49,7 +49,7 @@ impl EnumVariantContiguousIndex {
}
fn to_enum_variant_id(self, db: &dyn HirDatabase, eid: EnumId) -> EnumVariantId {
- db.enum_data(eid).variants[self.0].0
+ db.enum_variants(eid).variants[self.0].0
}
}
@@ -449,7 +449,7 @@ impl PatCx for MatchCheckCtx<'_> {
TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(),
TyKind::Array(..) | TyKind::Slice(..) => unhandled(),
&TyKind::Adt(AdtId(adt @ hir_def::AdtId::EnumId(enum_id)), ref subst) => {
- let enum_data = cx.db.enum_data(enum_id);
+ let enum_data = cx.db.enum_variants(enum_id);
let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive(adt);
if enum_data.variants.is_empty() && !is_declared_nonexhaustive {
diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs
index 4ad16cf8bc..ab17f86b5b 100644
--- a/crates/hir-ty/src/drop.rs
+++ b/crates/hir-ty/src/drop.rs
@@ -72,7 +72,7 @@ pub(crate) fn has_drop_glue(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironm
// Unions cannot have fields with destructors.
AdtId::UnionId(_) => DropGlue::None,
AdtId::EnumId(id) => db
- .enum_data(id)
+ .enum_variants(id)
.variants
.iter()
.map(|&(variant, _)| {
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 9a4b7af85d..ecadfccf00 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -1587,7 +1587,7 @@ impl<'a> InferenceContext<'a> {
// If we can resolve to an enum variant, it takes priority over associated type
// of the same name.
if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
- let enum_data = self.db.enum_data(id);
+ let enum_data = self.db.enum_variants(id);
if let Some(variant) = enum_data.variant(current_segment.name) {
return if remaining_segments.len() == 1 {
(ty, Some(variant.into()))
@@ -1701,7 +1701,7 @@ impl<'a> InferenceContext<'a> {
let segment = path.segments().last().unwrap();
// this could be an enum variant or associated type
if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
- let enum_data = self.db.enum_data(enum_id);
+ let enum_data = self.db.enum_variants(enum_id);
if let Some(variant) = enum_data.variant(segment) {
return (ty, Some(variant.into()));
}
diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs
index eb193686e9..6c0e0b0273 100644
--- a/crates/hir-ty/src/infer/cast.rs
+++ b/crates/hir-ty/src/infer/cast.rs
@@ -43,7 +43,7 @@ impl CastTy {
let (AdtId::EnumId(id), _) = t.as_adt()? else {
return None;
};
- let enum_data = table.db.enum_data(id);
+ let enum_data = table.db.enum_variants(id);
if enum_data.is_payload_free(table.db.upcast()) {
Some(Self::Int(Int::CEnum))
} else {
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index ef02762c80..6c50f056c1 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -963,7 +963,7 @@ impl InferenceContext<'_> {
if let Some(variant) = self.result.variant_resolution_for_pat(p) {
let adt = variant.adt_id(self.db.upcast());
let is_multivariant = match adt {
- hir_def::AdtId::EnumId(e) => self.db.enum_data(e).variants.len() != 1,
+ hir_def::AdtId::EnumId(e) => self.db.enum_variants(e).variants.len() != 1,
_ => false,
};
if is_multivariant {
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 29f455a61b..8ff0cf3082 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -398,7 +398,7 @@ impl InferenceContext<'_> {
Some((AdtId::EnumId(e), subst)) => (e, subst),
_ => return None,
};
- let enum_data = self.db.enum_data(enum_id);
+ let enum_data = self.db.enum_variants(enum_id);
let variant = enum_data.variant(name)?;
self.write_variant_resolution(id, variant.into());
Some((ValueNs::EnumVariantId(variant), subst.clone()))
diff --git a/crates/hir-ty/src/inhabitedness.rs b/crates/hir-ty/src/inhabitedness.rs
index d6039c548b..800ba0d454 100644
--- a/crates/hir-ty/src/inhabitedness.rs
+++ b/crates/hir-ty/src/inhabitedness.rs
@@ -98,7 +98,7 @@ impl UninhabitedFrom<'_> {
AdtId::UnionId(_) => CONTINUE_OPAQUELY_INHABITED,
AdtId::StructId(s) => self.visit_variant(s.into(), subst),
AdtId::EnumId(e) => {
- let enum_data = self.db.enum_data(e);
+ let enum_data = self.db.enum_variants(e);
for &(variant, _) in enum_data.variants.iter() {
let variant_inhabitedness = self.visit_variant(variant.into(), subst);
diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs
index ab9c07779c..40a1d4e670 100644
--- a/crates/hir-ty/src/layout/adt.rs
+++ b/crates/hir-ty/src/layout/adt.rs
@@ -54,13 +54,13 @@ pub fn layout_of_adt_query(
(r, data.repr.unwrap_or_default())
}
AdtId::EnumId(e) => {
- let data = db.enum_data(e);
- let r = data
+ let variants = db.enum_variants(e);
+ let r = variants
.variants
.iter()
.map(|&(v, _)| handle_variant(v.into(), &db.enum_variant_data(v).variant_data))
.collect::<Result<SmallVec<_>, _>>()?;
- (r, data.repr.unwrap_or_default())
+ (r, db.enum_data(e).repr.unwrap_or_default())
}
};
let variants = variants
@@ -80,7 +80,7 @@ pub fn layout_of_adt_query(
|min, max| repr_discr(dl, &repr, min, max).unwrap_or((Integer::I8, false)),
variants.iter_enumerated().filter_map(|(id, _)| {
let AdtId::EnumId(e) = def else { return None };
- let d = db.const_eval_discriminant(db.enum_data(e).variants[id.0].0).ok()?;
+ let d = db.const_eval_discriminant(db.enum_variants(e).variants[id.0].0).ok()?;
Some((id, d))
}),
// FIXME: The current code for niche-filling relies on variant indices
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 97710aab06..25aa260655 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -1641,7 +1641,8 @@ impl Evaluator<'_> {
match &layout.variants {
Variants::Empty => unreachable!(),
Variants::Single { index } => {
- let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?;
+ let r =
+ self.const_eval_discriminant(self.db.enum_variants(e).variants[index.0].0)?;
Ok(r)
}
Variants::Multiple { tag, tag_encoding, variants, .. } => {
@@ -1666,7 +1667,7 @@ impl Evaluator<'_> {
.unwrap_or(*untagged_variant)
.0;
let result =
- self.const_eval_discriminant(self.db.enum_data(e).variants[idx].0)?;
+ self.const_eval_discriminant(self.db.enum_variants(e).variants[idx].0)?;
Ok(result)
}
}
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index 9ad07922fa..13d74264c5 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -481,7 +481,7 @@ pub(crate) fn visit_module(
visit_body(db, &body, cb);
}
ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => {
- db.enum_data(it).variants.iter().for_each(|&(it, _)| {
+ db.enum_variants(it).variants.iter().for_each(|&(it, _)| {
let body = db.body(it.into());
cb(it.into());
visit_body(db, &body, cb);
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index cbb78ef40d..3bd04b21b2 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -369,7 +369,7 @@ pub(crate) fn detect_variant_from_bytes<'a>(
let (var_id, var_layout) = match &layout.variants {
hir_def::layout::Variants::Empty => unreachable!(),
hir_def::layout::Variants::Single { index } => {
- (db.enum_data(e).variants[index.0].0, layout)
+ (db.enum_variants(e).variants[index.0].0, layout)
}
hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => {
let size = tag.size(target_data_layout).bytes_usize();
@@ -379,7 +379,7 @@ pub(crate) fn detect_variant_from_bytes<'a>(
TagEncoding::Direct => {
let (var_idx, layout) =
variants.iter_enumerated().find_map(|(var_idx, v)| {
- let def = db.enum_data(e).variants[var_idx.0].0;
+ let def = db.enum_variants(e).variants[var_idx.0].0;
(db.const_eval_discriminant(def) == Ok(tag)).then_some((def, v))
})?;
(var_idx, layout)
@@ -392,7 +392,7 @@ pub(crate) fn detect_variant_from_bytes<'a>(
.filter(|x| x != untagged_variant)
.nth(candidate_tag)
.unwrap_or(*untagged_variant);
- (db.enum_data(e).variants[variant.0].0, &variants[variant])
+ (db.enum_variants(e).variants[variant.0].0, &variants[variant])
}
}
}
diff --git a/crates/hir-ty/src/variance.rs b/crates/hir-ty/src/variance.rs
index 425196d92f..ab3d098908 100644
--- a/crates/hir-ty/src/variance.rs
+++ b/crates/hir-ty/src/variance.rs
@@ -206,7 +206,7 @@ impl Context<'_> {
AdtId::StructId(s) => add_constraints_from_variant(VariantId::StructId(s)),
AdtId::UnionId(u) => add_constraints_from_variant(VariantId::UnionId(u)),
AdtId::EnumId(e) => {
- db.enum_data(e).variants.iter().for_each(|&(variant, _)| {
+ db.enum_variants(e).variants.iter().for_each(|&(variant, _)| {
add_constraints_from_variant(VariantId::EnumVariantId(variant))
});
}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 5cc330fb38..f78b7a5c43 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1519,7 +1519,11 @@ impl Enum {
}
pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
- db.enum_data(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect()
+ db.enum_variants(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect()
+ }
+
+ pub fn num_variants(self, db: &dyn HirDatabase) -> usize {
+ db.enum_variants(self.id).variants.len()
}
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs
index 556b21124d..b89d332238 100644
--- a/crates/hir/src/semantics/child_by_source.rs
+++ b/crates/hir/src/semantics/child_by_source.rs
@@ -182,7 +182,7 @@ impl ChildBySource for EnumId {
let tree = loc.id.item_tree(db);
let ast_id_map = db.ast_id_map(loc.id.file_id());
- db.enum_data(*self).variants.iter().for_each(|&(variant, _)| {
+ db.enum_variants(*self).variants.iter().for_each(|&(variant, _)| {
res[keys::ENUM_VARIANT]
.insert(ast_id_map.get(tree[variant.lookup(db).id.value].ast_id), variant);
});
diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs
index 8f38e02ed7..9df13c5a4e 100644
--- a/crates/ide-completion/src/completions/pattern.rs
+++ b/crates/ide-completion/src/completions/pattern.rs
@@ -1,6 +1,6 @@
//! Completes constants and paths in unqualified patterns.
-use hir::{db::DefDatabase, AssocItem, ScopeDef};
+use hir::{AssocItem, ScopeDef};
use ide_db::syntax_helpers::suggest_name;
use syntax::ast::Pat;
@@ -60,7 +60,7 @@ pub(crate) fn complete_pattern(
}
let refutable = pattern_ctx.refutability == PatternRefutability::Refutable;
- let single_variant_enum = |enum_: hir::Enum| ctx.db.enum_data(enum_.into()).variants.len() == 1;
+ let single_variant_enum = |enum_: hir::Enum| enum_.num_variants(ctx.db) == 1;
if let Some(hir::Adt::Enum(e)) =
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())