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.rs | 384 |
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, |