Skip to content

Commit 7001432

Browse files
authored
Rollup merge of rust-lang#136985 - zachs18:backend-repr-remove-uninhabited, r=workingjubilee
Do not ignore uninhabited types for function-call ABI purposes. (Remove BackendRepr::Uninhabited) Accepted MCP: rust-lang/compiler-team#832 Fixes rust-lang#135802 Do not consider the inhabitedness of a type for function call ABI purposes. * Remove the [`rustc_abi::BackendRepr::Uninhabited`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_abi/enum.BackendRepr.html) variant * Instead calculate the `BackendRepr` of uninhabited types "normally" (as though they were not uninhabited "at the top level", but still considering inhabitedness of variants to determine enum layout, etc) * Add an `uninhabited: bool` field to [`rustc_abi::LayoutData`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_abi/struct.LayoutData.html) so inhabitedness of a `LayoutData` can still be queried when necessary (e.g. when determining if an enum variant needs a tag value allocated to it). This should not affect type layouts (size/align/field offset); this should only affect function call ABI, and only of uninhabited types. cc ``@RalfJung``
2 parents a7ada04 + 85fe2b1 commit 7001432

Some content is hidden

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

49 files changed

+525
-162
lines changed

compiler/rustc_abi/src/callconv.rs

-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
6565
Ty: TyAbiInterface<'a, C> + Copy,
6666
{
6767
match self.backend_repr {
68-
BackendRepr::Uninhabited => Err(Heterogeneous),
69-
7068
// The primitive for this algorithm.
7169
BackendRepr::Scalar(scalar) => {
7270
let kind = match scalar.primitive() {

compiler/rustc_abi/src/layout.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
130130
},
131131
backend_repr: BackendRepr::ScalarPair(a, b),
132132
largest_niche,
133+
uninhabited: false,
133134
align,
134135
size,
135136
max_repr_align: None,
@@ -221,8 +222,9 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
221222
LayoutData {
222223
variants: Variants::Empty,
223224
fields: FieldsShape::Primitive,
224-
backend_repr: BackendRepr::Uninhabited,
225+
backend_repr: BackendRepr::Memory { sized: true },
225226
largest_niche: None,
227+
uninhabited: true,
226228
align: dl.i8_align,
227229
size: Size::ZERO,
228230
max_repr_align: None,
@@ -400,6 +402,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
400402
fields: FieldsShape::Union(union_field_count),
401403
backend_repr: abi,
402404
largest_niche: None,
405+
uninhabited: false,
403406
align,
404407
size: size.align_to(align.abi),
405408
max_repr_align,
@@ -447,7 +450,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
447450
Scalar::Union { .. } => {}
448451
};
449452
match &mut st.backend_repr {
450-
BackendRepr::Uninhabited => {}
451453
BackendRepr::Scalar(scalar) => hide_niches(scalar),
452454
BackendRepr::ScalarPair(a, b) => {
453455
hide_niches(a);
@@ -639,9 +641,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
639641
let same_size = size == variant_layouts[largest_variant_index].size;
640642
let same_align = align == variant_layouts[largest_variant_index].align;
641643

642-
let abi = if variant_layouts.iter().all(|v| v.is_uninhabited()) {
643-
BackendRepr::Uninhabited
644-
} else if same_size && same_align && others_zst {
644+
let uninhabited = variant_layouts.iter().all(|v| v.is_uninhabited());
645+
let abi = if same_size && same_align && others_zst {
645646
match variant_layouts[largest_variant_index].backend_repr {
646647
// When the total alignment and size match, we can use the
647648
// same ABI as the scalar variant with the reserved niche.
@@ -683,6 +684,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
683684
},
684685
backend_repr: abi,
685686
largest_niche,
687+
uninhabited,
686688
size,
687689
align,
688690
max_repr_align,
@@ -853,9 +855,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
853855
};
854856
let mut abi = BackendRepr::Memory { sized: true };
855857

856-
if layout_variants.iter().all(|v| v.is_uninhabited()) {
857-
abi = BackendRepr::Uninhabited;
858-
} else if tag.size(dl) == size {
858+
let uninhabited = layout_variants.iter().all(|v| v.is_uninhabited());
859+
if tag.size(dl) == size {
859860
// Make sure we only use scalar layout when the enum is entirely its
860861
// own tag (i.e. it has no padding nor any non-ZST variant fields).
861862
abi = BackendRepr::Scalar(tag);
@@ -995,6 +996,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
995996
memory_index: [0].into(),
996997
},
997998
largest_niche,
999+
uninhabited,
9981000
backend_repr: abi,
9991001
align,
10001002
size,
@@ -1355,9 +1357,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
13551357
_ => {}
13561358
}
13571359
}
1358-
if fields.iter().any(|f| f.is_uninhabited()) {
1359-
abi = BackendRepr::Uninhabited;
1360-
}
1360+
let uninhabited = fields.iter().any(|f| f.is_uninhabited());
13611361

13621362
let unadjusted_abi_align = if repr.transparent() {
13631363
match layout_of_single_non_zst_field {
@@ -1378,6 +1378,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
13781378
fields: FieldsShape::Arbitrary { offsets, memory_index },
13791379
backend_repr: abi,
13801380
largest_niche,
1381+
uninhabited,
13811382
align,
13821383
size,
13831384
max_repr_align,

compiler/rustc_abi/src/lib.rs

+16-19
Original file line numberDiff line numberDiff line change
@@ -1404,7 +1404,6 @@ impl AddressSpace {
14041404
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
14051405
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
14061406
pub enum BackendRepr {
1407-
Uninhabited,
14081407
Scalar(Scalar),
14091408
ScalarPair(Scalar, Scalar),
14101409
Vector {
@@ -1423,10 +1422,9 @@ impl BackendRepr {
14231422
#[inline]
14241423
pub fn is_unsized(&self) -> bool {
14251424
match *self {
1426-
BackendRepr::Uninhabited
1427-
| BackendRepr::Scalar(_)
1428-
| BackendRepr::ScalarPair(..)
1429-
| BackendRepr::Vector { .. } => false,
1425+
BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => {
1426+
false
1427+
}
14301428
BackendRepr::Memory { sized } => !sized,
14311429
}
14321430
}
@@ -1445,12 +1443,6 @@ impl BackendRepr {
14451443
}
14461444
}
14471445

1448-
/// Returns `true` if this is an uninhabited type
1449-
#[inline]
1450-
pub fn is_uninhabited(&self) -> bool {
1451-
matches!(*self, BackendRepr::Uninhabited)
1452-
}
1453-
14541446
/// Returns `true` if this is a scalar type
14551447
#[inline]
14561448
pub fn is_scalar(&self) -> bool {
@@ -1471,7 +1463,7 @@ impl BackendRepr {
14711463
BackendRepr::Vector { element, count } => {
14721464
cx.data_layout().vector_align(element.size(cx) * count)
14731465
}
1474-
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None,
1466+
BackendRepr::Memory { .. } => return None,
14751467
})
14761468
}
14771469

@@ -1492,7 +1484,7 @@ impl BackendRepr {
14921484
// to make the size a multiple of align (e.g. for vectors of size 3).
14931485
(element.size(cx) * count).align_to(self.inherent_align(cx)?.abi)
14941486
}
1495-
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None,
1487+
BackendRepr::Memory { .. } => return None,
14961488
})
14971489
}
14981490

@@ -1506,9 +1498,7 @@ impl BackendRepr {
15061498
BackendRepr::Vector { element, count } => {
15071499
BackendRepr::Vector { element: element.to_union(), count }
15081500
}
1509-
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
1510-
BackendRepr::Memory { sized: true }
1511-
}
1501+
BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true },
15121502
}
15131503
}
15141504

@@ -1704,6 +1694,11 @@ pub struct LayoutData<FieldIdx: Idx, VariantIdx: Idx> {
17041694
/// The leaf scalar with the largest number of invalid values
17051695
/// (i.e. outside of its `valid_range`), if it exists.
17061696
pub largest_niche: Option<Niche>,
1697+
/// Is this type known to be uninhabted?
1698+
///
1699+
/// This is separate from BackendRepr because uninhabited return types can affect ABI,
1700+
/// especially in the case of by-pointer struct returns, which allocate stack even when unused.
1701+
pub uninhabited: bool,
17071702

17081703
pub align: AbiAndPrefAlign,
17091704
pub size: Size,
@@ -1735,14 +1730,14 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
17351730
/// Returns `true` if this is an aggregate type (including a ScalarPair!)
17361731
pub fn is_aggregate(&self) -> bool {
17371732
match self.backend_repr {
1738-
BackendRepr::Uninhabited | BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false,
1733+
BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false,
17391734
BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => true,
17401735
}
17411736
}
17421737

17431738
/// Returns `true` if this is an uninhabited type
17441739
pub fn is_uninhabited(&self) -> bool {
1745-
self.backend_repr.is_uninhabited()
1740+
self.uninhabited
17461741
}
17471742

17481743
pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
@@ -1778,6 +1773,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
17781773
fields: FieldsShape::Primitive,
17791774
backend_repr: BackendRepr::Scalar(scalar),
17801775
largest_niche,
1776+
uninhabited: false,
17811777
size,
17821778
align,
17831779
max_repr_align: None,
@@ -1802,6 +1798,7 @@ where
18021798
backend_repr,
18031799
fields,
18041800
largest_niche,
1801+
uninhabited,
18051802
variants,
18061803
max_repr_align,
18071804
unadjusted_abi_align,
@@ -1813,6 +1810,7 @@ where
18131810
.field("abi", backend_repr)
18141811
.field("fields", fields)
18151812
.field("largest_niche", largest_niche)
1813+
.field("uninhabited", uninhabited)
18161814
.field("variants", variants)
18171815
.field("max_repr_align", max_repr_align)
18181816
.field("unadjusted_abi_align", unadjusted_abi_align)
@@ -1877,7 +1875,6 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
18771875
BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => {
18781876
false
18791877
}
1880-
BackendRepr::Uninhabited => self.size.bytes() == 0,
18811878
BackendRepr::Memory { sized } => sized && self.size.bytes() == 0,
18821879
}
18831880
}

compiler/rustc_codegen_cranelift/src/value_and_place.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -638,9 +638,7 @@ impl<'tcx> CPlace<'tcx> {
638638
}
639639
CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self),
640640
CPlaceInner::Addr(to_ptr, None) => {
641-
if dst_layout.size == Size::ZERO
642-
|| dst_layout.backend_repr == BackendRepr::Uninhabited
643-
{
641+
if dst_layout.size == Size::ZERO {
644642
return;
645643
}
646644

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
310310
let layout = self.layout_of(tp_ty).layout;
311311
let _use_integer_compare = match layout.backend_repr() {
312312
Scalar(_) | ScalarPair(_, _) => true,
313-
Uninhabited | Vector { .. } => false,
313+
Vector { .. } => false,
314314
Memory { .. } => {
315315
// For rusty ABIs, small aggregates are actually passed
316316
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),

compiler/rustc_codegen_gcc/src/type_of.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
8484
false,
8585
);
8686
}
87-
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {}
87+
BackendRepr::Memory { .. } => {}
8888
}
8989

9090
let name = match *layout.ty.kind() {
@@ -179,19 +179,16 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
179179
fn is_gcc_immediate(&self) -> bool {
180180
match self.backend_repr {
181181
BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true,
182-
BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
183-
false
184-
}
182+
BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
185183
}
186184
}
187185

188186
fn is_gcc_scalar_pair(&self) -> bool {
189187
match self.backend_repr {
190188
BackendRepr::ScalarPair(..) => true,
191-
BackendRepr::Uninhabited
192-
| BackendRepr::Scalar(_)
193-
| BackendRepr::Vector { .. }
194-
| BackendRepr::Memory { .. } => false,
189+
BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => {
190+
false
191+
}
195192
}
196193
}
197194

compiler/rustc_codegen_llvm/src/intrinsic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
475475
let layout = self.layout_of(tp_ty).layout;
476476
let use_integer_compare = match layout.backend_repr() {
477477
Scalar(_) | ScalarPair(_, _) => true,
478-
Uninhabited | Vector { .. } => false,
478+
Vector { .. } => false,
479479
Memory { .. } => {
480480
// For rusty ABIs, small aggregates are actually passed
481481
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),

compiler/rustc_codegen_llvm/src/type_of.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn uncached_llvm_type<'a, 'tcx>(
2323
let element = layout.scalar_llvm_type_at(cx, element);
2424
return cx.type_vector(element, count);
2525
}
26-
BackendRepr::Uninhabited | BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}
26+
BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}
2727
}
2828

2929
let name = match layout.ty.kind() {
@@ -172,19 +172,16 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
172172
fn is_llvm_immediate(&self) -> bool {
173173
match self.backend_repr {
174174
BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true,
175-
BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
176-
false
177-
}
175+
BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
178176
}
179177
}
180178

181179
fn is_llvm_scalar_pair(&self) -> bool {
182180
match self.backend_repr {
183181
BackendRepr::ScalarPair(..) => true,
184-
BackendRepr::Uninhabited
185-
| BackendRepr::Scalar(_)
186-
| BackendRepr::Vector { .. }
187-
| BackendRepr::Memory { .. } => false,
182+
BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => {
183+
false
184+
}
188185
}
189186
}
190187

compiler/rustc_codegen_ssa/src/mir/block.rs

+7-21
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, WrappingRange};
44
use rustc_ast as ast;
55
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
66
use rustc_hir::lang_items::LangItem;
7-
use rustc_middle::mir::{
8-
self, AssertKind, BasicBlock, InlineAsmMacro, SwitchTargets, UnwindTerminateReason,
9-
};
7+
use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
108
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
119
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
1210
use rustc_middle::ty::{self, Instance, Ty};
@@ -919,7 +917,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
919917
&fn_abi.ret,
920918
&mut llargs,
921919
Some(intrinsic),
922-
target,
923920
);
924921
let dest = match ret_dest {
925922
_ if fn_abi.ret.is_indirect() => llargs[0],
@@ -975,19 +972,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
975972
};
976973

977974
let mut llargs = Vec::with_capacity(arg_count);
978-
let destination = target.as_ref().map(|&target| {
979-
(
980-
self.make_return_dest(
981-
bx,
982-
destination,
983-
&fn_abi.ret,
984-
&mut llargs,
985-
None,
986-
Some(target),
987-
),
988-
target,
989-
)
990-
});
975+
976+
// We still need to call `make_return_dest` even if there's no `target`, since
977+
// `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited,
978+
// and `make_return_dest` adds the return-place indirect pointer to `llargs`.
979+
let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, None);
980+
let destination = target.map(|target| (return_dest, target));
991981

992982
// Split the rust-call tupled arguments off.
993983
let (first_args, untuple) = if abi == ExternAbi::RustCall && !args.is_empty() {
@@ -1790,11 +1780,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
17901780
fn_ret: &ArgAbi<'tcx, Ty<'tcx>>,
17911781
llargs: &mut Vec<Bx::Value>,
17921782
intrinsic: Option<ty::IntrinsicDef>,
1793-
target: Option<BasicBlock>,
17941783
) -> ReturnDest<'tcx, Bx::Value> {
1795-
if target.is_none() {
1796-
return ReturnDest::Nothing;
1797-
}
17981784
// If the return is ignored, we can just return a do-nothing `ReturnDest`.
17991785
if fn_ret.is_ignore() {
18001786
return ReturnDest::Nothing;

compiler/rustc_codegen_ssa/src/mir/operand.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
415415
bx.store(*llval, llptr, field.align.abi);
416416
*llval = bx.load(llfield_ty, llptr, field.align.abi);
417417
}
418-
(
419-
OperandValue::Immediate(_),
420-
BackendRepr::Uninhabited | BackendRepr::Memory { sized: false },
421-
) => {
418+
(OperandValue::Immediate(_), BackendRepr::Memory { sized: false }) => {
422419
bug!()
423420
}
424421
(OperandValue::Pair(..), _) => bug!(),

0 commit comments

Comments
 (0)