Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
a4bd5f5
compiler: suggest `.collect()` when `String` is expected and `Iterato…
thiago-fealves May 3, 2026
e1941ff
Update compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
thiago-fealves May 4, 2026
464dc07
Introduce `VariantLayout` struct
moulins Dec 17, 2025
1162bdc
Remove redundant `VariantLayout.variants` field
moulins Dec 17, 2025
0569574
Store `FieldsShape::Arbitrary` fields directly in `VariantLayout`
moulins Dec 17, 2025
3459964
Remove unused `VariantLayout.randomization_seed` field
moulins Dec 18, 2025
75015f4
Remove per-variant alignment in `VariantLayout`
moulins Jan 13, 2026
19c6365
Inline and remove `late_lint_crate_inner`
nnethercote May 15, 2026
4033268
Remove an unnecessary `push` argument
nnethercote May 15, 2026
ecf0191
Avoid rustfix suggestions for macro-expanded unused imports
cijiugechu May 15, 2026
9d76912
comment for issue id
cijiugechu May 15, 2026
209ee9d
use edition 2021
cijiugechu May 15, 2026
19045f8
ci: Update FreeBSD version to FreeBSD 14
mrkajetanp May 15, 2026
e15861b
Add trait methods for experimental retags to cg.
icmccorm Apr 30, 2026
5f2e455
rustdoc: add test case for `-Drustdoc::` CLI param
notriddle May 15, 2026
0344a02
rustdoc: add test case for `--cap-lints=allow`
notriddle May 15, 2026
124126e
Test EII UI tests with prefer-dynamic
AsakuraMizu May 14, 2026
87821d9
Add regression test for issue 41261
eval-exec May 16, 2026
6d91f14
fix
bb1yd May 16, 2026
053761d
minor `rustc_mir_transform` cleanup
Human9000-bit May 11, 2026
22cf1fb
Split `LintExpectationId`
nnethercote May 15, 2026
36738a1
Remove some low-value method wrappers
nnethercote May 15, 2026
6c9d519
Add some comments to `ShallowLintLevelMap`
nnethercote May 15, 2026
e599831
suggest hex escapes for C-style escapes
euclio May 9, 2026
04c325f
ignore some musttail tests on unsupported LLVM targets
InvalidPathException May 14, 2026
2071c66
Add interior-mutability suggestion to `static_mut_refs`
JohnTitor Jan 19, 2026
cbaee5d
Tweak note condition
JohnTitor Mar 5, 2026
33d92f7
Add test for the case span is unavailable
JohnTitor May 17, 2026
ee8949e
Add FIXME for `interior_mutability_suggestion`
JohnTitor May 17, 2026
346f43e
Rollup merge of #151742 - moulins:variant-layout, r=saethlin
JonathanBrouwer May 17, 2026
9de8fa9
Rollup merge of #151362 - JohnTitor:interior-mutability-sugg, r=estebank
JonathanBrouwer May 17, 2026
fe32c70
Rollup merge of #156121 - thiago-fealves:suggest-collect-string, r=es…
JonathanBrouwer May 17, 2026
ff42fc0
Rollup merge of #156208 - BorrowSanitizer:codegen-emit-retag-1, r=sae…
JonathanBrouwer May 17, 2026
b0c869a
Rollup merge of #156596 - nnethercote:split-LintExpectation, r=Guilla…
JonathanBrouwer May 17, 2026
7efacb0
Rollup merge of #156607 - mrkajetanp:freebsd-14, r=marcoieni
JonathanBrouwer May 17, 2026
4bb8551
Rollup merge of #156376 - euclio:foreign-escapes, r=mu001999
JonathanBrouwer May 17, 2026
4babf87
Rollup merge of #156577 - AsakuraMizu:eii-default-dynamic, r=mejrs
JonathanBrouwer May 17, 2026
ded0aab
Rollup merge of #156585 - InvalidPathException:llvm-error, r=folkertdev
JonathanBrouwer May 17, 2026
9e8d48c
Rollup merge of #156598 - cijiugechu:decl-macro-diag, r=mu001999
JonathanBrouwer May 17, 2026
06763ba
Rollup merge of #156616 - notriddle:rustdoc-ui-test-cli, r=GuillaumeG…
JonathanBrouwer May 17, 2026
c340b0a
Rollup merge of #156633 - eval-exec:issue-41261-regression-test, r=mu…
JonathanBrouwer May 17, 2026
4cce8bc
Rollup merge of #156635 - bb1yd:rename_unexpected_try_recover, r=John…
JonathanBrouwer May 17, 2026
fc7ac3d
Rollup merge of #156636 - Human9000-bit:mir-transform-ref, r=Kivooeo
JonathanBrouwer May 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 36 additions & 56 deletions compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use tracing::{debug, trace};
use crate::{
AbiAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer,
LayoutData, Niche, NonZeroUsize, NumScalableVectors, Primitive, ReprOptions, Scalar, Size,
StructKind, TagEncoding, TargetDataLayout, Variants, WrappingRange,
StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants, WrappingRange,
};

mod coroutine;
Expand Down Expand Up @@ -589,6 +589,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
}

let calculate_niche_filling_layout = || -> Option<LayoutData<FieldIdx, VariantIdx>> {
struct VariantLayoutInfo {
align_abi: Align,
}

if repr.inhibit_enum_layout_opt() {
return None;
}
Expand All @@ -600,18 +604,22 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
let mut align = dl.aggregate_align;
let mut max_repr_align = repr.align;
let mut unadjusted_abi_align = align;
let mut combined_seed = repr.field_shuffle_seed;

let mut variants_info = IndexVec::<VariantIdx, _>::with_capacity(variants.len());
let mut variant_layouts = variants
.iter_enumerated()
.map(|(j, v)| {
let mut st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?;
st.variants = Variants::Single { index: j };
.iter()
.map(|v| {
let st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?;

variants_info.push(VariantLayoutInfo { align_abi: st.align.abi });

align = align.max(st.align.abi);
max_repr_align = max_repr_align.max(st.max_repr_align);
unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align);
combined_seed = combined_seed.wrapping_add(st.randomization_seed);

Some(st)
Some(VariantLayout::from_layout(st))
})
.collect::<Option<IndexVec<VariantIdx, _>>>()?;

Expand Down Expand Up @@ -649,23 +657,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
}

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

if this_offset + layout.size > size {
return false;
}

// It'll fit, but we need to make some adjustments.
match layout.fields {
FieldsShape::Arbitrary { ref mut offsets, .. } => {
for offset in offsets.iter_mut() {
*offset += this_offset;
}
}
FieldsShape::Primitive | FieldsShape::Array { .. } | FieldsShape::Union(..) => {
panic!("Layout of fields should be Arbitrary for variants")
}
for offset in layout.field_offsets.iter_mut() {
*offset += this_offset;
}

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

let uninhabited = variant_layouts.iter().all(|v| v.is_uninhabited());
let abi = if same_size && same_align && others_zst {
Expand All @@ -710,11 +711,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
BackendRepr::Memory { sized: true }
};

let combined_seed = variant_layouts
.iter()
.map(|v| v.randomization_seed)
.fold(repr.field_shuffle_seed, |acc, seed| acc.wrapping_add(seed));

let layout = LayoutData {
variants: Variants::Multiple {
tag: niche_scalar,
Expand Down Expand Up @@ -807,6 +803,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
let mut align = dl.aggregate_align;
let mut max_repr_align = repr.align;
let mut unadjusted_abi_align = align;
let mut combined_seed = repr.field_shuffle_seed;

let mut size = Size::ZERO;

Expand All @@ -830,14 +827,13 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {

// Create the set of structs that represent each variant.
let mut layout_variants = variants
.iter_enumerated()
.map(|(i, field_layouts)| {
let mut st = self.univariant(
.iter()
.map(|field_layouts| {
let st = self.univariant(
field_layouts,
repr,
StructKind::Prefixed(min_ity.size(), prefix_align),
)?;
st.variants = Variants::Single { index: i };
// Find the first field we can't move later
// to make room for a larger discriminant.
for field_idx in st.fields.index_by_increasing_offset() {
Expand All @@ -851,7 +847,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
align = align.max(st.align.abi);
max_repr_align = max_repr_align.max(st.max_repr_align);
unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align);
Ok(st)
combined_seed = combined_seed.wrapping_add(st.randomization_seed);
Ok(VariantLayout::from_layout(st))
})
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?;

Expand Down Expand Up @@ -906,23 +903,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
let old_ity_size = min_ity.size();
let new_ity_size = ity.size();
for variant in &mut layout_variants {
match variant.fields {
FieldsShape::Arbitrary { ref mut offsets, .. } => {
for i in offsets {
if *i <= old_ity_size {
assert_eq!(*i, old_ity_size);
*i = new_ity_size;
}
}
// We might be making the struct larger.
if variant.size <= old_ity_size {
variant.size = new_ity_size;
}
}
FieldsShape::Primitive | FieldsShape::Array { .. } | FieldsShape::Union(..) => {
panic!("encountered a non-arbitrary layout during enum layout")
for i in &mut variant.field_offsets {
if *i <= old_ity_size {
assert_eq!(*i, old_ity_size);
*i = new_ity_size;
}
}
// We might be making the struct larger.
if variant.size <= old_ity_size {
variant.size = new_ity_size;
}
}
}

Expand All @@ -947,12 +937,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
let mut common_prim = None;
let mut common_prim_initialized_in_all_variants = true;
for (field_layouts, layout_variant) in iter::zip(variants, &layout_variants) {
let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
panic!("encountered a non-arbitrary layout during enum layout");
};
// We skip *all* ZST here and later check if we are good in terms of alignment.
// This lets us handle some cases involving aligned ZST.
let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
let mut fields = iter::zip(field_layouts, &layout_variant.field_offsets)
.filter(|p| !p.0.is_zst());
let (field, offset) = match (fields.next(), fields.next()) {
(None, None) => {
common_prim_initialized_in_all_variants = false;
Expand Down Expand Up @@ -1047,25 +1035,17 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
for variant in &mut layout_variants {
// We only do this for variants with fields; the others are not accessed anyway.
// Also do not overwrite any already existing "clever" ABIs.
if variant.fields.count() > 0
&& matches!(variant.backend_repr, BackendRepr::Memory { .. })
if matches!(variant.backend_repr, BackendRepr::Memory { .. } if variant.has_fields())
{
variant.backend_repr = abi;
// Also need to bump up the size and alignment, so that the entire value fits
// in here.
// Also need to bump up the size, so that the entire value fits in here.
variant.size = cmp::max(variant.size, size);
variant.align.abi = cmp::max(variant.align.abi, align);
}
}
}

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

let combined_seed = layout_variants
.iter()
.map(|v| v.randomization_seed)
.fold(repr.field_shuffle_seed, |acc, seed| acc.wrapping_add(seed));

let tagged_layout = LayoutData {
variants: Variants::Multiple {
tag,
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_abi/src/layout/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use tracing::{debug, trace};

use crate::{
BackendRepr, FieldsShape, HasDataLayout, Integer, LayoutData, Primitive, ReprOptions, Scalar,
StructKind, TagEncoding, Variants, WrappingRange,
StructKind, TagEncoding, VariantLayout, Variants, WrappingRange,
};

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

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

size = size.max(variant.size);
align = align.max(variant.align);
Ok(variant)
Ok(VariantLayout::from_layout(variant))
})
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?;

Expand Down
28 changes: 28 additions & 0 deletions compiler/rustc_abi/src/layout/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,34 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align,
// Variant layouts never flow back into actual layout computations,
// so dummy values are fine here.
randomization_seed: Hash64::ZERO,
}
}

/// Returns a layout for an inhabited variant.
pub fn for_variant(parent: &Self, index: VariantIdx) -> Self {
let layout = match &parent.variants {
Variants::Multiple { variants, .. } => &variants[index],
_ => panic!("Expected multi-variant layout in `Layout::for_variant`"),
};

Self {
fields: FieldsShape::Arbitrary {
offsets: layout.field_offsets.clone(),
in_memory_order: layout.fields_in_memory_order.clone(),
},
variants: Variants::Single { index },
backend_repr: layout.backend_repr,
largest_niche: layout.largest_niche,
uninhabited: layout.uninhabited,
size: layout.size,
align: parent.align,
max_repr_align: parent.max_repr_align,
unadjusted_abi_align: parent.unadjusted_abi_align,
// Variant layouts never flow back into actual layout computations,
// so dummy values are fine here.
randomization_seed: Hash64::ZERO,
}
}
Expand Down
39 changes: 38 additions & 1 deletion compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1953,7 +1953,7 @@ pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
tag: Scalar,
tag_encoding: TagEncoding<VariantIdx>,
tag_field: FieldIdx,
variants: IndexVec<VariantIdx, LayoutData<FieldIdx, VariantIdx>>,
variants: IndexVec<VariantIdx, VariantLayout<FieldIdx>>,
},
}

Expand Down Expand Up @@ -2319,3 +2319,40 @@ pub enum AbiFromStrErr {
/// no "-unwind" variant can be used here
NoExplicitUnwind,
}

// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub struct VariantLayout<FieldIdx: Idx> {
pub size: Size,
pub backend_repr: BackendRepr,
pub field_offsets: IndexVec<FieldIdx, Size>,
fields_in_memory_order: IndexVec<u32, FieldIdx>,
largest_niche: Option<Niche>,
uninhabited: bool,
}

impl<FieldIdx: Idx> VariantLayout<FieldIdx> {
pub fn from_layout(layout: LayoutData<FieldIdx, impl Idx>) -> Self {
let FieldsShape::Arbitrary { offsets, in_memory_order } = layout.fields else {
panic!("Layout of fields should be Arbitrary for variants");
};

Self {
size: layout.size,
backend_repr: layout.backend_repr,
field_offsets: offsets,
fields_in_memory_order: in_memory_order,
largest_niche: layout.largest_niche,
uninhabited: layout.uninhabited,
}
}

pub fn is_uninhabited(&self) -> bool {
self.uninhabited
}

pub fn has_fields(&self) -> bool {
self.field_offsets.len() > 0
}
}
10 changes: 9 additions & 1 deletion compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use std::iter;

use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp};
use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::base::wants_msvc_seh;
use rustc_codegen_ssa::common::IntPredicate;
use rustc_codegen_ssa::errors::InvalidMonomorphization;
Expand All @@ -18,6 +17,7 @@ use rustc_codegen_ssa::traits::{
ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods,
IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods,
};
use rustc_codegen_ssa::{MemFlags, RetagInfo};
use rustc_data_structures::fx::FxHashSet;
#[cfg(feature = "master")]
use rustc_middle::ty::layout::FnAbiOf;
Expand Down Expand Up @@ -702,6 +702,14 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
// FIXME(antoyo): implement.
self.context.new_rvalue_from_int(self.int_type, 0)
}

fn retag_reg(&mut self, _ptr: Self::Value, _info: &RetagInfo<Self::Value>) -> Self::Value {
unimplemented!()
}

fn retag_mem(&mut self, _ptr: Self::Value, _info: &RetagInfo<Self::Value>) {
unimplemented!()
}
}

impl<'a, 'gcc, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
Expand Down
Loading
Loading