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 | 922 |
1 files changed, 430 insertions, 492 deletions
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 6e09cf9aeb..444336ca3f 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -2,14 +2,11 @@ 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 base_db::{Crate, target::TargetLoadError}; use either::Either; use hir_def::{ - AdtId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, StaticId, - VariantId, - builtin_type::BuiltinType, + AdtId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, HasModule, ItemContainerId, + Lookup, StaticId, VariantId, expr_store::HygieneId, item_tree::FieldsShape, lang_item::LangItem, @@ -25,33 +22,33 @@ use rustc_apfloat::{ Float, ieee::{Half as f16, Quad as f128}, }; +use rustc_ast_ir::Mutability; use rustc_hash::{FxHashMap, FxHashSet}; -use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike}; +use rustc_type_ir::{ + AliasTyKind, + inherent::{AdtDef, IntoKind, Region as _, SliceLike, Ty as _}, +}; use span::FileId; use stdx::never; use syntax::{SyntaxNodePtr, TextRange}; use triomphe::Arc; use crate::{ - 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}, + CallableDefId, ComplexMemoryMap, MemoryMap, TraitEnvironment, + consteval::{self, ConstEvalError, try_const_usize}, + db::{HirDatabase, InternedClosure, InternedClosureId}, display::{ClosureStyle, DisplayTarget, HirDisplay}, infer::PointerCast, layout::{Layout, LayoutError, RustcEnumVariantIdx}, method_resolution::{is_dyn_method, lookup_impl_const}, next_solver::{ - DbInterner, TypingMode, - infer::{DbInternerInferExt, InferCtxt}, - mapping::{ - ChalkToNextSolver, NextSolverToChalk, convert_args_for_result, convert_ty_for_result, - }, + Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, Region, + SolverDefId, Ty, TyKind, TypingMode, UnevaluatedConst, ValueConst, + infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause}, + obligation_ctxt::ObligationCtxt, }, - static_lifetime, traits::FnTrait, - utils::{ClosureSubst, detect_variant_from_bytes}, + utils::detect_variant_from_bytes, }; use super::{ @@ -88,14 +85,14 @@ macro_rules! not_supported { #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct VTableMap<'db> { - ty_to_id: FxHashMap<crate::next_solver::Ty<'db>, usize>, - id_to_ty: Vec<crate::next_solver::Ty<'db>>, + ty_to_id: FxHashMap<Ty<'db>, usize>, + id_to_ty: Vec<Ty<'db>>, } 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: crate::next_solver::Ty<'db>) -> usize { + fn id(&mut self, ty: Ty<'db>) -> usize { if let Some(it) = self.ty_to_id.get(&ty) { return *it; } @@ -105,13 +102,13 @@ impl<'db> VTableMap<'db> { id } - pub(crate) fn ty(&self, id: usize) -> Result<'db, crate::next_solver::Ty<'db>> { + pub(crate) fn ty(&self, id: usize) -> Result<'db, Ty<'db>> { id.checked_sub(VTableMap::OFFSET) .and_then(|id| self.id_to_ty.get(id).copied()) .ok_or(MirEvalError::InvalidVTableId(id)) } - fn ty_of_bytes(&self, bytes: &[u8]) -> Result<'db, crate::next_solver::Ty<'db>> { + fn ty_of_bytes(&self, bytes: &[u8]) -> Result<'db, Ty<'db>> { let id = from_bytes!(usize, bytes); self.ty(id) } @@ -153,45 +150,45 @@ impl TlsData { } } -struct StackFrame { - locals: Locals, - destination: Option<BasicBlockId>, +struct StackFrame<'db> { + locals: Locals<'db>, + destination: Option<BasicBlockId<'db>>, prev_stack_ptr: usize, span: (MirSpan, DefWithBodyId), } #[derive(Clone)] -enum MirOrDynIndex { - Mir(Arc<MirBody>), +enum MirOrDynIndex<'db> { + Mir(Arc<MirBody<'db>>), Dyn(usize), } -pub struct Evaluator<'a> { - db: &'a dyn HirDatabase, - trait_env: Arc<TraitEnvironment<'a>>, +pub struct Evaluator<'db> { + db: &'db dyn HirDatabase, + trait_env: Arc<TraitEnvironment<'db>>, target_data_layout: Arc<TargetDataLayout>, stack: Vec<u8>, heap: Vec<u8>, - code_stack: Vec<StackFrame>, + code_stack: Vec<StackFrame<'db>>, /// Stores the global location of the statics. We const evaluate every static first time we need it /// and see it's missing, then we add it to this to reuse. static_locations: FxHashMap<StaticId, Address>, /// 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<'a>, + vtable_map: VTableMap<'db>, thread_local_storage: TlsData, random_state: oorandom::Rand64, stdout: Vec<u8>, stderr: Vec<u8>, - layout_cache: RefCell<FxHashMap<crate::next_solver::Ty<'a>, Arc<Layout>>>, - projected_ty_cache: RefCell<FxHashMap<(Ty, PlaceElem), Ty>>, + layout_cache: RefCell<FxHashMap<Ty<'db>, Arc<Layout>>>, + projected_ty_cache: RefCell<FxHashMap<(Ty<'db>, PlaceElem<'db>), Ty<'db>>>, not_special_fn_cache: RefCell<FxHashSet<FunctionId>>, - mir_or_dyn_index_cache: RefCell<FxHashMap<(FunctionId, Substitution), MirOrDynIndex>>, - /// Constantly dropping and creating `Locals` is very costly. We store + mir_or_dyn_index_cache: RefCell<FxHashMap<(FunctionId, GenericArgs<'db>), MirOrDynIndex<'db>>>, + /// Constantly dropping and creating `Locals<'db>` is very costly. We store /// old locals that we normally want to drop here, to reuse their allocations /// later. - unused_locals_store: RefCell<FxHashMap<DefWithBodyId, Vec<Locals>>>, + unused_locals_store: RefCell<FxHashMap<DefWithBodyId, Vec<Locals<'db>>>>, cached_ptr_size: usize, cached_fn_trait_func: Option<FunctionId>, cached_fn_mut_trait_func: Option<FunctionId>, @@ -205,8 +202,7 @@ pub struct Evaluator<'a> { stack_depth_limit: usize, /// Maximum count of bytes that heap and stack can grow memory_limit: usize, - interner: DbInterner<'a>, - infcx: InferCtxt<'a>, + infcx: InferCtxt<'db>, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -225,9 +221,9 @@ struct Interval { } #[derive(Debug, Clone)] -struct IntervalAndTy { +struct IntervalAndTy<'db> { interval: Interval, - ty: Ty, + ty: Ty<'db>, } impl Interval { @@ -256,18 +252,18 @@ impl Interval { } } -impl IntervalAndTy { - fn get<'a, 'db>(&self, memory: &'a Evaluator<'db>) -> Result<'db, &'a [u8]> { +impl<'db> IntervalAndTy<'db> { + fn get<'a>(&self, memory: &'a Evaluator<'db>) -> Result<'db, &'a [u8]> { memory.read_memory(self.interval.addr, self.interval.size) } - fn new<'db>( + fn new( addr: Address, - ty: Ty, + ty: Ty<'db>, evaluator: &Evaluator<'db>, - locals: &Locals, - ) -> Result<'db, IntervalAndTy> { - let size = evaluator.size_of_sized(&ty, locals, "type of interval")?; + locals: &Locals<'db>, + ) -> Result<'db, IntervalAndTy<'db>> { + let size = evaluator.size_of_sized(ty, locals, "type of interval")?; Ok(IntervalAndTy { interval: Interval { addr, size }, ty }) } } @@ -346,7 +342,7 @@ impl Address { #[derive(Clone, PartialEq, Eq)] pub enum MirEvalError<'db> { ConstEvalError(String, Box<ConstEvalError<'db>>), - LayoutError(LayoutError, Ty), + LayoutError(LayoutError, Ty<'db>), 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. @@ -354,20 +350,20 @@ pub enum MirEvalError<'db> { Panic(String), // FIXME: This should be folded into ConstEvalError? MirLowerError(FunctionId, MirLowerError<'db>), - MirLowerErrorForClosure(ClosureId, MirLowerError<'db>), - TypeIsUnsized(Ty, &'static str), + MirLowerErrorForClosure(InternedClosureId, MirLowerError<'db>), + TypeIsUnsized(Ty<'db>, &'static str), NotSupported(String), - InvalidConst(Const), + InvalidConst(Const<'db>), InFunction( Box<MirEvalError<'db>>, - Vec<(Either<FunctionId, ClosureId>, MirSpan, DefWithBodyId)>, + Vec<(Either<FunctionId, InternedClosureId>, MirSpan, DefWithBodyId)>, ), ExecutionLimitExceeded, StackOverflow, /// FIXME: Fold this into InternalError InvalidVTableId(usize), /// ? - CoerceUnsizedError(Ty), + CoerceUnsizedError(Ty<'db>), /// These should not occur, usually indicates a bug in mir lowering. InternalError(Box<str>), } @@ -443,13 +439,8 @@ impl MirEvalError<'_> { let function_name = db.function_signature(*func); let self_ = match func.lookup(db).container { ItemContainerId::ImplId(impl_id) => Some({ - let generics = crate::generics::generics(db, impl_id.into()); - let interner = DbInterner::new_with(db, None, None); - let substs = generics.placeholder_subst(db); - let args: crate::next_solver::GenericArgs<'_> = - substs.to_nextsolver(interner); db.impl_self_ty(impl_id) - .instantiate(interner, args) + .instantiate_identity() .display(db, display_target) .to_string() }), @@ -535,10 +526,7 @@ impl std::fmt::Debug for MirEvalError<'_> { Self::InternalError(arg0) => f.debug_tuple("InternalError").field(arg0).finish(), Self::InvalidVTableId(arg0) => f.debug_tuple("InvalidVTableId").field(arg0).finish(), Self::NotSupported(arg0) => f.debug_tuple("NotSupported").field(arg0).finish(), - Self::InvalidConst(arg0) => { - let data = &arg0.data(Interner); - f.debug_struct("InvalidConst").field("ty", &data.ty).field("value", &arg0).finish() - } + Self::InvalidConst(arg0) => f.debug_tuple("InvalidConst").field(&arg0).finish(), Self::InFunction(e, stack) => { f.debug_struct("WithStack").field("error", e).field("stack", &stack).finish() } @@ -549,12 +537,12 @@ impl std::fmt::Debug for MirEvalError<'_> { type Result<'db, T> = std::result::Result<T, MirEvalError<'db>>; #[derive(Debug, Default)] -struct DropFlags { - need_drop: FxHashSet<Place>, +struct DropFlags<'db> { + need_drop: FxHashSet<Place<'db>>, } -impl DropFlags { - fn add_place(&mut self, p: Place, store: &ProjectionStore) { +impl<'db> DropFlags<'db> { + fn add_place(&mut self, p: Place<'db>, store: &ProjectionStore<'db>) { if p.iterate_over_parents(store).any(|it| self.need_drop.contains(&it)) { return; } @@ -562,7 +550,7 @@ impl DropFlags { self.need_drop.insert(p); } - fn remove_place(&mut self, p: &Place, store: &ProjectionStore) -> bool { + fn remove_place(&mut self, p: &Place<'db>, store: &ProjectionStore<'db>) -> bool { // FIXME: replace parents with parts if let Some(parent) = p.iterate_over_parents(store).find(|it| self.need_drop.contains(it)) { self.need_drop.remove(&parent); @@ -577,10 +565,10 @@ impl DropFlags { } #[derive(Debug)] -struct Locals { - ptr: ArenaMap<LocalId, Interval>, - body: Arc<MirBody>, - drop_flags: DropFlags, +struct Locals<'db> { + ptr: ArenaMap<LocalId<'db>, Interval>, + body: Arc<MirBody<'db>>, + drop_flags: DropFlags<'db>, } pub struct MirOutput { @@ -599,7 +587,7 @@ impl MirOutput { pub fn interpret_mir<'db>( db: &'db dyn HirDatabase, - body: Arc<MirBody>, + body: Arc<MirBody<'db>>, // FIXME: This is workaround. Ideally, const generics should have a separate body (issue #7434), but now // they share their body with their parent, so in MIR lowering we have locals of the parent body, which // might have placeholders. With this argument, we (wrongly) assume that every placeholder type has @@ -607,10 +595,10 @@ pub fn interpret_mir<'db>( // (and probably should) do better here, for example by excluding bindings outside of the target expression. assert_placeholder_ty_is_unused: bool, trait_env: Option<Arc<TraitEnvironment<'db>>>, -) -> Result<'db, (Result<'db, Const>, MirOutput)> { - let ty = body.locals[return_slot()].ty.clone(); +) -> Result<'db, (Result<'db, Const<'db>>, MirOutput)> { + let ty = body.locals[return_slot()].ty; let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env)?; - let it: Result<'db, Const> = (|| { + let it: Result<'db, Const<'db>> = (|| { if evaluator.ptr_size() != size_of::<usize>() { not_supported!("targets with different pointer size from host"); } @@ -618,7 +606,7 @@ pub fn interpret_mir<'db>( let bytes = interval.get(&evaluator)?; let mut memory_map = evaluator.create_memory_map( bytes, - &ty, + ty, &Locals { ptr: ArenaMap::new(), body, drop_flags: DropFlags::default() }, )?; let bytes = bytes.into(); @@ -629,13 +617,7 @@ pub fn interpret_mir<'db>( memory_map.vtable.shrink_to_fit(); MemoryMap::Complex(Box::new(memory_map)) }; - // 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(Const::new_valtree(evaluator.interner(), ty, bytes, memory_map)) })(); Ok((it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr })) } @@ -652,13 +634,15 @@ impl<'db> Evaluator<'db> { assert_placeholder_ty_is_unused: bool, trait_env: Option<Arc<TraitEnvironment<'db>>>, ) -> Result<'db, Evaluator<'db>> { - let crate_id = owner.module(db).krate(); + let module = owner.module(db); + let crate_id = module.krate(); let target_data_layout = match db.target_data_layout(crate_id) { Ok(target_data_layout) => target_data_layout, Err(e) => return Err(MirEvalError::TargetDataLayoutNotAvailable(e)), }; let cached_ptr_size = target_data_layout.pointer_size().bytes_usize(); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_with(db, Some(crate_id), module.containing_block()); + let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); Ok(Evaluator { target_data_layout, stack: vec![0], @@ -692,21 +676,25 @@ impl<'db> Evaluator<'db> { cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| { x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_once)) }), - interner, - infcx: interner.infer_ctxt().build(TypingMode::non_body_analysis()), + infcx, }) } - fn place_addr(&self, p: &Place, locals: &Locals) -> Result<'db, Address> { + #[inline] + fn interner(&self) -> DbInterner<'db> { + self.infcx.interner + } + + fn place_addr(&self, p: &Place<'db>, locals: &Locals<'db>) -> Result<'db, Address> { Ok(self.place_addr_and_ty_and_metadata(p, locals)?.0) } - fn place_interval(&self, p: &Place, locals: &Locals) -> Result<'db, Interval> { + fn place_interval(&self, p: &Place<'db>, locals: &Locals<'db>) -> Result<'db, Interval> { let place_addr_and_ty = self.place_addr_and_ty_and_metadata(p, locals)?; Ok(Interval { addr: place_addr_and_ty.0, size: self.size_of_sized( - &place_addr_and_ty.1, + place_addr_and_ty.1, locals, "Type of place that we need its interval", )?, @@ -717,54 +705,46 @@ impl<'db> Evaluator<'db> { self.cached_ptr_size } - fn projected_ty(&self, ty: Ty, proj: PlaceElem) -> Ty { + fn projected_ty(&self, ty: Ty<'db>, proj: PlaceElem<'db>) -> Ty<'db> { let pair = (ty, proj); if let Some(r) = self.projected_ty_cache.borrow().get(&pair) { - return r.clone(); + return *r; } let (ty, proj) = pair; let r = proj.projected_ty( - ty.clone(), - self.db, + &self.infcx, + ty, |c, subst, f| { - let InternedClosure(def, _) = self.db.lookup_intern_closure(c.into()); + let InternedClosure(def, _) = self.db.lookup_intern_closure(c); let infer = self.db.infer(def); - let (captures, _) = infer.closure_info(c.into()); - let parent_subst = ClosureSubst(subst).parent_subst(self.db); + let (captures, _) = infer.closure_info(c); + let parent_subst = subst.split_closure_args_untupled().parent_args; captures .get(f) .expect("broken closure field") .ty - .instantiate( - self.interner, - <_ as ChalkToNextSolver<'db, crate::next_solver::GenericArgs<'db>>>::to_nextsolver( - &parent_subst, - self.interner, - ), - ) - .to_chalk(self.interner) + .instantiate(self.interner(), parent_subst) }, self.crate_id, ); - self.projected_ty_cache.borrow_mut().insert((ty, proj), r.clone()); + self.projected_ty_cache.borrow_mut().insert((ty, proj), r); r } fn place_addr_and_ty_and_metadata<'a>( &'a self, - p: &Place, - locals: &'a Locals, - ) -> Result<'db, (Address, Ty, Option<IntervalOrOwned>)> { - let interner = DbInterner::new_with(self.db, None, None); + p: &Place<'db>, + locals: &'a Locals<'db>, + ) -> Result<'db, (Address, Ty<'db>, Option<IntervalOrOwned>)> { let mut addr = locals.ptr[p.local].addr; - let mut ty: Ty = locals.body.locals[p.local].ty.clone(); + let mut ty: Ty<'db> = locals.body.locals[p.local].ty; let mut metadata: Option<IntervalOrOwned> = None; // locals are always sized for proj in p.projection.lookup(&locals.body.projection_store) { - let prev_ty = ty.clone(); + let prev_ty = ty; ty = self.projected_ty(ty, proj.clone()); match proj { ProjectionElem::Deref => { - metadata = if self.size_align_of(&ty, locals)?.is_none() { + metadata = if self.size_align_of(ty, locals)?.is_none() { Some( Interval { addr: addr.offset(self.ptr_size()), size: self.ptr_size() } .into(), @@ -782,12 +762,12 @@ impl<'db> Evaluator<'db> { ); metadata = None; // Result of index is always sized let ty_size = - self.size_of_sized(&ty, locals, "array inner type should be sized")?; + self.size_of_sized(ty, locals, "array inner type should be sized")?; addr = addr.offset(ty_size * offset); } &ProjectionElem::ConstantIndex { from_end, offset } => { let offset = if from_end { - let len = match prev_ty.kind(Interner) { + let len = match prev_ty.kind() { TyKind::Array(_, c) => match try_const_usize(self.db, c) { Some(it) => it as u64, None => { @@ -806,13 +786,13 @@ impl<'db> Evaluator<'db> { }; metadata = None; // Result of index is always sized let ty_size = - self.size_of_sized(&ty, locals, "array inner type should be sized")?; + self.size_of_sized(ty, locals, "array inner type should be sized")?; addr = addr.offset(ty_size * offset); } &ProjectionElem::Subslice { from, to } => { - let inner_ty = match &ty.kind(Interner) { - TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(), - _ => TyKind::Error.intern(Interner), + let inner_ty = match ty.kind() { + TyKind::Array(inner, _) | TyKind::Slice(inner) => inner, + _ => Ty::new_error(self.interner(), ErrorGuaranteed), }; metadata = match metadata { Some(it) => { @@ -824,23 +804,23 @@ impl<'db> Evaluator<'db> { None => None, }; let ty_size = - self.size_of_sized(&inner_ty, locals, "array inner type should be sized")?; + self.size_of_sized(inner_ty, locals, "array inner type should be sized")?; addr = addr.offset(ty_size * (from as usize)); } &ProjectionElem::ClosureField(f) => { - let layout = self.layout(prev_ty.to_nextsolver(interner))?; + let layout = self.layout(prev_ty)?; 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.to_nextsolver(interner))?; + let layout = self.layout(prev_ty)?; 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.to_nextsolver(interner))?; + let layout = self.layout(prev_ty)?; let variant_layout = match &layout.variants { Variants::Single { .. } | Variants::Empty => &layout, Variants::Multiple { variants, .. } => { @@ -862,7 +842,7 @@ impl<'db> Evaluator<'db> { .bytes_usize(); addr = addr.offset(offset); // Unsized field metadata is equal to the metadata of the struct - if self.size_align_of(&ty, locals)?.is_some() { + if self.size_align_of(ty, locals)?.is_some() { metadata = None; } } @@ -872,51 +852,47 @@ impl<'db> Evaluator<'db> { Ok((addr, ty, metadata)) } - fn layout(&self, ty: crate::next_solver::Ty<'db>) -> Result<'db, Arc<Layout>> { + fn layout(&self, ty: Ty<'db>) -> Result<'db, 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, self.trait_env.clone()) - .map_err(|e| MirEvalError::LayoutError(e, convert_ty_for_result(interner, ty)))?; + .map_err(|e| MirEvalError::LayoutError(e, ty))?; self.layout_cache.borrow_mut().insert(ty, r.clone()); Ok(r) } - fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result<'db, Arc<Layout>> { - 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 layout_adt(&self, adt: AdtId, subst: GenericArgs<'db>) -> Result<'db, Arc<Layout>> { + self.layout(Ty::new_adt(self.interner(), adt, subst)) } - fn place_ty<'a>(&'a self, p: &Place, locals: &'a Locals) -> Result<'db, Ty> { + fn place_ty<'a>(&'a self, p: &Place<'db>, locals: &'a Locals<'db>) -> Result<'db, Ty<'db>> { Ok(self.place_addr_and_ty_and_metadata(p, locals)?.1) } - fn operand_ty(&self, o: &Operand, locals: &Locals) -> Result<'db, Ty> { + fn operand_ty(&self, o: &Operand<'db>, locals: &Locals<'db>) -> Result<'db, Ty<'db>> { Ok(match &o.kind { OperandKind::Copy(p) | OperandKind::Move(p) => self.place_ty(p, locals)?, - OperandKind::Constant(c) => c.data(Interner).ty.clone(), + OperandKind::Constant { konst: _, ty } => *ty, &OperandKind::Static(s) => { - let ty = self.db.infer(s.into())[self.db.body(s.into()).body_expr] - .to_chalk(self.interner); - TyKind::Ref(Mutability::Not, static_lifetime(), ty).intern(Interner) + let ty = self.db.infer(s.into())[self.db.body(s.into()).body_expr]; + Ty::new_ref( + self.interner(), + Region::new_static(self.interner()), + ty, + Mutability::Not, + ) } }) } fn operand_ty_and_eval( &mut self, - o: &Operand, - locals: &mut Locals, - ) -> Result<'db, IntervalAndTy> { + o: &Operand<'db>, + locals: &mut Locals<'db>, + ) -> Result<'db, IntervalAndTy<'db>> { Ok(IntervalAndTy { interval: self.eval_operand(o, locals)?, ty: self.operand_ty(o, locals)?, @@ -925,7 +901,7 @@ impl<'db> Evaluator<'db> { fn interpret_mir( &mut self, - body: Arc<MirBody>, + body: Arc<MirBody<'db>>, args: impl Iterator<Item = IntervalOrOwned>, ) -> Result<'db, Interval> { if let Some(it) = self.stack_depth_limit.checked_sub(1) { @@ -989,8 +965,8 @@ impl<'db> Evaluator<'db> { .iter() .map(|it| self.operand_ty_and_eval(it, locals)) .collect::<Result<'db, Vec<_>>>()?; - let stack_frame = match &fn_ty.kind(Interner) { - TyKind::Function(_) => { + let stack_frame = match fn_ty.kind() { + TyKind::FnPtr(..) => { let bytes = self.eval_operand(func, locals)?; self.exec_fn_pointer( bytes, @@ -1002,7 +978,7 @@ impl<'db> Evaluator<'db> { )? } TyKind::FnDef(def, generic_args) => self.exec_fn_def( - CallableDefId::from_chalk(self.db, *def), + def.0, generic_args, destination_interval, &args, @@ -1089,8 +1065,8 @@ impl<'db> Evaluator<'db> { fn fill_locals_for_body( &mut self, - body: &MirBody, - locals: &mut Locals, + body: &MirBody<'db>, + locals: &mut Locals<'db>, args: impl Iterator<Item = IntervalOrOwned>, ) -> Result<'db, ()> { let mut remain_args = body.param_locals.len(); @@ -1113,9 +1089,9 @@ impl<'db> Evaluator<'db> { fn create_locals_for_body( &mut self, - body: &Arc<MirBody>, + body: &Arc<MirBody<'db>>, destination: Option<Interval>, - ) -> Result<'db, (Locals, usize)> { + ) -> Result<'db, (Locals<'db>, usize)> { let mut locals = match self.unused_locals_store.borrow_mut().entry(body.owner).or_default().pop() { None => Locals { @@ -1139,7 +1115,7 @@ impl<'db> Evaluator<'db> { continue; } let (size, align) = self.size_align_of_sized( - &it.ty, + it.ty, &locals, "no unsized local in extending stack", )?; @@ -1162,8 +1138,11 @@ impl<'db> Evaluator<'db> { Ok((locals, prev_stack_pointer)) } - fn eval_rvalue(&mut self, r: &Rvalue, locals: &mut Locals) -> Result<'db, IntervalOrOwned> { - let interner = DbInterner::new_with(self.db, None, None); + fn eval_rvalue( + &mut self, + r: &Rvalue<'db>, + locals: &mut Locals<'db>, + ) -> Result<'db, IntervalOrOwned> { use IntervalOrOwned::*; Ok(match r { Rvalue::Use(it) => Borrowed(self.eval_operand(it, locals)?), @@ -1189,33 +1168,33 @@ impl<'db> Evaluator<'db> { Rvalue::UnaryOp(op, val) => { let mut c = self.eval_operand(val, locals)?.get(self)?; let mut ty = self.operand_ty(val, locals)?; - while let TyKind::Ref(_, _, z) = ty.kind(Interner) { - ty = z.clone(); - let size = self.size_of_sized(&ty, locals, "operand of unary op")?; + while let TyKind::Ref(_, z, _) = ty.kind() { + ty = z; + let size = self.size_of_sized(ty, locals, "operand of unary op")?; c = self.read_memory(Address::from_bytes(c)?, size)?; } - if let TyKind::Scalar(chalk_ir::Scalar::Float(f)) = ty.kind(Interner) { + if let TyKind::Float(f) = ty.kind() { match f { - chalk_ir::FloatTy::F16 => { + rustc_type_ir::FloatTy::F16 => { let c = -from_bytes!(f16, u16, c); Owned(u16::try_from(c.to_bits()).unwrap().to_le_bytes().into()) } - chalk_ir::FloatTy::F32 => { + rustc_type_ir::FloatTy::F32 => { let c = -from_bytes!(f32, c); Owned(c.to_le_bytes().into()) } - chalk_ir::FloatTy::F64 => { + rustc_type_ir::FloatTy::F64 => { let c = -from_bytes!(f64, c); Owned(c.to_le_bytes().into()) } - chalk_ir::FloatTy::F128 => { + rustc_type_ir::FloatTy::F128 => { let c = -from_bytes!(f128, u128, c); Owned(c.to_bits().to_le_bytes().into()) } } } else { let mut c = c.to_vec(); - if ty.as_builtin() == Some(BuiltinType::Bool) { + if matches!(ty.kind(), TyKind::Bool) { c[0] = 1 - c[0]; } else { match op { @@ -1241,8 +1220,8 @@ impl<'db> Evaluator<'db> { let mut lc = lc.get(self)?; let mut rc = rc.get(self)?; let mut ty = self.operand_ty(lhs, locals)?; - while let TyKind::Ref(_, _, z) = ty.kind(Interner) { - ty = z.clone(); + while let TyKind::Ref(_, z, _) = ty.kind() { + ty = z; let size = if ty.is_str() { if *op != BinOp::Eq { never!("Only eq is builtin for `str`"); @@ -1258,14 +1237,14 @@ impl<'db> Evaluator<'db> { rc = self.read_memory(Address::from_bytes(rc)?, ls)?; break 'binary_op Owned(vec![u8::from(lc == rc)]); } else { - self.size_of_sized(&ty, locals, "operand of binary op")? + self.size_of_sized(ty, locals, "operand of binary op")? }; lc = self.read_memory(Address::from_bytes(lc)?, size)?; rc = self.read_memory(Address::from_bytes(rc)?, size)?; } - if let TyKind::Scalar(chalk_ir::Scalar::Float(f)) = ty.kind(Interner) { + if let TyKind::Float(f) = ty.kind() { match f { - chalk_ir::FloatTy::F16 => { + rustc_type_ir::FloatTy::F16 => { let l = from_bytes!(f16, u16, lc); let r = from_bytes!(f16, u16, rc); match op { @@ -1298,7 +1277,7 @@ impl<'db> Evaluator<'db> { ), } } - chalk_ir::FloatTy::F32 => { + rustc_type_ir::FloatTy::F32 => { let l = from_bytes!(f32, lc); let r = from_bytes!(f32, rc); match op { @@ -1326,7 +1305,7 @@ impl<'db> Evaluator<'db> { ), } } - chalk_ir::FloatTy::F64 => { + rustc_type_ir::FloatTy::F64 => { let l = from_bytes!(f64, lc); let r = from_bytes!(f64, rc); match op { @@ -1354,7 +1333,7 @@ impl<'db> Evaluator<'db> { ), } } - chalk_ir::FloatTy::F128 => { + rustc_type_ir::FloatTy::F128 => { let l = from_bytes!(f128, u128, lc); let r = from_bytes!(f128, u128, rc); match op { @@ -1384,7 +1363,7 @@ impl<'db> Evaluator<'db> { } } } else { - let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_))); + let is_signed = matches!(ty.kind(), TyKind::Int(_)); let l128 = IntValue::from_bytes(lc, is_signed); let r128 = IntValue::from_bytes(rc, is_signed); match op { @@ -1455,7 +1434,7 @@ impl<'db> Evaluator<'db> { Owned(result.to_le_bytes().to_vec()) } Rvalue::Repeat(it, len) => { - let len = match try_const_usize(self.db, len) { + let len = match try_const_usize(self.db, *len) { Some(it) => it as usize, None => not_supported!("non evaluatable array len in repeat Rvalue"), }; @@ -1465,7 +1444,7 @@ impl<'db> Evaluator<'db> { } Rvalue::ShallowInitBox(_, _) => not_supported!("shallow init box"), Rvalue::ShallowInitBoxWithAlloc(ty) => { - let Some((size, align)) = self.size_align_of(ty, locals)? else { + let Some((size, align)) = self.size_align_of(*ty, locals)? else { not_supported!("unsized box initialization"); }; let addr = self.heap_allocate(size, align)?; @@ -1487,7 +1466,7 @@ impl<'db> Evaluator<'db> { Owned(r) } AggregateKind::Tuple(ty) => { - let layout = self.layout(ty.to_nextsolver(interner))?; + let layout = self.layout(*ty)?; Owned(self.construct_with_layout( layout.size.bytes_usize(), &layout, @@ -1496,8 +1475,10 @@ impl<'db> Evaluator<'db> { )?) } AggregateKind::Union(it, f) => { - let layout = - self.layout_adt((*it).into(), Substitution::empty(Interner))?; + let layout = self.layout_adt( + (*it).into(), + GenericArgs::new_from_iter(self.interner(), []), + )?; let offset = layout .fields .offset(u32::from(f.local_id.into_raw()) as usize) @@ -1509,7 +1490,7 @@ impl<'db> Evaluator<'db> { } AggregateKind::Adt(it, subst) => { let (size, variant_layout, tag) = - self.layout_of_variant(*it, subst.clone(), locals)?; + self.layout_of_variant(*it, *subst, locals)?; Owned(self.construct_with_layout( size, &variant_layout, @@ -1518,7 +1499,7 @@ impl<'db> Evaluator<'db> { )?) } AggregateKind::Closure(ty) => { - let layout = self.layout(ty.to_nextsolver(interner))?; + let layout = self.layout(*ty)?; Owned(self.construct_with_layout( layout.size.bytes_usize(), &layout, @@ -1532,11 +1513,7 @@ impl<'db> Evaluator<'db> { CastKind::PointerCoercion(cast) => match cast { PointerCast::ReifyFnPointer | PointerCast::ClosureFnPointer(_) => { let current_ty = self.operand_ty(operand, locals)?; - 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); + if let TyKind::FnDef(_, _) | TyKind::Closure(_, _) = current_ty.kind() { let id = self.vtable_map.id(current_ty); let ptr_size = self.ptr_size(); Owned(id.to_le_bytes()[0..ptr_size].to_vec()) @@ -1549,7 +1526,7 @@ impl<'db> Evaluator<'db> { PointerCast::Unsize => { let current_ty = self.operand_ty(operand, locals)?; let addr = self.eval_operand(operand, locals)?; - self.coerce_unsized(addr, ¤t_ty, target_ty)? + self.coerce_unsized(addr, current_ty, *target_ty)? } PointerCast::MutToConstPointer | PointerCast::UnsafeFnPointer => { // This is no-op @@ -1566,40 +1543,34 @@ impl<'db> Evaluator<'db> { | CastKind::PointerExposeAddress | CastKind::PointerFromExposedAddress => { let current_ty = self.operand_ty(operand, locals)?; - let is_signed = matches!( - current_ty.kind(Interner), - TyKind::Scalar(chalk_ir::Scalar::Int(_)) - ); + let is_signed = matches!(current_ty.kind(), TyKind::Int(_)); let current = pad16(self.eval_operand(operand, locals)?.get(self)?, is_signed); let dest_size = - self.size_of_sized(target_ty, locals, "destination of int to int cast")?; + self.size_of_sized(*target_ty, locals, "destination of int to int cast")?; Owned(current[0..dest_size].to_vec()) } CastKind::FloatToInt => { let ty = self.operand_ty(operand, locals)?; - let TyKind::Scalar(chalk_ir::Scalar::Float(ty)) = ty.kind(Interner) else { + let TyKind::Float(ty) = ty.kind() else { not_supported!("invalid float to int cast"); }; let value = self.eval_operand(operand, locals)?.get(self)?; let value = match ty { - chalk_ir::FloatTy::F32 => { + rustc_type_ir::FloatTy::F32 => { let value = value.try_into().unwrap(); f32::from_le_bytes(value) as f64 } - chalk_ir::FloatTy::F64 => { + rustc_type_ir::FloatTy::F64 => { let value = value.try_into().unwrap(); f64::from_le_bytes(value) } - chalk_ir::FloatTy::F16 | chalk_ir::FloatTy::F128 => { + rustc_type_ir::FloatTy::F16 | rustc_type_ir::FloatTy::F128 => { not_supported!("unstable floating point type f16 and f128"); } }; - let is_signed = matches!( - target_ty.kind(Interner), - TyKind::Scalar(chalk_ir::Scalar::Int(_)) - ); + let is_signed = matches!(target_ty.kind(), TyKind::Int(_)); let dest_size = - self.size_of_sized(target_ty, locals, "destination of float to int cast")?; + self.size_of_sized(*target_ty, locals, "destination of float to int cast")?; let dest_bits = dest_size * 8; let (max, min) = if dest_bits == 128 { (i128::MAX, i128::MIN) @@ -1615,53 +1586,46 @@ impl<'db> Evaluator<'db> { } CastKind::FloatToFloat => { let ty = self.operand_ty(operand, locals)?; - let TyKind::Scalar(chalk_ir::Scalar::Float(ty)) = ty.kind(Interner) else { + let TyKind::Float(ty) = ty.kind() else { not_supported!("invalid float to int cast"); }; let value = self.eval_operand(operand, locals)?.get(self)?; let value = match ty { - chalk_ir::FloatTy::F32 => { + rustc_type_ir::FloatTy::F32 => { let value = value.try_into().unwrap(); f32::from_le_bytes(value) as f64 } - chalk_ir::FloatTy::F64 => { + rustc_type_ir::FloatTy::F64 => { let value = value.try_into().unwrap(); f64::from_le_bytes(value) } - chalk_ir::FloatTy::F16 | chalk_ir::FloatTy::F128 => { + rustc_type_ir::FloatTy::F16 | rustc_type_ir::FloatTy::F128 => { not_supported!("unstable floating point type f16 and f128"); } }; - let TyKind::Scalar(chalk_ir::Scalar::Float(target_ty)) = - target_ty.kind(Interner) - else { + let TyKind::Float(target_ty) = target_ty.kind() else { not_supported!("invalid float to float cast"); }; match target_ty { - chalk_ir::FloatTy::F32 => Owned((value as f32).to_le_bytes().to_vec()), - chalk_ir::FloatTy::F64 => Owned((value as f64).to_le_bytes().to_vec()), - chalk_ir::FloatTy::F16 | chalk_ir::FloatTy::F128 => { + rustc_type_ir::FloatTy::F32 => Owned((value as f32).to_le_bytes().to_vec()), + rustc_type_ir::FloatTy::F64 => Owned((value as f64).to_le_bytes().to_vec()), + rustc_type_ir::FloatTy::F16 | rustc_type_ir::FloatTy::F128 => { not_supported!("unstable floating point type f16 and f128"); } } } CastKind::IntToFloat => { let current_ty = self.operand_ty(operand, locals)?; - let is_signed = matches!( - current_ty.kind(Interner), - TyKind::Scalar(chalk_ir::Scalar::Int(_)) - ); + let is_signed = matches!(current_ty.kind(), TyKind::Int(_)); let value = pad16(self.eval_operand(operand, locals)?.get(self)?, is_signed); let value = i128::from_le_bytes(value); - let TyKind::Scalar(chalk_ir::Scalar::Float(target_ty)) = - target_ty.kind(Interner) - else { + let TyKind::Float(target_ty) = target_ty.kind() else { not_supported!("invalid int to float cast"); }; match target_ty { - chalk_ir::FloatTy::F32 => Owned((value as f32).to_le_bytes().to_vec()), - chalk_ir::FloatTy::F64 => Owned((value as f64).to_le_bytes().to_vec()), - chalk_ir::FloatTy::F16 | chalk_ir::FloatTy::F128 => { + rustc_type_ir::FloatTy::F32 => Owned((value as f32).to_le_bytes().to_vec()), + rustc_type_ir::FloatTy::F64 => Owned((value as f64).to_le_bytes().to_vec()), + rustc_type_ir::FloatTy::F16 | rustc_type_ir::FloatTy::F128 => { not_supported!("unstable floating point type f16 and f128"); } } @@ -1675,10 +1639,12 @@ impl<'db> Evaluator<'db> { }) } - fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<'db, i128> { - 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 { + fn compute_discriminant(&self, ty: Ty<'db>, bytes: &[u8]) -> Result<'db, i128> { + let layout = self.layout(ty)?; + let TyKind::Adt(adt_def, _) = ty.kind() else { + return Ok(0); + }; + let AdtId::EnumId(e) = adt_def.def_id().0 else { return Ok(0); }; match &layout.variants { @@ -1720,35 +1686,35 @@ impl<'db> Evaluator<'db> { fn coerce_unsized_look_through_fields<T>( &self, - ty: &Ty, - goal: impl Fn(&TyKind) -> Option<T>, + ty: Ty<'db>, + goal: impl Fn(TyKind<'db>) -> Option<T>, ) -> Result<'db, T> { - let kind = ty.kind(Interner); + let kind = ty.kind(); if let Some(it) = goal(kind) { return Ok(it); } - if let TyKind::Adt(id, subst) = kind - && let AdtId::StructId(struct_id) = id.0 + if let TyKind::Adt(adt_ef, subst) = kind + && let AdtId::StructId(struct_id) = adt_ef.def_id().0 { - let field_types = self.db.field_types(struct_id.into()); + let field_types = self.db.field_types_ns(struct_id.into()); if let Some(ty) = - field_types.iter().last().map(|it| it.1.clone().substitute(Interner, subst)) + field_types.iter().last().map(|it| it.1.instantiate(self.interner(), subst)) { - return self.coerce_unsized_look_through_fields(&ty, goal); + return self.coerce_unsized_look_through_fields(ty, goal); } } - Err(MirEvalError::CoerceUnsizedError(ty.clone())) + Err(MirEvalError::CoerceUnsizedError(ty)) } fn coerce_unsized( &mut self, addr: Interval, - current_ty: &Ty, - target_ty: &Ty, + current_ty: Ty<'db>, + target_ty: Ty<'db>, ) -> Result<'db, IntervalOrOwned> { - fn for_ptr(it: &TyKind) -> Option<Ty> { + fn for_ptr<'db>(it: TyKind<'db>) -> Option<Ty<'db>> { match it { - TyKind::Raw(_, ty) | TyKind::Ref(_, _, ty) => Some(ty.clone()), + TyKind::RawPtr(ty, _) | TyKind::Ref(_, ty, _) => Some(ty), _ => None, } } @@ -1761,15 +1727,15 @@ impl<'db> Evaluator<'db> { /// Adds metadata to the address and create the fat pointer result of the unsizing operation. fn unsizing_ptr_from_addr( &mut self, - target_ty: Ty, - current_ty: Ty, + target_ty: Ty<'db>, + current_ty: Ty<'db>, addr: Interval, ) -> Result<'db, IntervalOrOwned> { use IntervalOrOwned::*; - Ok(match &target_ty.kind(Interner) { - TyKind::Slice(_) => match ¤t_ty.kind(Interner) { + Ok(match &target_ty.kind() { + TyKind::Slice(_) => match ¤t_ty.kind() { TyKind::Array(_, size) => { - let len = match try_const_usize(self.db, size) { + let len = match try_const_usize(self.db, *size) { None => { not_supported!("unevaluatble len of array in coerce unsized") } @@ -1785,9 +1751,7 @@ impl<'db> Evaluator<'db> { not_supported!("slice unsizing from non array type {t:?}") } }, - TyKind::Dyn(_) => { - let interner = DbInterner::new_with(self.db, None, None); - let current_ty = current_ty.to_nextsolver(interner); + TyKind::Dynamic(..) => { let vtable = self.vtable_map.id(current_ty); let mut r = Vec::with_capacity(16); let addr = addr.get(self)?; @@ -1795,12 +1759,14 @@ impl<'db> Evaluator<'db> { r.extend(vtable.to_le_bytes()); Owned(r) } - TyKind::Adt(id, target_subst) => match ¤t_ty.kind(Interner) { - TyKind::Adt(current_id, current_subst) => { + TyKind::Adt(adt_def, target_subst) => match ¤t_ty.kind() { + TyKind::Adt(current_adt_def, current_subst) => { + let id = adt_def.def_id().0; + let current_id = current_adt_def.def_id().0; if id != current_id { not_supported!("unsizing struct with different type"); } - let id = match id.0 { + let id = match id { AdtId::StructId(s) => s, AdtId::UnionId(_) => not_supported!("unsizing unions"), AdtId::EnumId(_) => not_supported!("unsizing enums"), @@ -1809,12 +1775,10 @@ impl<'db> Evaluator<'db> { else { not_supported!("unsizing struct without field"); }; - let target_last_field = self.db.field_types(id.into())[last_field] - .clone() - .substitute(Interner, target_subst); - let current_last_field = self.db.field_types(id.into())[last_field] - .clone() - .substitute(Interner, current_subst); + let target_last_field = self.db.field_types_ns(id.into())[last_field] + .instantiate(self.interner(), target_subst); + let current_last_field = self.db.field_types_ns(id.into())[last_field] + .instantiate(self.interner(), current_subst); return self.unsizing_ptr_from_addr( target_last_field, current_last_field, @@ -1830,10 +1794,9 @@ impl<'db> Evaluator<'db> { fn layout_of_variant( &mut self, it: VariantId, - subst: Substitution, - locals: &Locals, + subst: GenericArgs<'db>, + locals: &Locals<'db>, ) -> Result<'db, (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 @@ -1843,11 +1806,7 @@ impl<'db> Evaluator<'db> { // 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(crate::next_solver::Ty::new_empty_tuple(interner))?, - Some((0, 16, i)), - )); + return Ok((16, self.layout(Ty::new_empty_tuple(self.interner()))?, Some((0, 16, i)))); } let layout = self.layout_adt(adt, subst)?; Ok(match &layout.variants { @@ -1930,7 +1889,11 @@ impl<'db> Evaluator<'db> { Ok(result) } - fn eval_operand(&mut self, it: &Operand, locals: &mut Locals) -> Result<'db, Interval> { + fn eval_operand( + &mut self, + it: &Operand<'db>, + locals: &mut Locals<'db>, + ) -> Result<'db, Interval> { Ok(match &it.kind { OperandKind::Copy(p) | OperandKind::Move(p) => { locals.drop_flags.remove_place(p, &locals.body.projection_store); @@ -1940,32 +1903,30 @@ impl<'db> Evaluator<'db> { let addr = self.eval_static(*st, locals)?; Interval::new(addr, self.ptr_size()) } - OperandKind::Constant(konst) => self.allocate_const_in_heap(locals, konst)?, + OperandKind::Constant { konst, .. } => self.allocate_const_in_heap(locals, *konst)?, }) } #[allow(clippy::double_parens)] - fn allocate_const_in_heap(&mut self, locals: &Locals, konst: &Const) -> Result<'db, Interval> { - let interner = self.interner; - let ConstData { ty, value: chalk_ir::ConstValue::Concrete(c) } = &konst.data(Interner) - else { - not_supported!("evaluating non concrete constant"); - }; + fn allocate_const_in_heap( + &mut self, + locals: &Locals<'db>, + konst: Const<'db>, + ) -> Result<'db, Interval> { 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(); + let value = match konst.kind() { + ConstKind::Value(value) => value, + ConstKind::Unevaluated(UnevaluatedConst { def: const_id, args: subst }) => 'b: { + let mut const_id = match const_id { + SolverDefId::ConstId(it) => GeneralConstId::from(it), + SolverDefId::StaticId(it) => it.into(), + _ => unreachable!("unevaluated consts should be consts or statics"), + }; + let mut subst = subst; if let hir_def::GeneralConstId::ConstId(c) = const_id { - let (c, s) = lookup_impl_const( - self.interner, - self.trait_env.clone(), - c, - subst.to_nextsolver(self.interner), - ); + let (c, s) = lookup_impl_const(&self.infcx, self.trait_env.clone(), c, subst); const_id = hir_def::GeneralConstId::ConstId(c); - subst = s.to_chalk(self.interner); + subst = s; } result_owner = self .db @@ -1974,15 +1935,15 @@ impl<'db> Evaluator<'db> { let name = const_id.name(self.db); MirEvalError::ConstEvalError(name, Box::new(e)) })?; - if let chalk_ir::ConstValue::Concrete(c) = &result_owner.data(Interner).value - && let ConstScalar::Bytes(v, mm) = &c.interned - { - break 'b (v, mm); + if let ConstKind::Value(value) = result_owner.kind() { + break 'b value; } not_supported!("unevaluatable constant"); } - ConstScalar::Unknown => not_supported!("evaluating unknown const"), + _ => not_supported!("evaluating unknown const"), }; + let ValueConst { ty, value } = value; + let ConstBytes { memory: v, memory_map } = value.inner(); let patch_map = memory_map.transform_addresses(|b, align| { let addr = self.heap_allocate(b.len(), align)?; self.write_memory(addr, b)?; @@ -1996,7 +1957,7 @@ impl<'db> Evaluator<'db> { } else if size < 16 && v.len() == 16 { Cow::Borrowed(&v[0..size]) } else { - return Err(MirEvalError::InvalidConst(konst.clone())); + return Err(MirEvalError::InvalidConst(konst)); } } else { Cow::Borrowed(v) @@ -2012,17 +1973,17 @@ impl<'db> Evaluator<'db> { MemoryMap::Complex(cm) => cm.vtable.ty_of_bytes(bytes), }, addr, - ty.to_nextsolver(interner), + ty, locals, )?; Ok(Interval::new(addr, size)) } - fn eval_place(&mut self, p: &Place, locals: &Locals) -> Result<'db, Interval> { + fn eval_place(&mut self, p: &Place<'db>, locals: &Locals<'db>) -> Result<'db, Interval> { let addr = self.place_addr(p, locals)?; Ok(Interval::new( addr, - self.size_of_sized(&self.place_ty(p, locals)?, locals, "type of this place")?, + self.size_of_sized(self.place_ty(p, locals)?, locals, "type of this place")?, )) } @@ -2118,9 +2079,12 @@ impl<'db> Evaluator<'db> { Ok(()) } - fn size_align_of(&self, ty: &Ty, locals: &Locals) -> Result<'db, Option<(usize, usize)>> { - let interner = DbInterner::new_with(self.db, None, None); - if let Some(layout) = self.layout_cache.borrow().get(&ty.to_nextsolver(interner)) { + fn size_align_of( + &self, + ty: Ty<'db>, + locals: &Locals<'db>, + ) -> Result<'db, Option<(usize, usize)>> { + if let Some(layout) = self.layout_cache.borrow().get(&ty) { return Ok(layout .is_sized() .then(|| (layout.size.bytes_usize(), layout.align.bytes() as usize))); @@ -2133,7 +2097,7 @@ impl<'db> Evaluator<'db> { // infinite sized type errors) we use a dummy size return Ok(Some((16, 16))); } - let layout = self.layout(ty.to_nextsolver(interner)); + let layout = self.layout(ty); if self.assert_placeholder_ty_is_unused && matches!(layout, Err(MirEvalError::LayoutError(LayoutError::HasPlaceholder, _))) { @@ -2145,10 +2109,15 @@ impl<'db> Evaluator<'db> { /// A version of `self.size_of` which returns error if the type is unsized. `what` argument should /// be something that complete this: `error: type {ty} was unsized. {what} should be sized` - fn size_of_sized(&self, ty: &Ty, locals: &Locals, what: &'static str) -> Result<'db, usize> { + fn size_of_sized( + &self, + ty: Ty<'db>, + locals: &Locals<'db>, + what: &'static str, + ) -> Result<'db, usize> { match self.size_align_of(ty, locals)? { Some(it) => Ok(it.0), - None => Err(MirEvalError::TypeIsUnsized(ty.clone(), what)), + None => Err(MirEvalError::TypeIsUnsized(ty, what)), } } @@ -2156,13 +2125,13 @@ impl<'db> Evaluator<'db> { /// be something that complete this: `error: type {ty} was unsized. {what} should be sized` fn size_align_of_sized( &self, - ty: &Ty, - locals: &Locals, + ty: Ty<'db>, + locals: &Locals<'db>, what: &'static str, ) -> Result<'db, (usize, usize)> { match self.size_align_of(ty, locals)? { Some(it) => Ok(it), - None => Err(MirEvalError::TypeIsUnsized(ty.clone(), what)), + None => Err(MirEvalError::TypeIsUnsized(ty, what)), } } @@ -2197,23 +2166,22 @@ impl<'db> Evaluator<'db> { fn create_memory_map( &self, bytes: &[u8], - ty: &Ty, - locals: &Locals, + ty: Ty<'db>, + locals: &Locals<'db>, ) -> Result<'db, ComplexMemoryMap<'db>> { fn rec<'db>( this: &Evaluator<'db>, bytes: &[u8], - ty: &Ty, - locals: &Locals, + ty: Ty<'db>, + locals: &Locals<'db>, mm: &mut ComplexMemoryMap<'db>, stack_depth_limit: usize, ) -> Result<'db, ()> { - let interner = DbInterner::new_with(this.db, None, None); if stack_depth_limit.checked_sub(1).is_none() { return Err(MirEvalError::StackOverflow); } - match ty.kind(Interner) { - TyKind::Ref(_, _, t) => { + match ty.kind() { + TyKind::Ref(_, t, _) => { let size = this.size_align_of(t, locals)?; match size { Some((size, _)) => { @@ -2226,29 +2194,28 @@ impl<'db> Evaluator<'db> { None => { let mut check_inner = None; let (addr, meta) = bytes.split_at(bytes.len() / 2); - let element_size = match t.kind(Interner) { + let element_size = match t.kind() { TyKind::Str => 1, TyKind::Slice(t) => { - check_inner = Some(t.clone()); + check_inner = Some(t); this.size_of_sized(t, locals, "slice inner type")? } - TyKind::Dyn(_) => { + TyKind::Dynamic(..) => { let t = this.vtable_map.ty_of_bytes(meta)?; - let t = convert_ty_for_result(interner, t); - check_inner = Some(t.clone()); - this.size_of_sized(&t, locals, "dyn concrete type")? + check_inner = Some(t); + this.size_of_sized(t, locals, "dyn concrete type")? } _ => return Ok(()), }; - let count = match t.kind(Interner) { - TyKind::Dyn(_) => 1, + let count = match t.kind() { + TyKind::Dynamic(..) => 1, _ => from_bytes!(usize, meta), }; let size = element_size * count; 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( @@ -2282,12 +2249,11 @@ impl<'db> Evaluator<'db> { )?; } } - TyKind::Tuple(_, subst) => { - 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 + TyKind::Tuple(subst) => { + let layout = this.layout(ty)?; + for (id, ty) in subst.iter().enumerate() { let offset = layout.fields.offset(id).bytes_usize(); - let size = this.layout(ty.to_nextsolver(interner))?.size.bytes_usize(); + let size = this.layout(ty)?.size.bytes_usize(); rec( this, &bytes[offset..offset + size], @@ -2298,18 +2264,18 @@ impl<'db> Evaluator<'db> { )?; } } - TyKind::Adt(adt, subst) => match adt.0 { + TyKind::Adt(adt, subst) => match adt.def_id().0 { AdtId::StructId(s) => { let data = s.fields(this.db); - let layout = this.layout(ty.to_nextsolver(interner))?; - let field_types = this.db.field_types(s.into()); + let layout = this.layout(ty)?; + let field_types = this.db.field_types_ns(s.into()); for (f, _) in data.fields().iter() { let offset = layout .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.to_nextsolver(interner))?.size.bytes_usize(); + let ty = field_types[f].instantiate(this.interner(), subst); + let size = this.layout(ty)?.size.bytes_usize(); rec( this, &bytes[offset..offset + size], @@ -2321,7 +2287,7 @@ impl<'db> Evaluator<'db> { } } AdtId::EnumId(e) => { - let layout = this.layout(ty.to_nextsolver(interner))?; + let layout = this.layout(ty)?; if let Some((v, l)) = detect_variant_from_bytes( &layout, this.db, @@ -2330,13 +2296,12 @@ impl<'db> Evaluator<'db> { e, ) { let data = v.fields(this.db); - let field_types = this.db.field_types(v.into()); + let field_types = this.db.field_types_ns(v.into()); for (f, _) in data.fields().iter() { 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.to_nextsolver(interner))?.size.bytes_usize(); + let ty = field_types[f].instantiate(this.interner(), subst); + let size = this.layout(ty)?.size.bytes_usize(); rec( this, &bytes[offset..offset + size], @@ -2350,9 +2315,17 @@ impl<'db> Evaluator<'db> { } AdtId::UnionId(_) => (), }, - TyKind::Alias(AliasTy::Projection(proj)) => { - let ty = this.db.normalize_projection(proj.clone(), this.trait_env.clone()); - rec(this, bytes, &ty, locals, mm, stack_depth_limit - 1)?; + TyKind::Alias(AliasTyKind::Projection, _) => { + let mut ocx = ObligationCtxt::new(&this.infcx); + let ty = ocx + .structurally_normalize_ty( + &ObligationCause::dummy(), + this.trait_env.env, + ty, + ) + .map_err(|_| MirEvalError::NotSupported("couldn't normalize".to_owned()))?; + + rec(this, bytes, ty, locals, mm, stack_depth_limit - 1)?; } _ => (), } @@ -2366,23 +2339,18 @@ impl<'db> Evaluator<'db> { fn patch_addresses( &mut self, patch_map: &FxHashMap<usize, usize>, - ty_of_bytes: impl Fn(&[u8]) -> Result<'db, crate::next_solver::Ty<'db>> + Copy, + ty_of_bytes: impl Fn(&[u8]) -> Result<'db, Ty<'db>> + Copy, addr: Address, - ty: crate::next_solver::Ty<'db>, - locals: &Locals, + ty: Ty<'db>, + locals: &Locals<'db>, ) -> Result<'db, ()> { - 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( - &convert_ty_for_result(interner, ty), - locals, - "value to patch address", - )?; + let my_size = self.size_of_sized(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)?; + let size = self.size_align_of(t, locals)?; match size { Some(_) => { let current = from_bytes!(usize, self.read_memory(addr, my_size)?); @@ -2407,7 +2375,7 @@ impl<'db> Evaluator<'db> { AdtId::StructId(s) => { for (i, (_, ty)) in self.db.field_types_ns(s.into()).iter().enumerate() { let offset = layout.fields.offset(i).bytes_usize(); - let ty = ty.instantiate(interner, args); + let ty = ty.instantiate(self.interner(), args); self.patch_addresses( patch_map, ty_of_bytes, @@ -2428,7 +2396,7 @@ impl<'db> Evaluator<'db> { ) { for (i, (_, ty)) in self.db.field_types_ns(ev.into()).iter().enumerate() { let offset = layout.fields.offset(i).bytes_usize(); - let ty = ty.instantiate(interner, args); + let ty = ty.instantiate(self.interner(), args); self.patch_addresses( patch_map, ty_of_bytes, @@ -2447,15 +2415,11 @@ impl<'db> Evaluator<'db> { } } TyKind::Array(inner, len) => { - let len = match consteval_nextsolver::try_const_usize(self.db, len) { + let len = match consteval::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( - &convert_ty_for_result(interner, inner), - locals, - "inner of array", - )?; + let size = self.size_of_sized(inner, locals, "inner of array")?; for i in 0..len { self.patch_addresses( patch_map, @@ -2498,29 +2462,22 @@ impl<'db> Evaluator<'db> { &mut self, bytes: Interval, destination: Interval, - args: &[IntervalAndTy], - locals: &Locals, - target_bb: Option<BasicBlockId>, + args: &[IntervalAndTy<'db>], + locals: &Locals<'db>, + target_bb: Option<BasicBlockId<'db>>, span: MirSpan, - ) -> Result<'db, Option<StackFrame>> { + ) -> Result<'db, Option<StackFrame<'db>>> { let id = from_bytes!(usize, bytes.get(self)?); 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::FnDef(def, generic_args) => { + self.exec_fn_def(def.0, generic_args, destination, args, locals, target_bb, span) + } TyKind::Closure(id, generic_args) => self.exec_closure( - id.0.into(), + id.0, bytes.slice(0..0), - &convert_args_for_result(interner, generic_args.as_slice()), + generic_args, destination, args, locals, @@ -2532,21 +2489,17 @@ impl<'db> Evaluator<'db> { fn exec_closure( &mut self, - closure: ClosureId, + closure: InternedClosureId, closure_data: Interval, - generic_args: &Substitution, + generic_args: GenericArgs<'db>, destination: Interval, - args: &[IntervalAndTy], - locals: &Locals, + args: &[IntervalAndTy<'db>], + locals: &Locals<'db>, span: MirSpan, - ) -> Result<'db, Option<StackFrame>> { + ) -> Result<'db, Option<StackFrame<'db>>> { let mir_body = self .db - .monomorphized_mir_body_for_closure( - closure.into(), - generic_args.clone(), - self.trait_env.clone(), - ) + .monomorphized_mir_body_for_closure(closure, generic_args, self.trait_env.clone()) .map_err(|it| MirEvalError::MirLowerErrorForClosure(closure, it))?; let closure_data = if mir_body.locals[mir_body.param_locals[0]].ty.as_reference().is_some() { @@ -2572,14 +2525,13 @@ impl<'db> Evaluator<'db> { fn exec_fn_def( &mut self, def: CallableDefId, - generic_args: &Substitution, + generic_args: GenericArgs<'db>, destination: Interval, - args: &[IntervalAndTy], - locals: &Locals, - target_bb: Option<BasicBlockId>, + args: &[IntervalAndTy<'db>], + locals: &Locals<'db>, + target_bb: Option<BasicBlockId<'db>>, span: MirSpan, - ) -> Result<'db, Option<StackFrame>> { - let generic_args = generic_args.clone(); + ) -> Result<'db, Option<StackFrame<'db>>> { match def { CallableDefId::FunctionId(def) => { if self.detect_fn_trait(def).is_some() { @@ -2633,36 +2585,26 @@ impl<'db> Evaluator<'db> { fn get_mir_or_dyn_index( &self, def: FunctionId, - generic_args: Substitution, - locals: &Locals, + generic_args: GenericArgs<'db>, + locals: &Locals<'db>, span: MirSpan, - ) -> Result<'db, MirOrDynIndex> { + ) -> Result<'db, MirOrDynIndex<'db>> { let pair = (def, generic_args); if let Some(r) = self.mir_or_dyn_index_cache.borrow().get(&pair) { return Ok(r.clone()); } let (def, generic_args) = pair; - let r = if let Some(self_ty_idx) = is_dyn_method( - self.interner, - self.trait_env.clone(), - def, - generic_args.to_nextsolver(self.interner), - ) { + let r = if let Some(self_ty_idx) = + is_dyn_method(self.interner(), self.trait_env.clone(), def, generic_args) + { MirOrDynIndex::Dyn(self_ty_idx) } else { - let (imp, generic_args) = self.db.lookup_impl_method( - self.trait_env.clone(), - def, - generic_args.to_nextsolver(self.interner), - ); + let (imp, generic_args) = + self.db.lookup_impl_method(self.trait_env.clone(), def, generic_args); let mir_body = self .db - .monomorphized_mir_body( - imp.into(), - generic_args.to_chalk(self.interner), - self.trait_env.clone(), - ) + .monomorphized_mir_body(imp.into(), generic_args, self.trait_env.clone()) .map_err(|e| { MirEvalError::InFunction( Box::new(MirEvalError::MirLowerError(imp, e)), @@ -2678,18 +2620,17 @@ impl<'db> Evaluator<'db> { fn exec_fn_with_args( &mut self, mut def: FunctionId, - args: &[IntervalAndTy], - generic_args: Substitution, - locals: &Locals, + args: &[IntervalAndTy<'db>], + generic_args: GenericArgs<'db>, + locals: &Locals<'db>, destination: Interval, - target_bb: Option<BasicBlockId>, + target_bb: Option<BasicBlockId<'db>>, span: MirSpan, - ) -> Result<'db, Option<StackFrame>> { - let interner = DbInterner::new_with(self.db, None, None); + ) -> Result<'db, Option<StackFrame<'db>>> { if self.detect_and_exec_special_function( def, args, - &generic_args, + generic_args, locals, destination, span, @@ -2700,7 +2641,7 @@ impl<'db> Evaluator<'db> { def = redirect_def; } let arg_bytes = args.iter().map(|it| IntervalOrOwned::Borrowed(it.interval)); - match self.get_mir_or_dyn_index(def, generic_args.clone(), locals, span)? { + match self.get_mir_or_dyn_index(def, generic_args, locals, span)? { MirOrDynIndex::Dyn(self_ty_idx) => { // In the layout of current possible receiver, which at the moment of writing this code is one of // `&T`, `&mut T`, `Box<T>`, `Rc<T>`, `Arc<T>`, and `Pin<P>` where `P` is one of possible receivers, @@ -2712,18 +2653,16 @@ impl<'db> Evaluator<'db> { .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(), + ty, }; - let ty = ty.clone().cast(Interner); - let generics_for_target = Substitution::from_iter( - Interner, + let generics_for_target = GenericArgs::new_from_iter( + self.interner(), generic_args - .iter(Interner) + .iter() .enumerate() - .map(|(i, it)| if i == self_ty_idx { &ty } else { it }), + .map(|(i, it)| if i == self_ty_idx { ty.into() } else { it }), ); self.exec_fn_with_args( def, @@ -2749,14 +2688,14 @@ impl<'db> Evaluator<'db> { fn exec_looked_up_function( &mut self, - mir_body: Arc<MirBody>, - locals: &Locals, + mir_body: Arc<MirBody<'db>>, + locals: &Locals<'db>, def: FunctionId, arg_bytes: impl Iterator<Item = IntervalOrOwned>, span: MirSpan, destination: Interval, - target_bb: Option<BasicBlockId>, - ) -> Result<'db, Option<StackFrame>> { + target_bb: Option<BasicBlockId<'db>>, + ) -> Result<'db, Option<StackFrame<'db>>> { Ok(if let Some(target_bb) = target_bb { let (mut locals, prev_stack_ptr) = self.create_locals_for_body(&mir_body, Some(destination))?; @@ -2778,47 +2717,40 @@ impl<'db> Evaluator<'db> { fn exec_fn_trait( &mut self, def: FunctionId, - args: &[IntervalAndTy], - generic_args: Substitution, - locals: &Locals, + args: &[IntervalAndTy<'db>], + generic_args: GenericArgs<'db>, + locals: &Locals<'db>, destination: Interval, - target_bb: Option<BasicBlockId>, + target_bb: Option<BasicBlockId<'db>>, span: MirSpan, - ) -> Result<'db, Option<StackFrame>> { - let interner = DbInterner::new_with(self.db, None, None); + ) -> Result<'db, Option<StackFrame<'db>>> { let func = args .first() .ok_or_else(|| MirEvalError::InternalError("fn trait with no arg".into()))?; - let mut func_ty = func.ty.clone(); + let mut func_ty = func.ty; let mut func_data = func.interval; - while let TyKind::Ref(_, _, z) = func_ty.kind(Interner) { - func_ty = z.clone(); - if matches!(func_ty.kind(Interner), TyKind::Dyn(_)) { + while let TyKind::Ref(_, z, _) = func_ty.kind() { + func_ty = z; + if matches!(func_ty.kind(), TyKind::Dynamic(..)) { 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 = convert_ty_for_result(interner, self.vtable_map.ty(id)?); + func_ty = self.vtable_map.ty(id)?; } - let size = self.size_of_sized(&func_ty, locals, "self type of fn trait")?; + 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( - CallableDefId::from_chalk(self.db, *def), - subst, - destination, - &args[1..], - locals, - target_bb, - span, - ), - TyKind::Function(_) => { + match func_ty.kind() { + TyKind::FnDef(def, subst) => { + self.exec_fn_def(def.0, subst, destination, &args[1..], locals, target_bb, span) + } + TyKind::FnPtr(..) => { self.exec_fn_pointer(func_data, destination, &args[1..], locals, target_bb, span) } TyKind::Closure(closure, subst) => self.exec_closure( - *closure, + closure.0, func_data, - &ClosureSubst(subst).parent_subst(self.db), + subst.split_closure_args_untupled().parent_args, destination, &args[1..], locals, @@ -2829,12 +2761,8 @@ impl<'db> Evaluator<'db> { let arg0 = func; let args = &args[1..]; let arg1 = { - let ty = TyKind::Tuple( - args.len(), - Substitution::from_iter(Interner, args.iter().map(|it| it.ty.clone())), - ) - .intern(Interner); - let layout = self.layout(ty.to_nextsolver(interner))?; + let ty = Ty::new_tup_from_iter(self.interner(), args.iter().map(|it| it.ty)); + let layout = self.layout(ty)?; let result = self.construct_with_layout( layout.size.bytes_usize(), &layout, @@ -2860,7 +2788,7 @@ impl<'db> Evaluator<'db> { } } - fn eval_static(&mut self, st: StaticId, locals: &Locals) -> Result<'db, Address> { + fn eval_static(&mut self, st: StaticId, locals: &Locals<'db>) -> Result<'db, Address> { if let Some(o) = self.static_locations.get(&st) { return Ok(*o); }; @@ -2869,11 +2797,10 @@ impl<'db> Evaluator<'db> { let konst = self.db.const_eval_static(st).map_err(|e| { MirEvalError::ConstEvalError(static_data.name.as_str().to_owned(), Box::new(e)) })?; - self.allocate_const_in_heap(locals, &konst)? + self.allocate_const_in_heap(locals, konst)? } else { - let ty = - self.db.infer(st.into())[self.db.body(st.into()).body_expr].to_chalk(self.interner); - let Some((size, align)) = self.size_align_of(&ty, locals)? else { + let ty = self.db.infer(st.into())[self.db.body(st.into()).body_expr]; + let Some((size, align)) = self.size_align_of(ty, locals)? else { not_supported!("unsized extern static"); }; let addr = self.heap_allocate(size, align)?; @@ -2907,7 +2834,12 @@ impl<'db> Evaluator<'db> { } } - fn drop_place(&mut self, place: &Place, locals: &mut Locals, span: MirSpan) -> Result<'db, ()> { + fn drop_place( + &mut self, + place: &Place<'db>, + locals: &mut Locals<'db>, + span: MirSpan, + ) -> Result<'db, ()> { let (addr, ty, metadata) = self.place_addr_and_ty_and_metadata(place, locals)?; if !locals.drop_flags.remove_place(place, &locals.body.projection_store) { return Ok(()); @@ -2921,8 +2853,8 @@ impl<'db> Evaluator<'db> { fn run_drop_glue_deep( &mut self, - ty: Ty, - locals: &Locals, + ty: Ty<'db>, + locals: &Locals<'db>, addr: Address, _metadata: &[u8], span: MirSpan, @@ -2936,7 +2868,7 @@ impl<'db> Evaluator<'db> { return Ok(()); }; - let generic_args = Substitution::from1(Interner, ty.clone()); + let generic_args = GenericArgs::new_from_iter(self.interner(), [ty.into()]); if let Ok(MirOrDynIndex::Mir(body)) = self.get_mir_or_dyn_index(drop_fn, generic_args, locals, span) { @@ -2950,26 +2882,27 @@ impl<'db> Evaluator<'db> { None, )?; } - match ty.kind(Interner) { - TyKind::Adt(id, subst) => { - match id.0 { + match ty.kind() { + TyKind::Adt(adt_def, subst) => { + let id = adt_def.def_id().0; + match id { AdtId::StructId(s) => { let data = self.db.struct_signature(s); if data.flags.contains(StructFlags::IS_MANUALLY_DROP) { return Ok(()); } - let layout = self.layout_adt(id.0, subst.clone())?; + let layout = self.layout_adt(id, subst)?; let variant_fields = s.fields(self.db); match variant_fields.shape { FieldsShape::Record | FieldsShape::Tuple => { - let field_types = self.db.field_types(s.into()); + let field_types = self.db.field_types_ns(s.into()); for (field, _) in variant_fields.fields().iter() { let offset = layout .fields .offset(u32::from(field.into_raw()) as usize) .bytes_usize(); let addr = addr.offset(offset); - let ty = field_types[field].clone().substitute(Interner, subst); + let ty = field_types[field].instantiate(self.interner(), subst); self.run_drop_glue_deep(ty, locals, addr, &[], span)?; } } @@ -2980,28 +2913,34 @@ impl<'db> Evaluator<'db> { AdtId::EnumId(_) => (), } } - TyKind::AssociatedType(_, _) - | TyKind::Scalar(_) - | TyKind::Tuple(_, _) + TyKind::Bool + | TyKind::Char + | TyKind::Int(_) + | TyKind::Uint(_) + | TyKind::Float(_) + | TyKind::Tuple(_) | TyKind::Array(_, _) | TyKind::Slice(_) - | TyKind::Raw(_, _) + | TyKind::RawPtr(_, _) | TyKind::Ref(_, _, _) - | TyKind::OpaqueType(_, _) + | TyKind::Alias(..) | TyKind::FnDef(_, _) | TyKind::Str | TyKind::Never | TyKind::Closure(_, _) | TyKind::Coroutine(_, _) + | TyKind::CoroutineClosure(..) | TyKind::CoroutineWitness(_, _) | TyKind::Foreign(_) - | TyKind::Error + | TyKind::Error(_) + | TyKind::Param(_) | TyKind::Placeholder(_) - | TyKind::Dyn(_) - | TyKind::Alias(_) - | TyKind::Function(_) - | TyKind::BoundVar(_) - | TyKind::InferenceVar(_, _) => (), + | TyKind::Dynamic(..) + | TyKind::FnPtr(..) + | TyKind::Bound(..) + | TyKind::Infer(..) + | TyKind::Pat(..) + | TyKind::UnsafeBinder(..) => (), }; Ok(()) } @@ -3020,9 +2959,9 @@ impl<'db> Evaluator<'db> { pub fn render_const_using_debug_impl<'db>( db: &'db dyn HirDatabase, owner: DefWithBodyId, - c: &Const, + c: Const<'db>, + ty: Ty<'db>, ) -> Result<'db, String> { - let interner = DbInterner::new_with(db, None, None); let mut evaluator = Evaluator::new(db, owner, false, None)?; let locals = &Locals { ptr: ArenaMap::new(), @@ -3051,12 +2990,11 @@ pub fn render_const_using_debug_impl<'db>( // and its ABI doesn't break yet, we put it in memory manually. let a2 = evaluator.heap_allocate(evaluator.ptr_size() * 2, evaluator.ptr_size())?; evaluator.write_memory(a2, &data.addr.to_bytes())?; - let debug_fmt_fn_ptr = evaluator.vtable_map.id(TyKind::FnDef( - CallableDefId::FunctionId(debug_fmt_fn).to_chalk(db), - Substitution::from1(Interner, c.data(Interner).ty.clone()), - ) - .intern(Interner) - .to_nextsolver(interner)); + let debug_fmt_fn_ptr = evaluator.vtable_map.id(Ty::new_fn_def( + evaluator.interner(), + CallableDefId::FunctionId(debug_fmt_fn).into(), + GenericArgs::new_from_iter(evaluator.interner(), [ty.into()]), + )); 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. |