Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/layout.rs')
| -rw-r--r-- | crates/hir-ty/src/layout.rs | 325 |
1 files changed, 161 insertions, 164 deletions
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index 107da6a5af..fc0b9d30b3 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -2,33 +2,38 @@ use std::fmt; -use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy}; use hir_def::{ - LocalFieldId, StructId, - layout::{ - Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutData, Primitive, - ReprOptions, Scalar, StructKind, TargetDataLayout, WrappingRange, - }, + AdtId, LocalFieldId, StructId, + layout::{LayoutCalculatorError, LayoutData}, }; use la_arena::{Idx, RawIdx}; -use rustc_abi::AddressSpace; -use rustc_index::IndexVec; +use rustc_abi::{ + AddressSpace, Float, Integer, LayoutCalculator, Primitive, ReprOptions, Scalar, StructKind, + TargetDataLayout, WrappingRange, +}; +use rustc_index::IndexVec; +use rustc_type_ir::{ + FloatTy, IntTy, UintTy, + inherent::{IntoKind, SliceLike}, +}; use triomphe::Arc; use crate::{ - Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, + TraitEnvironment, consteval::try_const_usize, - db::{HirDatabase, InternedClosure}, - infer::normalize, - utils::ClosureSubst, + db::HirDatabase, + next_solver::{ + DbInterner, GenericArgs, ParamEnv, Ty, TyKind, TypingMode, + infer::{DbInternerInferExt, traits::ObligationCause}, + }, }; pub(crate) use self::adt::layout_of_adt_cycle_result; pub use self::{adt::layout_of_adt_query, target::target_data_layout_query}; -mod adt; -mod target; +pub(crate) mod adt; +pub(crate) mod target; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct RustcEnumVariantIdx(pub usize); @@ -119,12 +124,13 @@ impl<'a> LayoutCx<'a> { } } -fn layout_of_simd_ty( - db: &dyn HirDatabase, +// FIXME: move this to the `rustc_abi`. +fn layout_of_simd_ty<'db>( + db: &'db dyn HirDatabase, id: StructId, repr_packed: bool, - subst: &Substitution, - env: Arc<TraitEnvironment>, + args: &GenericArgs<'db>, + env: Arc<TraitEnvironment<'db>>, dl: &TargetDataLayout, ) -> Result<Arc<Layout>, LayoutError> { // Supported SIMD vectors are homogeneous ADTs with exactly one array field: @@ -137,110 +143,114 @@ fn layout_of_simd_ty( let Some(TyKind::Array(e_ty, e_len)) = fields .next() .filter(|_| fields.next().is_none()) - .map(|f| f.1.clone().substitute(Interner, subst).kind(Interner).clone()) + .map(|f| (*f.1).instantiate(DbInterner::new_with(db, None, None), args).kind()) else { return Err(LayoutError::InvalidSimdType); }; - let e_len = try_const_usize(db, &e_len).ok_or(LayoutError::HasErrorConst)? as u64; + let e_len = try_const_usize(db, e_len).ok_or(LayoutError::HasErrorConst)? as u64; let e_ly = db.layout_of_ty(e_ty, env)?; let cx = LayoutCx::new(dl); Ok(Arc::new(cx.calc.simd_type(e_ly, e_len, repr_packed)?)) } -pub fn layout_of_ty_query( - db: &dyn HirDatabase, - ty: Ty, - trait_env: Arc<TraitEnvironment>, +pub fn layout_of_ty_query<'db>( + db: &'db dyn HirDatabase, + ty: Ty<'db>, + trait_env: Arc<TraitEnvironment<'db>>, ) -> Result<Arc<Layout>, LayoutError> { let krate = trait_env.krate; + let interner = DbInterner::new_with(db, Some(krate), trait_env.block); let Ok(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable); }; let dl = &*target; let cx = LayoutCx::new(dl); - let ty = normalize(db, trait_env.clone(), ty); - let kind = ty.kind(Interner); - let result = match kind { - TyKind::Adt(AdtId(def), subst) => { - if let hir_def::AdtId::StructId(s) = def { - let data = db.struct_signature(*s); - let repr = data.repr.unwrap_or_default(); - if repr.simd() { - return layout_of_simd_ty(db, *s, repr.packed(), subst, trait_env, &target); + let infer_ctxt = interner.infer_ctxt().build(TypingMode::PostAnalysis); + let cause = ObligationCause::dummy(); + let ty = infer_ctxt.at(&cause, ParamEnv::empty()).deeply_normalize(ty).unwrap_or(ty); + let result = match ty.kind() { + TyKind::Adt(def, args) => { + match def.inner().id { + hir_def::AdtId::StructId(s) => { + let data = db.struct_signature(s); + let repr = data.repr.unwrap_or_default(); + if repr.simd() { + return layout_of_simd_ty(db, s, repr.packed(), &args, trait_env, &target); + } } - }; - return db.layout_of_adt(*def, subst.clone(), trait_env); + _ => {} + } + return db.layout_of_adt(def.inner().id, args, trait_env); } - TyKind::Scalar(s) => match s { - chalk_ir::Scalar::Bool => Layout::scalar( - dl, - Scalar::Initialized { - value: Primitive::Int(Integer::I8, false), - valid_range: WrappingRange { start: 0, end: 1 }, - }, - ), - chalk_ir::Scalar::Char => Layout::scalar( + TyKind::Bool => Layout::scalar( + dl, + Scalar::Initialized { + value: Primitive::Int(Integer::I8, false), + valid_range: WrappingRange { start: 0, end: 1 }, + }, + ), + TyKind::Char => Layout::scalar( + dl, + Scalar::Initialized { + value: Primitive::Int(Integer::I32, false), + valid_range: WrappingRange { start: 0, end: 0x10FFFF }, + }, + ), + TyKind::Int(i) => Layout::scalar( + dl, + scalar_unit( dl, - Scalar::Initialized { - value: Primitive::Int(Integer::I32, false), - valid_range: WrappingRange { start: 0, end: 0x10FFFF }, - }, - ), - chalk_ir::Scalar::Int(i) => Layout::scalar( - dl, - scalar_unit( - dl, - Primitive::Int( - match i { - IntTy::Isize => dl.ptr_sized_integer(), - IntTy::I8 => Integer::I8, - IntTy::I16 => Integer::I16, - IntTy::I32 => Integer::I32, - IntTy::I64 => Integer::I64, - IntTy::I128 => Integer::I128, - }, - true, - ), + Primitive::Int( + match i { + IntTy::Isize => dl.ptr_sized_integer(), + IntTy::I8 => Integer::I8, + IntTy::I16 => Integer::I16, + IntTy::I32 => Integer::I32, + IntTy::I64 => Integer::I64, + IntTy::I128 => Integer::I128, + }, + true, ), ), - chalk_ir::Scalar::Uint(i) => Layout::scalar( + ), + TyKind::Uint(i) => Layout::scalar( + dl, + scalar_unit( dl, - scalar_unit( - dl, - Primitive::Int( - match i { - UintTy::Usize => dl.ptr_sized_integer(), - UintTy::U8 => Integer::I8, - UintTy::U16 => Integer::I16, - UintTy::U32 => Integer::I32, - UintTy::U64 => Integer::I64, - UintTy::U128 => Integer::I128, - }, - false, - ), + Primitive::Int( + match i { + UintTy::Usize => dl.ptr_sized_integer(), + UintTy::U8 => Integer::I8, + UintTy::U16 => Integer::I16, + UintTy::U32 => Integer::I32, + UintTy::U64 => Integer::I64, + UintTy::U128 => Integer::I128, + }, + false, ), ), - chalk_ir::Scalar::Float(f) => Layout::scalar( + ), + TyKind::Float(f) => Layout::scalar( + dl, + scalar_unit( dl, - scalar_unit( - dl, - Primitive::Float(match f { - FloatTy::F16 => Float::F16, - FloatTy::F32 => Float::F32, - FloatTy::F64 => Float::F64, - FloatTy::F128 => Float::F128, - }), - ), + Primitive::Float(match f { + FloatTy::F16 => Float::F16, + FloatTy::F32 => Float::F32, + FloatTy::F64 => Float::F64, + FloatTy::F128 => Float::F128, + }), ), - }, - TyKind::Tuple(len, tys) => { - let kind = if *len == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; + ), + TyKind::Tuple(tys) => { + let kind = + if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; let fields = tys - .iter(Interner) - .map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), trait_env.clone())) + .iter() + .map(|k| db.layout_of_ty(k, trait_env.clone())) .collect::<Result<Vec<_>, _>>()?; let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>(); let fields = fields.iter().collect::<IndexVec<_, _>>(); @@ -248,11 +258,11 @@ pub fn layout_of_ty_query( } TyKind::Array(element, count) => { let count = try_const_usize(db, count).ok_or(LayoutError::HasErrorConst)? as u64; - let element = db.layout_of_ty(element.clone(), trait_env)?; + let element = db.layout_of_ty(element, trait_env)?; cx.calc.array_like::<_, _, ()>(&element, Some(count))? } TyKind::Slice(element) => { - let element = db.layout_of_ty(element.clone(), trait_env)?; + let element = db.layout_of_ty(element, trait_env)?; cx.calc.array_like::<_, _, ()>(&element, None)? } TyKind::Str => { @@ -260,18 +270,21 @@ pub fn layout_of_ty_query( cx.calc.array_like::<_, _, ()>(&Layout::scalar(dl, element), None)? } // Potentially-wide pointers. - TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => { + TyKind::Ref(_, pointee, _) | TyKind::RawPtr(pointee, _) => { let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::ZERO)); - if matches!(ty.kind(Interner), TyKind::Ref(..)) { + if matches!(ty.kind(), TyKind::Ref(..)) { data_ptr.valid_range_mut().start = 1; } + // FIXME(next-solver) // let pointee = tcx.normalize_erasing_regions(param_env, pointee); // if pointee.is_sized(tcx.at(DUMMY_SP), param_env) { - // return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); + // return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); // } - let mut unsized_part = struct_tail_erasing_lifetimes(db, pointee.clone()); + let unsized_part = struct_tail_erasing_lifetimes(db, pointee); + // FIXME(next-solver) + /* if let TyKind::AssociatedType(id, subst) = unsized_part.kind(Interner) { unsized_part = TyKind::Alias(chalk_ir::AliasTy::Projection(ProjectionTy { associated_ty_id: *id, @@ -280,11 +293,12 @@ pub fn layout_of_ty_query( .intern(Interner); } unsized_part = normalize(db, trait_env, unsized_part); - let metadata = match unsized_part.kind(Interner) { + */ + let metadata = match unsized_part.kind() { TyKind::Slice(_) | TyKind::Str => { scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false)) } - TyKind::Dyn(..) => { + TyKind::Dynamic(..) => { let mut vtable = scalar_unit(dl, Primitive::Pointer(AddressSpace::ZERO)); vtable.valid_range_mut().start = 1; vtable @@ -299,97 +313,80 @@ pub fn layout_of_ty_query( LayoutData::scalar_pair(dl, data_ptr, metadata) } TyKind::Never => LayoutData::never_type(dl), - TyKind::FnDef(..) | TyKind::Dyn(_) | TyKind::Foreign(_) => { - let sized = matches!(kind, TyKind::FnDef(..)); - LayoutData::unit(dl, sized) - } - TyKind::Function(_) => { + TyKind::FnDef(..) => LayoutData::unit(dl, true), + TyKind::Dynamic(..) | TyKind::Foreign(_) => LayoutData::unit(dl, false), + TyKind::FnPtr(..) => { let mut ptr = scalar_unit(dl, Primitive::Pointer(dl.instruction_address_space)); ptr.valid_range_mut().start = 1; Layout::scalar(dl, ptr) } - TyKind::OpaqueType(opaque_ty_id, _) => { - let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into()); - match impl_trait_id { - crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => { - let infer = db.infer(func.into()); - return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env); - } - crate::ImplTraitId::TypeAliasImplTrait(..) => { - return Err(LayoutError::NotImplemented); - } - crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => { - return Err(LayoutError::NotImplemented); - } - } - } - TyKind::Closure(c, subst) => { - let InternedClosure(def, _) = db.lookup_intern_closure((*c).into()); - let infer = db.infer(def); - let (captures, _) = infer.closure_info(c); + TyKind::Closure(id, args) => { + let def = db.lookup_intern_closure(id.0); + let infer = db.infer(def.0); + let (captures, _) = infer.closure_info(id.0); let fields = captures .iter() .map(|it| { - db.layout_of_ty( - it.ty.clone().substitute(Interner, ClosureSubst(subst).parent_subst()), - trait_env.clone(), - ) + let ty = + it.ty.instantiate(interner, args.split_closure_args_untupled().parent_args); + db.layout_of_ty(ty, trait_env.clone()) }) .collect::<Result<Vec<_>, _>>()?; let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>(); let fields = fields.iter().collect::<IndexVec<_, _>>(); cx.calc.univariant(&fields, &ReprOptions::default(), StructKind::AlwaysSized)? } - TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => { + + TyKind::Coroutine(_, _) + | TyKind::CoroutineWitness(_, _) + | TyKind::CoroutineClosure(_, _) => { + return Err(LayoutError::NotImplemented); + } + + TyKind::Pat(_, _) | TyKind::UnsafeBinder(_) => { return Err(LayoutError::NotImplemented); } - TyKind::Error => return Err(LayoutError::HasErrorType), - TyKind::AssociatedType(id, subst) => { - // Try again with `TyKind::Alias` to normalize the associated type. - // Usually we should not try to normalize `TyKind::AssociatedType`, but layout calculation is used - // in monomorphized MIR where this is okay. If outside monomorphization, this will lead to cycle, - // which we will recover from with an error. - let ty = TyKind::Alias(chalk_ir::AliasTy::Projection(ProjectionTy { - associated_ty_id: *id, - substitution: subst.clone(), - })) - .intern(Interner); - return db.layout_of_ty(ty, trait_env); + + TyKind::Error(_) => return Err(LayoutError::HasErrorType), + TyKind::Placeholder(_) + | TyKind::Bound(..) + | TyKind::Infer(..) + | TyKind::Param(..) + | TyKind::Alias(..) => { + return Err(LayoutError::HasPlaceholder); } - TyKind::Alias(_) - | TyKind::Placeholder(_) - | TyKind::BoundVar(_) - | TyKind::InferenceVar(_, _) => return Err(LayoutError::HasPlaceholder), }; Ok(Arc::new(result)) } -pub(crate) fn layout_of_ty_cycle_result( +pub(crate) fn layout_of_ty_cycle_result<'db>( _: &dyn HirDatabase, - _: Ty, - _: Arc<TraitEnvironment>, + _: Ty<'db>, + _: Arc<TraitEnvironment<'db>>, ) -> Result<Arc<Layout>, LayoutError> { Err(LayoutError::RecursiveTypeWithoutIndirection) } -fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty { - match pointee.kind(Interner) { - &TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), ref subst) => { - let data = i.fields(db); +fn struct_tail_erasing_lifetimes<'a>(db: &'a dyn HirDatabase, pointee: Ty<'a>) -> Ty<'a> { + match pointee.kind() { + TyKind::Adt(def, args) => { + let struct_id = match def.inner().id { + AdtId::StructId(id) => id, + _ => return pointee, + }; + let data = struct_id.fields(db); let mut it = data.fields().iter().rev(); match it.next() { Some((f, _)) => { - let last_field_ty = field_ty(db, i.into(), f, subst); + let last_field_ty = field_ty(db, struct_id.into(), f, &args); struct_tail_erasing_lifetimes(db, last_field_ty) } None => pointee, } } - TyKind::Tuple(_, subst) => { - if let Some(last_field_ty) = - subst.iter(Interner).last().and_then(|arg| arg.ty(Interner)) - { - struct_tail_erasing_lifetimes(db, last_field_ty.clone()) + TyKind::Tuple(tys) => { + if let Some(last_field_ty) = tys.iter().next_back() { + struct_tail_erasing_lifetimes(db, last_field_ty) } else { pointee } @@ -398,13 +395,13 @@ fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty { } } -fn field_ty( - db: &dyn HirDatabase, +fn field_ty<'a>( + db: &'a dyn HirDatabase, def: hir_def::VariantId, fd: LocalFieldId, - subst: &Substitution, -) -> Ty { - db.field_types(def)[fd].clone().substitute(Interner, subst) + args: &GenericArgs<'a>, +) -> Ty<'a> { + db.field_types(def)[fd].instantiate(DbInterner::new_with(db, None, None), args) } fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar { |