Skip to content

Commit c4789e8

Browse files
committed
Auto merge of #155843 - JonathanBrouwer:rollup-d6xHqF5, r=<try>
Rollup of 10 pull requests try-job: dist-various-1 try-job: test-various try-job: x86_64-gnu-aux try-job: x86_64-gnu-llvm-21-3 try-job: x86_64-msvc-1 try-job: aarch64-apple try-job: x86_64-mingw-1 try-job: i686-msvc-2
2 parents d4f7856 + d33e6e2 commit c4789e8

60 files changed

Lines changed: 1081 additions & 1646 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_abi/src/layout.rs

Lines changed: 47 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use tracing::{debug, trace};
1111
use crate::{
1212
AbiAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer,
1313
LayoutData, Niche, NonZeroUsize, NumScalableVectors, Primitive, ReprOptions, Scalar, Size,
14-
StructKind, TagEncoding, TargetDataLayout, Variants, WrappingRange,
14+
StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants, WrappingRange,
1515
};
1616

1717
mod coroutine;
@@ -638,6 +638,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
638638
}
639639

640640
let calculate_niche_filling_layout = || -> Option<LayoutData<FieldIdx, VariantIdx>> {
641+
struct VariantLayoutInfo {
642+
align_abi: Align,
643+
}
644+
641645
if repr.inhibit_enum_layout_opt() {
642646
return None;
643647
}
@@ -649,26 +653,35 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
649653
let mut align = dl.aggregate_align;
650654
let mut max_repr_align = repr.align;
651655
let mut unadjusted_abi_align = align;
656+
let mut combined_seed = repr.field_shuffle_seed;
657+
658+
let mut largest_variant_size = Size::ZERO;
659+
let mut largest_variant_index = VariantIdx::new(0);
660+
let mut largest_variant_niche = None;
652661

662+
let mut variants_info = IndexVec::<VariantIdx, _>::with_capacity(variants.len());
653663
let mut variant_layouts = variants
654664
.iter_enumerated()
655-
.map(|(j, v)| {
656-
let mut st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?;
657-
st.variants = Variants::Single { index: j };
665+
.map(|(i, v)| {
666+
let st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?;
667+
668+
variants_info.push(VariantLayoutInfo { align_abi: st.align.abi });
669+
670+
if st.size > largest_variant_size {
671+
largest_variant_index = i;
672+
largest_variant_size = st.size;
673+
largest_variant_niche = st.largest_niche;
674+
}
658675

659676
align = align.max(st.align.abi);
660677
max_repr_align = max_repr_align.max(st.max_repr_align);
661678
unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align);
679+
combined_seed = combined_seed.wrapping_add(st.randomization_seed);
662680

663-
Some(st)
681+
Some(VariantLayout::from_layout(st))
664682
})
665683
.collect::<Option<IndexVec<VariantIdx, _>>>()?;
666684

667-
let largest_variant_index = variant_layouts
668-
.iter_enumerated()
669-
.max_by_key(|(_i, layout)| layout.size.bytes())
670-
.map(|(i, _layout)| i)?;
671-
672685
let all_indices = variants.indices();
673686
let needs_disc =
674687
|index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
@@ -679,42 +692,33 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
679692
(niche_variants.end().index() as u128 - niche_variants.start().index() as u128) + 1;
680693

681694
// Use the largest niche in the largest variant.
682-
let niche = variant_layouts[largest_variant_index].largest_niche?;
695+
let niche = largest_variant_niche?;
683696
let (niche_start, niche_scalar) = niche.reserve(dl, count)?;
684697
let niche_offset = niche.offset;
685698
let niche_size = niche.value.size(dl);
686-
let size = variant_layouts[largest_variant_index].size.align_to(align);
699+
let size = largest_variant_size.align_to(align);
687700

688701
let all_variants_fit = variant_layouts.iter_enumerated_mut().all(|(i, layout)| {
689702
if i == largest_variant_index {
690703
return true;
691704
}
692705

693-
layout.largest_niche = None;
694-
695706
if layout.size <= niche_offset {
696707
// This variant will fit before the niche.
697708
return true;
698709
}
699710

700711
// Determine if it'll fit after the niche.
701-
let this_align = layout.align.abi;
712+
let this_align = variants_info[i].align_abi;
702713
let this_offset = (niche_offset + niche_size).align_to(this_align);
703714

704715
if this_offset + layout.size > size {
705716
return false;
706717
}
707718

708719
// It'll fit, but we need to make some adjustments.
709-
match layout.fields {
710-
FieldsShape::Arbitrary { ref mut offsets, .. } => {
711-
for offset in offsets.iter_mut() {
712-
*offset += this_offset;
713-
}
714-
}
715-
FieldsShape::Primitive | FieldsShape::Array { .. } | FieldsShape::Union(..) => {
716-
panic!("Layout of fields should be Arbitrary for variants")
717-
}
720+
for offset in layout.field_offsets.iter_mut() {
721+
*offset += this_offset;
718722
}
719723

720724
// It can't be a Scalar or ScalarPair because the offset isn't 0.
@@ -736,7 +740,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
736740
.iter_enumerated()
737741
.all(|(i, layout)| i == largest_variant_index || layout.size == Size::ZERO);
738742
let same_size = size == variant_layouts[largest_variant_index].size;
739-
let same_align = align == variant_layouts[largest_variant_index].align.abi;
743+
let same_align = align == variants_info[largest_variant_index].align_abi;
740744

741745
let uninhabited = variant_layouts.iter().all(|v| v.is_uninhabited());
742746
let abi = if same_size && same_align && others_zst {
@@ -759,11 +763,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
759763
BackendRepr::Memory { sized: true }
760764
};
761765

762-
let combined_seed = variant_layouts
763-
.iter()
764-
.map(|v| v.randomization_seed)
765-
.fold(repr.field_shuffle_seed, |acc, seed| acc.wrapping_add(seed));
766-
767766
let layout = LayoutData {
768767
variants: Variants::Multiple {
769768
tag: niche_scalar,
@@ -856,6 +855,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
856855
let mut align = dl.aggregate_align;
857856
let mut max_repr_align = repr.align;
858857
let mut unadjusted_abi_align = align;
858+
let mut combined_seed = repr.field_shuffle_seed;
859859

860860
let mut size = Size::ZERO;
861861

@@ -879,14 +879,13 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
879879

880880
// Create the set of structs that represent each variant.
881881
let mut layout_variants = variants
882-
.iter_enumerated()
883-
.map(|(i, field_layouts)| {
884-
let mut st = self.univariant(
882+
.iter()
883+
.map(|field_layouts| {
884+
let st = self.univariant(
885885
field_layouts,
886886
repr,
887887
StructKind::Prefixed(min_ity.size(), prefix_align),
888888
)?;
889-
st.variants = Variants::Single { index: i };
890889
// Find the first field we can't move later
891890
// to make room for a larger discriminant.
892891
for field_idx in st.fields.index_by_increasing_offset() {
@@ -900,7 +899,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
900899
align = align.max(st.align.abi);
901900
max_repr_align = max_repr_align.max(st.max_repr_align);
902901
unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align);
903-
Ok(st)
902+
combined_seed = combined_seed.wrapping_add(st.randomization_seed);
903+
Ok(VariantLayout::from_layout(st))
904904
})
905905
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
906906

@@ -955,23 +955,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
955955
let old_ity_size = min_ity.size();
956956
let new_ity_size = ity.size();
957957
for variant in &mut layout_variants {
958-
match variant.fields {
959-
FieldsShape::Arbitrary { ref mut offsets, .. } => {
960-
for i in offsets {
961-
if *i <= old_ity_size {
962-
assert_eq!(*i, old_ity_size);
963-
*i = new_ity_size;
964-
}
965-
}
966-
// We might be making the struct larger.
967-
if variant.size <= old_ity_size {
968-
variant.size = new_ity_size;
969-
}
970-
}
971-
FieldsShape::Primitive | FieldsShape::Array { .. } | FieldsShape::Union(..) => {
972-
panic!("encountered a non-arbitrary layout during enum layout")
958+
for i in &mut variant.field_offsets {
959+
if *i <= old_ity_size {
960+
assert_eq!(*i, old_ity_size);
961+
*i = new_ity_size;
973962
}
974963
}
964+
// We might be making the struct larger.
965+
if variant.size <= old_ity_size {
966+
variant.size = new_ity_size;
967+
}
975968
}
976969
}
977970

@@ -996,12 +989,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
996989
let mut common_prim = None;
997990
let mut common_prim_initialized_in_all_variants = true;
998991
for (field_layouts, layout_variant) in iter::zip(variants, &layout_variants) {
999-
let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
1000-
panic!("encountered a non-arbitrary layout during enum layout");
1001-
};
1002992
// We skip *all* ZST here and later check if we are good in terms of alignment.
1003993
// This lets us handle some cases involving aligned ZST.
1004-
let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
994+
let mut fields = iter::zip(field_layouts, &layout_variant.field_offsets)
995+
.filter(|p| !p.0.is_zst());
1005996
let (field, offset) = match (fields.next(), fields.next()) {
1006997
(None, None) => {
1007998
common_prim_initialized_in_all_variants = false;
@@ -1096,25 +1087,17 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
10961087
for variant in &mut layout_variants {
10971088
// We only do this for variants with fields; the others are not accessed anyway.
10981089
// Also do not overwrite any already existing "clever" ABIs.
1099-
if variant.fields.count() > 0
1100-
&& matches!(variant.backend_repr, BackendRepr::Memory { .. })
1090+
if matches!(variant.backend_repr, BackendRepr::Memory { .. } if variant.has_fields())
11011091
{
11021092
variant.backend_repr = abi;
1103-
// Also need to bump up the size and alignment, so that the entire value fits
1104-
// in here.
1093+
// Also need to bump up the size, so that the entire value fits in here.
11051094
variant.size = cmp::max(variant.size, size);
1106-
variant.align.abi = cmp::max(variant.align.abi, align);
11071095
}
11081096
}
11091097
}
11101098

11111099
let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
11121100

1113-
let combined_seed = layout_variants
1114-
.iter()
1115-
.map(|v| v.randomization_seed)
1116-
.fold(repr.field_shuffle_seed, |acc, seed| acc.wrapping_add(seed));
1117-
11181101
let tagged_layout = LayoutData {
11191102
variants: Variants::Multiple {
11201103
tag,

compiler/rustc_abi/src/layout/coroutine.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use tracing::{debug, trace};
2727

2828
use crate::{
2929
BackendRepr, FieldsShape, HasDataLayout, Integer, LayoutData, Primitive, ReprOptions, Scalar,
30-
StructKind, TagEncoding, Variants, WrappingRange,
30+
StructKind, TagEncoding, VariantLayout, Variants, WrappingRange,
3131
};
3232

3333
/// Overlap eligibility and variant assignment for each CoroutineSavedLocal.
@@ -230,7 +230,6 @@ pub(super) fn layout<
230230
&ReprOptions::default(),
231231
StructKind::Prefixed(prefix_size, prefix_align.abi),
232232
)?;
233-
variant.variants = Variants::Single { index };
234233

235234
let FieldsShape::Arbitrary { offsets, in_memory_order } = variant.fields else {
236235
unreachable!();
@@ -281,7 +280,7 @@ pub(super) fn layout<
281280

282281
size = size.max(variant.size);
283282
align = align.max(variant.align);
284-
Ok(variant)
283+
Ok(VariantLayout::from_layout(variant))
285284
})
286285
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
287286

compiler/rustc_abi/src/layout/simple.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,28 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
146146
randomization_seed: Hash64::ZERO,
147147
}
148148
}
149+
150+
/// Returns a layout for an inhabited variant.
151+
pub fn for_variant(parent: &Self, index: VariantIdx) -> Self {
152+
let layout = match &parent.variants {
153+
Variants::Multiple { variants, .. } => &variants[index],
154+
_ => panic!("Expected multi-variant layout in `Layout::for_variant`"),
155+
};
156+
157+
Self {
158+
fields: FieldsShape::Arbitrary {
159+
offsets: layout.field_offsets.clone(),
160+
in_memory_order: layout.fields_in_memory_order.clone(),
161+
},
162+
variants: Variants::Single { index },
163+
backend_repr: layout.backend_repr,
164+
largest_niche: None,
165+
uninhabited: layout.uninhabited,
166+
size: layout.size,
167+
align: parent.align,
168+
max_repr_align: parent.max_repr_align,
169+
unadjusted_abi_align: parent.unadjusted_abi_align,
170+
randomization_seed: Hash64::ZERO,
171+
}
172+
}
149173
}

compiler/rustc_abi/src/lib.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1974,7 +1974,7 @@ pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
19741974
tag: Scalar,
19751975
tag_encoding: TagEncoding<VariantIdx>,
19761976
tag_field: FieldIdx,
1977-
variants: IndexVec<VariantIdx, LayoutData<FieldIdx, VariantIdx>>,
1977+
variants: IndexVec<VariantIdx, VariantLayout<FieldIdx>>,
19781978
},
19791979
}
19801980

@@ -2339,3 +2339,38 @@ pub enum AbiFromStrErr {
23392339
/// no "-unwind" variant can be used here
23402340
NoExplicitUnwind,
23412341
}
2342+
2343+
// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage.
2344+
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
2345+
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
2346+
pub struct VariantLayout<FieldIdx: Idx> {
2347+
pub size: Size,
2348+
pub backend_repr: BackendRepr,
2349+
pub field_offsets: IndexVec<FieldIdx, Size>,
2350+
fields_in_memory_order: IndexVec<u32, FieldIdx>,
2351+
uninhabited: bool,
2352+
}
2353+
2354+
impl<FieldIdx: Idx> VariantLayout<FieldIdx> {
2355+
pub fn from_layout(layout: LayoutData<FieldIdx, impl Idx>) -> Self {
2356+
let FieldsShape::Arbitrary { offsets, in_memory_order } = layout.fields else {
2357+
panic!("Layout of fields should be Arbitrary for variants");
2358+
};
2359+
2360+
Self {
2361+
size: layout.size,
2362+
backend_repr: layout.backend_repr,
2363+
field_offsets: offsets,
2364+
fields_in_memory_order: in_memory_order,
2365+
uninhabited: layout.uninhabited,
2366+
}
2367+
}
2368+
2369+
pub fn is_uninhabited(&self) -> bool {
2370+
self.uninhabited
2371+
}
2372+
2373+
pub fn has_fields(&self) -> bool {
2374+
self.field_offsets.len() > 0
2375+
}
2376+
}

compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,11 @@ fn parse_directive_items<'p, S: Stage>(
236236
}}
237237

238238
macro or_malformed($($code:tt)*) {{
239-
let Some(ret) = (||{
240-
Some($($code)*)
241-
})() else {
239+
let Some(ret) = (
240+
try {
241+
$($code)*
242+
}
243+
) else {
242244
malformed!()
243245
};
244246
ret

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ pub(super) struct GroupTypeInnerAccept<S: Stage> {
8484

8585
pub(crate) type AcceptFn<S> =
8686
Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser) + Send + Sync>;
87-
pub(crate) type FinalizeFn<S> =
88-
Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>>;
87+
pub(crate) type FinalizeFn<S> = fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>;
8988

9089
macro_rules! attribute_parsers {
9190
(
@@ -131,10 +130,10 @@ macro_rules! attribute_parsers {
131130
}),
132131
safety: <$names as crate::attributes::AttributeParser<$stage>>::SAFETY,
133132
allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
134-
finalizer: Box::new(|cx| {
133+
finalizer: |cx| {
135134
let state = STATE_OBJECT.take();
136135
state.finalize(cx)
137-
})
136+
}
138137
});
139138
}
140139
Entry::Occupied(_) => panic!("Attribute {path:?} has multiple accepters"),

0 commit comments

Comments
 (0)