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.rs392
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)