mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 06:11:35 +00:00
Auto merge of #16351 - Veykril:eager-enum-variant, r=Veykril
internal: Eagerly lower enum variants in CrateDefMap construction
This commit is contained in:
commit
5df53c9612
54 changed files with 675 additions and 711 deletions
|
@ -10,7 +10,7 @@ use hir_def::{
|
|||
type_ref::LiteralConstRef,
|
||||
ConstBlockLoc, EnumVariantId, GeneralConstId, StaticId,
|
||||
};
|
||||
use la_arena::{Idx, RawIdx};
|
||||
use hir_expand::Lookup;
|
||||
use stdx::never;
|
||||
use triomphe::Arc;
|
||||
|
||||
|
@ -256,12 +256,13 @@ pub(crate) fn const_eval_discriminant_variant(
|
|||
let def = variant_id.into();
|
||||
let body = db.body(def);
|
||||
if body.exprs[body.body_expr] == Expr::Missing {
|
||||
let prev_idx: u32 = variant_id.local_id.into_raw().into();
|
||||
let prev_idx = prev_idx.checked_sub(1).map(RawIdx::from).map(Idx::from_raw);
|
||||
let loc = variant_id.lookup(db.upcast());
|
||||
let prev_idx = loc.index.checked_sub(1);
|
||||
let value = match prev_idx {
|
||||
Some(local_id) => {
|
||||
let prev_variant = EnumVariantId { local_id, parent: variant_id.parent };
|
||||
1 + db.const_eval_discriminant(prev_variant)?
|
||||
Some(prev_idx) => {
|
||||
1 + db.const_eval_discriminant(
|
||||
db.enum_data(loc.parent).variants[prev_idx as usize].0,
|
||||
)?
|
||||
}
|
||||
_ => 0,
|
||||
};
|
||||
|
|
|
@ -292,7 +292,7 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
|
|||
.display(db.upcast())
|
||||
.to_string(),
|
||||
DefWithBodyId::VariantId(it) => {
|
||||
db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()).to_string()
|
||||
db.enum_variant_data(it).name.display(db.upcast()).to_string()
|
||||
}
|
||||
DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
|
||||
});
|
||||
|
|
|
@ -582,11 +582,11 @@ impl<'a> DeclValidator<'a> {
|
|||
// Check the field names.
|
||||
let enum_fields_replacements = data
|
||||
.variants
|
||||
.values()
|
||||
.filter_map(|variant| {
|
||||
.iter()
|
||||
.filter_map(|(_, name)| {
|
||||
Some(Replacement {
|
||||
current_name: variant.name.clone(),
|
||||
suggested_text: to_camel_case(&variant.name.to_smol_str())?,
|
||||
current_name: name.clone(),
|
||||
suggested_text: to_camel_case(&name.to_smol_str())?,
|
||||
expected_case: CaseType::UpperCamelCase,
|
||||
})
|
||||
})
|
||||
|
|
|
@ -318,8 +318,7 @@ impl HirDisplay for Pat {
|
|||
if let Some(variant) = variant {
|
||||
match variant {
|
||||
VariantId::EnumVariantId(v) => {
|
||||
let data = f.db.enum_data(v.parent);
|
||||
write!(f, "{}", data.variants[v.local_id].name.display(f.db.upcast()))?;
|
||||
write!(f, "{}", f.db.enum_variant_data(v).name.display(f.db.upcast()))?;
|
||||
}
|
||||
VariantId::StructId(s) => {
|
||||
write!(f, "{}", f.db.struct_data(s).name.display(f.db.upcast()))?
|
||||
|
|
|
@ -594,7 +594,7 @@ impl SplitWildcard {
|
|||
let mut ctors: SmallVec<[_; 1]> = enum_data
|
||||
.variants
|
||||
.iter()
|
||||
.map(|(local_id, _)| EnumVariantId { parent: *enum_id, local_id })
|
||||
.map(|&(variant, _)| variant)
|
||||
.filter(|&variant| {
|
||||
// If `exhaustive_patterns` is enabled, we exclude variants known to be
|
||||
// uninhabited.
|
||||
|
|
|
@ -20,8 +20,7 @@ use hir_def::{
|
|||
path::{Path, PathKind},
|
||||
type_ref::{TraitBoundModifier, TypeBound, TypeRef},
|
||||
visibility::Visibility,
|
||||
EnumVariantId, HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId,
|
||||
TraitId,
|
||||
HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, TraitId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use intern::{Internable, Interned};
|
||||
|
@ -613,10 +612,9 @@ fn render_const_scalar(
|
|||
else {
|
||||
return f.write_str("<failed-to-detect-variant>");
|
||||
};
|
||||
let data = &f.db.enum_data(e).variants[var_id];
|
||||
let data = f.db.enum_variant_data(var_id);
|
||||
write!(f, "{}", data.name.display(f.db.upcast()))?;
|
||||
let field_types =
|
||||
f.db.field_types(EnumVariantId { parent: e, local_id: var_id }.into());
|
||||
let field_types = f.db.field_types(var_id.into());
|
||||
render_variant_after_name(
|
||||
&data.variant_data,
|
||||
f,
|
||||
|
@ -892,11 +890,9 @@ impl HirDisplay for Ty {
|
|||
CallableDefId::StructId(s) => {
|
||||
write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))?
|
||||
}
|
||||
CallableDefId::EnumVariantId(e) => write!(
|
||||
f,
|
||||
"{}",
|
||||
db.enum_data(e.parent).variants[e.local_id].name.display(f.db.upcast())
|
||||
)?,
|
||||
CallableDefId::EnumVariantId(e) => {
|
||||
write!(f, "{}", db.enum_variant_data(e).name.display(f.db.upcast()))?
|
||||
}
|
||||
};
|
||||
f.end_location_link();
|
||||
if parameters.len(Interner) > 0 {
|
||||
|
|
|
@ -40,8 +40,8 @@ use hir_def::{
|
|||
path::{ModPath, Path},
|
||||
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
|
||||
type_ref::TypeRef,
|
||||
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, ItemContainerId, Lookup,
|
||||
TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId,
|
||||
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
|
||||
TupleFieldId, TupleId, TypeAliasId, VariantId,
|
||||
};
|
||||
use hir_expand::name::{name, Name};
|
||||
use indexmap::IndexSet;
|
||||
|
@ -87,28 +87,30 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
|
|||
DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
|
||||
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
|
||||
DefWithBodyId::VariantId(v) => {
|
||||
ctx.return_ty = TyBuilder::builtin(match db.enum_data(v.parent).variant_body_type() {
|
||||
hir_def::layout::IntegerType::Pointer(signed) => match signed {
|
||||
true => BuiltinType::Int(BuiltinInt::Isize),
|
||||
false => BuiltinType::Uint(BuiltinUint::Usize),
|
||||
ctx.return_ty = TyBuilder::builtin(
|
||||
match db.enum_data(v.lookup(db.upcast()).parent.into()).variant_body_type() {
|
||||
hir_def::layout::IntegerType::Pointer(signed) => match signed {
|
||||
true => BuiltinType::Int(BuiltinInt::Isize),
|
||||
false => BuiltinType::Uint(BuiltinUint::Usize),
|
||||
},
|
||||
hir_def::layout::IntegerType::Fixed(size, signed) => match signed {
|
||||
true => BuiltinType::Int(match size {
|
||||
Integer::I8 => BuiltinInt::I8,
|
||||
Integer::I16 => BuiltinInt::I16,
|
||||
Integer::I32 => BuiltinInt::I32,
|
||||
Integer::I64 => BuiltinInt::I64,
|
||||
Integer::I128 => BuiltinInt::I128,
|
||||
}),
|
||||
false => BuiltinType::Uint(match size {
|
||||
Integer::I8 => BuiltinUint::U8,
|
||||
Integer::I16 => BuiltinUint::U16,
|
||||
Integer::I32 => BuiltinUint::U32,
|
||||
Integer::I64 => BuiltinUint::U64,
|
||||
Integer::I128 => BuiltinUint::U128,
|
||||
}),
|
||||
},
|
||||
},
|
||||
hir_def::layout::IntegerType::Fixed(size, signed) => match signed {
|
||||
true => BuiltinType::Int(match size {
|
||||
Integer::I8 => BuiltinInt::I8,
|
||||
Integer::I16 => BuiltinInt::I16,
|
||||
Integer::I32 => BuiltinInt::I32,
|
||||
Integer::I64 => BuiltinInt::I64,
|
||||
Integer::I128 => BuiltinInt::I128,
|
||||
}),
|
||||
false => BuiltinType::Uint(match size {
|
||||
Integer::I8 => BuiltinUint::U8,
|
||||
Integer::I16 => BuiltinUint::U16,
|
||||
Integer::I32 => BuiltinUint::U32,
|
||||
Integer::I64 => BuiltinUint::U64,
|
||||
Integer::I128 => BuiltinUint::U128,
|
||||
}),
|
||||
},
|
||||
});
|
||||
);
|
||||
}
|
||||
DefWithBodyId::InTypeConstId(c) => {
|
||||
// FIXME(const-generic-body): We should not get the return type in this way.
|
||||
|
@ -1062,7 +1064,7 @@ impl<'a> InferenceContext<'a> {
|
|||
Some(ResolveValueResult::ValueNs(value, _)) => match value {
|
||||
ValueNs::EnumVariantId(var) => {
|
||||
let substs = ctx.substs_from_path(path, var.into(), true);
|
||||
let ty = self.db.ty(var.parent.into());
|
||||
let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into());
|
||||
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
||||
return (ty, Some(var.into()));
|
||||
}
|
||||
|
@ -1105,7 +1107,7 @@ impl<'a> InferenceContext<'a> {
|
|||
}
|
||||
TypeNs::EnumVariantId(var) => {
|
||||
let substs = ctx.substs_from_path(path, var.into(), true);
|
||||
let ty = self.db.ty(var.parent.into());
|
||||
let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into());
|
||||
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
||||
forbid_unresolved_segments((ty, Some(var.into())), unresolved)
|
||||
}
|
||||
|
@ -1131,8 +1133,7 @@ impl<'a> InferenceContext<'a> {
|
|||
if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
|
||||
let enum_data = self.db.enum_data(id);
|
||||
let name = current_segment.first().unwrap().name;
|
||||
if let Some(local_id) = enum_data.variant(name) {
|
||||
let variant = EnumVariantId { parent: id, local_id };
|
||||
if let Some(variant) = enum_data.variant(name) {
|
||||
return if remaining_segments.len() == 1 {
|
||||
(ty, Some(variant.into()))
|
||||
} else {
|
||||
|
@ -1247,8 +1248,7 @@ impl<'a> InferenceContext<'a> {
|
|||
// 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);
|
||||
if let Some(local_id) = enum_data.variant(segment) {
|
||||
let variant = EnumVariantId { parent: enum_id, local_id };
|
||||
if let Some(variant) = enum_data.variant(segment) {
|
||||
return (ty, Some(variant.into()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -666,7 +666,7 @@ impl InferenceContext<'_> {
|
|||
| Pat::Or(_) => (),
|
||||
Pat::TupleStruct { .. } | Pat::Record { .. } => {
|
||||
if let Some(variant) = self.result.variant_resolution_for_pat(p) {
|
||||
let adt = variant.adt_id();
|
||||
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,
|
||||
_ => false,
|
||||
|
|
|
@ -4,7 +4,7 @@ use chalk_ir::cast::Cast;
|
|||
use hir_def::{
|
||||
path::{Path, PathSegment},
|
||||
resolver::{ResolveValueResult, TypeNs, ValueNs},
|
||||
AdtId, AssocItemId, EnumVariantId, GenericDefId, ItemContainerId, Lookup,
|
||||
AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use stdx::never;
|
||||
|
@ -395,8 +395,7 @@ impl InferenceContext<'_> {
|
|||
_ => return None,
|
||||
};
|
||||
let enum_data = self.db.enum_data(enum_id);
|
||||
let local_id = enum_data.variant(name)?;
|
||||
let variant = EnumVariantId { parent: enum_id, local_id };
|
||||
let variant = enum_data.variant(name)?;
|
||||
self.write_variant_resolution(id, variant.into());
|
||||
Some((ValueNs::EnumVariantId(variant), subst.clone()))
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use chalk_ir::{
|
|||
};
|
||||
use hir_def::{
|
||||
attr::Attrs, data::adt::VariantData, visibility::Visibility, AdtId, EnumVariantId, HasModule,
|
||||
Lookup, ModuleId, VariantId,
|
||||
ModuleId, VariantId,
|
||||
};
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
|
@ -30,17 +30,15 @@ pub(crate) fn is_enum_variant_uninhabited_from(
|
|||
target_mod: ModuleId,
|
||||
db: &dyn HirDatabase,
|
||||
) -> bool {
|
||||
let enum_data = db.enum_data(variant.parent);
|
||||
let vars_attrs = db.variants_attrs(variant.parent);
|
||||
let is_local = variant.parent.lookup(db.upcast()).container.krate() == target_mod.krate();
|
||||
let is_local = variant.module(db.upcast()).krate() == target_mod.krate();
|
||||
|
||||
let mut uninhabited_from =
|
||||
UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() };
|
||||
let inhabitedness = uninhabited_from.visit_variant(
|
||||
variant.into(),
|
||||
&enum_data.variants[variant.local_id].variant_data,
|
||||
&db.enum_variant_data(variant).variant_data,
|
||||
subst,
|
||||
&vars_attrs[variant.local_id],
|
||||
&db.attrs(variant.into()),
|
||||
is_local,
|
||||
);
|
||||
inhabitedness == BREAK_VISIBLY_UNINHABITED
|
||||
|
@ -117,15 +115,14 @@ impl UninhabitedFrom<'_> {
|
|||
self.visit_variant(s.into(), &struct_data.variant_data, subst, &attrs, is_local)
|
||||
}
|
||||
AdtId::EnumId(e) => {
|
||||
let vars_attrs = self.db.variants_attrs(e);
|
||||
let enum_data = self.db.enum_data(e);
|
||||
|
||||
for (local_id, enum_var) in enum_data.variants.iter() {
|
||||
for &(variant, _) in enum_data.variants.iter() {
|
||||
let variant_inhabitedness = self.visit_variant(
|
||||
EnumVariantId { parent: e, local_id }.into(),
|
||||
&enum_var.variant_data,
|
||||
variant.into(),
|
||||
&self.db.enum_variant_data(variant).variant_data,
|
||||
subst,
|
||||
&vars_attrs[local_id],
|
||||
&self.db.attrs(variant.into()),
|
||||
is_local,
|
||||
);
|
||||
match variant_inhabitedness {
|
||||
|
|
|
@ -9,7 +9,7 @@ use hir_def::{
|
|||
Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
|
||||
StructKind, TargetDataLayout, WrappingRange,
|
||||
},
|
||||
LocalEnumVariantId, LocalFieldId, StructId,
|
||||
LocalFieldId, StructId,
|
||||
};
|
||||
use la_arena::{Idx, RawIdx};
|
||||
use rustc_abi::AddressSpace;
|
||||
|
@ -32,15 +32,15 @@ mod adt;
|
|||
mod target;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct RustcEnumVariantIdx(pub LocalEnumVariantId);
|
||||
pub struct RustcEnumVariantIdx(pub usize);
|
||||
|
||||
impl rustc_index::Idx for RustcEnumVariantIdx {
|
||||
fn new(idx: usize) -> Self {
|
||||
RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32)))
|
||||
RustcEnumVariantIdx(idx)
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
u32::from(self.0.into_raw()) as usize
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,9 +6,8 @@ use base_db::salsa::Cycle;
|
|||
use hir_def::{
|
||||
data::adt::VariantData,
|
||||
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
|
||||
AdtId, EnumVariantId, LocalEnumVariantId, VariantId,
|
||||
AdtId, VariantId,
|
||||
};
|
||||
use la_arena::RawIdx;
|
||||
use rustc_index::IndexVec;
|
||||
use smallvec::SmallVec;
|
||||
use triomphe::Arc;
|
||||
|
@ -22,8 +21,8 @@ use crate::{
|
|||
|
||||
use super::LayoutCx;
|
||||
|
||||
pub(crate) const fn struct_variant_idx() -> RustcEnumVariantIdx {
|
||||
RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from_u32(0)))
|
||||
pub(crate) fn struct_variant_idx() -> RustcEnumVariantIdx {
|
||||
RustcEnumVariantIdx(0)
|
||||
}
|
||||
|
||||
pub fn layout_of_adt_query(
|
||||
|
@ -62,12 +61,7 @@ pub fn layout_of_adt_query(
|
|||
let r = data
|
||||
.variants
|
||||
.iter()
|
||||
.map(|(idx, v)| {
|
||||
handle_variant(
|
||||
EnumVariantId { parent: e, local_id: idx }.into(),
|
||||
&v.variant_data,
|
||||
)
|
||||
})
|
||||
.map(|&(v, _)| handle_variant(v.into(), &db.enum_variant_data(v).variant_data))
|
||||
.collect::<Result<SmallVec<_>, _>>()?;
|
||||
(r, data.repr.unwrap_or_default())
|
||||
}
|
||||
|
@ -89,8 +83,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(EnumVariantId { parent: e, local_id: id.0 }).ok()?;
|
||||
let d = db.const_eval_discriminant(db.enum_data(e).variants[id.0].0).ok()?;
|
||||
Some((id, d))
|
||||
}),
|
||||
// FIXME: The current code for niche-filling relies on variant indices
|
||||
|
|
|
@ -762,7 +762,7 @@ impl<'a> TyLoweringContext<'a> {
|
|||
Some(segment) if segment.args_and_bindings.is_some() => Some(segment),
|
||||
_ => last,
|
||||
};
|
||||
(segment, Some(var.parent.into()))
|
||||
(segment, Some(var.lookup(self.db.upcast()).parent.into()))
|
||||
}
|
||||
};
|
||||
if let Some(segment) = segment {
|
||||
|
@ -1375,11 +1375,13 @@ pub(crate) fn field_types_query(
|
|||
let (resolver, def): (_, GenericDefId) = match variant_id {
|
||||
VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()),
|
||||
VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()),
|
||||
VariantId::EnumVariantId(it) => (it.parent.resolver(db.upcast()), it.parent.into()),
|
||||
VariantId::EnumVariantId(it) => {
|
||||
(it.resolver(db.upcast()), it.lookup(db.upcast()).parent.into())
|
||||
}
|
||||
};
|
||||
let generics = generics(db.upcast(), def);
|
||||
let mut res = ArenaMap::default();
|
||||
let ctx = TyLoweringContext::new(db, &resolver, GenericDefId::from(variant_id.adt_id()).into())
|
||||
let ctx = TyLoweringContext::new(db, &resolver, def.into())
|
||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||
for (field_id, field_data) in var_data.fields().iter() {
|
||||
res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(&field_data.type_ref)));
|
||||
|
@ -1727,44 +1729,50 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
|
|||
/// Build the type of a tuple struct constructor.
|
||||
fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<Ty> {
|
||||
let struct_data = db.struct_data(def);
|
||||
if let StructKind::Unit = struct_data.variant_data.kind() {
|
||||
return type_for_adt(db, def.into());
|
||||
match struct_data.variant_data.kind() {
|
||||
StructKind::Record => unreachable!("callers check for valueness of variant"),
|
||||
StructKind::Unit => return type_for_adt(db, def.into()),
|
||||
StructKind::Tuple => {
|
||||
let generics = generics(db.upcast(), AdtId::from(def).into());
|
||||
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
||||
make_binders(
|
||||
db,
|
||||
&generics,
|
||||
TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(Interner),
|
||||
)
|
||||
}
|
||||
}
|
||||
let generics = generics(db.upcast(), AdtId::from(def).into());
|
||||
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
||||
make_binders(
|
||||
db,
|
||||
&generics,
|
||||
TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(Interner),
|
||||
)
|
||||
}
|
||||
|
||||
fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig {
|
||||
let enum_data = db.enum_data(def.parent);
|
||||
let var_data = &enum_data.variants[def.local_id];
|
||||
let var_data = db.enum_variant_data(def);
|
||||
let fields = var_data.variant_data.fields();
|
||||
let resolver = def.parent.resolver(db.upcast());
|
||||
let resolver = def.resolver(db.upcast());
|
||||
let ctx = TyLoweringContext::new(db, &resolver, DefWithBodyId::VariantId(def).into())
|
||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
|
||||
let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders();
|
||||
let (ret, binders) =
|
||||
type_for_adt(db, def.lookup(db.upcast()).parent.into()).into_value_and_skipped_binders();
|
||||
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
|
||||
}
|
||||
|
||||
/// Build the type of a tuple enum variant constructor.
|
||||
fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> Binders<Ty> {
|
||||
let enum_data = db.enum_data(def.parent);
|
||||
let var_data = &enum_data.variants[def.local_id].variant_data;
|
||||
if let StructKind::Unit = var_data.kind() {
|
||||
return type_for_adt(db, def.parent.into());
|
||||
let e = def.lookup(db.upcast()).parent;
|
||||
match db.enum_variant_data(def).variant_data.kind() {
|
||||
StructKind::Record => unreachable!("callers check for valueness of variant"),
|
||||
StructKind::Unit => return type_for_adt(db, e.into()),
|
||||
StructKind::Tuple => {
|
||||
let generics = generics(db.upcast(), e.into());
|
||||
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
||||
make_binders(
|
||||
db,
|
||||
&generics,
|
||||
TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs)
|
||||
.intern(Interner),
|
||||
)
|
||||
}
|
||||
}
|
||||
let generics = generics(db.upcast(), def.parent.into());
|
||||
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
||||
make_binders(
|
||||
db,
|
||||
&generics,
|
||||
TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(Interner),
|
||||
)
|
||||
}
|
||||
|
||||
fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
|
||||
|
@ -1812,7 +1820,7 @@ impl CallableDefId {
|
|||
match self {
|
||||
CallableDefId::FunctionId(f) => f.lookup(db).module(db),
|
||||
CallableDefId::StructId(s) => s.lookup(db).container,
|
||||
CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container,
|
||||
CallableDefId::EnumVariantId(e) => e.module(db),
|
||||
}
|
||||
.krate()
|
||||
}
|
||||
|
@ -1893,12 +1901,8 @@ pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders
|
|||
}
|
||||
|
||||
pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binders<Ty> {
|
||||
let impl_loc = impl_id.lookup(db.upcast());
|
||||
let impl_data = db.impl_data(impl_id);
|
||||
let resolver = impl_id.resolver(db.upcast());
|
||||
let _cx = stdx::panic_context::enter(format!(
|
||||
"impl_self_ty_query({impl_id:?} -> {impl_loc:?} -> {impl_data:?})"
|
||||
));
|
||||
let generics = generics(db.upcast(), impl_id.into());
|
||||
let ctx = TyLoweringContext::new(db, &resolver, impl_id.into())
|
||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||
|
@ -1930,12 +1934,8 @@ pub(crate) fn impl_self_ty_recover(
|
|||
}
|
||||
|
||||
pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
|
||||
let impl_loc = impl_id.lookup(db.upcast());
|
||||
let impl_data = db.impl_data(impl_id);
|
||||
let resolver = impl_id.resolver(db.upcast());
|
||||
let _cx = stdx::panic_context::enter(format!(
|
||||
"impl_trait_query({impl_id:?} -> {impl_loc:?} -> {impl_data:?})"
|
||||
));
|
||||
let ctx = TyLoweringContext::new(db, &resolver, impl_id.into())
|
||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||
let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();
|
||||
|
|
|
@ -752,7 +752,7 @@ impl Evaluator<'_> {
|
|||
Variants::Multiple { variants, .. } => {
|
||||
&variants[match f.parent {
|
||||
hir_def::VariantId::EnumVariantId(it) => {
|
||||
RustcEnumVariantIdx(it.local_id)
|
||||
RustcEnumVariantIdx(it.lookup(self.db.upcast()).index as usize)
|
||||
}
|
||||
_ => {
|
||||
return Err(MirEvalError::TypeError(
|
||||
|
@ -1412,22 +1412,12 @@ impl Evaluator<'_> {
|
|||
|
||||
fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<i128> {
|
||||
let layout = self.layout(&ty)?;
|
||||
let enum_id = 'b: {
|
||||
match ty.kind(Interner) {
|
||||
TyKind::Adt(e, _) => match e.0 {
|
||||
AdtId::EnumId(e) => break 'b e,
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
let &TyKind::Adt(chalk_ir::AdtId(AdtId::EnumId(e)), _) = ty.kind(Interner) else {
|
||||
return Ok(0);
|
||||
};
|
||||
match &layout.variants {
|
||||
Variants::Single { index } => {
|
||||
let r = self.const_eval_discriminant(EnumVariantId {
|
||||
parent: enum_id,
|
||||
local_id: index.0,
|
||||
})?;
|
||||
let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?;
|
||||
Ok(r)
|
||||
}
|
||||
Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
||||
|
@ -1446,17 +1436,15 @@ impl Evaluator<'_> {
|
|||
let candidate_tag = i128::from_le_bytes(pad16(tag, false))
|
||||
.wrapping_sub(*niche_start as i128)
|
||||
as usize;
|
||||
let variant = variants
|
||||
let idx = variants
|
||||
.iter_enumerated()
|
||||
.map(|(it, _)| it)
|
||||
.filter(|it| it != untagged_variant)
|
||||
.nth(candidate_tag)
|
||||
.unwrap_or(*untagged_variant)
|
||||
.0;
|
||||
let result = self.const_eval_discriminant(EnumVariantId {
|
||||
parent: enum_id,
|
||||
local_id: variant,
|
||||
})?;
|
||||
let result =
|
||||
self.const_eval_discriminant(self.db.enum_data(e).variants[idx].0)?;
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
@ -1579,14 +1567,16 @@ impl Evaluator<'_> {
|
|||
subst: Substitution,
|
||||
locals: &Locals,
|
||||
) -> Result<(usize, Arc<Layout>, Option<(usize, usize, i128)>)> {
|
||||
let adt = it.adt_id();
|
||||
let adt = it.adt_id(self.db.upcast());
|
||||
if let DefWithBodyId::VariantId(f) = locals.body.owner {
|
||||
if let VariantId::EnumVariantId(it) = it {
|
||||
if AdtId::from(f.parent) == adt {
|
||||
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
||||
// infinite sized type errors) we use a dummy layout
|
||||
let i = self.const_eval_discriminant(it)?;
|
||||
return Ok((16, self.layout(&TyBuilder::unit())?, Some((0, 16, i))));
|
||||
if let AdtId::EnumId(e) = adt {
|
||||
if f.lookup(self.db.upcast()).parent == e {
|
||||
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
||||
// infinite sized type errors) we use a dummy layout
|
||||
let i = self.const_eval_discriminant(it)?;
|
||||
return Ok((16, self.layout(&TyBuilder::unit())?, Some((0, 16, i))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1602,8 +1592,9 @@ impl Evaluator<'_> {
|
|||
VariantId::EnumVariantId(it) => it,
|
||||
_ => not_supported!("multi variant layout for non-enums"),
|
||||
};
|
||||
let rustc_enum_variant_idx = RustcEnumVariantIdx(enum_variant_id.local_id);
|
||||
let mut discriminant = self.const_eval_discriminant(enum_variant_id)?;
|
||||
let lookup = enum_variant_id.lookup(self.db.upcast());
|
||||
let rustc_enum_variant_idx = RustcEnumVariantIdx(lookup.index as usize);
|
||||
let variant_layout = variants[rustc_enum_variant_idx].clone();
|
||||
let have_tag = match tag_encoding {
|
||||
TagEncoding::Direct => true,
|
||||
|
@ -1847,8 +1838,8 @@ impl Evaluator<'_> {
|
|||
.then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize)));
|
||||
}
|
||||
if let DefWithBodyId::VariantId(f) = locals.body.owner {
|
||||
if let Some((adt, _)) = ty.as_adt() {
|
||||
if AdtId::from(f.parent) == adt {
|
||||
if let Some((AdtId::EnumId(e), _)) = ty.as_adt() {
|
||||
if f.lookup(self.db.upcast()).parent == e {
|
||||
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
||||
// infinite sized type errors) we use a dummy size
|
||||
return Ok(Some((16, 16)));
|
||||
|
@ -2019,10 +2010,8 @@ impl Evaluator<'_> {
|
|||
bytes,
|
||||
e,
|
||||
) {
|
||||
let data = &this.db.enum_data(e).variants[v].variant_data;
|
||||
let field_types = this
|
||||
.db
|
||||
.field_types(EnumVariantId { parent: e, local_id: v }.into());
|
||||
let data = &this.db.enum_variant_data(v).variant_data;
|
||||
let field_types = this.db.field_types(v.into());
|
||||
for (f, _) in data.fields().iter() {
|
||||
let offset =
|
||||
l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize();
|
||||
|
@ -2093,14 +2082,13 @@ impl Evaluator<'_> {
|
|||
}
|
||||
AdtId::UnionId(_) => (),
|
||||
AdtId::EnumId(e) => {
|
||||
if let Some((variant, layout)) = detect_variant_from_bytes(
|
||||
if let Some((ev, layout)) = detect_variant_from_bytes(
|
||||
&layout,
|
||||
self.db,
|
||||
self.trait_env.clone(),
|
||||
self.read_memory(addr, layout.size.bytes_usize())?,
|
||||
e,
|
||||
) {
|
||||
let ev = EnumVariantId { parent: e, local_id: variant };
|
||||
for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() {
|
||||
let offset = layout.fields.offset(i).bytes_usize();
|
||||
let ty = ty.clone().substitute(Interner, subst);
|
||||
|
@ -2540,11 +2528,13 @@ impl Evaluator<'_> {
|
|||
match r {
|
||||
Ok(r) => Ok(r),
|
||||
Err(e) => {
|
||||
let data = self.db.enum_data(variant.parent);
|
||||
let db = self.db.upcast();
|
||||
let loc = variant.lookup(db);
|
||||
let enum_loc = loc.parent.lookup(db);
|
||||
let name = format!(
|
||||
"{}::{}",
|
||||
data.name.display(self.db.upcast()),
|
||||
data.variants[variant.local_id].name.display(self.db.upcast())
|
||||
enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
|
||||
loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
|
||||
);
|
||||
Err(MirEvalError::ConstEvalError(name, Box::new(e)))
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ struct MirLowerCtx<'a> {
|
|||
drop_scopes: Vec<DropScope>,
|
||||
}
|
||||
|
||||
// FIXME: Make this smaller, its stored in database queries
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum MirLowerError {
|
||||
ConstEvalError(Box<str>, Box<ConstEvalError>),
|
||||
|
@ -456,9 +457,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
Ok(Some(current))
|
||||
}
|
||||
ValueNs::EnumVariantId(variant_id) => {
|
||||
let variant_data =
|
||||
&self.db.enum_data(variant_id.parent).variants[variant_id.local_id];
|
||||
if variant_data.variant_data.kind() == StructKind::Unit {
|
||||
let variant_data = &self.db.enum_variant_data(variant_id).variant_data;
|
||||
if variant_data.kind() == StructKind::Unit {
|
||||
let ty = self.infer.type_of_expr[expr_id].clone();
|
||||
current = self.lower_enum_variant(
|
||||
variant_id,
|
||||
|
@ -1874,11 +1874,13 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
match r {
|
||||
Ok(r) => Ok(r),
|
||||
Err(e) => {
|
||||
let data = self.db.enum_data(variant.parent);
|
||||
let db = self.db.upcast();
|
||||
let loc = variant.lookup(db);
|
||||
let enum_loc = loc.parent.lookup(db);
|
||||
let name = format!(
|
||||
"{}::{}",
|
||||
data.name.display(self.db.upcast()),
|
||||
data.variants[variant.local_id].name.display(self.db.upcast())
|
||||
enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
|
||||
loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
|
||||
);
|
||||
Err(MirLowerError::ConstEvalError(name.into(), Box::new(e)))
|
||||
}
|
||||
|
@ -2104,7 +2106,7 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<Mi
|
|||
.display(db.upcast())
|
||||
.to_string(),
|
||||
DefWithBodyId::VariantId(it) => {
|
||||
db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()).to_string()
|
||||
db.enum_variant_data(it).name.display(db.upcast()).to_string()
|
||||
}
|
||||
DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
|
||||
});
|
||||
|
|
|
@ -524,22 +524,9 @@ impl MirLowerCtx<'_> {
|
|||
);
|
||||
current = next;
|
||||
}
|
||||
let enum_data = self.db.enum_data(v.parent);
|
||||
self.pattern_matching_variant_fields(
|
||||
shape,
|
||||
&enum_data.variants[v.local_id].variant_data,
|
||||
variant,
|
||||
current,
|
||||
current_else,
|
||||
&cond_place,
|
||||
mode,
|
||||
)?
|
||||
}
|
||||
VariantId::StructId(s) => {
|
||||
let struct_data = self.db.struct_data(s);
|
||||
self.pattern_matching_variant_fields(
|
||||
shape,
|
||||
&struct_data.variant_data,
|
||||
&self.db.enum_variant_data(v).variant_data,
|
||||
variant,
|
||||
current,
|
||||
current_else,
|
||||
|
@ -547,6 +534,15 @@ impl MirLowerCtx<'_> {
|
|||
mode,
|
||||
)?
|
||||
}
|
||||
VariantId::StructId(s) => self.pattern_matching_variant_fields(
|
||||
shape,
|
||||
&self.db.struct_data(s).variant_data,
|
||||
variant,
|
||||
current,
|
||||
current_else,
|
||||
&cond_place,
|
||||
mode,
|
||||
)?,
|
||||
VariantId::UnionId(_) => {
|
||||
return Err(MirLowerError::TypeError("pattern matching on union"))
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::{
|
|||
|
||||
use either::Either;
|
||||
use hir_def::{body::Body, hir::BindingId};
|
||||
use hir_expand::name::Name;
|
||||
use hir_expand::{name::Name, Lookup};
|
||||
use la_arena::ArenaMap;
|
||||
|
||||
use crate::{
|
||||
|
@ -58,8 +58,14 @@ impl MirBody {
|
|||
);
|
||||
}
|
||||
hir_def::DefWithBodyId::VariantId(id) => {
|
||||
let data = db.enum_data(id.parent);
|
||||
w!(this, "enum {} = ", data.name.display(db.upcast()));
|
||||
let loc = id.lookup(db.upcast());
|
||||
let enum_loc = loc.parent.lookup(db.upcast());
|
||||
w!(
|
||||
this,
|
||||
"enum {}::{} = ",
|
||||
enum_loc.id.item_tree(db.upcast())[enum_loc.id.value].name.display(db.upcast()),
|
||||
loc.id.item_tree(db.upcast())[loc.id.value].name.display(db.upcast()),
|
||||
)
|
||||
}
|
||||
hir_def::DefWithBodyId::InTypeConstId(id) => {
|
||||
w!(this, "in type const {id:?} = ");
|
||||
|
@ -306,8 +312,7 @@ impl<'a> MirPrettyCtx<'a> {
|
|||
hir_def::VariantId::EnumVariantId(e) => {
|
||||
w!(this, "(");
|
||||
f(this, local, head);
|
||||
let variant_name =
|
||||
&this.db.enum_data(e.parent).variants[e.local_id].name;
|
||||
let variant_name = &this.db.enum_variant_data(e).name;
|
||||
w!(
|
||||
this,
|
||||
" as {}).{}",
|
||||
|
|
|
@ -16,7 +16,7 @@ use base_db::{FileRange, SourceDatabaseExt};
|
|||
use expect_test::Expect;
|
||||
use hir_def::{
|
||||
body::{Body, BodySourceMap, SyntheticSyntax},
|
||||
db::{DefDatabase, InternDatabase},
|
||||
db::DefDatabase,
|
||||
hir::{ExprId, Pat, PatId},
|
||||
item_scope::ItemScope,
|
||||
nameres::DefMap,
|
||||
|
@ -145,7 +145,7 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
|
|||
loc.source(&db).value.syntax().text_range().start()
|
||||
}
|
||||
DefWithBodyId::VariantId(it) => {
|
||||
let loc = db.lookup_intern_enum(it.parent);
|
||||
let loc = it.lookup(&db);
|
||||
loc.source(&db).value.syntax().text_range().start()
|
||||
}
|
||||
DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
|
||||
|
@ -383,7 +383,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
|
|||
loc.source(&db).value.syntax().text_range().start()
|
||||
}
|
||||
DefWithBodyId::VariantId(it) => {
|
||||
let loc = db.lookup_intern_enum(it.parent);
|
||||
let loc = it.lookup(&db);
|
||||
loc.source(&db).value.syntax().text_range().start()
|
||||
}
|
||||
DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
|
||||
|
@ -453,16 +453,12 @@ fn visit_module(
|
|||
visit_body(db, &body, cb);
|
||||
}
|
||||
ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => {
|
||||
db.enum_data(it)
|
||||
.variants
|
||||
.iter()
|
||||
.map(|(id, _)| hir_def::EnumVariantId { parent: it, local_id: id })
|
||||
.for_each(|it| {
|
||||
let def = it.into();
|
||||
cb(def);
|
||||
let body = db.body(def);
|
||||
visit_body(db, &body, cb);
|
||||
});
|
||||
db.enum_data(it).variants.iter().for_each(|&(it, _)| {
|
||||
let def = it.into();
|
||||
cb(def);
|
||||
let body = db.body(def);
|
||||
visit_body(db, &body, cb);
|
||||
});
|
||||
}
|
||||
ModuleDefId::TraitId(it) => {
|
||||
let trait_data = db.trait_data(it);
|
||||
|
|
|
@ -107,10 +107,7 @@ impl DebugContext<'_> {
|
|||
let name = match def {
|
||||
CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(),
|
||||
CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(),
|
||||
CallableDefId::EnumVariantId(e) => {
|
||||
let enum_data = self.0.enum_data(e.parent);
|
||||
enum_data.variants[e.local_id].name.clone()
|
||||
}
|
||||
CallableDefId::EnumVariantId(e) => self.0.enum_variant_data(e).name.clone(),
|
||||
};
|
||||
match def {
|
||||
CallableDefId::FunctionId(_) => write!(fmt, "{{fn {}}}", name.display(self.0.upcast())),
|
||||
|
|
|
@ -19,9 +19,8 @@ use hir_def::{
|
|||
lang_item::LangItem,
|
||||
resolver::{HasResolver, TypeNs},
|
||||
type_ref::{TraitBoundModifier, TypeRef},
|
||||
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId,
|
||||
LocalEnumVariantId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
|
||||
TypeParamId,
|
||||
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, Lookup,
|
||||
OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use intern::Interned;
|
||||
|
@ -355,7 +354,7 @@ fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<Generic
|
|||
GenericDefId::FunctionId(it) => it.lookup(db).container,
|
||||
GenericDefId::TypeAliasId(it) => it.lookup(db).container,
|
||||
GenericDefId::ConstId(it) => it.lookup(db).container,
|
||||
GenericDefId::EnumVariantId(it) => return Some(it.parent.into()),
|
||||
GenericDefId::EnumVariantId(it) => return Some(it.lookup(db).parent.into()),
|
||||
GenericDefId::AdtId(_)
|
||||
| GenericDefId::TraitId(_)
|
||||
| GenericDefId::ImplId(_)
|
||||
|
@ -435,10 +434,12 @@ pub(crate) fn detect_variant_from_bytes<'a>(
|
|||
trait_env: Arc<TraitEnvironment>,
|
||||
b: &[u8],
|
||||
e: EnumId,
|
||||
) -> Option<(LocalEnumVariantId, &'a Layout)> {
|
||||
) -> Option<(EnumVariantId, &'a Layout)> {
|
||||
let krate = trait_env.krate;
|
||||
let (var_id, var_layout) = match &layout.variants {
|
||||
hir_def::layout::Variants::Single { index } => (index.0, &*layout),
|
||||
hir_def::layout::Variants::Single { index } => {
|
||||
(db.enum_data(e).variants[index.0].0, &*layout)
|
||||
}
|
||||
hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
||||
let target_data_layout = db.target_data_layout(krate)?;
|
||||
let size = tag.size(&*target_data_layout).bytes_usize();
|
||||
|
@ -446,11 +447,12 @@ pub(crate) fn detect_variant_from_bytes<'a>(
|
|||
let tag = i128::from_le_bytes(pad16(&b[offset..offset + size], false));
|
||||
match tag_encoding {
|
||||
TagEncoding::Direct => {
|
||||
let x = variants.iter_enumerated().find(|x| {
|
||||
db.const_eval_discriminant(EnumVariantId { parent: e, local_id: x.0 .0 })
|
||||
== Ok(tag)
|
||||
})?;
|
||||
(x.0 .0, x.1)
|
||||
let (var_idx, layout) =
|
||||
variants.iter_enumerated().find_map(|(var_idx, v)| {
|
||||
let def = db.enum_data(e).variants[var_idx.0].0;
|
||||
(db.const_eval_discriminant(def) == Ok(tag)).then_some((def, v))
|
||||
})?;
|
||||
(var_idx, layout)
|
||||
}
|
||||
TagEncoding::Niche { untagged_variant, niche_start, .. } => {
|
||||
let candidate_tag = tag.wrapping_sub(*niche_start as i128) as usize;
|
||||
|
@ -460,7 +462,7 @@ pub(crate) fn detect_variant_from_bytes<'a>(
|
|||
.filter(|x| x != untagged_variant)
|
||||
.nth(candidate_tag)
|
||||
.unwrap_or(*untagged_variant);
|
||||
(variant.0, &variants[variant])
|
||||
(db.enum_data(e).variants[variant.0].0, &variants[variant])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue