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 | 392 |
1 files changed, 208 insertions, 184 deletions
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 6e62bcbbdd..5de08313f4 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -9,7 +9,7 @@ use hir_def::{ Lookup, StaticId, VariantId, expr_store::HygieneId, item_tree::FieldsShape, - lang_item::LangItem, + lang_item::LangItems, layout::{TagEncoding, Variants}, resolver::{HasResolver, TypeNs, ValueNs}, signatures::{StaticFlags, StructFlags}, @@ -17,6 +17,7 @@ use hir_def::{ use hir_expand::{InFile, mod_path::path, name::Name}; use intern::sym; use la_arena::ArenaMap; +use macros::GenericTypeVisitable; use rustc_abi::TargetDataLayout; use rustc_apfloat::{ Float, @@ -26,7 +27,7 @@ use rustc_ast_ir::Mutability; use rustc_hash::{FxHashMap, FxHashSet}; use rustc_type_ir::{ AliasTyKind, - inherent::{AdtDef, IntoKind, Region as _, SliceLike, Ty as _}, + inherent::{AdtDef, GenericArgs as _, IntoKind, Region as _, SliceLike, Ty as _}, }; use span::FileId; use stdx::never; @@ -34,7 +35,7 @@ use syntax::{SyntaxNodePtr, TextRange}; use triomphe::Arc; use crate::{ - CallableDefId, ComplexMemoryMap, MemoryMap, TraitEnvironment, + CallableDefId, ComplexMemoryMap, InferenceResult, MemoryMap, ParamEnvAndCrate, consteval::{self, ConstEvalError, try_const_usize}, db::{HirDatabase, InternedClosure, InternedClosureId}, display::{ClosureStyle, DisplayTarget, HirDisplay}, @@ -43,7 +44,7 @@ use crate::{ method_resolution::{is_dyn_method, lookup_impl_const}, next_solver::{ Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, Region, - SolverDefId, Ty, TyKind, TypingMode, UnevaluatedConst, ValueConst, + StoredConst, StoredTy, Ty, TyKind, TypingMode, UnevaluatedConst, ValueConst, infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause}, obligation_ctxt::ObligationCtxt, }, @@ -76,14 +77,16 @@ macro_rules! from_bytes { }).into()) }; } +use from_bytes; macro_rules! not_supported { ($it: expr) => { - return Err(MirEvalError::NotSupported(format!($it))) + return Err($crate::mir::eval::MirEvalError::NotSupported(format!($it))) }; } +use not_supported; -#[derive(Debug, Default, Clone, PartialEq, Eq)] +#[derive(Debug, Default, Clone, PartialEq, Eq, GenericTypeVisitable)] pub struct VTableMap<'db> { ty_to_id: FxHashMap<Ty<'db>, usize>, id_to_ty: Vec<Ty<'db>>, @@ -150,26 +153,26 @@ impl TlsData { } } -struct StackFrame<'db> { - locals: Locals<'db>, - destination: Option<BasicBlockId<'db>>, +struct StackFrame { + locals: Locals, + destination: Option<BasicBlockId>, prev_stack_ptr: usize, span: (MirSpan, DefWithBodyId), } #[derive(Clone)] -enum MirOrDynIndex<'db> { - Mir(Arc<MirBody<'db>>), +enum MirOrDynIndex { + Mir(Arc<MirBody>), Dyn(usize), } pub struct Evaluator<'db> { db: &'db dyn HirDatabase, - trait_env: Arc<TraitEnvironment<'db>>, + param_env: ParamEnvAndCrate<'db>, target_data_layout: Arc<TargetDataLayout>, stack: Vec<u8>, heap: Vec<u8>, - code_stack: Vec<StackFrame<'db>>, + code_stack: Vec<StackFrame>, /// 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>, @@ -182,13 +185,13 @@ pub struct Evaluator<'db> { stdout: Vec<u8>, stderr: Vec<u8>, layout_cache: RefCell<FxHashMap<Ty<'db>, Arc<Layout>>>, - projected_ty_cache: RefCell<FxHashMap<(Ty<'db>, PlaceElem<'db>), Ty<'db>>>, + projected_ty_cache: RefCell<FxHashMap<(Ty<'db>, PlaceElem), Ty<'db>>>, not_special_fn_cache: RefCell<FxHashSet<FunctionId>>, - mir_or_dyn_index_cache: RefCell<FxHashMap<(FunctionId, GenericArgs<'db>), MirOrDynIndex<'db>>>, - /// Constantly dropping and creating `Locals<'db>` is very costly. We store + mir_or_dyn_index_cache: RefCell<FxHashMap<(FunctionId, GenericArgs<'db>), MirOrDynIndex>>, + /// Constantly dropping and creating `Locals` 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<'db>>>>, + unused_locals_store: RefCell<FxHashMap<DefWithBodyId, Vec<Locals>>>, cached_ptr_size: usize, cached_fn_trait_func: Option<FunctionId>, cached_fn_mut_trait_func: Option<FunctionId>, @@ -261,7 +264,7 @@ impl<'db> IntervalAndTy<'db> { addr: Address, ty: Ty<'db>, evaluator: &Evaluator<'db>, - locals: &Locals<'db>, + locals: &Locals, ) -> Result<'db, IntervalAndTy<'db>> { let size = evaluator.size_of_sized(ty, locals, "type of interval")?; Ok(IntervalAndTy { interval: Interval { addr, size }, ty }) @@ -340,22 +343,22 @@ impl Address { } #[derive(Clone, PartialEq, Eq)] -pub enum MirEvalError<'db> { - ConstEvalError(String, Box<ConstEvalError<'db>>), - LayoutError(LayoutError, Ty<'db>), +pub enum MirEvalError { + ConstEvalError(String, Box<ConstEvalError>), + LayoutError(LayoutError, StoredTy), 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), Panic(String), // FIXME: This should be folded into ConstEvalError? - MirLowerError(FunctionId, MirLowerError<'db>), - MirLowerErrorForClosure(InternedClosureId, MirLowerError<'db>), - TypeIsUnsized(Ty<'db>, &'static str), + MirLowerError(FunctionId, MirLowerError), + MirLowerErrorForClosure(InternedClosureId, MirLowerError), + TypeIsUnsized(StoredTy, &'static str), NotSupported(String), - InvalidConst(Const<'db>), + InvalidConst(StoredConst), InFunction( - Box<MirEvalError<'db>>, + Box<MirEvalError>, Vec<(Either<FunctionId, InternedClosureId>, MirSpan, DefWithBodyId)>, ), ExecutionLimitExceeded, @@ -363,12 +366,12 @@ pub enum MirEvalError<'db> { /// FIXME: Fold this into InternalError InvalidVTableId(usize), /// ? - CoerceUnsizedError(Ty<'db>), + CoerceUnsizedError(StoredTy), /// These should not occur, usually indicates a bug in mir lowering. InternalError(Box<str>), } -impl MirEvalError<'_> { +impl MirEvalError { pub fn pretty_print( &self, f: &mut String, @@ -432,7 +435,9 @@ impl MirEvalError<'_> { write!( f, "Layout for type `{}` is not available due {err:?}", - ty.display(db, display_target).with_closure_style(ClosureStyle::ClosureWithId) + ty.as_ref() + .display(db, display_target) + .with_closure_style(ClosureStyle::ClosureWithId) )?; } MirEvalError::MirLowerError(func, err) => { @@ -495,7 +500,7 @@ impl MirEvalError<'_> { } } -impl std::fmt::Debug for MirEvalError<'_> { +impl std::fmt::Debug for MirEvalError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::ConstEvalError(arg0, arg1) => { @@ -534,15 +539,15 @@ impl std::fmt::Debug for MirEvalError<'_> { } } -type Result<'db, T> = std::result::Result<T, MirEvalError<'db>>; +type Result<'db, T> = std::result::Result<T, MirEvalError>; #[derive(Debug, Default)] -struct DropFlags<'db> { - need_drop: FxHashSet<Place<'db>>, +struct DropFlags { + need_drop: FxHashSet<Place>, } -impl<'db> DropFlags<'db> { - fn add_place(&mut self, p: Place<'db>, store: &ProjectionStore<'db>) { +impl DropFlags { + fn add_place(&mut self, p: Place, store: &ProjectionStore) { if p.iterate_over_parents(store).any(|it| self.need_drop.contains(&it)) { return; } @@ -550,7 +555,7 @@ impl<'db> DropFlags<'db> { self.need_drop.insert(p); } - fn remove_place(&mut self, p: &Place<'db>, store: &ProjectionStore<'db>) -> bool { + fn remove_place(&mut self, p: &Place, store: &ProjectionStore) -> 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); @@ -565,10 +570,10 @@ impl<'db> DropFlags<'db> { } #[derive(Debug)] -struct Locals<'db> { - ptr: ArenaMap<LocalId<'db>, Interval>, - body: Arc<MirBody<'db>>, - drop_flags: DropFlags<'db>, +struct Locals { + ptr: ArenaMap<LocalId, Interval>, + body: Arc<MirBody>, + drop_flags: DropFlags, } pub struct MirOutput { @@ -587,16 +592,16 @@ impl MirOutput { pub fn interpret_mir<'db>( db: &'db dyn HirDatabase, - body: Arc<MirBody<'db>>, + body: Arc<MirBody>, // 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 // a zero size, hoping that they are all outside of our current body. Even without a fix for #7434, we can // (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>>>, + trait_env: Option<ParamEnvAndCrate<'db>>, ) -> Result<'db, (Result<'db, Const<'db>>, MirOutput)> { - let ty = body.locals[return_slot()].ty; + let ty = body.locals[return_slot()].ty.as_ref(); let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env)?; let it: Result<'db, Const<'db>> = (|| { if evaluator.ptr_size() != size_of::<usize>() { @@ -632,17 +637,18 @@ impl<'db> Evaluator<'db> { db: &'db dyn HirDatabase, owner: DefWithBodyId, assert_placeholder_ty_is_unused: bool, - trait_env: Option<Arc<TraitEnvironment<'db>>>, + trait_env: Option<ParamEnvAndCrate<'db>>, ) -> Result<'db, Evaluator<'db>> { let module = owner.module(db); - let crate_id = module.krate(); + let crate_id = module.krate(db); 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, Some(crate_id), module.containing_block()); + let interner = DbInterner::new_with(db, crate_id); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); + let lang_items = interner.lang_items(); Ok(Evaluator { target_data_layout, stack: vec![0], @@ -653,7 +659,10 @@ impl<'db> Evaluator<'db> { static_locations: Default::default(), db, random_state: oorandom::Rand64::new(0), - trait_env: trait_env.unwrap_or_else(|| db.trait_environment_for_body(owner)), + param_env: trait_env.unwrap_or_else(|| ParamEnvAndCrate { + param_env: db.trait_environment_for_body(owner), + krate: crate_id, + }), crate_id, stdout: vec![], stderr: vec![], @@ -667,13 +676,13 @@ impl<'db> Evaluator<'db> { mir_or_dyn_index_cache: RefCell::new(Default::default()), unused_locals_store: RefCell::new(Default::default()), cached_ptr_size, - cached_fn_trait_func: LangItem::Fn - .resolve_trait(db, crate_id) + cached_fn_trait_func: lang_items + .Fn .and_then(|x| x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call))), - cached_fn_mut_trait_func: LangItem::FnMut.resolve_trait(db, crate_id).and_then(|x| { + cached_fn_mut_trait_func: lang_items.FnMut.and_then(|x| { x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_mut)) }), - cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| { + cached_fn_once_trait_func: lang_items.FnOnce.and_then(|x| { x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_once)) }), infcx, @@ -685,11 +694,16 @@ impl<'db> Evaluator<'db> { self.infcx.interner } - fn place_addr(&self, p: &Place<'db>, locals: &Locals<'db>) -> Result<'db, Address> { + #[inline] + fn lang_items(&self) -> &'db LangItems { + self.infcx.interner.lang_items() + } + + fn place_addr(&self, p: &Place, locals: &Locals) -> Result<'db, Address> { Ok(self.place_addr_and_ty_and_metadata(p, locals)?.0) } - fn place_interval(&self, p: &Place<'db>, locals: &Locals<'db>) -> Result<'db, Interval> { + fn place_interval(&self, p: &Place, locals: &Locals) -> 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, @@ -705,7 +719,7 @@ impl<'db> Evaluator<'db> { self.cached_ptr_size } - fn projected_ty(&self, ty: Ty<'db>, proj: PlaceElem<'db>) -> Ty<'db> { + fn projected_ty(&self, ty: Ty<'db>, proj: PlaceElem) -> Ty<'db> { let pair = (ty, proj); if let Some(r) = self.projected_ty_cache.borrow().get(&pair) { return *r; @@ -713,16 +727,18 @@ impl<'db> Evaluator<'db> { let (ty, proj) = pair; let r = proj.projected_ty( &self.infcx, + self.param_env.param_env, ty, |c, subst, f| { let InternedClosure(def, _) = self.db.lookup_intern_closure(c); - let infer = self.db.infer(def); + let infer = InferenceResult::for_body(self.db, def); let (captures, _) = infer.closure_info(c); - let parent_subst = subst.split_closure_args_untupled().parent_args; + let parent_subst = subst.as_closure().parent_args(); captures .get(f) .expect("broken closure field") .ty + .get() .instantiate(self.interner(), parent_subst) }, self.crate_id, @@ -733,11 +749,11 @@ impl<'db> Evaluator<'db> { fn place_addr_and_ty_and_metadata<'a>( &'a self, - p: &Place<'db>, - locals: &'a Locals<'db>, + p: &Place, + locals: &'a Locals, ) -> Result<'db, (Address, Ty<'db>, Option<IntervalOrOwned>)> { let mut addr = locals.ptr[p.local].addr; - let mut ty: Ty<'db> = locals.body.locals[p.local].ty; + let mut ty: Ty<'db> = locals.body.locals[p.local].ty.as_ref(); let mut metadata: Option<IntervalOrOwned> = None; // locals are always sized for proj in p.projection.lookup(&locals.body.projection_store) { let prev_ty = ty; @@ -858,8 +874,8 @@ impl<'db> Evaluator<'db> { } let r = self .db - .layout_of_ty(ty, self.trait_env.clone()) - .map_err(|e| MirEvalError::LayoutError(e, ty))?; + .layout_of_ty(ty.store(), self.param_env.store()) + .map_err(|e| MirEvalError::LayoutError(e, ty.store()))?; self.layout_cache.borrow_mut().insert(ty, r.clone()); Ok(r) } @@ -868,16 +884,17 @@ impl<'db> Evaluator<'db> { self.layout(Ty::new_adt(self.interner(), adt, subst)) } - fn place_ty<'a>(&'a self, p: &Place<'db>, locals: &'a Locals<'db>) -> Result<'db, Ty<'db>> { + fn place_ty<'a>(&'a self, p: &Place, locals: &'a Locals) -> Result<'db, Ty<'db>> { Ok(self.place_addr_and_ty_and_metadata(p, locals)?.1) } - fn operand_ty(&self, o: &Operand<'db>, locals: &Locals<'db>) -> Result<'db, Ty<'db>> { + fn operand_ty(&self, o: &Operand, locals: &Locals) -> Result<'db, Ty<'db>> { Ok(match &o.kind { OperandKind::Copy(p) | OperandKind::Move(p) => self.place_ty(p, locals)?, - OperandKind::Constant { konst: _, ty } => *ty, + OperandKind::Constant { konst: _, ty } => ty.as_ref(), &OperandKind::Static(s) => { - let ty = self.db.infer(s.into())[self.db.body(s.into()).body_expr]; + let ty = InferenceResult::for_body(self.db, s.into()) + .expr_ty(self.db.body(s.into()).body_expr); Ty::new_ref( self.interner(), Region::new_static(self.interner()), @@ -890,8 +907,8 @@ impl<'db> Evaluator<'db> { fn operand_ty_and_eval( &mut self, - o: &Operand<'db>, - locals: &mut Locals<'db>, + o: &Operand, + locals: &mut Locals, ) -> Result<'db, IntervalAndTy<'db>> { Ok(IntervalAndTy { interval: self.eval_operand(o, locals)?, @@ -901,7 +918,7 @@ impl<'db> Evaluator<'db> { fn interpret_mir( &mut self, - body: Arc<MirBody<'db>>, + body: Arc<MirBody>, args: impl Iterator<Item = IntervalOrOwned>, ) -> Result<'db, Interval> { if let Some(it) = self.stack_depth_limit.checked_sub(1) { @@ -1065,8 +1082,8 @@ impl<'db> Evaluator<'db> { fn fill_locals_for_body( &mut self, - body: &MirBody<'db>, - locals: &mut Locals<'db>, + body: &MirBody, + locals: &mut Locals, args: impl Iterator<Item = IntervalOrOwned>, ) -> Result<'db, ()> { let mut remain_args = body.param_locals.len(); @@ -1089,9 +1106,9 @@ impl<'db> Evaluator<'db> { fn create_locals_for_body( &mut self, - body: &Arc<MirBody<'db>>, + body: &Arc<MirBody>, destination: Option<Interval>, - ) -> Result<'db, (Locals<'db>, usize)> { + ) -> Result<'db, (Locals, usize)> { let mut locals = match self.unused_locals_store.borrow_mut().entry(body.owner).or_default().pop() { None => Locals { @@ -1115,7 +1132,7 @@ impl<'db> Evaluator<'db> { continue; } let (size, align) = self.size_align_of_sized( - it.ty, + it.ty.as_ref(), &locals, "no unsized local in extending stack", )?; @@ -1138,11 +1155,7 @@ impl<'db> Evaluator<'db> { Ok((locals, prev_stack_pointer)) } - fn eval_rvalue( - &mut self, - r: &Rvalue<'db>, - locals: &mut Locals<'db>, - ) -> Result<'db, IntervalOrOwned> { + fn eval_rvalue(&mut self, r: &Rvalue, locals: &mut Locals) -> Result<'db, IntervalOrOwned> { use IntervalOrOwned::*; Ok(match r { Rvalue::Use(it) => Borrowed(self.eval_operand(it, locals)?), @@ -1434,7 +1447,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.as_ref()) { Some(it) => it as usize, None => not_supported!("non evaluatable array len in repeat Rvalue"), }; @@ -1444,7 +1457,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.as_ref(), locals)? else { not_supported!("unsized box initialization"); }; let addr = self.heap_allocate(size, align)?; @@ -1466,7 +1479,7 @@ impl<'db> Evaluator<'db> { Owned(r) } AggregateKind::Tuple(ty) => { - let layout = self.layout(*ty)?; + let layout = self.layout(ty.as_ref())?; Owned(self.construct_with_layout( layout.size.bytes_usize(), &layout, @@ -1475,10 +1488,8 @@ impl<'db> Evaluator<'db> { )?) } AggregateKind::Union(it, f) => { - let layout = self.layout_adt( - (*it).into(), - GenericArgs::new_from_iter(self.interner(), []), - )?; + let layout = + self.layout_adt((*it).into(), GenericArgs::empty(self.interner()))?; let offset = layout .fields .offset(u32::from(f.local_id.into_raw()) as usize) @@ -1490,7 +1501,7 @@ impl<'db> Evaluator<'db> { } AggregateKind::Adt(it, subst) => { let (size, variant_layout, tag) = - self.layout_of_variant(*it, *subst, locals)?; + self.layout_of_variant(*it, subst.as_ref(), locals)?; Owned(self.construct_with_layout( size, &variant_layout, @@ -1499,7 +1510,7 @@ impl<'db> Evaluator<'db> { )?) } AggregateKind::Closure(ty) => { - let layout = self.layout(*ty)?; + let layout = self.layout(ty.as_ref())?; Owned(self.construct_with_layout( layout.size.bytes_usize(), &layout, @@ -1526,7 +1537,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, current_ty, *target_ty)? + self.coerce_unsized(addr, current_ty, target_ty.as_ref())? } PointerCast::MutToConstPointer | PointerCast::UnsafeFnPointer => { // This is no-op @@ -1545,8 +1556,11 @@ impl<'db> Evaluator<'db> { let current_ty = self.operand_ty(operand, locals)?; 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")?; + let dest_size = self.size_of_sized( + target_ty.as_ref(), + locals, + "destination of int to int cast", + )?; Owned(current[0..dest_size].to_vec()) } CastKind::FloatToInt => { @@ -1568,9 +1582,12 @@ impl<'db> Evaluator<'db> { not_supported!("unstable floating point type f16 and f128"); } }; - 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")?; + let is_signed = matches!(target_ty.as_ref().kind(), TyKind::Int(_)); + let dest_size = self.size_of_sized( + target_ty.as_ref(), + locals, + "destination of float to int cast", + )?; let dest_bits = dest_size * 8; let (max, min) = if dest_bits == 128 { (i128::MAX, i128::MIN) @@ -1603,7 +1620,7 @@ impl<'db> Evaluator<'db> { not_supported!("unstable floating point type f16 and f128"); } }; - let TyKind::Float(target_ty) = target_ty.kind() else { + let TyKind::Float(target_ty) = target_ty.as_ref().kind() else { not_supported!("invalid float to float cast"); }; match target_ty { @@ -1619,7 +1636,7 @@ impl<'db> Evaluator<'db> { 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::Float(target_ty) = target_ty.kind() else { + let TyKind::Float(target_ty) = target_ty.as_ref().kind() else { not_supported!("invalid int to float cast"); }; match target_ty { @@ -1698,12 +1715,12 @@ impl<'db> Evaluator<'db> { { let field_types = self.db.field_types(struct_id.into()); if let Some(ty) = - field_types.iter().last().map(|it| it.1.instantiate(self.interner(), subst)) + field_types.iter().last().map(|it| it.1.get().instantiate(self.interner(), subst)) { return self.coerce_unsized_look_through_fields(ty, goal); } } - Err(MirEvalError::CoerceUnsizedError(ty)) + Err(MirEvalError::CoerceUnsizedError(ty.store())) } fn coerce_unsized( @@ -1776,8 +1793,10 @@ impl<'db> Evaluator<'db> { not_supported!("unsizing struct without field"); }; let target_last_field = self.db.field_types(id.into())[last_field] + .get() .instantiate(self.interner(), target_subst); let current_last_field = self.db.field_types(id.into())[last_field] + .get() .instantiate(self.interner(), current_subst); return self.unsizing_ptr_from_addr( target_last_field, @@ -1795,7 +1814,7 @@ impl<'db> Evaluator<'db> { &mut self, it: VariantId, subst: GenericArgs<'db>, - locals: &Locals<'db>, + locals: &Locals, ) -> Result<'db, (usize, Arc<Layout>, Option<(usize, usize, i128)>)> { let adt = it.adt_id(self.db); if let DefWithBodyId::VariantId(f) = locals.body.owner @@ -1889,11 +1908,7 @@ impl<'db> Evaluator<'db> { Ok(result) } - fn eval_operand( - &mut self, - it: &Operand<'db>, - locals: &mut Locals<'db>, - ) -> Result<'db, Interval> { + fn eval_operand(&mut self, it: &Operand, locals: &mut Locals) -> Result<'db, Interval> { Ok(match &it.kind { OperandKind::Copy(p) | OperandKind::Move(p) => { locals.drop_flags.remove_place(p, &locals.body.projection_store); @@ -1903,38 +1918,43 @@ 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.as_ref())? + } }) } #[allow(clippy::double_parens)] fn allocate_const_in_heap( &mut self, - locals: &Locals<'db>, + locals: &Locals, konst: Const<'db>, ) -> Result<'db, Interval> { let result_owner; 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 id = const_id.0; let mut subst = subst; - if let hir_def::GeneralConstId::ConstId(c) = const_id { - let (c, s) = lookup_impl_const(&self.infcx, self.trait_env.clone(), c, subst); - const_id = hir_def::GeneralConstId::ConstId(c); + if let hir_def::GeneralConstId::ConstId(c) = id { + let (c, s) = lookup_impl_const(&self.infcx, self.param_env.param_env, c, subst); + id = hir_def::GeneralConstId::ConstId(c); subst = s; } - result_owner = self - .db - .const_eval(const_id, subst, Some(self.trait_env.clone())) - .map_err(|e| { - let name = const_id.name(self.db); - MirEvalError::ConstEvalError(name, Box::new(e)) - })?; + result_owner = match id { + GeneralConstId::ConstId(const_id) => { + self.db.const_eval(const_id, subst, Some(self.param_env)).map_err(|e| { + let name = id.name(self.db); + MirEvalError::ConstEvalError(name, Box::new(e)) + })? + } + GeneralConstId::StaticId(static_id) => { + self.db.const_eval_static(static_id).map_err(|e| { + let name = id.name(self.db); + MirEvalError::ConstEvalError(name, Box::new(e)) + })? + } + }; if let ConstKind::Value(value) = result_owner.kind() { break 'b value; } @@ -1957,7 +1977,7 @@ impl<'db> Evaluator<'db> { } else if size < 16 && v.len() == 16 { Cow::Borrowed(&v[0..size]) } else { - return Err(MirEvalError::InvalidConst(konst)); + return Err(MirEvalError::InvalidConst(konst.store())); } } else { Cow::Borrowed(v) @@ -1979,7 +1999,7 @@ impl<'db> Evaluator<'db> { Ok(Interval::new(addr, size)) } - fn eval_place(&mut self, p: &Place<'db>, locals: &Locals<'db>) -> Result<'db, Interval> { + fn eval_place(&mut self, p: &Place, locals: &Locals) -> Result<'db, Interval> { let addr = self.place_addr(p, locals)?; Ok(Interval::new( addr, @@ -2079,11 +2099,7 @@ impl<'db> Evaluator<'db> { Ok(()) } - fn size_align_of( - &self, - ty: Ty<'db>, - locals: &Locals<'db>, - ) -> Result<'db, Option<(usize, usize)>> { + fn size_align_of(&self, ty: Ty<'db>, locals: &Locals) -> Result<'db, Option<(usize, usize)>> { if let Some(layout) = self.layout_cache.borrow().get(&ty) { return Ok(layout .is_sized() @@ -2112,12 +2128,12 @@ impl<'db> Evaluator<'db> { fn size_of_sized( &self, ty: Ty<'db>, - locals: &Locals<'db>, + locals: &Locals, what: &'static str, ) -> Result<'db, usize> { match self.size_align_of(ty, locals)? { Some(it) => Ok(it.0), - None => Err(MirEvalError::TypeIsUnsized(ty, what)), + None => Err(MirEvalError::TypeIsUnsized(ty.store(), what)), } } @@ -2126,12 +2142,12 @@ impl<'db> Evaluator<'db> { fn size_align_of_sized( &self, ty: Ty<'db>, - locals: &Locals<'db>, + locals: &Locals, what: &'static str, ) -> Result<'db, (usize, usize)> { match self.size_align_of(ty, locals)? { Some(it) => Ok(it), - None => Err(MirEvalError::TypeIsUnsized(ty, what)), + None => Err(MirEvalError::TypeIsUnsized(ty.store(), what)), } } @@ -2167,13 +2183,13 @@ impl<'db> Evaluator<'db> { &self, bytes: &[u8], ty: Ty<'db>, - locals: &Locals<'db>, + locals: &Locals, ) -> Result<'db, ComplexMemoryMap<'db>> { fn rec<'db>( this: &Evaluator<'db>, bytes: &[u8], ty: Ty<'db>, - locals: &Locals<'db>, + locals: &Locals, mm: &mut ComplexMemoryMap<'db>, stack_depth_limit: usize, ) -> Result<'db, ()> { @@ -2274,7 +2290,7 @@ impl<'db> Evaluator<'db> { .fields .offset(u32::from(f.into_raw()) as usize) .bytes_usize(); - let ty = field_types[f].instantiate(this.interner(), subst); + let ty = field_types[f].get().instantiate(this.interner(), subst); let size = this.layout(ty)?.size.bytes_usize(); rec( this, @@ -2300,7 +2316,7 @@ impl<'db> Evaluator<'db> { 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].instantiate(this.interner(), subst); + let ty = field_types[f].get().instantiate(this.interner(), subst); let size = this.layout(ty)?.size.bytes_usize(); rec( this, @@ -2320,7 +2336,7 @@ impl<'db> Evaluator<'db> { let ty = ocx .structurally_normalize_ty( &ObligationCause::dummy(), - this.trait_env.env, + this.param_env.param_env, ty, ) .map_err(|_| MirEvalError::NotSupported("couldn't normalize".to_owned()))?; @@ -2342,7 +2358,7 @@ impl<'db> Evaluator<'db> { ty_of_bytes: impl Fn(&[u8]) -> Result<'db, Ty<'db>> + Copy, addr: Address, ty: Ty<'db>, - locals: &Locals<'db>, + locals: &Locals, ) -> Result<'db, ()> { // FIXME: support indirect references let layout = self.layout(ty)?; @@ -2375,7 +2391,7 @@ impl<'db> Evaluator<'db> { AdtId::StructId(s) => { for (i, (_, ty)) in self.db.field_types(s.into()).iter().enumerate() { let offset = layout.fields.offset(i).bytes_usize(); - let ty = ty.instantiate(self.interner(), args); + let ty = ty.get().instantiate(self.interner(), args); self.patch_addresses( patch_map, ty_of_bytes, @@ -2396,7 +2412,7 @@ impl<'db> Evaluator<'db> { ) { for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() { let offset = layout.fields.offset(i).bytes_usize(); - let ty = ty.instantiate(self.interner(), args); + let ty = ty.get().instantiate(self.interner(), args); self.patch_addresses( patch_map, ty_of_bytes, @@ -2463,10 +2479,10 @@ impl<'db> Evaluator<'db> { bytes: Interval, destination: Interval, args: &[IntervalAndTy<'db>], - locals: &Locals<'db>, - target_bb: Option<BasicBlockId<'db>>, + locals: &Locals, + target_bb: Option<BasicBlockId>, span: MirSpan, - ) -> Result<'db, Option<StackFrame<'db>>> { + ) -> Result<'db, Option<StackFrame>> { let id = from_bytes!(usize, bytes.get(self)?); let next_ty = self.vtable_map.ty(id)?; use rustc_type_ir::TyKind; @@ -2494,19 +2510,23 @@ impl<'db> Evaluator<'db> { generic_args: GenericArgs<'db>, destination: Interval, args: &[IntervalAndTy<'db>], - locals: &Locals<'db>, + locals: &Locals, span: MirSpan, - ) -> Result<'db, Option<StackFrame<'db>>> { + ) -> Result<'db, Option<StackFrame>> { let mir_body = self .db - .monomorphized_mir_body_for_closure(closure, generic_args, self.trait_env.clone()) + .monomorphized_mir_body_for_closure( + closure, + generic_args.store(), + self.param_env.store(), + ) .map_err(|it| MirEvalError::MirLowerErrorForClosure(closure, it))?; - let closure_data = if mir_body.locals[mir_body.param_locals[0]].ty.as_reference().is_some() - { - closure_data.addr.to_bytes().to_vec() - } else { - closure_data.get(self)?.to_owned() - }; + let closure_data = + if mir_body.locals[mir_body.param_locals[0]].ty.as_ref().as_reference().is_some() { + closure_data.addr.to_bytes().to_vec() + } else { + closure_data.get(self)?.to_owned() + }; let arg_bytes = iter::once(Ok(closure_data)) .chain(args.iter().map(|it| Ok(it.get(self)?.to_owned()))) .collect::<Result<'db, Vec<_>>>()?; @@ -2528,10 +2548,10 @@ impl<'db> Evaluator<'db> { generic_args: GenericArgs<'db>, destination: Interval, args: &[IntervalAndTy<'db>], - locals: &Locals<'db>, - target_bb: Option<BasicBlockId<'db>>, + locals: &Locals, + target_bb: Option<BasicBlockId>, span: MirSpan, - ) -> Result<'db, Option<StackFrame<'db>>> { + ) -> Result<'db, Option<StackFrame>> { match def { CallableDefId::FunctionId(def) => { if self.detect_fn_trait(def).is_some() { @@ -2586,25 +2606,31 @@ impl<'db> Evaluator<'db> { &self, def: FunctionId, generic_args: GenericArgs<'db>, - locals: &Locals<'db>, + locals: &Locals, span: MirSpan, - ) -> Result<'db, MirOrDynIndex<'db>> { + ) -> Result<'db, MirOrDynIndex> { 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) + is_dyn_method(self.interner(), self.param_env.param_env, 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); + let (imp, generic_args) = self.db.lookup_impl_method( + ParamEnvAndCrate { param_env: self.param_env.param_env, krate: self.crate_id }, + def, + generic_args, + ); + let Either::Left(imp) = imp else { + not_supported!("evaluating builtin derive impls is not supported") + }; let mir_body = self .db - .monomorphized_mir_body(imp.into(), generic_args, self.trait_env.clone()) + .monomorphized_mir_body(imp.into(), generic_args.store(), self.param_env.store()) .map_err(|e| { MirEvalError::InFunction( Box::new(MirEvalError::MirLowerError(imp, e)), @@ -2622,11 +2648,11 @@ impl<'db> Evaluator<'db> { mut def: FunctionId, args: &[IntervalAndTy<'db>], generic_args: GenericArgs<'db>, - locals: &Locals<'db>, + locals: &Locals, destination: Interval, - target_bb: Option<BasicBlockId<'db>>, + target_bb: Option<BasicBlockId>, span: MirSpan, - ) -> Result<'db, Option<StackFrame<'db>>> { + ) -> Result<'db, Option<StackFrame>> { if self.detect_and_exec_special_function( def, args, @@ -2688,14 +2714,14 @@ impl<'db> Evaluator<'db> { fn exec_looked_up_function( &mut self, - mir_body: Arc<MirBody<'db>>, - locals: &Locals<'db>, + mir_body: Arc<MirBody>, + locals: &Locals, def: FunctionId, arg_bytes: impl Iterator<Item = IntervalOrOwned>, span: MirSpan, destination: Interval, - target_bb: Option<BasicBlockId<'db>>, - ) -> Result<'db, Option<StackFrame<'db>>> { + target_bb: Option<BasicBlockId>, + ) -> Result<'db, Option<StackFrame>> { Ok(if let Some(target_bb) = target_bb { let (mut locals, prev_stack_ptr) = self.create_locals_for_body(&mir_body, Some(destination))?; @@ -2719,11 +2745,11 @@ impl<'db> Evaluator<'db> { def: FunctionId, args: &[IntervalAndTy<'db>], generic_args: GenericArgs<'db>, - locals: &Locals<'db>, + locals: &Locals, destination: Interval, - target_bb: Option<BasicBlockId<'db>>, + target_bb: Option<BasicBlockId>, span: MirSpan, - ) -> Result<'db, Option<StackFrame<'db>>> { + ) -> Result<'db, Option<StackFrame>> { let func = args .first() .ok_or_else(|| MirEvalError::InternalError("fn trait with no arg".into()))?; @@ -2750,7 +2776,7 @@ impl<'db> Evaluator<'db> { TyKind::Closure(closure, subst) => self.exec_closure( closure.0, func_data, - subst.split_closure_args_untupled().parent_args, + GenericArgs::new_from_slice(subst.as_closure().parent_args()), destination, &args[1..], locals, @@ -2788,7 +2814,7 @@ impl<'db> Evaluator<'db> { } } - fn eval_static(&mut self, st: StaticId, locals: &Locals<'db>) -> Result<'db, Address> { + fn eval_static(&mut self, st: StaticId, locals: &Locals) -> Result<'db, Address> { if let Some(o) = self.static_locations.get(&st) { return Ok(*o); }; @@ -2799,7 +2825,8 @@ impl<'db> Evaluator<'db> { })?; self.allocate_const_in_heap(locals, konst)? } else { - let ty = self.db.infer(st.into())[self.db.body(st.into()).body_expr]; + let ty = InferenceResult::for_body(self.db, st.into()) + .expr_ty(self.db.body(st.into()).body_expr); let Some((size, align)) = self.size_align_of(ty, locals)? else { not_supported!("unsized extern static"); }; @@ -2834,12 +2861,7 @@ impl<'db> Evaluator<'db> { } } - fn drop_place( - &mut self, - place: &Place<'db>, - locals: &mut Locals<'db>, - span: MirSpan, - ) -> Result<'db, ()> { + fn drop_place(&mut self, place: &Place, locals: &mut Locals, 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(()); @@ -2854,13 +2876,13 @@ impl<'db> Evaluator<'db> { fn run_drop_glue_deep( &mut self, ty: Ty<'db>, - locals: &Locals<'db>, + locals: &Locals, addr: Address, _metadata: &[u8], span: MirSpan, ) -> Result<'db, ()> { let Some(drop_fn) = (|| { - let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?; + let drop_trait = self.lang_items().Drop?; drop_trait.trait_items(self.db).method_by_name(&Name::new_symbol_root(sym::drop)) })() else { // in some tests we don't have drop trait in minicore, and @@ -2868,7 +2890,7 @@ impl<'db> Evaluator<'db> { return Ok(()); }; - let generic_args = GenericArgs::new_from_iter(self.interner(), [ty.into()]); + let generic_args = GenericArgs::new_from_slice(&[ty.into()]); if let Ok(MirOrDynIndex::Mir(body)) = self.get_mir_or_dyn_index(drop_fn, generic_args, locals, span) { @@ -2902,7 +2924,9 @@ impl<'db> Evaluator<'db> { .offset(u32::from(field.into_raw()) as usize) .bytes_usize(); let addr = addr.offset(offset); - let ty = field_types[field].instantiate(self.interner(), subst); + let ty = field_types[field] + .get() + .instantiate(self.interner(), subst); self.run_drop_glue_deep(ty, locals, addr, &[], span)?; } } @@ -2993,7 +3017,7 @@ pub fn render_const_using_debug_impl<'db>( 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()]), + GenericArgs::new_from_slice(&[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) |