Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/mir/eval/shim.rs')
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs384
1 files changed, 168 insertions, 216 deletions
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index e9665d5ae9..4b1adecf8c 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -3,26 +3,21 @@
//!
use std::cmp::{self, Ordering};
-use chalk_ir::TyKind;
-use hir_def::{
- CrateRootModuleId,
- builtin_type::{BuiltinInt, BuiltinUint},
- resolver::HasResolver,
-};
+use hir_def::{CrateRootModuleId, resolver::HasResolver, signatures::FunctionSignature};
use hir_expand::name::Name;
use intern::{Symbol, sym};
+use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike, Ty as _};
use stdx::never;
use crate::{
- DropGlue,
display::DisplayTarget,
- error_lifetime,
+ drop::{DropGlue, has_drop_glue},
mir::eval::{
- Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay,
- InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId,
- LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Substitution,
- Ty, TyBuilder, TyExt, pad16,
+ Address, AdtId, Arc, Evaluator, FunctionId, GenericArgs, HasModule, HirDisplay,
+ InternedClosure, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId, LangItem,
+ Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Ty, TyKind, pad16,
},
+ next_solver::Region,
};
mod simd;
@@ -43,33 +38,23 @@ macro_rules! not_supported {
};
}
-impl Evaluator<'_> {
+impl<'db> Evaluator<'db> {
pub(super) fn detect_and_exec_special_function(
&mut self,
def: FunctionId,
- args: &[IntervalAndTy],
- generic_args: &Substitution,
- locals: &Locals,
+ args: &[IntervalAndTy<'db>],
+ generic_args: GenericArgs<'db>,
+ locals: &Locals<'db>,
destination: Interval,
span: MirSpan,
- ) -> Result<bool> {
+ ) -> Result<'db, bool> {
if self.not_special_fn_cache.borrow().contains(&def) {
return Ok(false);
}
let function_data = self.db.function_signature(def);
let attrs = self.db.attrs(def.into());
- let is_intrinsic = attrs.by_key(sym::rustc_intrinsic).exists()
- // Keep this around for a bit until extern "rustc-intrinsic" abis are no longer used
- || (match &function_data.abi {
- Some(abi) => *abi == sym::rust_dash_intrinsic,
- None => match def.lookup(self.db).container {
- hir_def::ItemContainerId::ExternBlockId(block) => {
- block.abi(self.db) == Some(sym::rust_dash_intrinsic)
- }
- _ => false,
- },
- });
+ let is_intrinsic = FunctionSignature::is_intrinsic(self.db, def);
if is_intrinsic {
return self.exec_intrinsic(
@@ -119,25 +104,23 @@ impl Evaluator<'_> {
destination.write_from_bytes(self, &result)?;
return Ok(true);
}
- if let ItemContainerId::TraitId(t) = def.lookup(self.db).container {
- if self.db.lang_attr(t.into()) == Some(LangItem::Clone) {
- let [self_ty] = generic_args.as_slice(Interner) else {
- not_supported!("wrong generic arg count for clone");
- };
- let Some(self_ty) = self_ty.ty(Interner) else {
- not_supported!("wrong generic arg kind for clone");
- };
- // Clone has special impls for tuples and function pointers
- if matches!(
- self_ty.kind(Interner),
- TyKind::Function(_) | TyKind::Tuple(..) | TyKind::Closure(..)
- ) {
- self.exec_clone(def, args, self_ty.clone(), locals, destination, span)?;
- return Ok(true);
- }
- // Return early to prevent caching clone as non special fn.
- return Ok(false);
+ if let ItemContainerId::TraitId(t) = def.lookup(self.db).container
+ && self.db.lang_attr(t.into()) == Some(LangItem::Clone)
+ {
+ let [self_ty] = generic_args.as_slice() else {
+ not_supported!("wrong generic arg count for clone");
+ };
+ let Some(self_ty) = self_ty.ty() else {
+ not_supported!("wrong generic arg kind for clone");
+ };
+ // Clone has special impls for tuples and function pointers
+ if matches!(self_ty.kind(), TyKind::FnPtr(..) | TyKind::Tuple(..) | TyKind::Closure(..))
+ {
+ self.exec_clone(def, args, self_ty, locals, destination, span)?;
+ return Ok(true);
}
+ // Return early to prevent caching clone as non special fn.
+ return Ok(false);
}
self.not_special_fn_cache.borrow_mut().insert(def);
Ok(false)
@@ -146,7 +129,7 @@ impl Evaluator<'_> {
pub(super) fn detect_and_redirect_special_function(
&mut self,
def: FunctionId,
- ) -> Result<Option<FunctionId>> {
+ ) -> Result<'db, Option<FunctionId>> {
// `PanicFmt` is redirected to `ConstPanicFmt`
if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) {
let resolver = CrateRootModuleId::from(self.crate_id).resolver(self.db);
@@ -165,14 +148,14 @@ impl Evaluator<'_> {
fn exec_clone(
&mut self,
def: FunctionId,
- args: &[IntervalAndTy],
- self_ty: Ty,
- locals: &Locals,
+ args: &[IntervalAndTy<'db>],
+ self_ty: Ty<'db>,
+ locals: &Locals<'db>,
destination: Interval,
span: MirSpan,
- ) -> Result<()> {
- match self_ty.kind(Interner) {
- TyKind::Function(_) => {
+ ) -> Result<'db, ()> {
+ match self_ty.kind() {
+ TyKind::FnPtr(..) => {
let [arg] = args else {
not_supported!("wrong arg count for clone");
};
@@ -185,27 +168,35 @@ impl Evaluator<'_> {
not_supported!("wrong arg count for clone");
};
let addr = Address::from_bytes(arg.get(self)?)?;
- let InternedClosure(closure_owner, _) = self.db.lookup_intern_closure((*id).into());
+ let InternedClosure(closure_owner, _) = self.db.lookup_intern_closure(id.0);
let infer = self.db.infer(closure_owner);
- let (captures, _) = infer.closure_info(id);
- let layout = self.layout(&self_ty)?;
- let ty_iter = captures.iter().map(|c| c.ty(subst));
+ let (captures, _) = infer.closure_info(id.0);
+ let layout = self.layout(self_ty)?;
+ let db = self.db;
+ let ty_iter = captures.iter().map(|c| c.ty(db, subst));
self.exec_clone_for_fields(ty_iter, layout, addr, def, locals, destination, span)?;
}
- TyKind::Tuple(_, subst) => {
+ TyKind::Tuple(subst) => {
let [arg] = args else {
not_supported!("wrong arg count for clone");
};
let addr = Address::from_bytes(arg.get(self)?)?;
- let layout = self.layout(&self_ty)?;
- let ty_iter = subst.iter(Interner).map(|ga| ga.assert_ty_ref(Interner).clone());
- self.exec_clone_for_fields(ty_iter, layout, addr, def, locals, destination, span)?;
+ let layout = self.layout(self_ty)?;
+ self.exec_clone_for_fields(
+ subst.iter(),
+ layout,
+ addr,
+ def,
+ locals,
+ destination,
+ span,
+ )?;
}
_ => {
self.exec_fn_with_args(
def,
args,
- Substitution::from1(Interner, self_ty),
+ GenericArgs::new_from_iter(self.interner(), [self_ty.into()]),
locals,
destination,
None,
@@ -218,20 +209,25 @@ impl Evaluator<'_> {
fn exec_clone_for_fields(
&mut self,
- ty_iter: impl Iterator<Item = Ty>,
+ ty_iter: impl Iterator<Item = Ty<'db>>,
layout: Arc<Layout>,
addr: Address,
def: FunctionId,
- locals: &Locals,
+ locals: &Locals<'db>,
destination: Interval,
span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
for (i, ty) in ty_iter.enumerate() {
- let size = self.layout(&ty)?.size.bytes_usize();
+ let size = self.layout(ty)?.size.bytes_usize();
let tmp = self.heap_allocate(self.ptr_size(), self.ptr_size())?;
let arg = IntervalAndTy {
interval: Interval { addr: tmp, size: self.ptr_size() },
- ty: TyKind::Ref(Mutability::Not, error_lifetime(), ty.clone()).intern(Interner),
+ ty: Ty::new_ref(
+ self.interner(),
+ Region::error(self.interner()),
+ ty,
+ Mutability::Not,
+ ),
};
let offset = layout.fields.offset(i).bytes_usize();
self.write_memory(tmp, &addr.offset(offset).to_bytes())?;
@@ -250,9 +246,9 @@ impl Evaluator<'_> {
fn exec_alloc_fn(
&mut self,
alloc_fn: &Symbol,
- args: &[IntervalAndTy],
+ args: &[IntervalAndTy<'db>],
destination: Interval,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
match alloc_fn {
_ if *alloc_fn == sym::rustc_allocator_zeroed || *alloc_fn == sym::rustc_allocator => {
let [size, align] = args else {
@@ -312,11 +308,11 @@ impl Evaluator<'_> {
fn exec_lang_item(
&mut self,
it: LangItem,
- generic_args: &Substitution,
- args: &[IntervalAndTy],
- locals: &Locals,
+ generic_args: GenericArgs<'db>,
+ args: &[IntervalAndTy<'db>],
+ locals: &Locals<'db>,
span: MirSpan,
- ) -> Result<Vec<u8>> {
+ ) -> Result<'db, Vec<u8>> {
use LangItem::*;
let mut args = args.iter();
match it {
@@ -327,7 +323,7 @@ impl Evaluator<'_> {
"argument of BeginPanic is not provided".into(),
))?
.clone();
- while let TyKind::Ref(_, _, ty) = arg.ty.kind(Interner) {
+ while let TyKind::Ref(_, ty, _) = arg.ty.kind() {
if ty.is_str() {
let (pointee, metadata) = arg.interval.get(self)?.split_at(self.ptr_size());
let len = from_bytes!(usize, metadata);
@@ -346,13 +342,10 @@ impl Evaluator<'_> {
let pointee = arg.interval.get(self)?;
arg = IntervalAndTy {
interval: Interval::new(Address::from_bytes(pointee)?, size),
- ty: ty.clone(),
+ ty,
};
}
- Err(MirEvalError::Panic(format!(
- "unknown-panic-payload: {:?}",
- arg.ty.kind(Interner)
- )))
+ Err(MirEvalError::Panic(format!("unknown-panic-payload: {:?}", arg.ty.kind())))
}
SliceLen => {
let arg = args.next().ok_or(MirEvalError::InternalError(
@@ -363,18 +356,17 @@ impl Evaluator<'_> {
Ok(arg[ptr_size..].into())
}
DropInPlace => {
- let ty =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)).ok_or(
- MirEvalError::InternalError(
- "generic argument of drop_in_place is not provided".into(),
- ),
- )?;
+ let ty = generic_args.as_slice().first().and_then(|it| it.ty()).ok_or(
+ MirEvalError::InternalError(
+ "generic argument of drop_in_place is not provided".into(),
+ ),
+ )?;
let arg = args.next().ok_or(MirEvalError::InternalError(
"argument of drop_in_place is not provided".into(),
))?;
let arg = arg.interval.get(self)?.to_owned();
self.run_drop_glue_deep(
- ty.clone(),
+ ty,
locals,
Address::from_bytes(&arg[0..self.ptr_size()])?,
&arg[self.ptr_size()..],
@@ -389,11 +381,11 @@ impl Evaluator<'_> {
fn exec_syscall(
&mut self,
id: i64,
- args: &[IntervalAndTy],
+ args: &[IntervalAndTy<'db>],
destination: Interval,
- _locals: &Locals,
+ _locals: &Locals<'db>,
_span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
match id {
318 => {
// SYS_getrandom
@@ -419,12 +411,12 @@ impl Evaluator<'_> {
fn exec_extern_c(
&mut self,
as_str: &str,
- args: &[IntervalAndTy],
- _generic_args: &Substitution,
+ args: &[IntervalAndTy<'db>],
+ _generic_args: GenericArgs<'db>,
destination: Interval,
- locals: &Locals,
+ locals: &Locals<'db>,
span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
match as_str {
"memcmp" => {
let [ptr1, ptr2, size] = args else {
@@ -585,13 +577,13 @@ impl Evaluator<'_> {
fn exec_intrinsic(
&mut self,
name: &str,
- args: &[IntervalAndTy],
- generic_args: &Substitution,
+ args: &[IntervalAndTy<'db>],
+ generic_args: GenericArgs<'db>,
destination: Interval,
- locals: &Locals,
+ locals: &Locals<'db>,
span: MirSpan,
needs_override: bool,
- ) -> Result<bool> {
+ ) -> Result<'db, bool> {
if let Some(name) = name.strip_prefix("atomic_") {
return self
.exec_atomic_intrinsic(name, args, generic_args, destination, locals, span)
@@ -749,9 +741,7 @@ impl Evaluator<'_> {
}
match name {
"size_of" => {
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"size_of generic arg is not provided".into(),
));
@@ -762,20 +752,16 @@ impl Evaluator<'_> {
// FIXME: `min_align_of` was renamed to `align_of` in Rust 1.89
// (https://github.com/rust-lang/rust/pull/142410)
"min_align_of" | "align_of" => {
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"align_of generic arg is not provided".into(),
));
};
- let align = self.layout(ty)?.align.abi.bytes();
+ let align = self.layout(ty)?.align.bytes();
destination.write_from_bytes(self, &align.to_le_bytes()[0..destination.size])
}
"size_of_val" => {
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"size_of_val generic arg is not provided".into(),
));
@@ -796,9 +782,7 @@ impl Evaluator<'_> {
// FIXME: `min_align_of_val` was renamed to `align_of_val` in Rust 1.89
// (https://github.com/rust-lang/rust/pull/142410)
"min_align_of_val" | "align_of_val" => {
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"align_of_val generic arg is not provided".into(),
));
@@ -817,9 +801,7 @@ impl Evaluator<'_> {
}
}
"type_name" => {
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"type_name generic arg is not provided".into(),
));
@@ -846,14 +828,12 @@ impl Evaluator<'_> {
.write_from_bytes(self, &len.to_le_bytes())
}
"needs_drop" => {
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"size_of generic arg is not provided".into(),
));
};
- let result = match self.db.has_drop_glue(ty.clone(), self.trait_env.clone()) {
+ let result = match has_drop_glue(&self.infcx, ty, self.trait_env.clone()) {
DropGlue::HasDropGlue => true,
DropGlue::None => false,
DropGlue::DependOnParams => {
@@ -916,9 +896,7 @@ impl Evaluator<'_> {
let lhs = i128::from_le_bytes(pad16(lhs.get(self)?, false));
let rhs = i128::from_le_bytes(pad16(rhs.get(self)?, false));
let ans = lhs.wrapping_sub(rhs);
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"ptr_offset_from generic arg is not provided".into(),
));
@@ -1007,13 +985,11 @@ impl Evaluator<'_> {
"const_eval_select args are not provided".into(),
));
};
- let result_ty = TyKind::Tuple(
- 2,
- Substitution::from_iter(Interner, [lhs.ty.clone(), TyBuilder::bool()]),
- )
- .intern(Interner);
- let op_size =
- self.size_of_sized(&lhs.ty, locals, "operand of add_with_overflow")?;
+ let result_ty = Ty::new_tup_from_iter(
+ self.interner(),
+ [lhs.ty, Ty::new_bool(self.interner())].into_iter(),
+ );
+ let op_size = self.size_of_sized(lhs.ty, locals, "operand of add_with_overflow")?;
let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false));
let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false));
let (ans, u128overflow) = match name {
@@ -1025,7 +1001,7 @@ impl Evaluator<'_> {
let is_overflow = u128overflow
|| ans.to_le_bytes()[op_size..].iter().any(|&it| it != 0 && it != 255);
let is_overflow = vec![u8::from(is_overflow)];
- let layout = self.layout(&result_ty)?;
+ let layout = self.layout(result_ty)?;
let result = self.construct_with_layout(
layout.size.bytes_usize(),
&layout,
@@ -1042,9 +1018,7 @@ impl Evaluator<'_> {
"copy_nonoverlapping args are not provided".into(),
));
};
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"copy_nonoverlapping generic arg is not provided".into(),
));
@@ -1063,43 +1037,35 @@ impl Evaluator<'_> {
return Err(MirEvalError::InternalError("offset args are not provided".into()));
};
let ty = if name == "offset" {
- let Some(ty0) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty0) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"offset generic arg is not provided".into(),
));
};
- let Some(ty1) =
- generic_args.as_slice(Interner).get(1).and_then(|it| it.ty(Interner))
- else {
+ let Some(ty1) = generic_args.as_slice().get(1).and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"offset generic arg is not provided".into(),
));
};
if !matches!(
- ty1.as_builtin(),
- Some(
- BuiltinType::Int(BuiltinInt::Isize)
- | BuiltinType::Uint(BuiltinUint::Usize)
- )
+ ty1.kind(),
+ TyKind::Int(rustc_type_ir::IntTy::Isize)
+ | TyKind::Uint(rustc_type_ir::UintTy::Usize)
) {
return Err(MirEvalError::InternalError(
"offset generic arg is not usize or isize".into(),
));
}
- match ty0.as_raw_ptr() {
- Some((ty, _)) => ty,
- None => {
+ match ty0.kind() {
+ TyKind::RawPtr(ty, _) => ty,
+ _ => {
return Err(MirEvalError::InternalError(
"offset generic arg is not a raw pointer".into(),
));
}
}
} else {
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"arith_offset generic arg is not provided".into(),
));
@@ -1224,9 +1190,7 @@ impl Evaluator<'_> {
"discriminant_value arg is not provided".into(),
));
};
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"discriminant_value generic arg is not provided".into(),
));
@@ -1234,7 +1198,7 @@ impl Evaluator<'_> {
let addr = Address::from_bytes(arg.get(self)?)?;
let size = self.size_of_sized(ty, locals, "discriminant_value ptr type")?;
let interval = Interval { addr, size };
- let r = self.compute_discriminant(ty.clone(), interval.get(self)?)?;
+ let r = self.compute_discriminant(ty, interval.get(self)?)?;
destination.write_from_bytes(self, &r.to_le_bytes()[0..destination.size])
}
"const_eval_select" => {
@@ -1244,35 +1208,33 @@ impl Evaluator<'_> {
));
};
let mut args = vec![const_fn.clone()];
- let TyKind::Tuple(_, fields) = tuple.ty.kind(Interner) else {
+ let TyKind::Tuple(fields) = tuple.ty.kind() else {
return Err(MirEvalError::InternalError(
"const_eval_select arg[0] is not a tuple".into(),
));
};
- let layout = self.layout(&tuple.ty)?;
- for (i, field) in fields.iter(Interner).enumerate() {
- let field = field.assert_ty_ref(Interner).clone();
+ let layout = self.layout(tuple.ty)?;
+ for (i, field) in fields.iter().enumerate() {
let offset = layout.fields.offset(i).bytes_usize();
let addr = tuple.interval.addr.offset(offset);
args.push(IntervalAndTy::new(addr, field, self, locals)?);
}
- if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id) {
- if let Some(def) = target
+ if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id)
+ && let Some(def) = target
.trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::call_once))
- {
- self.exec_fn_trait(
- def,
- &args,
- // FIXME: wrong for manual impls of `FnOnce`
- Substitution::empty(Interner),
- locals,
- destination,
- None,
- span,
- )?;
- return Ok(true);
- }
+ {
+ self.exec_fn_trait(
+ def,
+ &args,
+ // FIXME: wrong for manual impls of `FnOnce`
+ GenericArgs::new_from_iter(self.interner(), []),
+ locals,
+ destination,
+ None,
+ span,
+ )?;
+ return Ok(true);
}
not_supported!("FnOnce was not available for executing const_eval_select");
}
@@ -1292,9 +1254,7 @@ impl Evaluator<'_> {
));
};
let dst = Address::from_bytes(ptr.get(self)?)?;
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"write_via_copy generic arg is not provided".into(),
));
@@ -1311,9 +1271,7 @@ impl Evaluator<'_> {
};
let count = from_bytes!(usize, count.get(self)?);
let val = from_bytes!(u8, val.get(self)?);
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"write_bytes generic arg is not provided".into(),
));
@@ -1341,16 +1299,14 @@ impl Evaluator<'_> {
"three_way_compare args are not provided".into(),
));
};
- let Some(ty) =
- generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"three_way_compare generic arg is not provided".into(),
));
};
- let signed = match ty.as_builtin().unwrap() {
- BuiltinType::Int(_) => true,
- BuiltinType::Uint(_) => false,
+ let signed = match ty.kind() {
+ TyKind::Int(_) => true,
+ TyKind::Uint(_) => false,
_ => {
return Err(MirEvalError::InternalError(
"three_way_compare expects an integral type".into(),
@@ -1367,17 +1323,15 @@ impl Evaluator<'_> {
break;
}
}
- if signed {
- if let Some((&l, &r)) = lhs.iter().zip(rhs).next_back() {
- if l != r {
- result = (l as i8).cmp(&(r as i8));
- }
- }
+ if signed
+ && let Some((&l, &r)) = lhs.iter().zip(rhs).next_back()
+ && l != r
+ {
+ result = (l as i8).cmp(&(r as i8));
}
if let Some(e) = LangItem::Ordering.resolve_enum(self.db, self.crate_id) {
- let ty = self.db.ty(e.into());
- let r = self
- .compute_discriminant(ty.skip_binders().clone(), &[result as i8 as u8])?;
+ let ty = self.db.ty(e.into()).skip_binder();
+ let r = self.compute_discriminant(ty, &[result as i8 as u8])?;
destination.write_from_bytes(self, &r.to_le_bytes()[0..destination.size])?;
Ok(())
} else {
@@ -1406,37 +1360,37 @@ impl Evaluator<'_> {
fn size_align_of_unsized(
&mut self,
- ty: &Ty,
+ ty: Ty<'db>,
metadata: Interval,
- locals: &Locals,
- ) -> Result<(usize, usize)> {
- Ok(match ty.kind(Interner) {
+ locals: &Locals<'db>,
+ ) -> Result<'db, (usize, usize)> {
+ Ok(match ty.kind() {
TyKind::Str => (from_bytes!(usize, metadata.get(self)?), 1),
TyKind::Slice(inner) => {
let len = from_bytes!(usize, metadata.get(self)?);
let (size, align) = self.size_align_of_sized(inner, locals, "slice inner type")?;
(size * len, align)
}
- TyKind::Dyn(_) => self.size_align_of_sized(
+ TyKind::Dynamic(..) => self.size_align_of_sized(
self.vtable_map.ty_of_bytes(metadata.get(self)?)?,
locals,
"dyn concrete type",
)?,
- TyKind::Adt(id, subst) => {
- let id = id.0;
- let layout = self.layout_adt(id, subst.clone())?;
+ TyKind::Adt(adt_def, subst) => {
+ let id = adt_def.def_id().0;
+ let layout = self.layout_adt(id, subst)?;
let id = match id {
AdtId::StructId(s) => s,
_ => not_supported!("unsized enum or union"),
};
- let field_types = &self.db.field_types(id.into());
+ let field_types = self.db.field_types(id.into());
let last_field_ty =
- field_types.iter().next_back().unwrap().1.clone().substitute(Interner, subst);
+ field_types.iter().next_back().unwrap().1.instantiate(self.interner(), subst);
let sized_part_size =
layout.fields.offset(field_types.iter().count() - 1).bytes_usize();
- let sized_part_align = layout.align.abi.bytes() as usize;
+ let sized_part_align = layout.align.bytes() as usize;
let (unsized_part_size, unsized_part_align) =
- self.size_align_of_unsized(&last_field_ty, metadata, locals)?;
+ self.size_align_of_unsized(last_field_ty, metadata, locals)?;
let align = sized_part_align.max(unsized_part_align) as isize;
let size = (sized_part_size + unsized_part_size) as isize;
// Must add any necessary padding to `size`
@@ -1459,12 +1413,12 @@ impl Evaluator<'_> {
fn exec_atomic_intrinsic(
&mut self,
name: &str,
- args: &[IntervalAndTy],
- generic_args: &Substitution,
+ args: &[IntervalAndTy<'db>],
+ generic_args: GenericArgs<'db>,
destination: Interval,
- locals: &Locals,
+ locals: &Locals<'db>,
_span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
// We are a single threaded runtime with no UB checking and no optimization, so
// we can implement atomic intrinsics as normal functions.
@@ -1474,8 +1428,7 @@ impl Evaluator<'_> {
// The rest of atomic intrinsics have exactly one generic arg
- let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
- else {
+ let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else {
return Err(MirEvalError::InternalError(
"atomic intrinsic generic arg is not provided".into(),
));
@@ -1557,12 +1510,11 @@ impl Evaluator<'_> {
} else {
(arg0_interval, false)
};
- let result_ty = TyKind::Tuple(
- 2,
- Substitution::from_iter(Interner, [ty.clone(), TyBuilder::bool()]),
- )
- .intern(Interner);
- let layout = self.layout(&result_ty)?;
+ let result_ty = Ty::new_tup_from_iter(
+ self.interner(),
+ [ty, Ty::new_bool(self.interner())].into_iter(),
+ );
+ let layout = self.layout(result_ty)?;
let result = self.construct_with_layout(
layout.size.bytes_usize(),
&layout,