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 | 276 |
1 files changed, 176 insertions, 100 deletions
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index dfb8ae704b..3e658cb93e 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -3,6 +3,7 @@ use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range}; use base_db::Crate; +use base_db::target::TargetLoadError; use chalk_ir::{Mutability, cast::Cast}; use either::Either; use hir_def::{ @@ -25,21 +26,26 @@ use rustc_apfloat::{ ieee::{Half as f16, Quad as f128}, }; use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike}; use span::FileId; use stdx::never; use syntax::{SyntaxNodePtr, TextRange}; use triomphe::Arc; use crate::{ - AliasTy, CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstData, ConstScalar, FnDefId, - Interner, MemoryMap, Substitution, ToChalk, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, + AliasTy, CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstData, ConstScalar, Interner, + MemoryMap, Substitution, ToChalk, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, consteval::{ConstEvalError, intern_const_scalar, try_const_usize}, + consteval_nextsolver, db::{HirDatabase, InternedClosure}, display::{ClosureStyle, DisplayTarget, HirDisplay}, infer::PointerCast, layout::{Layout, LayoutError, RustcEnumVariantIdx}, - mapping::from_chalk, method_resolution::{is_dyn_method, lookup_impl_const}, + next_solver::{ + DbInterner, + mapping::{ChalkToNextSolver, convert_args_for_result, convert_ty_for_result}, + }, static_lifetime, traits::FnTrait, utils::{ClosureSubst, detect_variant_from_bytes}, @@ -78,31 +84,31 @@ macro_rules! not_supported { } #[derive(Debug, Default, Clone, PartialEq, Eq)] -pub struct VTableMap { - ty_to_id: FxHashMap<Ty, usize>, - id_to_ty: Vec<Ty>, +pub struct VTableMap<'db> { + ty_to_id: FxHashMap<crate::next_solver::Ty<'db>, usize>, + id_to_ty: Vec<crate::next_solver::Ty<'db>>, } -impl VTableMap { +impl<'db> VTableMap<'db> { const OFFSET: usize = 1000; // We should add some offset to ids to make 0 (null) an invalid id. - fn id(&mut self, ty: Ty) -> usize { + fn id(&mut self, ty: crate::next_solver::Ty<'db>) -> usize { if let Some(it) = self.ty_to_id.get(&ty) { return *it; } let id = self.id_to_ty.len() + VTableMap::OFFSET; - self.id_to_ty.push(ty.clone()); + self.id_to_ty.push(ty); self.ty_to_id.insert(ty, id); id } - pub(crate) fn ty(&self, id: usize) -> Result<&Ty> { + pub(crate) fn ty(&self, id: usize) -> Result<crate::next_solver::Ty<'db>> { id.checked_sub(VTableMap::OFFSET) - .and_then(|id| self.id_to_ty.get(id)) + .and_then(|id| self.id_to_ty.get(id).copied()) .ok_or(MirEvalError::InvalidVTableId(id)) } - fn ty_of_bytes(&self, bytes: &[u8]) -> Result<&Ty> { + fn ty_of_bytes(&self, bytes: &[u8]) -> Result<crate::next_solver::Ty<'db>> { let id = from_bytes!(usize, bytes); self.ty(id) } @@ -170,12 +176,12 @@ pub struct Evaluator<'a> { /// We don't really have function pointers, i.e. pointers to some assembly instructions that we can run. Instead, we /// store the type as an interned id in place of function and vtable pointers, and we recover back the type at the /// time of use. - vtable_map: VTableMap, + vtable_map: VTableMap<'a>, thread_local_storage: TlsData, random_state: oorandom::Rand64, stdout: Vec<u8>, stderr: Vec<u8>, - layout_cache: RefCell<FxHashMap<Ty, Arc<Layout>>>, + layout_cache: RefCell<FxHashMap<crate::next_solver::Ty<'a>, Arc<Layout>>>, projected_ty_cache: RefCell<FxHashMap<(Ty, PlaceElem), Ty>>, not_special_fn_cache: RefCell<FxHashSet<FunctionId>>, mir_or_dyn_index_cache: RefCell<FxHashMap<(FunctionId, Substitution), MirOrDynIndex>>, @@ -224,7 +230,7 @@ impl Interval { Self { addr, size } } - fn get<'a>(&self, memory: &'a Evaluator<'a>) -> Result<&'a [u8]> { + fn get<'a, 'db>(&self, memory: &'a Evaluator<'db>) -> Result<&'a [u8]> { memory.read_memory(self.addr, self.size) } @@ -242,7 +248,7 @@ impl Interval { } impl IntervalAndTy { - fn get<'a>(&self, memory: &'a Evaluator<'a>) -> Result<&'a [u8]> { + fn get<'a, 'db>(&self, memory: &'a Evaluator<'db>) -> Result<&'a [u8]> { memory.read_memory(self.interval.addr, self.interval.size) } @@ -269,7 +275,7 @@ impl From<Interval> for IntervalOrOwned { } impl IntervalOrOwned { - fn get<'a>(&'a self, memory: &'a Evaluator<'a>) -> Result<&'a [u8]> { + fn get<'a, 'db>(&'a self, memory: &'a Evaluator<'db>) -> Result<&'a [u8]> { Ok(match self { IntervalOrOwned::Owned(o) => o, IntervalOrOwned::Borrowed(b) => b.get(memory)?, @@ -332,7 +338,7 @@ impl Address { pub enum MirEvalError { ConstEvalError(String, Box<ConstEvalError>), LayoutError(LayoutError, Ty), - TargetDataLayoutNotAvailable(Arc<str>), + TargetDataLayoutNotAvailable(TargetLoadError), /// Means that code had undefined behavior. We don't try to actively detect UB, but if it was detected /// then use this type of error. UndefinedBehavior(String), @@ -608,7 +614,13 @@ pub fn interpret_mir( memory_map.vtable.shrink_to_fit(); MemoryMap::Complex(Box::new(memory_map)) }; - Ok(intern_const_scalar(ConstScalar::Bytes(bytes, memory_map), ty)) + // SAFETY: will never use this without a db + Ok(intern_const_scalar( + ConstScalar::Bytes(bytes, unsafe { + std::mem::transmute::<MemoryMap<'_>, MemoryMap<'static>>(memory_map) + }), + ty, + )) })(); Ok((it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr })) } @@ -618,7 +630,7 @@ const EXECUTION_LIMIT: usize = 100_000; #[cfg(not(test))] const EXECUTION_LIMIT: usize = 10_000_000; -impl Evaluator<'_> { +impl<'db> Evaluator<'db> { pub fn new( db: &dyn HirDatabase, owner: DefWithBodyId, @@ -700,13 +712,13 @@ impl Evaluator<'_> { let InternedClosure(def, _) = self.db.lookup_intern_closure(c.into()); let infer = self.db.infer(def); let (captures, _) = infer.closure_info(&c); - let parent_subst = ClosureSubst(subst).parent_subst(); + let parent_subst = ClosureSubst(subst).parent_subst(self.db); captures .get(f) .expect("broken closure field") .ty .clone() - .substitute(Interner, parent_subst) + .substitute(Interner, &parent_subst) }, self.crate_id, ); @@ -719,6 +731,7 @@ impl Evaluator<'_> { p: &Place, locals: &'a Locals, ) -> Result<(Address, Ty, Option<IntervalOrOwned>)> { + let interner = DbInterner::new_with(self.db, None, None); let mut addr = locals.ptr[p.local].addr; let mut ty: Ty = locals.body.locals[p.local].ty.clone(); let mut metadata: Option<IntervalOrOwned> = None; // locals are always sized @@ -791,19 +804,19 @@ impl Evaluator<'_> { addr = addr.offset(ty_size * (from as usize)); } &ProjectionElem::ClosureField(f) => { - let layout = self.layout(&prev_ty)?; + let layout = self.layout(prev_ty.to_nextsolver(interner))?; let offset = layout.fields.offset(f).bytes_usize(); addr = addr.offset(offset); metadata = None; } ProjectionElem::Field(Either::Right(f)) => { - let layout = self.layout(&prev_ty)?; + let layout = self.layout(prev_ty.to_nextsolver(interner))?; let offset = layout.fields.offset(f.index as usize).bytes_usize(); addr = addr.offset(offset); metadata = None; // tuple field is always sized FIXME: This is wrong, the tail can be unsized } ProjectionElem::Field(Either::Left(f)) => { - let layout = self.layout(&prev_ty)?; + let layout = self.layout(prev_ty.to_nextsolver(interner))?; let variant_layout = match &layout.variants { Variants::Single { .. } | Variants::Empty => &layout, Variants::Multiple { variants, .. } => { @@ -835,20 +848,28 @@ impl Evaluator<'_> { Ok((addr, ty, metadata)) } - fn layout(&self, ty: &Ty) -> Result<Arc<Layout>> { - if let Some(x) = self.layout_cache.borrow().get(ty) { + fn layout(&self, ty: crate::next_solver::Ty<'db>) -> Result<Arc<Layout>> { + if let Some(x) = self.layout_cache.borrow().get(&ty) { return Ok(x.clone()); } + let interner = DbInterner::new_with(self.db, None, None); let r = self .db - .layout_of_ty(ty.clone(), self.trait_env.clone()) - .map_err(|e| MirEvalError::LayoutError(e, ty.clone()))?; - self.layout_cache.borrow_mut().insert(ty.clone(), r.clone()); + .layout_of_ty(ty, self.trait_env.clone()) + .map_err(|e| MirEvalError::LayoutError(e, convert_ty_for_result(interner, ty)))?; + self.layout_cache.borrow_mut().insert(ty, r.clone()); Ok(r) } fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result<Arc<Layout>> { - self.layout(&TyKind::Adt(chalk_ir::AdtId(adt), subst).intern(Interner)) + let interner = DbInterner::new_with(self.db, None, None); + self.layout(crate::next_solver::Ty::new( + interner, + rustc_type_ir::TyKind::Adt( + crate::next_solver::AdtDef::new(adt, interner), + subst.to_nextsolver(interner), + ), + )) } fn place_ty<'a>(&'a self, p: &Place, locals: &'a Locals) -> Result<Ty> { @@ -952,7 +973,7 @@ impl Evaluator<'_> { )? } TyKind::FnDef(def, generic_args) => self.exec_fn_def( - *def, + CallableDefId::from_chalk(self.db, *def), generic_args, destination_interval, &args, @@ -1113,6 +1134,7 @@ impl Evaluator<'_> { } fn eval_rvalue(&mut self, r: &Rvalue, locals: &mut Locals) -> Result<IntervalOrOwned> { + let interner = DbInterner::new_with(self.db, None, None); use IntervalOrOwned::*; Ok(match r { Rvalue::Use(it) => Borrowed(self.eval_operand(it, locals)?), @@ -1436,7 +1458,7 @@ impl Evaluator<'_> { Owned(r) } AggregateKind::Tuple(ty) => { - let layout = self.layout(ty)?; + let layout = self.layout(ty.to_nextsolver(interner))?; Owned(self.construct_with_layout( layout.size.bytes_usize(), &layout, @@ -1467,7 +1489,7 @@ impl Evaluator<'_> { )?) } AggregateKind::Closure(ty) => { - let layout = self.layout(ty)?; + let layout = self.layout(ty.to_nextsolver(interner))?; Owned(self.construct_with_layout( layout.size.bytes_usize(), &layout, @@ -1484,6 +1506,8 @@ impl Evaluator<'_> { if let TyKind::FnDef(_, _) | TyKind::Closure(_, _) = ¤t_ty.kind(Interner) { + let interner = DbInterner::new_with(self.db, None, None); + let current_ty = current_ty.to_nextsolver(interner); let id = self.vtable_map.id(current_ty); let ptr_size = self.ptr_size(); Owned(id.to_le_bytes()[0..ptr_size].to_vec()) @@ -1623,7 +1647,8 @@ impl Evaluator<'_> { } fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<i128> { - let layout = self.layout(&ty)?; + let interner = DbInterner::new_with(self.db, None, None); + let layout = self.layout(ty.to_nextsolver(interner))?; let &TyKind::Adt(chalk_ir::AdtId(AdtId::EnumId(e)), _) = ty.kind(Interner) else { return Ok(0); }; @@ -1732,6 +1757,8 @@ impl Evaluator<'_> { } }, TyKind::Dyn(_) => { + let interner = DbInterner::new_with(self.db, None, None); + let current_ty = current_ty.to_nextsolver(interner); let vtable = self.vtable_map.id(current_ty); let mut r = Vec::with_capacity(16); let addr = addr.get(self)?; @@ -1777,6 +1804,7 @@ impl Evaluator<'_> { subst: Substitution, locals: &Locals, ) -> Result<(usize, Arc<Layout>, Option<(usize, usize, i128)>)> { + let interner = DbInterner::new_with(self.db, None, None); let adt = it.adt_id(self.db); if let DefWithBodyId::VariantId(f) = locals.body.owner && let VariantId::EnumVariantId(it) = it @@ -1786,7 +1814,11 @@ impl Evaluator<'_> { // 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)))); + return Ok(( + 16, + self.layout(crate::next_solver::Ty::new_empty_tuple(interner))?, + Some((0, 16, i)), + )); } let layout = self.layout_adt(adt, subst)?; Ok(match &layout.variants { @@ -1885,6 +1917,7 @@ impl Evaluator<'_> { #[allow(clippy::double_parens)] fn allocate_const_in_heap(&mut self, locals: &Locals, konst: &Const) -> Result<Interval> { + let interner = DbInterner::new_with(self.db, None, None); let ConstData { ty, value: chalk_ir::ConstValue::Concrete(c) } = &konst.data(Interner) else { not_supported!("evaluating non concrete constant"); @@ -1945,7 +1978,7 @@ impl Evaluator<'_> { MemoryMap::Complex(cm) => cm.vtable.ty_of_bytes(bytes), }, addr, - ty, + ty.to_nextsolver(interner), locals, )?; Ok(Interval::new(addr, size)) @@ -2048,7 +2081,8 @@ impl Evaluator<'_> { } fn size_align_of(&self, ty: &Ty, locals: &Locals) -> Result<Option<(usize, usize)>> { - if let Some(layout) = self.layout_cache.borrow().get(ty) { + let interner = DbInterner::new_with(self.db, None, None); + if let Some(layout) = self.layout_cache.borrow().get(&ty.to_nextsolver(interner)) { return Ok(layout .is_sized() .then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize))); @@ -2061,7 +2095,7 @@ impl Evaluator<'_> { // infinite sized type errors) we use a dummy size return Ok(Some((16, 16))); } - let layout = self.layout(ty); + let layout = self.layout(ty.to_nextsolver(interner)); if self.assert_placeholder_ty_is_unused && matches!(layout, Err(MirEvalError::LayoutError(LayoutError::HasPlaceholder, _))) { @@ -2129,15 +2163,16 @@ impl Evaluator<'_> { bytes: &[u8], ty: &Ty, locals: &Locals, - ) -> Result<ComplexMemoryMap> { - fn rec( - this: &Evaluator<'_>, + ) -> Result<ComplexMemoryMap<'db>> { + fn rec<'db>( + this: &Evaluator<'db>, bytes: &[u8], ty: &Ty, locals: &Locals, - mm: &mut ComplexMemoryMap, + mm: &mut ComplexMemoryMap<'db>, stack_depth_limit: usize, ) -> Result<()> { + let interner = DbInterner::new_with(this.db, None, None); if stack_depth_limit.checked_sub(1).is_none() { return Err(MirEvalError::StackOverflow); } @@ -2158,13 +2193,14 @@ impl Evaluator<'_> { let element_size = match t.kind(Interner) { TyKind::Str => 1, TyKind::Slice(t) => { - check_inner = Some(t); + check_inner = Some(t.clone()); this.size_of_sized(t, locals, "slice inner type")? } TyKind::Dyn(_) => { let t = this.vtable_map.ty_of_bytes(meta)?; - check_inner = Some(t); - this.size_of_sized(t, locals, "dyn concrete type")? + let t = convert_ty_for_result(interner, t); + check_inner = Some(t.clone()); + this.size_of_sized(&t, locals, "dyn concrete type")? } _ => return Ok(()), }; @@ -2176,7 +2212,7 @@ impl Evaluator<'_> { let addr = Address::from_bytes(addr)?; let b = this.read_memory(addr, size)?; mm.insert(addr.to_usize(), b.into()); - if let Some(ty) = check_inner { + if let Some(ty) = &check_inner { for i in 0..count { let offset = element_size * i; rec( @@ -2211,11 +2247,11 @@ impl Evaluator<'_> { } } TyKind::Tuple(_, subst) => { - let layout = this.layout(ty)?; + let layout = this.layout(ty.to_nextsolver(interner))?; for (id, ty) in subst.iter(Interner).enumerate() { let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument let offset = layout.fields.offset(id).bytes_usize(); - let size = this.layout(ty)?.size.bytes_usize(); + let size = this.layout(ty.to_nextsolver(interner))?.size.bytes_usize(); rec( this, &bytes[offset..offset + size], @@ -2229,7 +2265,7 @@ impl Evaluator<'_> { TyKind::Adt(adt, subst) => match adt.0 { AdtId::StructId(s) => { let data = s.fields(this.db); - let layout = this.layout(ty)?; + let layout = this.layout(ty.to_nextsolver(interner))?; let field_types = this.db.field_types(s.into()); for (f, _) in data.fields().iter() { let offset = layout @@ -2237,7 +2273,7 @@ impl Evaluator<'_> { .offset(u32::from(f.into_raw()) as usize) .bytes_usize(); let ty = &field_types[f].clone().substitute(Interner, subst); - let size = this.layout(ty)?.size.bytes_usize(); + let size = this.layout(ty.to_nextsolver(interner))?.size.bytes_usize(); rec( this, &bytes[offset..offset + size], @@ -2249,7 +2285,7 @@ impl Evaluator<'_> { } } AdtId::EnumId(e) => { - let layout = this.layout(ty)?; + let layout = this.layout(ty.to_nextsolver(interner))?; if let Some((v, l)) = detect_variant_from_bytes( &layout, this.db, @@ -2263,7 +2299,8 @@ impl Evaluator<'_> { let offset = l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize(); let ty = &field_types[f].clone().substitute(Interner, subst); - let size = this.layout(ty)?.size.bytes_usize(); + let size = + this.layout(ty.to_nextsolver(interner))?.size.bytes_usize(); rec( this, &bytes[offset..offset + size], @@ -2290,20 +2327,26 @@ impl Evaluator<'_> { Ok(mm) } - fn patch_addresses<'vtable>( + fn patch_addresses( &mut self, patch_map: &FxHashMap<usize, usize>, - ty_of_bytes: impl Fn(&[u8]) -> Result<&'vtable Ty> + Copy, + ty_of_bytes: impl Fn(&[u8]) -> Result<crate::next_solver::Ty<'db>> + Copy, addr: Address, - ty: &Ty, + ty: crate::next_solver::Ty<'db>, locals: &Locals, ) -> Result<()> { + let interner = DbInterner::new_with(self.db, None, None); // FIXME: support indirect references let layout = self.layout(ty)?; - let my_size = self.size_of_sized(ty, locals, "value to patch address")?; - match ty.kind(Interner) { - TyKind::Ref(_, _, t) => { - let size = self.size_align_of(t, locals)?; + let my_size = self.size_of_sized( + &convert_ty_for_result(interner, ty), + locals, + "value to patch address", + )?; + use rustc_type_ir::TyKind; + match ty.kind() { + TyKind::Ref(_, t, _) => { + let size = self.size_align_of(&convert_ty_for_result(interner, t), locals)?; match size { Some(_) => { let current = from_bytes!(usize, self.read_memory(addr, my_size)?); @@ -2319,21 +2362,21 @@ impl Evaluator<'_> { } } } - TyKind::Function(_) => { - let ty = ty_of_bytes(self.read_memory(addr, my_size)?)?.clone(); + TyKind::FnPtr(_, _) => { + let ty = ty_of_bytes(self.read_memory(addr, my_size)?)?; let new_id = self.vtable_map.id(ty); self.write_memory(addr, &new_id.to_le_bytes())?; } - TyKind::Adt(id, subst) => match id.0 { + TyKind::Adt(id, args) => match id.def_id().0 { AdtId::StructId(s) => { - for (i, (_, ty)) in self.db.field_types(s.into()).iter().enumerate() { + for (i, (_, ty)) in self.db.field_types_ns(s.into()).iter().enumerate() { let offset = layout.fields.offset(i).bytes_usize(); - let ty = ty.clone().substitute(Interner, subst); + let ty = ty.instantiate(interner, args); self.patch_addresses( patch_map, ty_of_bytes, addr.offset(offset), - &ty, + ty, locals, )?; } @@ -2347,33 +2390,36 @@ impl Evaluator<'_> { self.read_memory(addr, layout.size.bytes_usize())?, e, ) { - for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() { + for (i, (_, ty)) in self.db.field_types_ns(ev.into()).iter().enumerate() { let offset = layout.fields.offset(i).bytes_usize(); - let ty = ty.clone().substitute(Interner, subst); + let ty = ty.instantiate(interner, args); self.patch_addresses( patch_map, ty_of_bytes, addr.offset(offset), - &ty, + ty, locals, )?; } } } }, - TyKind::Tuple(_, subst) => { - for (id, ty) in subst.iter(Interner).enumerate() { - let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument + TyKind::Tuple(tys) => { + for (id, ty) in tys.iter().enumerate() { let offset = layout.fields.offset(id).bytes_usize(); self.patch_addresses(patch_map, ty_of_bytes, addr.offset(offset), ty, locals)?; } } TyKind::Array(inner, len) => { - let len = match try_const_usize(self.db, len) { + let len = match consteval_nextsolver::try_const_usize(self.db, len) { Some(it) => it as usize, None => not_supported!("non evaluatable array len in patching addresses"), }; - let size = self.size_of_sized(inner, locals, "inner of array")?; + let size = self.size_of_sized( + &convert_ty_for_result(interner, inner), + locals, + "inner of array", + )?; for i in 0..len { self.patch_addresses( patch_map, @@ -2384,11 +2430,13 @@ impl Evaluator<'_> { )?; } } - TyKind::AssociatedType(_, _) - | TyKind::Scalar(_) + TyKind::Bool + | TyKind::Char + | TyKind::Int(_) + | TyKind::Uint(_) + | TyKind::Float(_) | TyKind::Slice(_) - | TyKind::Raw(_, _) - | TyKind::OpaqueType(_, _) + | TyKind::RawPtr(_, _) | TyKind::FnDef(_, _) | TyKind::Str | TyKind::Never @@ -2396,12 +2444,16 @@ impl Evaluator<'_> { | TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) | TyKind::Foreign(_) - | TyKind::Error + | TyKind::Error(_) | TyKind::Placeholder(_) - | TyKind::Dyn(_) - | TyKind::Alias(_) - | TyKind::BoundVar(_) - | TyKind::InferenceVar(_, _) => (), + | TyKind::Dynamic(_, _) + | TyKind::Alias(_, _) + | TyKind::Bound(_, _) + | TyKind::Infer(_) + | TyKind::Pat(_, _) + | TyKind::Param(_) + | TyKind::UnsafeBinder(_) + | TyKind::CoroutineClosure(_, _) => (), } Ok(()) } @@ -2416,14 +2468,28 @@ impl Evaluator<'_> { span: MirSpan, ) -> Result<Option<StackFrame>> { let id = from_bytes!(usize, bytes.get(self)?); - let next_ty = self.vtable_map.ty(id)?.clone(); - match next_ty.kind(Interner) { - TyKind::FnDef(def, generic_args) => { - self.exec_fn_def(*def, generic_args, destination, args, locals, target_bb, span) - } - TyKind::Closure(id, subst) => { - self.exec_closure(*id, bytes.slice(0..0), subst, destination, args, locals, span) - } + let next_ty = self.vtable_map.ty(id)?; + let interner = DbInterner::new_with(self.db, None, None); + use rustc_type_ir::TyKind; + match next_ty.kind() { + TyKind::FnDef(def, generic_args) => self.exec_fn_def( + def.0, + &convert_args_for_result(interner, generic_args.as_slice()), + destination, + args, + locals, + target_bb, + span, + ), + TyKind::Closure(id, generic_args) => self.exec_closure( + id.0.into(), + bytes.slice(0..0), + &convert_args_for_result(interner, generic_args.as_slice()), + destination, + args, + locals, + span, + ), _ => Err(MirEvalError::InternalError("function pointer to non function".into())), } } @@ -2469,7 +2535,7 @@ impl Evaluator<'_> { fn exec_fn_def( &mut self, - def: FnDefId, + def: CallableDefId, generic_args: &Substitution, destination: Interval, args: &[IntervalAndTy], @@ -2477,7 +2543,6 @@ impl Evaluator<'_> { target_bb: Option<BasicBlockId>, span: MirSpan, ) -> Result<Option<StackFrame>> { - let def: CallableDefId = from_chalk(self.db, def); let generic_args = generic_args.clone(); match def { CallableDefId::FunctionId(def) => { @@ -2574,6 +2639,7 @@ impl Evaluator<'_> { target_bb: Option<BasicBlockId>, span: MirSpan, ) -> Result<Option<StackFrame>> { + let interner = DbInterner::new_with(self.db, None, None); if self.detect_and_exec_special_function( def, args, @@ -2600,6 +2666,7 @@ impl Evaluator<'_> { .vtable_map .ty_of_bytes(&first_arg[self.ptr_size()..self.ptr_size() * 2])?; let mut args_for_target = args.to_vec(); + let ty = convert_ty_for_result(interner, ty); args_for_target[0] = IntervalAndTy { interval: args_for_target[0].interval.slice(0..self.ptr_size()), ty: ty.clone(), @@ -2672,6 +2739,7 @@ impl Evaluator<'_> { target_bb: Option<BasicBlockId>, span: MirSpan, ) -> Result<Option<StackFrame>> { + let interner = DbInterner::new_with(self.db, None, None); let func = args .first() .ok_or_else(|| MirEvalError::InternalError("fn trait with no arg".into()))?; @@ -2683,22 +2751,28 @@ impl Evaluator<'_> { 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(); + func_ty = convert_ty_for_result(interner, self.vtable_map.ty(id)?); } 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.kind(Interner) { - TyKind::FnDef(def, subst) => { - self.exec_fn_def(*def, subst, destination, &args[1..], locals, target_bb, span) - } + TyKind::FnDef(def, subst) => self.exec_fn_def( + CallableDefId::from_chalk(self.db, *def), + subst, + destination, + &args[1..], + locals, + target_bb, + span, + ), TyKind::Function(_) => { self.exec_fn_pointer(func_data, destination, &args[1..], locals, target_bb, span) } TyKind::Closure(closure, subst) => self.exec_closure( *closure, func_data, - &Substitution::from_iter(Interner, ClosureSubst(subst).parent_subst()), + &ClosureSubst(subst).parent_subst(self.db), destination, &args[1..], locals, @@ -2714,7 +2788,7 @@ impl Evaluator<'_> { Substitution::from_iter(Interner, args.iter().map(|it| it.ty.clone())), ) .intern(Interner); - let layout = self.layout(&ty)?; + let layout = self.layout(ty.to_nextsolver(interner))?; let result = self.construct_with_layout( layout.size.bytes_usize(), &layout, @@ -2901,6 +2975,7 @@ pub fn render_const_using_debug_impl( owner: DefWithBodyId, c: &Const, ) -> Result<String> { + let interner = DbInterner::new_with(db, None, None); let mut evaluator = Evaluator::new(db, owner, false, None)?; let locals = &Locals { ptr: ArenaMap::new(), @@ -2933,7 +3008,8 @@ pub fn render_const_using_debug_impl( CallableDefId::FunctionId(debug_fmt_fn).to_chalk(db), Substitution::from1(Interner, c.data(Interner).ty.clone()), ) - .intern(Interner)); + .intern(Interner) + .to_nextsolver(interner)); evaluator.write_memory(a2.offset(evaluator.ptr_size()), &debug_fmt_fn_ptr.to_le_bytes())?; // a3 = ::core::fmt::Arguments::new_v1(a1, a2) // FIXME: similarly, we should call function here, not directly working with memory. |