Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/mir/eval.rs')
| -rw-r--r-- | crates/hir-ty/src/mir/eval.rs | 66 |
1 files changed, 41 insertions, 25 deletions
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 47c9354768..d7820de629 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -29,7 +29,7 @@ use crate::{ infer::PointerCast, layout::{Layout, LayoutError, RustcEnumVariantIdx}, mapping::from_chalk, - method_resolution::is_dyn_method, + method_resolution::{is_dyn_method, lookup_impl_const}, name, static_lifetime, traits::FnTrait, utils::{detect_variant_from_bytes, ClosureSubst}, @@ -1571,35 +1571,51 @@ impl Evaluator<'_> { let chalk_ir::ConstValue::Concrete(c) = &konst.data(Interner).value else { not_supported!("evaluating non concrete constant"); }; - Ok(match &c.interned { - ConstScalar::Bytes(v, memory_map) => { - let mut v: Cow<'_, [u8]> = Cow::Borrowed(v); - let patch_map = memory_map.transform_addresses(|b, align| { - let addr = self.heap_allocate(b.len(), align)?; - self.write_memory(addr, b)?; - Ok(addr.to_usize()) + let result_owner; + let (v, memory_map) = match &c.interned { + ConstScalar::Bytes(v, mm) => (v, mm), + ConstScalar::UnevaluatedConst(const_id, subst) => 'b: { + let mut const_id = *const_id; + let mut subst = subst.clone(); + if let hir_def::GeneralConstId::ConstId(c) = const_id { + let (c, s) = lookup_impl_const(self.db, self.trait_env.clone(), c, subst); + const_id = hir_def::GeneralConstId::ConstId(c); + subst = s; + } + result_owner = self.db.const_eval(const_id.into(), subst).map_err(|e| { + let name = const_id.name(self.db.upcast()); + MirEvalError::ConstEvalError(name, Box::new(e)) })?; - let (size, align) = self.size_align_of(ty, locals)?.unwrap_or((v.len(), 1)); - if size != v.len() { - // Handle self enum - if size == 16 && v.len() < 16 { - v = Cow::Owned(pad16(&v, false).to_vec()); - } else if size < 16 && v.len() == 16 { - v = Cow::Owned(v[0..size].to_vec()); - } else { - return Err(MirEvalError::InvalidConst(konst.clone())); + if let chalk_ir::ConstValue::Concrete(c) = &result_owner.data(Interner).value { + if let ConstScalar::Bytes(v, mm) = &c.interned { + break 'b (v, mm); } } - let addr = self.heap_allocate(size, align)?; - self.write_memory(addr, &v)?; - self.patch_addresses(&patch_map, &memory_map.vtable, addr, ty, locals)?; - Interval::new(addr, size) - } - ConstScalar::UnevaluatedConst(..) => { - not_supported!("unevaluated const present in monomorphized mir"); + not_supported!("unevaluatable constant"); } ConstScalar::Unknown => not_supported!("evaluating unknown const"), - }) + }; + let mut v: Cow<'_, [u8]> = Cow::Borrowed(v); + let patch_map = memory_map.transform_addresses(|b, align| { + let addr = self.heap_allocate(b.len(), align)?; + self.write_memory(addr, b)?; + Ok(addr.to_usize()) + })?; + let (size, align) = self.size_align_of(ty, locals)?.unwrap_or((v.len(), 1)); + if size != v.len() { + // Handle self enum + if size == 16 && v.len() < 16 { + v = Cow::Owned(pad16(&v, false).to_vec()); + } else if size < 16 && v.len() == 16 { + v = Cow::Owned(v[0..size].to_vec()); + } else { + return Err(MirEvalError::InvalidConst(konst.clone())); + } + } + let addr = self.heap_allocate(size, align)?; + self.write_memory(addr, &v)?; + self.patch_addresses(&patch_map, &memory_map.vtable, addr, ty, locals)?; + Ok(Interval::new(addr, size)) } fn eval_place(&mut self, p: &Place, locals: &Locals) -> Result<Interval> { |