mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 04:26:48 +00:00
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:
parent
cdd8af2299
commit
9917173575
@ -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]);
|
||||
|
148
compiler/rustc_abi/src/layout/simple.rs
Normal file
148
compiler/rustc_abi/src/layout/simple.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
@ -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 });
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user