2023-01-09 18:36:22 +00:00
|
|
|
//! Compute the binary representation of a type
|
|
|
|
|
2024-09-15 20:16:21 +00:00
|
|
|
use std::fmt;
|
2023-11-14 12:32:04 +00:00
|
|
|
|
2024-10-04 19:48:11 +00:00
|
|
|
use base_db::ra_salsa::Cycle;
|
2023-05-26 14:41:45 +00:00
|
|
|
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
|
2023-01-09 18:36:22 +00:00
|
|
|
use hir_def::{
|
|
|
|
layout::{
|
2024-11-01 12:12:18 +00:00
|
|
|
BackendRepr, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError,
|
|
|
|
LayoutData, Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout,
|
|
|
|
WrappingRange,
|
2023-01-09 18:36:22 +00:00
|
|
|
},
|
2024-01-15 09:24:14 +00:00
|
|
|
LocalFieldId, StructId,
|
2023-01-09 18:36:22 +00:00
|
|
|
};
|
2023-04-16 10:21:12 +00:00
|
|
|
use la_arena::{Idx, RawIdx};
|
2024-01-08 14:39:35 +00:00
|
|
|
use rustc_abi::AddressSpace;
|
|
|
|
use rustc_index::{IndexSlice, IndexVec};
|
|
|
|
|
2023-05-02 14:12:22 +00:00
|
|
|
use triomphe::Arc;
|
2023-01-09 18:36:22 +00:00
|
|
|
|
2023-04-16 10:21:12 +00:00
|
|
|
use crate::{
|
2024-02-10 14:36:26 +00:00
|
|
|
consteval::try_const_usize,
|
|
|
|
db::{HirDatabase, InternedClosure},
|
|
|
|
infer::normalize,
|
|
|
|
layout::adt::struct_variant_idx,
|
|
|
|
utils::ClosureSubst,
|
|
|
|
Interner, ProjectionTy, Substitution, TraitEnvironment, Ty,
|
2023-04-16 10:21:12 +00:00
|
|
|
};
|
2023-01-09 18:36:22 +00:00
|
|
|
|
|
|
|
pub use self::{
|
|
|
|
adt::{layout_of_adt_query, layout_of_adt_recover},
|
|
|
|
target::target_data_layout_query,
|
|
|
|
};
|
|
|
|
|
|
|
|
mod adt;
|
|
|
|
mod target;
|
|
|
|
|
2023-04-16 10:21:12 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
2024-01-15 09:24:14 +00:00
|
|
|
pub struct RustcEnumVariantIdx(pub usize);
|
2023-04-16 10:21:12 +00:00
|
|
|
|
2024-01-08 14:39:35 +00:00
|
|
|
impl rustc_index::Idx for RustcEnumVariantIdx {
|
2023-04-16 10:21:12 +00:00
|
|
|
fn new(idx: usize) -> Self {
|
2024-01-15 09:24:14 +00:00
|
|
|
RustcEnumVariantIdx(idx)
|
2023-04-16 10:21:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn index(self) -> usize {
|
2024-01-15 09:24:14 +00:00
|
|
|
self.0
|
2023-04-16 10:21:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-29 18:42:26 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct RustcFieldIdx(pub LocalFieldId);
|
|
|
|
|
|
|
|
impl RustcFieldIdx {
|
|
|
|
pub fn new(idx: usize) -> Self {
|
|
|
|
RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-08 14:39:35 +00:00
|
|
|
impl rustc_index::Idx for RustcFieldIdx {
|
2023-09-29 18:42:26 +00:00
|
|
|
fn new(idx: usize) -> Self {
|
|
|
|
RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32)))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn index(self) -> usize {
|
|
|
|
u32::from(self.0.into_raw()) as usize
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-28 05:32:58 +00:00
|
|
|
pub type Layout = LayoutData<RustcFieldIdx, RustcEnumVariantIdx>;
|
2023-04-16 10:21:12 +00:00
|
|
|
pub type TagEncoding = hir_def::layout::TagEncoding<RustcEnumVariantIdx>;
|
2023-09-29 18:42:26 +00:00
|
|
|
pub type Variants = hir_def::layout::Variants<RustcFieldIdx, RustcEnumVariantIdx>;
|
2023-04-16 10:21:12 +00:00
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
|
|
pub enum LayoutError {
|
2024-10-22 07:19:25 +00:00
|
|
|
// FIXME: Remove more variants once they get added to LayoutCalculatorError
|
2024-10-17 19:59:40 +00:00
|
|
|
BadCalc(LayoutCalculatorError<()>),
|
2023-11-14 12:32:04 +00:00
|
|
|
HasErrorConst,
|
2023-04-16 10:21:12 +00:00
|
|
|
HasErrorType,
|
2023-11-14 12:32:04 +00:00
|
|
|
HasPlaceholder,
|
|
|
|
InvalidSimdType,
|
2023-04-16 10:21:12 +00:00
|
|
|
NotImplemented,
|
2023-11-14 12:32:04 +00:00
|
|
|
RecursiveTypeWithoutIndirection,
|
|
|
|
TargetLayoutNotAvailable,
|
2023-04-16 10:21:12 +00:00
|
|
|
Unknown,
|
2023-11-14 12:32:04 +00:00
|
|
|
UserReprTooSmall,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::error::Error for LayoutError {}
|
|
|
|
impl fmt::Display for LayoutError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
match self {
|
2024-10-17 19:59:40 +00:00
|
|
|
LayoutError::BadCalc(err) => err.fallback_fmt(f),
|
2023-11-14 12:32:04 +00:00
|
|
|
LayoutError::HasErrorConst => write!(f, "type contains an unevaluatable const"),
|
|
|
|
LayoutError::HasErrorType => write!(f, "type contains an error"),
|
|
|
|
LayoutError::HasPlaceholder => write!(f, "type contains placeholders"),
|
|
|
|
LayoutError::InvalidSimdType => write!(f, "invalid simd type definition"),
|
|
|
|
LayoutError::NotImplemented => write!(f, "not implemented"),
|
|
|
|
LayoutError::RecursiveTypeWithoutIndirection => {
|
|
|
|
write!(f, "recursive type without indirection")
|
|
|
|
}
|
|
|
|
LayoutError::TargetLayoutNotAvailable => write!(f, "target layout not available"),
|
|
|
|
LayoutError::Unknown => write!(f, "unknown"),
|
|
|
|
LayoutError::UserReprTooSmall => {
|
|
|
|
write!(f, "the `#[repr]` hint is too small to hold the discriminants of the enum")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-16 10:21:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-16 19:04:20 +00:00
|
|
|
impl<F> From<LayoutCalculatorError<F>> for LayoutError {
|
|
|
|
fn from(err: LayoutCalculatorError<F>) -> Self {
|
2024-10-17 19:59:40 +00:00
|
|
|
LayoutError::BadCalc(err.without_payload())
|
2024-09-15 20:16:21 +00:00
|
|
|
}
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
|
2024-09-15 20:16:21 +00:00
|
|
|
struct LayoutCx<'a> {
|
|
|
|
calc: LayoutCalculator<&'a TargetDataLayout>,
|
|
|
|
}
|
2023-01-09 18:36:22 +00:00
|
|
|
|
2024-09-15 20:16:21 +00:00
|
|
|
impl<'a> LayoutCx<'a> {
|
|
|
|
fn new(target: &'a TargetDataLayout) -> Self {
|
|
|
|
Self { calc: LayoutCalculator::new(target) }
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-01 21:12:33 +00:00
|
|
|
// FIXME: move this to the `rustc_abi`.
|
|
|
|
fn layout_of_simd_ty(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
id: StructId,
|
|
|
|
subst: &Substitution,
|
2023-07-20 09:38:38 +00:00
|
|
|
env: Arc<TraitEnvironment>,
|
2023-07-01 21:12:33 +00:00
|
|
|
dl: &TargetDataLayout,
|
|
|
|
) -> Result<Arc<Layout>, LayoutError> {
|
|
|
|
let fields = db.field_types(id.into());
|
|
|
|
|
|
|
|
// Supported SIMD vectors are homogeneous ADTs with at least one field:
|
|
|
|
//
|
|
|
|
// * #[repr(simd)] struct S(T, T, T, T);
|
2023-07-06 14:03:17 +00:00
|
|
|
// * #[repr(simd)] struct S { it: T, y: T, z: T, w: T }
|
2023-07-01 21:12:33 +00:00
|
|
|
// * #[repr(simd)] struct S([T; 4])
|
|
|
|
//
|
|
|
|
// where T is a primitive scalar (integer/float/pointer).
|
|
|
|
|
|
|
|
let f0_ty = match fields.iter().next() {
|
2023-07-06 14:03:17 +00:00
|
|
|
Some(it) => it.1.clone().substitute(Interner, subst),
|
2023-11-14 12:32:04 +00:00
|
|
|
None => return Err(LayoutError::InvalidSimdType),
|
2023-07-01 21:12:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// The element type and number of elements of the SIMD vector
|
|
|
|
// are obtained from:
|
|
|
|
//
|
|
|
|
// * the element type and length of the single array field, if
|
|
|
|
// the first field is of array type, or
|
|
|
|
//
|
|
|
|
// * the homogeneous field type and the number of fields.
|
|
|
|
let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) {
|
|
|
|
// Extract the number of elements from the layout of the array field:
|
2023-08-25 14:38:36 +00:00
|
|
|
let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields
|
|
|
|
else {
|
2023-11-14 12:32:04 +00:00
|
|
|
return Err(LayoutError::Unknown);
|
2023-07-01 21:12:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
(e_ty.clone(), count, true)
|
|
|
|
} else {
|
|
|
|
// First ADT field is not an array:
|
|
|
|
(f0_ty, fields.iter().count() as u64, false)
|
|
|
|
};
|
|
|
|
|
|
|
|
// Compute the ABI of the element type:
|
2024-01-06 23:17:48 +00:00
|
|
|
let e_ly = db.layout_of_ty(e_ty, env)?;
|
2024-10-29 20:38:30 +00:00
|
|
|
let BackendRepr::Scalar(e_abi) = e_ly.backend_repr else {
|
2023-11-14 12:32:04 +00:00
|
|
|
return Err(LayoutError::Unknown);
|
2023-07-01 21:12:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Compute the size and alignment of the vector:
|
2024-10-22 07:19:25 +00:00
|
|
|
let size = e_ly
|
|
|
|
.size
|
|
|
|
.checked_mul(e_len, dl)
|
|
|
|
.ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
|
2023-07-01 21:12:33 +00:00
|
|
|
let align = dl.vector_align(size);
|
|
|
|
let size = size.align_to(align.abi);
|
|
|
|
|
|
|
|
// Compute the placement of the vector fields:
|
|
|
|
let fields = if is_array {
|
|
|
|
FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() }
|
|
|
|
} else {
|
|
|
|
FieldsShape::Array { stride: e_ly.size, count: e_len }
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(Arc::new(Layout {
|
|
|
|
variants: Variants::Single { index: struct_variant_idx() },
|
|
|
|
fields,
|
2024-10-29 20:38:30 +00:00
|
|
|
backend_repr: BackendRepr::Vector { element: e_abi, count: e_len },
|
2023-07-01 21:12:33 +00:00
|
|
|
largest_niche: e_ly.largest_niche,
|
|
|
|
size,
|
|
|
|
align,
|
2023-09-29 18:42:26 +00:00
|
|
|
max_repr_align: None,
|
|
|
|
unadjusted_abi_align: align.abi,
|
2023-07-01 21:12:33 +00:00
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2023-05-25 21:15:37 +00:00
|
|
|
pub fn layout_of_ty_query(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
ty: Ty,
|
2023-07-20 09:38:38 +00:00
|
|
|
trait_env: Arc<TraitEnvironment>,
|
2023-05-25 21:15:37 +00:00
|
|
|
) -> Result<Arc<Layout>, LayoutError> {
|
2023-07-20 09:38:38 +00:00
|
|
|
let krate = trait_env.krate;
|
2024-01-30 08:51:28 +00:00
|
|
|
let Ok(target) = db.target_data_layout(krate) else {
|
2023-07-03 18:34:09 +00:00
|
|
|
return Err(LayoutError::TargetLayoutNotAvailable);
|
|
|
|
};
|
2024-09-15 20:16:21 +00:00
|
|
|
let dl = &*target;
|
|
|
|
let cx = LayoutCx::new(dl);
|
2024-01-06 23:17:48 +00:00
|
|
|
let ty = normalize(db, trait_env.clone(), ty);
|
2023-05-25 21:15:37 +00:00
|
|
|
let result = match ty.kind(Interner) {
|
2023-07-01 21:12:33 +00:00
|
|
|
TyKind::Adt(AdtId(def), subst) => {
|
|
|
|
if let hir_def::AdtId::StructId(s) = def {
|
|
|
|
let data = db.struct_data(*s);
|
|
|
|
let repr = data.repr.unwrap_or_default();
|
|
|
|
if repr.simd() {
|
2024-01-06 23:17:48 +00:00
|
|
|
return layout_of_simd_ty(db, *s, subst, trait_env, &target);
|
2023-07-01 21:12:33 +00:00
|
|
|
}
|
|
|
|
};
|
2024-01-06 23:17:48 +00:00
|
|
|
return db.layout_of_adt(*def, subst.clone(), trait_env);
|
2023-07-01 21:12:33 +00:00
|
|
|
}
|
2023-01-09 18:36:22 +00:00
|
|
|
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(
|
|
|
|
dl,
|
|
|
|
Scalar::Initialized {
|
|
|
|
value: Primitive::Int(Integer::I32, false),
|
|
|
|
valid_range: WrappingRange { start: 0, end: 0x10FFFF },
|
|
|
|
},
|
|
|
|
),
|
|
|
|
chalk_ir::Scalar::Int(i) => scalar(
|
|
|
|
dl,
|
|
|
|
Primitive::Int(
|
|
|
|
match i {
|
2023-05-26 14:41:45 +00:00
|
|
|
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,
|
2023-01-09 18:36:22 +00:00
|
|
|
},
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
chalk_ir::Scalar::Uint(i) => scalar(
|
|
|
|
dl,
|
|
|
|
Primitive::Int(
|
|
|
|
match i {
|
2023-05-26 14:41:45 +00:00
|
|
|
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,
|
2023-01-09 18:36:22 +00:00
|
|
|
},
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
chalk_ir::Scalar::Float(f) => scalar(
|
|
|
|
dl,
|
2024-05-06 12:27:40 +00:00
|
|
|
Primitive::Float(match f {
|
2024-07-10 08:38:47 +00:00
|
|
|
FloatTy::F16 => Float::F16,
|
2024-05-06 12:27:40 +00:00
|
|
|
FloatTy::F32 => Float::F32,
|
|
|
|
FloatTy::F64 => Float::F64,
|
2024-07-10 08:38:47 +00:00
|
|
|
FloatTy::F128 => Float::F128,
|
2024-05-06 12:27:40 +00:00
|
|
|
}),
|
2023-01-09 18:36:22 +00:00
|
|
|
),
|
|
|
|
},
|
|
|
|
TyKind::Tuple(len, tys) => {
|
|
|
|
let kind = if *len == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
|
|
|
|
|
|
|
|
let fields = tys
|
|
|
|
.iter(Interner)
|
2023-07-20 09:38:38 +00:00
|
|
|
.map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), trait_env.clone()))
|
2023-01-09 18:36:22 +00:00
|
|
|
.collect::<Result<Vec<_>, _>>()?;
|
2023-07-06 14:03:17 +00:00
|
|
|
let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
|
2023-09-29 18:42:26 +00:00
|
|
|
let fields = fields.iter().collect::<IndexVec<_, _>>();
|
2024-09-15 20:16:21 +00:00
|
|
|
cx.calc.univariant(&fields, &ReprOptions::default(), kind)?
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
TyKind::Array(element, count) => {
|
2024-01-18 12:59:49 +00:00
|
|
|
let count = try_const_usize(db, count).ok_or(LayoutError::HasErrorConst)? as u64;
|
2024-01-06 23:17:48 +00:00
|
|
|
let element = db.layout_of_ty(element.clone(), trait_env)?;
|
2024-10-22 07:19:25 +00:00
|
|
|
let size = element
|
|
|
|
.size
|
|
|
|
.checked_mul(count, dl)
|
|
|
|
.ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
|
2023-01-09 18:36:22 +00:00
|
|
|
|
2024-11-01 12:12:18 +00:00
|
|
|
let backend_repr =
|
|
|
|
if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) {
|
|
|
|
BackendRepr::Uninhabited
|
|
|
|
} else {
|
|
|
|
BackendRepr::Memory { sized: true }
|
|
|
|
};
|
2023-01-09 18:36:22 +00:00
|
|
|
|
|
|
|
let largest_niche = if count != 0 { element.largest_niche } else { None };
|
|
|
|
|
|
|
|
Layout {
|
|
|
|
variants: Variants::Single { index: struct_variant_idx() },
|
|
|
|
fields: FieldsShape::Array { stride: element.size, count },
|
2024-10-29 20:38:30 +00:00
|
|
|
backend_repr,
|
2023-01-09 18:36:22 +00:00
|
|
|
largest_niche,
|
|
|
|
align: element.align,
|
|
|
|
size,
|
2023-09-29 18:42:26 +00:00
|
|
|
max_repr_align: None,
|
|
|
|
unadjusted_abi_align: element.align.abi,
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
TyKind::Slice(element) => {
|
2024-01-06 23:17:48 +00:00
|
|
|
let element = db.layout_of_ty(element.clone(), trait_env)?;
|
2023-01-09 18:36:22 +00:00
|
|
|
Layout {
|
|
|
|
variants: Variants::Single { index: struct_variant_idx() },
|
|
|
|
fields: FieldsShape::Array { stride: element.size, count: 0 },
|
2024-10-29 20:38:30 +00:00
|
|
|
backend_repr: BackendRepr::Memory { sized: false },
|
2023-01-09 18:36:22 +00:00
|
|
|
largest_niche: None,
|
|
|
|
align: element.align,
|
|
|
|
size: Size::ZERO,
|
2023-09-29 18:42:26 +00:00
|
|
|
max_repr_align: None,
|
|
|
|
unadjusted_abi_align: element.align.abi,
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
}
|
2023-09-29 18:42:26 +00:00
|
|
|
TyKind::Str => Layout {
|
|
|
|
variants: Variants::Single { index: struct_variant_idx() },
|
|
|
|
fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
|
2024-10-29 20:38:30 +00:00
|
|
|
backend_repr: BackendRepr::Memory { sized: false },
|
2023-09-29 18:42:26 +00:00
|
|
|
largest_niche: None,
|
|
|
|
align: dl.i8_align,
|
|
|
|
size: Size::ZERO,
|
|
|
|
max_repr_align: None,
|
|
|
|
unadjusted_abi_align: dl.i8_align.abi,
|
|
|
|
},
|
2023-01-09 18:36:22 +00:00
|
|
|
// Potentially-wide pointers.
|
|
|
|
TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => {
|
2023-09-29 18:42:26 +00:00
|
|
|
let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA));
|
2023-01-09 18:36:22 +00:00
|
|
|
if matches!(ty.kind(Interner), TyKind::Ref(..)) {
|
|
|
|
data_ptr.valid_range_mut().start = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// let pointee = tcx.normalize_erasing_regions(param_env, pointee);
|
|
|
|
// if pointee.is_sized(tcx.at(DUMMY_SP), param_env) {
|
2023-02-17 03:33:08 +00:00
|
|
|
// return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
|
2023-01-09 18:36:22 +00:00
|
|
|
// }
|
|
|
|
|
2023-07-28 15:22:01 +00:00
|
|
|
let mut unsized_part = struct_tail_erasing_lifetimes(db, pointee.clone());
|
|
|
|
if let TyKind::AssociatedType(id, subst) = unsized_part.kind(Interner) {
|
|
|
|
unsized_part = TyKind::Alias(chalk_ir::AliasTy::Projection(ProjectionTy {
|
|
|
|
associated_ty_id: *id,
|
|
|
|
substitution: subst.clone(),
|
|
|
|
}))
|
|
|
|
.intern(Interner);
|
|
|
|
}
|
2024-01-06 23:17:48 +00:00
|
|
|
unsized_part = normalize(db, trait_env, unsized_part);
|
2023-01-09 18:36:22 +00:00
|
|
|
let metadata = match unsized_part.kind(Interner) {
|
|
|
|
TyKind::Slice(_) | TyKind::Str => {
|
|
|
|
scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false))
|
|
|
|
}
|
|
|
|
TyKind::Dyn(..) => {
|
2023-09-29 18:42:26 +00:00
|
|
|
let mut vtable = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA));
|
2023-01-09 18:36:22 +00:00
|
|
|
vtable.valid_range_mut().start = 1;
|
|
|
|
vtable
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
// pointee is sized
|
2023-05-25 21:15:37 +00:00
|
|
|
return Ok(Arc::new(Layout::scalar(dl, data_ptr)));
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Effectively a (ptr, meta) tuple.
|
2024-09-15 20:16:21 +00:00
|
|
|
cx.calc.scalar_pair(data_ptr, metadata)
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
2024-09-15 20:16:21 +00:00
|
|
|
TyKind::FnDef(_, _) => layout_of_unit(&cx)?,
|
|
|
|
TyKind::Never => cx.calc.layout_of_never_type(),
|
2023-01-09 18:36:22 +00:00
|
|
|
TyKind::Dyn(_) | TyKind::Foreign(_) => {
|
2024-09-15 20:16:21 +00:00
|
|
|
let mut unit = layout_of_unit(&cx)?;
|
2024-10-29 20:38:30 +00:00
|
|
|
match &mut unit.backend_repr {
|
|
|
|
BackendRepr::Memory { sized } => *sized = false,
|
2023-11-14 12:32:04 +00:00
|
|
|
_ => return Err(LayoutError::Unknown),
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
unit
|
|
|
|
}
|
|
|
|
TyKind::Function(_) => {
|
2023-09-29 18:42:26 +00:00
|
|
|
let mut ptr = scalar_unit(dl, Primitive::Pointer(dl.instruction_address_space));
|
2023-01-09 18:36:22 +00:00
|
|
|
ptr.valid_range_mut().start = 1;
|
|
|
|
Layout::scalar(dl, ptr)
|
|
|
|
}
|
2023-02-13 11:55:14 +00:00
|
|
|
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());
|
2024-01-06 23:17:48 +00:00
|
|
|
return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env);
|
2023-02-13 11:55:14 +00:00
|
|
|
}
|
2024-08-10 05:55:46 +00:00
|
|
|
crate::ImplTraitId::TypeAliasImplTrait(..) => {
|
2024-03-15 18:31:12 +00:00
|
|
|
return Err(LayoutError::NotImplemented);
|
|
|
|
}
|
2023-02-13 11:55:14 +00:00
|
|
|
crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
|
|
|
|
return Err(LayoutError::NotImplemented)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-28 17:14:30 +00:00
|
|
|
TyKind::Closure(c, subst) => {
|
2024-02-10 14:36:26 +00:00
|
|
|
let InternedClosure(def, _) = db.lookup_intern_closure((*c).into());
|
2023-04-06 12:44:38 +00:00
|
|
|
let infer = db.infer(def);
|
|
|
|
let (captures, _) = infer.closure_info(c);
|
|
|
|
let fields = captures
|
|
|
|
.iter()
|
2023-07-06 14:03:17 +00:00
|
|
|
.map(|it| {
|
2023-05-25 21:15:37 +00:00
|
|
|
db.layout_of_ty(
|
2023-07-06 14:03:17 +00:00
|
|
|
it.ty.clone().substitute(Interner, ClosureSubst(subst).parent_subst()),
|
2023-07-20 09:38:38 +00:00
|
|
|
trait_env.clone(),
|
2023-04-28 17:14:30 +00:00
|
|
|
)
|
|
|
|
})
|
2023-04-06 12:44:38 +00:00
|
|
|
.collect::<Result<Vec<_>, _>>()?;
|
2023-07-06 14:03:17 +00:00
|
|
|
let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
|
2023-09-29 18:42:26 +00:00
|
|
|
let fields = fields.iter().collect::<IndexVec<_, _>>();
|
2024-09-15 20:16:21 +00:00
|
|
|
cx.calc.univariant(&fields, &ReprOptions::default(), StructKind::AlwaysSized)?
|
2023-04-06 12:44:38 +00:00
|
|
|
}
|
2023-12-25 22:42:38 +00:00
|
|
|
TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => {
|
2023-02-13 11:55:14 +00:00
|
|
|
return Err(LayoutError::NotImplemented)
|
|
|
|
}
|
2023-04-11 01:02:11 +00:00
|
|
|
TyKind::Error => return Err(LayoutError::HasErrorType),
|
2023-07-28 15:22:01 +00:00
|
|
|
TyKind::AssociatedType(id, subst) => {
|
|
|
|
// Try again with `TyKind::Alias` to normalize the associated type.
|
|
|
|
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::Alias(_)
|
2023-01-09 18:36:22 +00:00
|
|
|
| TyKind::Placeholder(_)
|
|
|
|
| TyKind::BoundVar(_)
|
|
|
|
| TyKind::InferenceVar(_, _) => return Err(LayoutError::HasPlaceholder),
|
2023-05-26 14:41:45 +00:00
|
|
|
};
|
2023-05-25 21:15:37 +00:00
|
|
|
Ok(Arc::new(result))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn layout_of_ty_recover(
|
|
|
|
_: &dyn HirDatabase,
|
2023-12-07 09:57:51 +00:00
|
|
|
_: &Cycle,
|
2023-05-25 21:15:37 +00:00
|
|
|
_: &Ty,
|
2023-07-20 09:38:38 +00:00
|
|
|
_: &Arc<TraitEnvironment>,
|
2023-05-25 21:15:37 +00:00
|
|
|
) -> Result<Arc<Layout>, LayoutError> {
|
2023-11-14 12:32:04 +00:00
|
|
|
Err(LayoutError::RecursiveTypeWithoutIndirection)
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
|
2024-09-15 20:16:21 +00:00
|
|
|
fn layout_of_unit(cx: &LayoutCx<'_>) -> Result<Layout, LayoutError> {
|
|
|
|
cx.calc
|
|
|
|
.univariant::<RustcFieldIdx, RustcEnumVariantIdx, &&Layout>(
|
|
|
|
IndexSlice::empty(),
|
|
|
|
&ReprOptions::default(),
|
|
|
|
StructKind::AlwaysSized,
|
|
|
|
)
|
|
|
|
.map_err(Into::into)
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {
|
|
|
|
match pointee.kind(Interner) {
|
2023-02-13 11:55:14 +00:00
|
|
|
TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), subst) => {
|
|
|
|
let data = db.struct_data(*i);
|
|
|
|
let mut it = data.variant_data.fields().iter().rev();
|
|
|
|
match it.next() {
|
2023-06-29 20:08:13 +00:00
|
|
|
Some((f, _)) => {
|
|
|
|
let last_field_ty = field_ty(db, (*i).into(), f, subst);
|
|
|
|
struct_tail_erasing_lifetimes(db, last_field_ty)
|
|
|
|
}
|
2023-02-13 11:55:14 +00:00
|
|
|
None => pointee,
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
2023-02-13 11:55:14 +00:00
|
|
|
}
|
2023-01-09 18:36:22 +00:00
|
|
|
_ => pointee,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn field_ty(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: hir_def::VariantId,
|
|
|
|
fd: LocalFieldId,
|
|
|
|
subst: &Substitution,
|
|
|
|
) -> Ty {
|
|
|
|
db.field_types(def)[fd].clone().substitute(Interner, subst)
|
|
|
|
}
|
|
|
|
|
2023-04-16 10:21:12 +00:00
|
|
|
fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar {
|
|
|
|
Scalar::Initialized { value, valid_range: WrappingRange::full(value.size(dl)) }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn scalar(dl: &TargetDataLayout, value: Primitive) -> Layout {
|
|
|
|
Layout::scalar(dl, scalar_unit(dl, value))
|
|
|
|
}
|
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests;
|