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.rs332
1 files changed, 169 insertions, 163 deletions
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index 107da6a5af..f21673c732 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -2,33 +2,40 @@
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::utils::ClosureSubst;
use crate::{
- Interner, ProjectionTy, Substitution, TraitEnvironment, Ty,
- consteval::try_const_usize,
- db::{HirDatabase, InternedClosure},
- infer::normalize,
- utils::ClosureSubst,
+ Interner, TraitEnvironment,
+ consteval_nextsolver::try_const_usize,
+ db::HirDatabase,
+ next_solver::{
+ DbInterner, GenericArgs, ParamEnv, Ty, TyKind, TypingMode,
+ infer::{DbInternerInferExt, traits::ObligationCause},
+ mapping::{ChalkToNextSolver, convert_args_for_result},
+ },
};
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,11 +126,12 @@ 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,
+ args: &GenericArgs<'db>,
env: Arc<TraitEnvironment>,
dl: &TargetDataLayout,
) -> Result<Arc<Layout>, LayoutError> {
@@ -132,115 +140,119 @@ fn layout_of_simd_ty(
// * #[repr(simd)] struct S([T; 4])
//
// where T is a primitive scalar (integer/float/pointer).
- let fields = db.field_types(id.into());
+ let fields = db.field_types_ns(id.into());
let mut fields = fields.iter();
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,
+pub fn layout_of_ty_query<'db>(
+ db: &'db dyn HirDatabase,
+ ty: Ty<'db>,
trait_env: Arc<TraitEnvironment>,
) -> 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 +260,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 +272,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 +295,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 +315,87 @@ 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.into());
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
+ .clone()
+ .substitute(
+ Interner,
+ &ClosureSubst(&convert_args_for_result(interner, args.inner()))
+ .parent_subst(db),
+ )
+ .to_nextsolver(interner);
+ 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,
+ _: Ty<'db>,
_: Arc<TraitEnvironment>,
) -> 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().last() {
+ struct_tail_erasing_lifetimes(db, last_field_ty)
} else {
pointee
}
@@ -398,13 +404,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_ns(def)[fd].instantiate(DbInterner::new_with(db, None, None), args)
}
fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar {