Remove some superfluous type parameters from layout.rs.
Specifically remove V, which can always be VariantIdx, and F, which can always be Layout.
This commit is contained in:
parent
21f6839352
commit
8df27d07ae
7 changed files with 148 additions and 149 deletions
|
@ -1,11 +1,5 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::{
|
use std::{borrow::Borrow, cmp, iter, ops::Bound};
|
||||||
borrow::Borrow,
|
|
||||||
cmp,
|
|
||||||
fmt::Debug,
|
|
||||||
iter,
|
|
||||||
ops::{Bound, Deref},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(feature = "randomize")]
|
#[cfg(feature = "randomize")]
|
||||||
use rand::{seq::SliceRandom, SeedableRng};
|
use rand::{seq::SliceRandom, SeedableRng};
|
||||||
|
@ -33,7 +27,7 @@ pub trait LayoutCalculator {
|
||||||
fn delay_bug(&self, txt: &str);
|
fn delay_bug(&self, txt: &str);
|
||||||
fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
|
fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
|
||||||
|
|
||||||
fn scalar_pair<V: Idx>(&self, a: Scalar, b: Scalar) -> LayoutS<V> {
|
fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS {
|
||||||
let dl = self.current_data_layout();
|
let dl = self.current_data_layout();
|
||||||
let dl = dl.borrow();
|
let dl = dl.borrow();
|
||||||
let b_align = b.align(dl);
|
let b_align = b.align(dl);
|
||||||
|
@ -49,7 +43,7 @@ pub trait LayoutCalculator {
|
||||||
.max_by_key(|niche| niche.available(dl));
|
.max_by_key(|niche| niche.available(dl));
|
||||||
|
|
||||||
LayoutS {
|
LayoutS {
|
||||||
variants: Variants::Single { index: V::new(0) },
|
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||||
fields: FieldsShape::Arbitrary {
|
fields: FieldsShape::Arbitrary {
|
||||||
offsets: vec![Size::ZERO, b_offset],
|
offsets: vec![Size::ZERO, b_offset],
|
||||||
memory_index: vec![0, 1],
|
memory_index: vec![0, 1],
|
||||||
|
@ -61,13 +55,13 @@ pub trait LayoutCalculator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn univariant<'a, V: Idx, F: Deref<Target = &'a LayoutS<V>> + Debug>(
|
fn univariant(
|
||||||
&self,
|
&self,
|
||||||
dl: &TargetDataLayout,
|
dl: &TargetDataLayout,
|
||||||
fields: &[F],
|
fields: &[Layout<'_>],
|
||||||
repr: &ReprOptions,
|
repr: &ReprOptions,
|
||||||
kind: StructKind,
|
kind: StructKind,
|
||||||
) -> Option<LayoutS<V>> {
|
) -> Option<LayoutS> {
|
||||||
let pack = repr.pack;
|
let pack = repr.pack;
|
||||||
let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
|
let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
|
||||||
let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
|
let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
|
||||||
|
@ -76,17 +70,17 @@ pub trait LayoutCalculator {
|
||||||
let end =
|
let end =
|
||||||
if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
|
if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
|
||||||
let optimizing = &mut inverse_memory_index[..end];
|
let optimizing = &mut inverse_memory_index[..end];
|
||||||
let effective_field_align = |f: &F| {
|
let effective_field_align = |layout: Layout<'_>| {
|
||||||
if let Some(pack) = pack {
|
if let Some(pack) = pack {
|
||||||
// return the packed alignment in bytes
|
// return the packed alignment in bytes
|
||||||
f.align.abi.min(pack).bytes()
|
layout.align().abi.min(pack).bytes()
|
||||||
} else {
|
} else {
|
||||||
// returns log2(effective-align).
|
// returns log2(effective-align).
|
||||||
// This is ok since `pack` applies to all fields equally.
|
// This is ok since `pack` applies to all fields equally.
|
||||||
// The calculation assumes that size is an integer multiple of align, except for ZSTs.
|
// The calculation assumes that size is an integer multiple of align, except for ZSTs.
|
||||||
//
|
//
|
||||||
// group [u8; 4] with align-4 or [u8; 6] with align-2 fields
|
// group [u8; 4] with align-4 or [u8; 6] with align-2 fields
|
||||||
f.align.abi.bytes().max(f.size.bytes()).trailing_zeros() as u64
|
layout.align().abi.bytes().max(layout.size().bytes()).trailing_zeros() as u64
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,9 +105,9 @@ pub trait LayoutCalculator {
|
||||||
// Place ZSTs first to avoid "interesting offsets",
|
// Place ZSTs first to avoid "interesting offsets",
|
||||||
// especially with only one or two non-ZST fields.
|
// especially with only one or two non-ZST fields.
|
||||||
// Then place largest alignments first, largest niches within an alignment group last
|
// Then place largest alignments first, largest niches within an alignment group last
|
||||||
let f = &fields[x as usize];
|
let f = fields[x as usize];
|
||||||
let niche_size = f.largest_niche.map_or(0, |n| n.available(dl));
|
let niche_size = f.largest_niche().map_or(0, |n| n.available(dl));
|
||||||
(!f.is_zst(), cmp::Reverse(effective_field_align(f)), niche_size)
|
(!f.0.is_zst(), cmp::Reverse(effective_field_align(f)), niche_size)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,8 +117,8 @@ pub trait LayoutCalculator {
|
||||||
// And put the largest niche in an alignment group at the end
|
// And put the largest niche in an alignment group at the end
|
||||||
// so it can be used as discriminant in jagged enums
|
// so it can be used as discriminant in jagged enums
|
||||||
optimizing.sort_by_key(|&x| {
|
optimizing.sort_by_key(|&x| {
|
||||||
let f = &fields[x as usize];
|
let f = fields[x as usize];
|
||||||
let niche_size = f.largest_niche.map_or(0, |n| n.available(dl));
|
let niche_size = f.largest_niche().map_or(0, |n| n.available(dl));
|
||||||
(effective_field_align(f), niche_size)
|
(effective_field_align(f), niche_size)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -160,15 +154,15 @@ pub trait LayoutCalculator {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if field.is_unsized() {
|
if field.0.is_unsized() {
|
||||||
sized = false;
|
sized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invariant: offset < dl.obj_size_bound() <= 1<<61
|
// Invariant: offset < dl.obj_size_bound() <= 1<<61
|
||||||
let field_align = if let Some(pack) = pack {
|
let field_align = if let Some(pack) = pack {
|
||||||
field.align.min(AbiAndPrefAlign::new(pack))
|
field.align().min(AbiAndPrefAlign::new(pack))
|
||||||
} else {
|
} else {
|
||||||
field.align
|
field.align()
|
||||||
};
|
};
|
||||||
offset = offset.align_to(field_align.abi);
|
offset = offset.align_to(field_align.abi);
|
||||||
align = align.max(field_align);
|
align = align.max(field_align);
|
||||||
|
@ -176,7 +170,7 @@ pub trait LayoutCalculator {
|
||||||
debug!("univariant offset: {:?} field: {:#?}", offset, field);
|
debug!("univariant offset: {:?} field: {:#?}", offset, field);
|
||||||
offsets[i as usize] = offset;
|
offsets[i as usize] = offset;
|
||||||
|
|
||||||
if let Some(mut niche) = field.largest_niche {
|
if let Some(mut niche) = field.largest_niche() {
|
||||||
let available = niche.available(dl);
|
let available = niche.available(dl);
|
||||||
if available > largest_niche_available {
|
if available > largest_niche_available {
|
||||||
largest_niche_available = available;
|
largest_niche_available = available;
|
||||||
|
@ -185,7 +179,7 @@ pub trait LayoutCalculator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = offset.checked_add(field.size, dl)?;
|
offset = offset.checked_add(field.size(), dl)?;
|
||||||
}
|
}
|
||||||
if let Some(repr_align) = repr.align {
|
if let Some(repr_align) = repr.align {
|
||||||
align = align.max(AbiAndPrefAlign::new(repr_align));
|
align = align.max(AbiAndPrefAlign::new(repr_align));
|
||||||
|
@ -205,24 +199,26 @@ pub trait LayoutCalculator {
|
||||||
// Unpack newtype ABIs and find scalar pairs.
|
// Unpack newtype ABIs and find scalar pairs.
|
||||||
if sized && size.bytes() > 0 {
|
if sized && size.bytes() > 0 {
|
||||||
// All other fields must be ZSTs.
|
// All other fields must be ZSTs.
|
||||||
let mut non_zst_fields = fields.iter().enumerate().filter(|&(_, f)| !f.is_zst());
|
let mut non_zst_fields = fields.iter().enumerate().filter(|&(_, f)| !f.0.is_zst());
|
||||||
|
|
||||||
match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
|
match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
|
||||||
// We have exactly one non-ZST field.
|
// We have exactly one non-ZST field.
|
||||||
(Some((i, field)), None, None) => {
|
(Some((i, field)), None, None) => {
|
||||||
// Field fills the struct and it has a scalar or scalar pair ABI.
|
// Field fills the struct and it has a scalar or scalar pair ABI.
|
||||||
if offsets[i].bytes() == 0 && align.abi == field.align.abi && size == field.size
|
if offsets[i].bytes() == 0
|
||||||
|
&& align.abi == field.align().abi
|
||||||
|
&& size == field.size()
|
||||||
{
|
{
|
||||||
match field.abi {
|
match field.abi() {
|
||||||
// For plain scalars, or vectors of them, we can't unpack
|
// For plain scalars, or vectors of them, we can't unpack
|
||||||
// newtypes for `#[repr(C)]`, as that affects C ABIs.
|
// newtypes for `#[repr(C)]`, as that affects C ABIs.
|
||||||
Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
|
Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
|
||||||
abi = field.abi;
|
abi = field.abi();
|
||||||
}
|
}
|
||||||
// But scalar pairs are Rust-specific and get
|
// But scalar pairs are Rust-specific and get
|
||||||
// treated as aggregates by C ABIs anyway.
|
// treated as aggregates by C ABIs anyway.
|
||||||
Abi::ScalarPair(..) => {
|
Abi::ScalarPair(..) => {
|
||||||
abi = field.abi;
|
abi = field.abi();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -231,7 +227,7 @@ pub trait LayoutCalculator {
|
||||||
|
|
||||||
// Two non-ZST fields, and they're both scalars.
|
// Two non-ZST fields, and they're both scalars.
|
||||||
(Some((i, a)), Some((j, b)), None) => {
|
(Some((i, a)), Some((j, b)), None) => {
|
||||||
match (a.abi, b.abi) {
|
match (a.abi(), b.abi()) {
|
||||||
(Abi::Scalar(a), Abi::Scalar(b)) => {
|
(Abi::Scalar(a), Abi::Scalar(b)) => {
|
||||||
// Order by the memory placement, not source order.
|
// Order by the memory placement, not source order.
|
||||||
let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
|
let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
|
||||||
|
@ -239,7 +235,7 @@ pub trait LayoutCalculator {
|
||||||
} else {
|
} else {
|
||||||
((j, b), (i, a))
|
((j, b), (i, a))
|
||||||
};
|
};
|
||||||
let pair = self.scalar_pair::<V>(a, b);
|
let pair = self.scalar_pair(a, b);
|
||||||
let pair_offsets = match pair.fields {
|
let pair_offsets = match pair.fields {
|
||||||
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
|
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
|
||||||
assert_eq!(memory_index, &[0, 1]);
|
assert_eq!(memory_index, &[0, 1]);
|
||||||
|
@ -264,11 +260,11 @@ pub trait LayoutCalculator {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fields.iter().any(|f| f.abi.is_uninhabited()) {
|
if fields.iter().any(|f| f.abi().is_uninhabited()) {
|
||||||
abi = Abi::Uninhabited;
|
abi = Abi::Uninhabited;
|
||||||
}
|
}
|
||||||
Some(LayoutS {
|
Some(LayoutS {
|
||||||
variants: Variants::Single { index: V::new(0) },
|
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||||
fields: FieldsShape::Arbitrary { offsets, memory_index },
|
fields: FieldsShape::Arbitrary { offsets, memory_index },
|
||||||
abi,
|
abi,
|
||||||
largest_niche,
|
largest_niche,
|
||||||
|
@ -277,11 +273,11 @@ pub trait LayoutCalculator {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_of_never_type<V: Idx>(&self) -> LayoutS<V> {
|
fn layout_of_never_type(&self) -> LayoutS {
|
||||||
let dl = self.current_data_layout();
|
let dl = self.current_data_layout();
|
||||||
let dl = dl.borrow();
|
let dl = dl.borrow();
|
||||||
LayoutS {
|
LayoutS {
|
||||||
variants: Variants::Single { index: V::new(0) },
|
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||||
fields: FieldsShape::Primitive,
|
fields: FieldsShape::Primitive,
|
||||||
abi: Abi::Uninhabited,
|
abi: Abi::Uninhabited,
|
||||||
largest_niche: None,
|
largest_niche: None,
|
||||||
|
@ -290,18 +286,18 @@ pub trait LayoutCalculator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_of_struct_or_enum<'a, V: Idx, F: Deref<Target = &'a LayoutS<V>> + Debug>(
|
fn layout_of_struct_or_enum(
|
||||||
&self,
|
&self,
|
||||||
repr: &ReprOptions,
|
repr: &ReprOptions,
|
||||||
variants: &IndexVec<V, Vec<F>>,
|
variants: &IndexVec<VariantIdx, Vec<Layout<'_>>>,
|
||||||
is_enum: bool,
|
is_enum: bool,
|
||||||
is_unsafe_cell: bool,
|
is_unsafe_cell: bool,
|
||||||
scalar_valid_range: (Bound<u128>, Bound<u128>),
|
scalar_valid_range: (Bound<u128>, Bound<u128>),
|
||||||
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
|
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
|
||||||
discriminants: impl Iterator<Item = (V, i128)>,
|
discriminants: impl Iterator<Item = (VariantIdx, i128)>,
|
||||||
niche_optimize_enum: bool,
|
niche_optimize_enum: bool,
|
||||||
always_sized: bool,
|
always_sized: bool,
|
||||||
) -> Option<LayoutS<V>> {
|
) -> Option<LayoutS> {
|
||||||
let dl = self.current_data_layout();
|
let dl = self.current_data_layout();
|
||||||
let dl = dl.borrow();
|
let dl = dl.borrow();
|
||||||
|
|
||||||
|
@ -316,9 +312,9 @@ pub trait LayoutCalculator {
|
||||||
// but *not* an encoding of the discriminant (e.g., a tag value).
|
// but *not* an encoding of the discriminant (e.g., a tag value).
|
||||||
// See issue #49298 for more details on the need to leave space
|
// See issue #49298 for more details on the need to leave space
|
||||||
// for non-ZST uninhabited data (mostly partial initialization).
|
// for non-ZST uninhabited data (mostly partial initialization).
|
||||||
let absent = |fields: &[F]| {
|
let absent = |fields: &[Layout<'_>]| {
|
||||||
let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited());
|
let uninhabited = fields.iter().any(|f| f.abi().is_uninhabited());
|
||||||
let is_zst = fields.iter().all(|f| f.is_zst());
|
let is_zst = fields.iter().all(|f| f.0.is_zst());
|
||||||
uninhabited && is_zst
|
uninhabited && is_zst
|
||||||
};
|
};
|
||||||
let (present_first, present_second) = {
|
let (present_first, present_second) = {
|
||||||
|
@ -335,7 +331,7 @@ pub trait LayoutCalculator {
|
||||||
}
|
}
|
||||||
// If it's a struct, still compute a layout so that we can still compute the
|
// If it's a struct, still compute a layout so that we can still compute the
|
||||||
// field offsets.
|
// field offsets.
|
||||||
None => V::new(0),
|
None => VariantIdx::new(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
let is_struct = !is_enum ||
|
let is_struct = !is_enum ||
|
||||||
|
@ -439,12 +435,12 @@ pub trait LayoutCalculator {
|
||||||
// variant layouts, so we can't store them in the
|
// variant layouts, so we can't store them in the
|
||||||
// overall LayoutS. Store the overall LayoutS
|
// overall LayoutS. Store the overall LayoutS
|
||||||
// and the variant LayoutSs here until then.
|
// and the variant LayoutSs here until then.
|
||||||
struct TmpLayout<V: Idx> {
|
struct TmpLayout {
|
||||||
layout: LayoutS<V>,
|
layout: LayoutS,
|
||||||
variants: IndexVec<V, LayoutS<V>>,
|
variants: IndexVec<VariantIdx, LayoutS>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let calculate_niche_filling_layout = || -> Option<TmpLayout<V>> {
|
let calculate_niche_filling_layout = || -> Option<TmpLayout> {
|
||||||
if niche_optimize_enum {
|
if niche_optimize_enum {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -464,15 +460,16 @@ pub trait LayoutCalculator {
|
||||||
|
|
||||||
Some(st)
|
Some(st)
|
||||||
})
|
})
|
||||||
.collect::<Option<IndexVec<V, _>>>()?;
|
.collect::<Option<IndexVec<VariantIdx, _>>>()?;
|
||||||
|
|
||||||
let largest_variant_index = variant_layouts
|
let largest_variant_index = variant_layouts
|
||||||
.iter_enumerated()
|
.iter_enumerated()
|
||||||
.max_by_key(|(_i, layout)| layout.size.bytes())
|
.max_by_key(|(_i, layout)| layout.size.bytes())
|
||||||
.map(|(i, _layout)| i)?;
|
.map(|(i, _layout)| i)?;
|
||||||
|
|
||||||
let all_indices = (0..=variants.len() - 1).map(V::new);
|
let all_indices = (0..=variants.len() - 1).map(VariantIdx::new);
|
||||||
let needs_disc = |index: V| index != largest_variant_index && !absent(&variants[index]);
|
let needs_disc =
|
||||||
|
|index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
|
||||||
let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
|
let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
|
||||||
..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index();
|
..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index();
|
||||||
|
|
||||||
|
@ -482,7 +479,7 @@ pub trait LayoutCalculator {
|
||||||
let (field_index, niche, (niche_start, niche_scalar)) = variants[largest_variant_index]
|
let (field_index, niche, (niche_start, niche_scalar)) = variants[largest_variant_index]
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(j, field)| Some((j, field.largest_niche?)))
|
.filter_map(|(j, field)| Some((j, field.largest_niche()?)))
|
||||||
.max_by_key(|(_, niche)| niche.available(dl))
|
.max_by_key(|(_, niche)| niche.available(dl))
|
||||||
.and_then(|(j, niche)| Some((j, niche, niche.reserve(dl, count)?)))?;
|
.and_then(|(j, niche)| Some((j, niche, niche.reserve(dl, count)?)))?;
|
||||||
let niche_offset =
|
let niche_offset =
|
||||||
|
@ -514,7 +511,7 @@ pub trait LayoutCalculator {
|
||||||
match layout.fields {
|
match layout.fields {
|
||||||
FieldsShape::Arbitrary { ref mut offsets, .. } => {
|
FieldsShape::Arbitrary { ref mut offsets, .. } => {
|
||||||
for (j, offset) in offsets.iter_mut().enumerate() {
|
for (j, offset) in offsets.iter_mut().enumerate() {
|
||||||
if !variants[i][j].is_zst() {
|
if !variants[i][j].0.is_zst() {
|
||||||
*offset += this_offset;
|
*offset += this_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,8 +569,8 @@ pub trait LayoutCalculator {
|
||||||
tag: niche_scalar,
|
tag: niche_scalar,
|
||||||
tag_encoding: TagEncoding::Niche {
|
tag_encoding: TagEncoding::Niche {
|
||||||
untagged_variant: largest_variant_index,
|
untagged_variant: largest_variant_index,
|
||||||
niche_variants: (V::new(*niche_variants.start())
|
niche_variants: (VariantIdx::new(*niche_variants.start())
|
||||||
..=V::new(*niche_variants.end())),
|
..=VariantIdx::new(*niche_variants.end())),
|
||||||
niche_start,
|
niche_start,
|
||||||
},
|
},
|
||||||
tag_field: 0,
|
tag_field: 0,
|
||||||
|
@ -598,7 +595,7 @@ pub trait LayoutCalculator {
|
||||||
let discr_type = repr.discr_type();
|
let discr_type = repr.discr_type();
|
||||||
let bits = Integer::from_attr(dl, discr_type).size().bits();
|
let bits = Integer::from_attr(dl, discr_type).size().bits();
|
||||||
for (i, mut val) in discriminants {
|
for (i, mut val) in discriminants {
|
||||||
if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
|
if variants[i].iter().any(|f| f.abi().is_uninhabited()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if discr_type.is_signed() {
|
if discr_type.is_signed() {
|
||||||
|
@ -636,7 +633,7 @@ pub trait LayoutCalculator {
|
||||||
if repr.c() {
|
if repr.c() {
|
||||||
for fields in variants {
|
for fields in variants {
|
||||||
for field in fields {
|
for field in fields {
|
||||||
prefix_align = prefix_align.max(field.align.abi);
|
prefix_align = prefix_align.max(field.align().abi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -655,8 +652,8 @@ pub trait LayoutCalculator {
|
||||||
// Find the first field we can't move later
|
// Find the first field we can't move later
|
||||||
// to make room for a larger discriminant.
|
// to make room for a larger discriminant.
|
||||||
for field in st.fields.index_by_increasing_offset().map(|j| &field_layouts[j]) {
|
for field in st.fields.index_by_increasing_offset().map(|j| &field_layouts[j]) {
|
||||||
if !field.is_zst() || field.align.abi.bytes() != 1 {
|
if !field.0.is_zst() || field.align().abi.bytes() != 1 {
|
||||||
start_align = start_align.min(field.align.abi);
|
start_align = start_align.min(field.align().abi);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -664,7 +661,7 @@ pub trait LayoutCalculator {
|
||||||
align = align.max(st.align);
|
align = align.max(st.align);
|
||||||
Some(st)
|
Some(st)
|
||||||
})
|
})
|
||||||
.collect::<Option<IndexVec<V, _>>>()?;
|
.collect::<Option<IndexVec<VariantIdx, _>>>()?;
|
||||||
|
|
||||||
// Align the maximum variant size to the largest alignment.
|
// Align the maximum variant size to the largest alignment.
|
||||||
size = size.align_to(align.abi);
|
size = size.align_to(align.abi);
|
||||||
|
@ -759,7 +756,7 @@ pub trait LayoutCalculator {
|
||||||
let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
|
let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
|
||||||
panic!();
|
panic!();
|
||||||
};
|
};
|
||||||
let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
|
let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.0.is_zst());
|
||||||
let (field, offset) = match (fields.next(), fields.next()) {
|
let (field, offset) = match (fields.next(), fields.next()) {
|
||||||
(None, None) => {
|
(None, None) => {
|
||||||
common_prim_initialized_in_all_variants = false;
|
common_prim_initialized_in_all_variants = false;
|
||||||
|
@ -771,7 +768,7 @@ pub trait LayoutCalculator {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let prim = match field.abi {
|
let prim = match field.abi() {
|
||||||
Abi::Scalar(scalar) => {
|
Abi::Scalar(scalar) => {
|
||||||
common_prim_initialized_in_all_variants &=
|
common_prim_initialized_in_all_variants &=
|
||||||
matches!(scalar, Scalar::Initialized { .. });
|
matches!(scalar, Scalar::Initialized { .. });
|
||||||
|
@ -802,7 +799,7 @@ pub trait LayoutCalculator {
|
||||||
// Common prim might be uninit.
|
// Common prim might be uninit.
|
||||||
Scalar::Union { value: prim }
|
Scalar::Union { value: prim }
|
||||||
};
|
};
|
||||||
let pair = self.scalar_pair::<V>(tag, prim_scalar);
|
let pair = self.scalar_pair(tag, prim_scalar);
|
||||||
let pair_offsets = match pair.fields {
|
let pair_offsets = match pair.fields {
|
||||||
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
|
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
|
||||||
assert_eq!(memory_index, &[0, 1]);
|
assert_eq!(memory_index, &[0, 1]);
|
||||||
|
@ -862,9 +859,8 @@ pub trait LayoutCalculator {
|
||||||
// pick the layout with the larger niche; otherwise,
|
// pick the layout with the larger niche; otherwise,
|
||||||
// pick tagged as it has simpler codegen.
|
// pick tagged as it has simpler codegen.
|
||||||
use cmp::Ordering::*;
|
use cmp::Ordering::*;
|
||||||
let niche_size = |tmp_l: &TmpLayout<V>| {
|
let niche_size =
|
||||||
tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl))
|
|tmp_l: &TmpLayout| tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl));
|
||||||
};
|
|
||||||
match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) {
|
match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) {
|
||||||
(Greater, _) => nl,
|
(Greater, _) => nl,
|
||||||
(Equal, Less) => nl,
|
(Equal, Less) => nl,
|
||||||
|
@ -884,11 +880,11 @@ pub trait LayoutCalculator {
|
||||||
Some(best_layout.layout)
|
Some(best_layout.layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_of_union<'a, V: Idx, F: Deref<Target = &'a LayoutS<V>> + Debug>(
|
fn layout_of_union(
|
||||||
&self,
|
&self,
|
||||||
repr: &ReprOptions,
|
repr: &ReprOptions,
|
||||||
variants: &IndexVec<V, Vec<F>>,
|
variants: &IndexVec<VariantIdx, Vec<Layout<'_>>>,
|
||||||
) -> Option<LayoutS<V>> {
|
) -> Option<LayoutS> {
|
||||||
let dl = self.current_data_layout();
|
let dl = self.current_data_layout();
|
||||||
let dl = dl.borrow();
|
let dl = dl.borrow();
|
||||||
let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
|
let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
|
||||||
|
@ -900,15 +896,15 @@ pub trait LayoutCalculator {
|
||||||
let optimize = !repr.inhibit_union_abi_opt();
|
let optimize = !repr.inhibit_union_abi_opt();
|
||||||
let mut size = Size::ZERO;
|
let mut size = Size::ZERO;
|
||||||
let mut abi = Abi::Aggregate { sized: true };
|
let mut abi = Abi::Aggregate { sized: true };
|
||||||
let index = V::new(0);
|
let index = VariantIdx::new(0);
|
||||||
for field in &variants[index] {
|
for field in &variants[index] {
|
||||||
assert!(field.is_sized());
|
assert!(field.0.is_sized());
|
||||||
align = align.max(field.align);
|
align = align.max(field.align());
|
||||||
|
|
||||||
// If all non-ZST fields have the same ABI, forward this ABI
|
// If all non-ZST fields have the same ABI, forward this ABI
|
||||||
if optimize && !field.is_zst() {
|
if optimize && !field.0.is_zst() {
|
||||||
// Discard valid range information and allow undef
|
// Discard valid range information and allow undef
|
||||||
let field_abi = match field.abi {
|
let field_abi = match field.abi() {
|
||||||
Abi::Scalar(x) => Abi::Scalar(x.to_union()),
|
Abi::Scalar(x) => Abi::Scalar(x.to_union()),
|
||||||
Abi::ScalarPair(x, y) => Abi::ScalarPair(x.to_union(), y.to_union()),
|
Abi::ScalarPair(x, y) => Abi::ScalarPair(x.to_union(), y.to_union()),
|
||||||
Abi::Vector { element: x, count } => {
|
Abi::Vector { element: x, count } => {
|
||||||
|
@ -926,7 +922,7 @@ pub trait LayoutCalculator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size = cmp::max(size, field.size);
|
size = cmp::max(size, field.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(pack) = repr.pack {
|
if let Some(pack) = repr.pack {
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
use rustc_data_structures::intern::Interned;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use rustc_data_structures::stable_hasher::StableOrd;
|
use rustc_data_structures::stable_hasher::StableOrd;
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
|
@ -1257,9 +1258,9 @@ impl Abi {
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
||||||
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
||||||
pub enum Variants<V: Idx> {
|
pub enum Variants {
|
||||||
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
|
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
|
||||||
Single { index: V },
|
Single { index: VariantIdx },
|
||||||
|
|
||||||
/// Enum-likes with more than one inhabited variant: each variant comes with
|
/// Enum-likes with more than one inhabited variant: each variant comes with
|
||||||
/// a *discriminant* (usually the same as the variant index but the user can
|
/// a *discriminant* (usually the same as the variant index but the user can
|
||||||
|
@ -1269,15 +1270,15 @@ pub enum Variants<V: Idx> {
|
||||||
/// For enums, the tag is the sole field of the layout.
|
/// For enums, the tag is the sole field of the layout.
|
||||||
Multiple {
|
Multiple {
|
||||||
tag: Scalar,
|
tag: Scalar,
|
||||||
tag_encoding: TagEncoding<V>,
|
tag_encoding: TagEncoding,
|
||||||
tag_field: usize,
|
tag_field: usize,
|
||||||
variants: IndexVec<V, LayoutS<V>>,
|
variants: IndexVec<VariantIdx, LayoutS>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
||||||
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
||||||
pub enum TagEncoding<V: Idx> {
|
pub enum TagEncoding {
|
||||||
/// The tag directly stores the discriminant, but possibly with a smaller layout
|
/// The tag directly stores the discriminant, but possibly with a smaller layout
|
||||||
/// (so converting the tag to the discriminant can require sign extension).
|
/// (so converting the tag to the discriminant can require sign extension).
|
||||||
Direct,
|
Direct,
|
||||||
|
@ -1292,7 +1293,11 @@ pub enum TagEncoding<V: Idx> {
|
||||||
/// For example, `Option<(usize, &T)>` is represented such that
|
/// For example, `Option<(usize, &T)>` is represented such that
|
||||||
/// `None` has a null pointer for the second tuple field, and
|
/// `None` has a null pointer for the second tuple field, and
|
||||||
/// `Some` is the identity function (with a non-null reference).
|
/// `Some` is the identity function (with a non-null reference).
|
||||||
Niche { untagged_variant: V, niche_variants: RangeInclusive<V>, niche_start: u128 },
|
Niche {
|
||||||
|
untagged_variant: VariantIdx,
|
||||||
|
niche_variants: RangeInclusive<VariantIdx>,
|
||||||
|
niche_start: u128,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
|
@ -1379,9 +1384,14 @@ impl Niche {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rustc_index::newtype_index! {
|
||||||
|
#[derive(HashStable_Generic)]
|
||||||
|
pub struct VariantIdx {}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||||
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
||||||
pub struct LayoutS<V: Idx> {
|
pub struct LayoutS {
|
||||||
/// Says where the fields are located within the layout.
|
/// Says where the fields are located within the layout.
|
||||||
pub fields: FieldsShape,
|
pub fields: FieldsShape,
|
||||||
|
|
||||||
|
@ -1392,7 +1402,7 @@ pub struct LayoutS<V: Idx> {
|
||||||
///
|
///
|
||||||
/// To access all fields of this layout, both `fields` and the fields of the active variant
|
/// To access all fields of this layout, both `fields` and the fields of the active variant
|
||||||
/// must be taken into account.
|
/// must be taken into account.
|
||||||
pub variants: Variants<V>,
|
pub variants: Variants,
|
||||||
|
|
||||||
/// The `abi` defines how this data is passed between functions, and it defines
|
/// The `abi` defines how this data is passed between functions, and it defines
|
||||||
/// value restrictions via `valid_range`.
|
/// value restrictions via `valid_range`.
|
||||||
|
@ -1411,13 +1421,13 @@ pub struct LayoutS<V: Idx> {
|
||||||
pub size: Size,
|
pub size: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: Idx> LayoutS<V> {
|
impl LayoutS {
|
||||||
pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
|
pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
|
||||||
let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
|
let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
|
||||||
let size = scalar.size(cx);
|
let size = scalar.size(cx);
|
||||||
let align = scalar.align(cx);
|
let align = scalar.align(cx);
|
||||||
LayoutS {
|
LayoutS {
|
||||||
variants: Variants::Single { index: V::new(0) },
|
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||||
fields: FieldsShape::Primitive,
|
fields: FieldsShape::Primitive,
|
||||||
abi: Abi::Scalar(scalar),
|
abi: Abi::Scalar(scalar),
|
||||||
largest_niche,
|
largest_niche,
|
||||||
|
@ -1427,7 +1437,7 @@ impl<V: Idx> LayoutS<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: Idx> fmt::Debug for LayoutS<V> {
|
impl fmt::Debug for LayoutS {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
// This is how `Layout` used to print before it become
|
// This is how `Layout` used to print before it become
|
||||||
// `Interned<LayoutS>`. We print it like this to avoid having to update
|
// `Interned<LayoutS>`. We print it like this to avoid having to update
|
||||||
|
@ -1444,6 +1454,43 @@ impl<V: Idx> fmt::Debug for LayoutS<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
pub struct Layout<'a>(pub Interned<'a, LayoutS>);
|
||||||
|
|
||||||
|
impl<'a> fmt::Debug for Layout<'a> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
// See comment on `<LayoutS as Debug>::fmt` above.
|
||||||
|
self.0.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Layout<'a> {
|
||||||
|
pub fn fields(self) -> &'a FieldsShape {
|
||||||
|
&self.0.0.fields
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn variants(self) -> &'a Variants {
|
||||||
|
&self.0.0.variants
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn abi(self) -> Abi {
|
||||||
|
self.0.0.abi
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn largest_niche(self) -> Option<Niche> {
|
||||||
|
self.0.0.largest_niche
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn align(self) -> AbiAndPrefAlign {
|
||||||
|
self.0.0.align
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(self) -> Size {
|
||||||
|
self.0.0.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum PointerKind {
|
pub enum PointerKind {
|
||||||
/// Most general case, we know no restrictions to tell LLVM.
|
/// Most general case, we know no restrictions to tell LLVM.
|
||||||
|
@ -1479,7 +1526,7 @@ pub enum InitKind {
|
||||||
UninitMitigated0x01Fill,
|
UninitMitigated0x01Fill,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: Idx> LayoutS<V> {
|
impl LayoutS {
|
||||||
/// Returns `true` if the layout corresponds to an unsized type.
|
/// Returns `true` if the layout corresponds to an unsized type.
|
||||||
pub fn is_unsized(&self) -> bool {
|
pub fn is_unsized(&self) -> bool {
|
||||||
self.abi.is_unsized()
|
self.abi.is_unsized()
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
macro_rules! arena_types {
|
macro_rules! arena_types {
|
||||||
($macro:path) => (
|
($macro:path) => (
|
||||||
$macro!([
|
$macro!([
|
||||||
[] layout: rustc_target::abi::LayoutS<rustc_target::abi::VariantIdx>,
|
[] layout: rustc_target::abi::LayoutS,
|
||||||
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
|
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
|
||||||
// AdtDef are interned and compared by address
|
// AdtDef are interned and compared by address
|
||||||
[decode] adt_def: rustc_middle::ty::AdtDefData,
|
[decode] adt_def: rustc_middle::ty::AdtDefData,
|
||||||
|
|
|
@ -142,7 +142,7 @@ pub struct CtxtInterners<'tcx> {
|
||||||
const_: InternedSet<'tcx, ConstData<'tcx>>,
|
const_: InternedSet<'tcx, ConstData<'tcx>>,
|
||||||
const_allocation: InternedSet<'tcx, Allocation>,
|
const_allocation: InternedSet<'tcx, Allocation>,
|
||||||
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
||||||
layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
|
layout: InternedSet<'tcx, LayoutS>,
|
||||||
adt_def: InternedSet<'tcx, AdtDefData>,
|
adt_def: InternedSet<'tcx, AdtDefData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1586,7 +1586,7 @@ direct_interners! {
|
||||||
region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
|
region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
|
||||||
const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>,
|
const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>,
|
||||||
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
|
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
|
||||||
layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>,
|
layout: intern_layout(LayoutS): Layout -> Layout<'tcx>,
|
||||||
adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
|
adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,8 @@ pub use Primitive::*;
|
||||||
|
|
||||||
use crate::json::{Json, ToJson};
|
use crate::json::{Json, ToJson};
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use rustc_data_structures::intern::Interned;
|
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
|
|
||||||
pub mod call;
|
pub mod call;
|
||||||
|
@ -19,48 +17,6 @@ impl ToJson for Endian {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rustc_index::newtype_index! {
|
|
||||||
#[derive(HashStable_Generic)]
|
|
||||||
pub struct VariantIdx {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
|
|
||||||
#[rustc_pass_by_value]
|
|
||||||
pub struct Layout<'a>(pub Interned<'a, LayoutS<VariantIdx>>);
|
|
||||||
|
|
||||||
impl<'a> fmt::Debug for Layout<'a> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
// See comment on `<LayoutS as Debug>::fmt` above.
|
|
||||||
self.0.0.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Layout<'a> {
|
|
||||||
pub fn fields(self) -> &'a FieldsShape {
|
|
||||||
&self.0.0.fields
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variants(self) -> &'a Variants<VariantIdx> {
|
|
||||||
&self.0.0.variants
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn abi(self) -> Abi {
|
|
||||||
self.0.0.abi
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn largest_niche(self) -> Option<Niche> {
|
|
||||||
self.0.0.largest_niche
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn align(self) -> AbiAndPrefAlign {
|
|
||||||
self.0.0.align
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size(self) -> Size {
|
|
||||||
self.0.0.size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The layout of a type, alongside the type itself.
|
/// The layout of a type, alongside the type itself.
|
||||||
/// Provides various type traversal APIs (e.g., recursing into fields).
|
/// Provides various type traversal APIs (e.g., recursing into fields).
|
||||||
///
|
///
|
||||||
|
@ -75,8 +31,8 @@ pub struct TyAndLayout<'a, Ty> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
|
impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
|
||||||
type Target = &'a LayoutS<VariantIdx>;
|
type Target = &'a LayoutS;
|
||||||
fn deref(&self) -> &&'a LayoutS<VariantIdx> {
|
fn deref(&self) -> &&'a LayoutS {
|
||||||
&self.layout.0.0
|
&self.layout.0.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,10 +78,10 @@ fn invert_mapping(map: &[u32]) -> Vec<u32> {
|
||||||
fn univariant_uninterned<'tcx>(
|
fn univariant_uninterned<'tcx>(
|
||||||
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
|
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
fields: &[TyAndLayout<'_>],
|
fields: &[Layout<'_>],
|
||||||
repr: &ReprOptions,
|
repr: &ReprOptions,
|
||||||
kind: StructKind,
|
kind: StructKind,
|
||||||
) -> Result<LayoutS<VariantIdx>, LayoutError<'tcx>> {
|
) -> Result<LayoutS, LayoutError<'tcx>> {
|
||||||
let dl = cx.data_layout();
|
let dl = cx.data_layout();
|
||||||
let pack = repr.pack;
|
let pack = repr.pack;
|
||||||
if pack.is_some() && repr.align.is_some() {
|
if pack.is_some() && repr.align.is_some() {
|
||||||
|
@ -106,7 +106,7 @@ fn layout_of_uncached<'tcx>(
|
||||||
};
|
};
|
||||||
let scalar = |value: Primitive| tcx.intern_layout(LayoutS::scalar(cx, scalar_unit(value)));
|
let scalar = |value: Primitive| tcx.intern_layout(LayoutS::scalar(cx, scalar_unit(value)));
|
||||||
|
|
||||||
let univariant = |fields: &[TyAndLayout<'_>], repr: &ReprOptions, kind| {
|
let univariant = |fields: &[Layout<'_>], repr: &ReprOptions, kind| {
|
||||||
Ok(tcx.intern_layout(univariant_uninterned(cx, ty, fields, repr, kind)?))
|
Ok(tcx.intern_layout(univariant_uninterned(cx, ty, fields, repr, kind)?))
|
||||||
};
|
};
|
||||||
debug_assert!(!ty.has_non_region_infer());
|
debug_assert!(!ty.has_non_region_infer());
|
||||||
|
@ -272,7 +272,7 @@ fn layout_of_uncached<'tcx>(
|
||||||
ty::Closure(_, ref substs) => {
|
ty::Closure(_, ref substs) => {
|
||||||
let tys = substs.as_closure().upvar_tys();
|
let tys = substs.as_closure().upvar_tys();
|
||||||
univariant(
|
univariant(
|
||||||
&tys.map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
|
&tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).collect::<Result<Vec<_>, _>>()?,
|
||||||
&ReprOptions::default(),
|
&ReprOptions::default(),
|
||||||
StructKind::AlwaysSized,
|
StructKind::AlwaysSized,
|
||||||
)?
|
)?
|
||||||
|
@ -283,7 +283,7 @@ fn layout_of_uncached<'tcx>(
|
||||||
if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
|
if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
|
||||||
|
|
||||||
univariant(
|
univariant(
|
||||||
&tys.iter().map(|k| cx.layout_of(k)).collect::<Result<Vec<_>, _>>()?,
|
&tys.iter().map(|k| Ok(cx.layout_of(k)?.layout)).collect::<Result<Vec<_>, _>>()?,
|
||||||
&ReprOptions::default(),
|
&ReprOptions::default(),
|
||||||
kind,
|
kind,
|
||||||
)?
|
)?
|
||||||
|
@ -412,7 +412,7 @@ fn layout_of_uncached<'tcx>(
|
||||||
.map(|v| {
|
.map(|v| {
|
||||||
v.fields
|
v.fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| cx.layout_of(field.ty(tcx, substs)))
|
.map(|field| Ok(cx.layout_of(field.ty(tcx, substs))?.layout))
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
})
|
})
|
||||||
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
|
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
|
||||||
|
@ -630,23 +630,21 @@ fn generator_layout<'tcx>(
|
||||||
// `info.variant_fields` already accounts for the reserved variants, so no need to add them.
|
// `info.variant_fields` already accounts for the reserved variants, so no need to add them.
|
||||||
let max_discr = (info.variant_fields.len() - 1) as u128;
|
let max_discr = (info.variant_fields.len() - 1) as u128;
|
||||||
let discr_int = Integer::fit_unsigned(max_discr);
|
let discr_int = Integer::fit_unsigned(max_discr);
|
||||||
let discr_int_ty = discr_int.to_ty(tcx, false);
|
|
||||||
let tag = Scalar::Initialized {
|
let tag = Scalar::Initialized {
|
||||||
value: Primitive::Int(discr_int, false),
|
value: Primitive::Int(discr_int, false),
|
||||||
valid_range: WrappingRange { start: 0, end: max_discr },
|
valid_range: WrappingRange { start: 0, end: max_discr },
|
||||||
};
|
};
|
||||||
let tag_layout = cx.tcx.intern_layout(LayoutS::scalar(cx, tag));
|
let tag_layout = cx.tcx.intern_layout(LayoutS::scalar(cx, tag));
|
||||||
let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
|
|
||||||
|
|
||||||
let promoted_layouts = ineligible_locals
|
let promoted_layouts = ineligible_locals
|
||||||
.iter()
|
.iter()
|
||||||
.map(|local| subst_field(info.field_tys[local]))
|
.map(|local| subst_field(info.field_tys[local]))
|
||||||
.map(|ty| tcx.mk_maybe_uninit(ty))
|
.map(|ty| tcx.mk_maybe_uninit(ty))
|
||||||
.map(|ty| cx.layout_of(ty));
|
.map(|ty| Ok(cx.layout_of(ty)?.layout));
|
||||||
let prefix_layouts = substs
|
let prefix_layouts = substs
|
||||||
.as_generator()
|
.as_generator()
|
||||||
.prefix_tys()
|
.prefix_tys()
|
||||||
.map(|ty| cx.layout_of(ty))
|
.map(|ty| Ok(cx.layout_of(ty)?.layout))
|
||||||
.chain(iter::once(Ok(tag_layout)))
|
.chain(iter::once(Ok(tag_layout)))
|
||||||
.chain(promoted_layouts)
|
.chain(promoted_layouts)
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
@ -715,7 +713,9 @@ fn generator_layout<'tcx>(
|
||||||
let mut variant = univariant_uninterned(
|
let mut variant = univariant_uninterned(
|
||||||
cx,
|
cx,
|
||||||
ty,
|
ty,
|
||||||
&variant_only_tys.map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
|
&variant_only_tys
|
||||||
|
.map(|ty| Ok(cx.layout_of(ty)?.layout))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
&ReprOptions::default(),
|
&ReprOptions::default(),
|
||||||
StructKind::Prefixed(prefix_size, prefix_align.abi),
|
StructKind::Prefixed(prefix_size, prefix_align.abi),
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustc_middle::ty::layout::LayoutError;
|
||||||
use rustc_middle::ty::{self, Adt, TyCtxt};
|
use rustc_middle::ty::{self, Adt, TyCtxt};
|
||||||
use rustc_span::hygiene::MacroKind;
|
use rustc_span::hygiene::MacroKind;
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
use rustc_target::abi::{LayoutS, Primitive, TagEncoding, VariantIdx, Variants};
|
use rustc_target::abi::{LayoutS, Primitive, TagEncoding, Variants};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -1887,7 +1887,7 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
|
fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
|
||||||
fn write_size_of_layout(w: &mut Buffer, layout: &LayoutS<VariantIdx>, tag_size: u64) {
|
fn write_size_of_layout(w: &mut Buffer, layout: &LayoutS, tag_size: u64) {
|
||||||
if layout.abi.is_unsized() {
|
if layout.abi.is_unsized() {
|
||||||
write!(w, "(unsized)");
|
write!(w, "(unsized)");
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue