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.rs33
1 files changed, 18 insertions, 15 deletions
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 450cd5404e..f8545e88ad 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -1,6 +1,6 @@
//! This module provides a MIR interpreter, which is used in const eval.
-use std::{borrow::Cow, collections::HashMap, iter, sync::Arc};
+use std::{borrow::Cow, collections::HashMap, iter, ops::Range, sync::Arc};
use base_db::CrateId;
use chalk_ir::{
@@ -109,6 +109,10 @@ impl Interval {
fn get<'a>(&self, memory: &'a Evaluator<'a>) -> Result<&'a [u8]> {
memory.read_memory(self.addr, self.size)
}
+
+ fn slice(self, range: Range<usize>) -> Interval {
+ Interval { addr: self.addr.offset(range.start), size: range.len() }
+ }
}
enum IntervalOrOwned {
@@ -423,7 +427,6 @@ impl Evaluator<'_> {
args: impl Iterator<Item = Vec<u8>>,
subst: Substitution,
) -> Result<Vec<u8>> {
- dbg!(body.dbg(self.db));
if let Some(x) = self.stack_depth_limit.checked_sub(1) {
self.stack_depth_limit = x;
} else {
@@ -1360,24 +1363,24 @@ impl Evaluator<'_> {
locals: &Locals<'_>,
) -> Result<()> {
let func = args.get(0).ok_or(MirEvalError::TypeError("fn trait with no arg"))?;
- let ref_func_ty = self.operand_ty(func, locals)?;
- let func_ty = match ft {
- FnTrait::FnOnce => ref_func_ty,
- FnTrait::FnMut | FnTrait::Fn => match ref_func_ty.as_reference() {
- Some(x) => x.0.clone(),
- None => return Err(MirEvalError::TypeError("fn trait with non-reference arg")),
- },
- };
+ let mut func_ty = self.operand_ty(func, locals)?;
+ let mut func_data = self.eval_operand(func, locals)?;
+ while let TyKind::Ref(_, _, z) = func_ty.kind(Interner) {
+ func_ty = z.clone();
+ if matches!(func_ty.kind(Interner), TyKind::Dyn(_)) {
+ let id =
+ from_bytes!(usize, &func_data.get(self)?[self.ptr_size()..self.ptr_size() * 2]);
+ func_data = func_data.slice(0..self.ptr_size());
+ func_ty = self.vtable_map.ty(id)?.clone();
+ }
+ let size = self.size_of_sized(&func_ty, locals, "self type of fn trait")?;
+ func_data = Interval { addr: Address::from_bytes(func_data.get(self)?)?, size };
+ }
match &func_ty.data(Interner).kind {
TyKind::FnDef(def, subst) => {
self.exec_fn_def(*def, subst, destination, &args[1..], locals)?;
}
TyKind::Function(_) => {
- let mut func_data = self.eval_operand(func, locals)?;
- if let FnTrait::FnMut | FnTrait::Fn = ft {
- let addr = Address::from_bytes(func_data.get(self)?)?;
- func_data = Interval { addr, size: self.ptr_size() };
- }
self.exec_fn_pointer(func_data, destination, &args[1..], locals)?;
}
x => not_supported!("Call {ft:?} trait methods with type {x:?}"),