Remove most manual LayoutData creations and move them to rustc_abi

...either as:
- methods on LayoutCalculator, for faillible operations;
- constructors on LayoutData, for infaillible ones.
This commit is contained in:
Moulins 2025-02-28 04:57:17 +01:00
parent cdd8af2299
commit 9917173575
6 changed files with 228 additions and 267 deletions

View File

@ -12,6 +12,8 @@ use crate::{
Variants, WrappingRange,
};
mod simple;
#[cfg(feature = "nightly")]
mod ty;
@ -102,41 +104,27 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
Self { cx }
}
pub fn scalar_pair<FieldIdx: Idx, VariantIdx: Idx>(
pub fn array_like<FieldIdx: Idx, VariantIdx: Idx, F>(
&self,
a: Scalar,
b: Scalar,
) -> LayoutData<FieldIdx, VariantIdx> {
let dl = self.cx.data_layout();
let b_align = b.align(dl);
let align = a.align(dl).max(b_align).max(dl.aggregate_align);
let b_offset = a.size(dl).align_to(b_align.abi);
let size = (b_offset + b.size(dl)).align_to(align.abi);
element: &LayoutData<FieldIdx, VariantIdx>,
count_if_sized: Option<u64>, // None for slices
) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
let count = count_if_sized.unwrap_or(0);
let size =
element.size.checked_mul(count, &self.cx).ok_or(LayoutCalculatorError::SizeOverflow)?;
// HACK(nox): We iter on `b` and then `a` because `max_by_key`
// returns the last maximum.
let largest_niche = Niche::from_scalar(dl, b_offset, b)
.into_iter()
.chain(Niche::from_scalar(dl, Size::ZERO, a))
.max_by_key(|niche| niche.available(dl));
let combined_seed = a.size(&self.cx).bytes().wrapping_add(b.size(&self.cx).bytes());
LayoutData {
Ok(LayoutData {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Arbitrary {
offsets: [Size::ZERO, b_offset].into(),
memory_index: [0, 1].into(),
},
backend_repr: BackendRepr::ScalarPair(a, b),
largest_niche,
uninhabited: false,
align,
fields: FieldsShape::Array { stride: element.size, count },
backend_repr: BackendRepr::Memory { sized: count_if_sized.is_some() },
largest_niche: element.largest_niche.filter(|_| count != 0),
uninhabited: element.uninhabited && count != 0,
align: element.align,
size,
max_repr_align: None,
unadjusted_abi_align: align.abi,
randomization_seed: Hash64::new(combined_seed),
}
unadjusted_abi_align: element.align.abi,
randomization_seed: element.randomization_seed.wrapping_add(Hash64::new(count)),
})
}
pub fn univariant<
@ -214,25 +202,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
layout
}
pub fn layout_of_never_type<FieldIdx: Idx, VariantIdx: Idx>(
&self,
) -> LayoutData<FieldIdx, VariantIdx> {
let dl = self.cx.data_layout();
// This is also used for uninhabited enums, so we use `Variants::Empty`.
LayoutData {
variants: Variants::Empty,
fields: FieldsShape::Primitive,
backend_repr: BackendRepr::Memory { sized: true },
largest_niche: None,
uninhabited: true,
align: dl.i8_align,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align.abi,
randomization_seed: Hash64::ZERO,
}
}
pub fn layout_of_struct_or_enum<
'a,
FieldIdx: Idx,
@ -260,7 +229,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
Some(present_first) => present_first,
// Uninhabited because it has no variants, or only absent ones.
None if is_enum => {
return Ok(self.layout_of_never_type());
return Ok(LayoutData::never_type(&self.cx));
}
// If it's a struct, still compute a layout so that we can still compute the
// field offsets.
@ -949,7 +918,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
// Common prim might be uninit.
Scalar::Union { value: prim }
};
let pair = self.scalar_pair::<FieldIdx, VariantIdx>(tag, prim_scalar);
let pair =
LayoutData::<FieldIdx, VariantIdx>::scalar_pair(&self.cx, tag, prim_scalar);
let pair_offsets = match pair.fields {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index.raw, [0, 1]);
@ -1341,7 +1311,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
} else {
((j, b), (i, a))
};
let pair = self.scalar_pair::<FieldIdx, VariantIdx>(a, b);
let pair =
LayoutData::<FieldIdx, VariantIdx>::scalar_pair(&self.cx, a, b);
let pair_offsets = match pair.fields {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index.raw, [0, 1]);

View File

@ -0,0 +1,148 @@
use std::num::NonZero;
use rustc_hashes::Hash64;
use rustc_index::{Idx, IndexVec};
use crate::{
BackendRepr, FieldsShape, HasDataLayout, LayoutData, Niche, Primitive, Scalar, Size, Variants,
};
/// "Simple" layout constructors that cannot fail.
impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
pub fn unit<C: HasDataLayout>(cx: &C, sized: bool) -> Self {
let dl = cx.data_layout();
LayoutData {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Arbitrary {
offsets: IndexVec::new(),
memory_index: IndexVec::new(),
},
backend_repr: BackendRepr::Memory { sized },
largest_niche: None,
uninhabited: false,
align: dl.i8_align,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align.abi,
randomization_seed: Hash64::new(0),
}
}
pub fn never_type<C: HasDataLayout>(cx: &C) -> Self {
let dl = cx.data_layout();
// This is also used for uninhabited enums, so we use `Variants::Empty`.
LayoutData {
variants: Variants::Empty,
fields: FieldsShape::Primitive,
backend_repr: BackendRepr::Memory { sized: true },
largest_niche: None,
uninhabited: true,
align: dl.i8_align,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align.abi,
randomization_seed: Hash64::ZERO,
}
}
pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
let size = scalar.size(cx);
let align = scalar.align(cx);
let range = scalar.valid_range(cx);
// All primitive types for which we don't have subtype coercions should get a distinct seed,
// so that types wrapping them can use randomization to arrive at distinct layouts.
//
// Some type information is already lost at this point, so as an approximation we derive
// the seed from what remains. For example on 64-bit targets usize and u64 can no longer
// be distinguished.
let randomization_seed = size
.bytes()
.wrapping_add(
match scalar.primitive() {
Primitive::Int(_, true) => 1,
Primitive::Int(_, false) => 2,
Primitive::Float(_) => 3,
Primitive::Pointer(_) => 4,
} << 32,
)
// distinguishes references from pointers
.wrapping_add((range.start as u64).rotate_right(16))
// distinguishes char from u32 and bool from u8
.wrapping_add((range.end as u64).rotate_right(16));
LayoutData {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Primitive,
backend_repr: BackendRepr::Scalar(scalar),
largest_niche,
uninhabited: false,
size,
align,
max_repr_align: None,
unadjusted_abi_align: align.abi,
randomization_seed: Hash64::new(randomization_seed),
}
}
pub fn scalar_pair<C: HasDataLayout>(cx: &C, a: Scalar, b: Scalar) -> Self {
let dl = cx.data_layout();
let b_align = b.align(dl);
let align = a.align(dl).max(b_align).max(dl.aggregate_align);
let b_offset = a.size(dl).align_to(b_align.abi);
let size = (b_offset + b.size(dl)).align_to(align.abi);
// HACK(nox): We iter on `b` and then `a` because `max_by_key`
// returns the last maximum.
let largest_niche = Niche::from_scalar(dl, b_offset, b)
.into_iter()
.chain(Niche::from_scalar(dl, Size::ZERO, a))
.max_by_key(|niche| niche.available(dl));
let combined_seed = a.size(dl).bytes().wrapping_add(b.size(dl).bytes());
LayoutData {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Arbitrary {
offsets: [Size::ZERO, b_offset].into(),
memory_index: [0, 1].into(),
},
backend_repr: BackendRepr::ScalarPair(a, b),
largest_niche,
uninhabited: false,
align,
size,
max_repr_align: None,
unadjusted_abi_align: align.abi,
randomization_seed: Hash64::new(combined_seed),
}
}
/// Returns a dummy layout for an uninhabited variant.
///
/// Uninhabited variants get pruned as part of the layout calculation,
/// so this can be used after the fact to reconstitute a layout.
pub fn uninhabited_variant<C: HasDataLayout>(cx: &C, index: VariantIdx, fields: usize) -> Self {
let dl = cx.data_layout();
LayoutData {
variants: Variants::Single { index },
fields: match NonZero::new(fields) {
Some(fields) => FieldsShape::Union(fields),
None => FieldsShape::Arbitrary {
offsets: IndexVec::new(),
memory_index: IndexVec::new(),
},
},
backend_repr: BackendRepr::Memory { sized: true },
largest_niche: None,
uninhabited: true,
align: dl.i8_align,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align.abi,
randomization_seed: Hash64::ZERO,
}
}
}

View File

@ -1744,48 +1744,6 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
pub fn is_uninhabited(&self) -> bool {
self.uninhabited
}
pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
let size = scalar.size(cx);
let align = scalar.align(cx);
let range = scalar.valid_range(cx);
// All primitive types for which we don't have subtype coercions should get a distinct seed,
// so that types wrapping them can use randomization to arrive at distinct layouts.
//
// Some type information is already lost at this point, so as an approximation we derive
// the seed from what remains. For example on 64-bit targets usize and u64 can no longer
// be distinguished.
let randomization_seed = size
.bytes()
.wrapping_add(
match scalar.primitive() {
Primitive::Int(_, true) => 1,
Primitive::Int(_, false) => 2,
Primitive::Float(_) => 3,
Primitive::Pointer(_) => 4,
} << 32,
)
// distinguishes references from pointers
.wrapping_add((range.start as u64).rotate_right(16))
// distinguishes char from u32 and bool from u8
.wrapping_add((range.end as u64).rotate_right(16));
LayoutData {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Primitive,
backend_repr: BackendRepr::Scalar(scalar),
largest_niche,
uninhabited: false,
size,
align,
max_repr_align: None,
unadjusted_abi_align: align.abi,
randomization_seed: Hash64::new(randomization_seed),
}
}
}
impl<FieldIdx: Idx, VariantIdx: Idx> fmt::Debug for LayoutData<FieldIdx, VariantIdx>

View File

@ -1,20 +1,17 @@
use std::num::NonZero;
use std::ops::Bound;
use std::{cmp, fmt};
use rustc_abi::{
AddressSpace, Align, BackendRepr, ExternAbi, FieldIdx, FieldsShape, HasDataLayout, LayoutData,
PointeeInfo, PointerKind, Primitive, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout,
AddressSpace, Align, ExternAbi, FieldIdx, FieldsShape, HasDataLayout, LayoutData, PointeeInfo,
PointerKind, Primitive, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout,
TyAbiInterface, VariantIdx, Variants,
};
use rustc_error_messages::DiagMessage;
use rustc_errors::{
Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
};
use rustc_hashes::Hash64;
use rustc_hir::LangItem;
use rustc_hir::def_id::DefId;
use rustc_index::IndexVec;
use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension};
use rustc_session::config::OptLevel;
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
@ -762,11 +759,9 @@ where
variant_index: VariantIdx,
) -> TyAndLayout<'tcx> {
let layout = match this.variants {
Variants::Single { index }
// If all variants but one are uninhabited, the variant layout is the enum layout.
if index == variant_index =>
{
this.layout
// If all variants but one are uninhabited, the variant layout is the enum layout.
Variants::Single { index } if index == variant_index => {
return this;
}
Variants::Single { .. } | Variants::Empty => {
@ -783,29 +778,18 @@ where
}
let fields = match this.ty.kind() {
ty::Adt(def, _) if def.variants().is_empty() =>
bug!("for_variant called on zero-variant enum {}", this.ty),
ty::Adt(def, _) if def.variants().is_empty() => {
bug!("for_variant called on zero-variant enum {}", this.ty)
}
ty::Adt(def, _) => def.variant(variant_index).fields.len(),
_ => bug!("`ty_and_layout_for_variant` on unexpected type {}", this.ty),
};
tcx.mk_layout(LayoutData {
variants: Variants::Single { index: variant_index },
fields: match NonZero::new(fields) {
Some(fields) => FieldsShape::Union(fields),
None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() },
},
backend_repr: BackendRepr::Memory { sized: true },
largest_niche: None,
uninhabited: true,
align: tcx.data_layout.i8_align,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: tcx.data_layout.i8_align.abi,
randomization_seed: Hash64::ZERO,
})
tcx.mk_layout(LayoutData::uninhabited_variant(cx, variant_index, fields))
}
Variants::Multiple { ref variants, .. } => cx.tcx().mk_layout(variants[variant_index].clone()),
Variants::Multiple { ref variants, .. } => {
cx.tcx().mk_layout(variants[variant_index].clone())
}
};
assert_eq!(*layout.variants(), Variants::Single { index: variant_index });

View File

@ -188,6 +188,10 @@ fn layout_of_uncached<'tcx>(
let tcx = cx.tcx();
let dl = cx.data_layout();
let map_layout = |result: Result<_, _>| match result {
Ok(layout) => Ok(tcx.mk_layout(layout)),
Err(err) => Err(map_error(cx, ty, err)),
};
let scalar_unit = |value: Primitive| {
let size = value.size(dl);
assert!(size.bits() <= 128);
@ -258,7 +262,7 @@ fn layout_of_uncached<'tcx>(
}
// The never type.
ty::Never => tcx.mk_layout(cx.calc.layout_of_never_type()),
ty::Never => tcx.mk_layout(LayoutData::never_type(cx)),
// Potentially-wide pointers.
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
@ -329,7 +333,7 @@ fn layout_of_uncached<'tcx>(
};
// Effectively a (ptr, meta) tuple.
tcx.mk_layout(cx.calc.scalar_pair(data_ptr, metadata))
tcx.mk_layout(LayoutData::scalar_pair(cx, data_ptr, metadata))
}
ty::Dynamic(_, _, ty::DynStar) => {
@ -337,7 +341,7 @@ fn layout_of_uncached<'tcx>(
data.valid_range_mut().start = 0;
let mut vtable = scalar_unit(Pointer(AddressSpace::DATA));
vtable.valid_range_mut().start = 1;
tcx.mk_layout(cx.calc.scalar_pair(data, vtable))
tcx.mk_layout(LayoutData::scalar_pair(cx, data, vtable))
}
// Arrays and slices.
@ -347,71 +351,29 @@ fn layout_of_uncached<'tcx>(
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
let element = cx.layout_of(element)?;
let size = element
.size
.checked_mul(count, dl)
.ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
let abi = BackendRepr::Memory { sized: true };
let largest_niche = if count != 0 { element.largest_niche } else { None };
let uninhabited = if count != 0 { element.uninhabited } else { false };
tcx.mk_layout(LayoutData {
variants: Variants::Single { index: FIRST_VARIANT },
fields: FieldsShape::Array { stride: element.size, count },
backend_repr: abi,
largest_niche,
uninhabited,
align: element.align,
size,
max_repr_align: None,
unadjusted_abi_align: element.align.abi,
randomization_seed: element.randomization_seed.wrapping_add(Hash64::new(count)),
})
map_layout(cx.calc.array_like(&element, Some(count)))?
}
ty::Slice(element) => {
let element = cx.layout_of(element)?;
tcx.mk_layout(LayoutData {
variants: Variants::Single { index: FIRST_VARIANT },
fields: FieldsShape::Array { stride: element.size, count: 0 },
backend_repr: BackendRepr::Memory { sized: false },
largest_niche: None,
uninhabited: false,
align: element.align,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: element.align.abi,
// adding a randomly chosen value to distinguish slices
randomization_seed: element
.randomization_seed
.wrapping_add(Hash64::new(0x2dcba99c39784102)),
})
map_layout(cx.calc.array_like(&element, None).map(|mut layout| {
// a randomly chosen value to distinguish slices
layout.randomization_seed = Hash64::new(0x2dcba99c39784102);
layout
}))?
}
ty::Str => {
let element = scalar(Int(I8, false));
map_layout(cx.calc.array_like(&element, None).map(|mut layout| {
// another random value
layout.randomization_seed = Hash64::new(0xc1325f37d127be22);
layout
}))?
}
ty::Str => tcx.mk_layout(LayoutData {
variants: Variants::Single { index: FIRST_VARIANT },
fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
backend_repr: BackendRepr::Memory { sized: false },
largest_niche: None,
uninhabited: false,
align: dl.i8_align,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align.abi,
// another random value
randomization_seed: Hash64::new(0xc1325f37d127be22),
}),
// Odd unit types.
ty::FnDef(..) => univariant(IndexSlice::empty(), StructKind::AlwaysSized)?,
ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => {
let mut unit =
univariant_uninterned(cx, ty, IndexSlice::empty(), StructKind::AlwaysSized)?;
match unit.backend_repr {
BackendRepr::Memory { ref mut sized } => *sized = false,
_ => bug!(),
}
tcx.mk_layout(unit)
ty::FnDef(..) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => {
let sized = matches!(ty.kind(), ty::FnDef(..));
tcx.mk_layout(LayoutData::unit(cx, sized))
}
ty::Coroutine(def_id, args) => coroutine_layout(cx, ty, def_id, args)?,
@ -545,11 +507,7 @@ fn layout_of_uncached<'tcx>(
return Err(error(cx, LayoutError::ReferencesError(guar)));
}
return Ok(tcx.mk_layout(
cx.calc
.layout_of_union(&def.repr(), &variants)
.map_err(|err| map_error(cx, ty, err))?,
));
return map_layout(cx.calc.layout_of_union(&def.repr(), &variants));
}
let get_discriminant_type =

View File

@ -15,7 +15,7 @@ use hir_def::{
use la_arena::{Idx, RawIdx};
use rustc_abi::AddressSpace;
use rustc_hashes::Hash64;
use rustc_index::{IndexSlice, IndexVec};
use rustc_index::IndexVec;
use triomphe::Arc;
@ -190,7 +190,8 @@ pub fn layout_of_ty_query(
let dl = &*target;
let cx = LayoutCx::new(dl);
let ty = normalize(db, trait_env.clone(), ty);
let result = match ty.kind(Interner) {
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_data(*s);
@ -216,7 +217,7 @@ pub fn layout_of_ty_query(
valid_range: WrappingRange { start: 0, end: 0x10FFFF },
},
),
chalk_ir::Scalar::Int(i) => scalar(
chalk_ir::Scalar::Int(i) => Layout::scalar(dl, scalar_unit(
dl,
Primitive::Int(
match i {
@ -229,8 +230,8 @@ pub fn layout_of_ty_query(
},
true,
),
),
chalk_ir::Scalar::Uint(i) => scalar(
)),
chalk_ir::Scalar::Uint(i) => Layout::scalar(dl, scalar_unit(
dl,
Primitive::Int(
match i {
@ -243,8 +244,8 @@ pub fn layout_of_ty_query(
},
false,
),
),
chalk_ir::Scalar::Float(f) => scalar(
)),
chalk_ir::Scalar::Float(f) => Layout::scalar(dl, scalar_unit(
dl,
Primitive::Float(match f {
FloatTy::F16 => Float::F16,
@ -252,7 +253,7 @@ pub fn layout_of_ty_query(
FloatTy::F64 => Float::F64,
FloatTy::F128 => Float::F128,
}),
),
)),
},
TyKind::Tuple(len, tys) => {
let kind = if *len == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
@ -268,56 +269,16 @@ 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 size = element
.size
.checked_mul(count, dl)
.ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
let backend_repr = BackendRepr::Memory { sized: true };
let largest_niche = if count != 0 { element.largest_niche } else { None };
let uninhabited = if count != 0 { element.uninhabited } else { false };
Layout {
variants: Variants::Single { index: struct_variant_idx() },
fields: FieldsShape::Array { stride: element.size, count },
backend_repr,
largest_niche,
uninhabited,
align: element.align,
size,
max_repr_align: None,
unadjusted_abi_align: element.align.abi,
randomization_seed: Hash64::ZERO,
}
cx.calc.array_like::<_, _, ()>(&element, Some(count))?
}
TyKind::Slice(element) => {
let element = db.layout_of_ty(element.clone(), trait_env)?;
Layout {
variants: Variants::Single { index: struct_variant_idx() },
fields: FieldsShape::Array { stride: element.size, count: 0 },
backend_repr: BackendRepr::Memory { sized: false },
largest_niche: None,
uninhabited: false,
align: element.align,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: element.align.abi,
randomization_seed: Hash64::ZERO,
}
cx.calc.array_like::<_, _, ()>(&element, None)?
}
TyKind::Str => {
let element = scalar_unit(dl, Primitive::Int(Integer::I8, false));
cx.calc.array_like::<_, _, ()>(&Layout::scalar(dl, element), None)?
}
TyKind::Str => Layout {
variants: Variants::Single { index: struct_variant_idx() },
fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
backend_repr: BackendRepr::Memory { sized: false },
largest_niche: None,
uninhabited: false,
align: dl.i8_align,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align.abi,
randomization_seed: Hash64::ZERO,
},
// Potentially-wide pointers.
TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => {
let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA));
@ -355,17 +316,12 @@ pub fn layout_of_ty_query(
};
// Effectively a (ptr, meta) tuple.
cx.calc.scalar_pair(data_ptr, metadata)
LayoutData::scalar_pair(dl, data_ptr, metadata)
}
TyKind::FnDef(_, _) => layout_of_unit(&cx)?,
TyKind::Never => cx.calc.layout_of_never_type(),
TyKind::Dyn(_) | TyKind::Foreign(_) => {
let mut unit = layout_of_unit(&cx)?;
match &mut unit.backend_repr {
BackendRepr::Memory { sized } => *sized = false,
_ => return Err(LayoutError::Unknown),
}
unit
TyKind::Never => LayoutData::never_type(dl),
TyKind::FnDef(..) | TyKind::Dyn(_) | TyKind::Foreign(_) => {
let sized = matches!(kind, TyKind::FnDef(..));
LayoutData::unit(dl, sized)
}
TyKind::Function(_) => {
let mut ptr = scalar_unit(dl, Primitive::Pointer(dl.instruction_address_space));
@ -434,16 +390,6 @@ pub fn layout_of_ty_recover(
Err(LayoutError::RecursiveTypeWithoutIndirection)
}
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)
}
fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {
match pointee.kind(Interner) {
TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), subst) => {
@ -474,9 +420,5 @@ 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))
}
#[cfg(test)]
mod tests;