Skip to content

Commit 8f081d5

Browse files
committed
rustc_target::abi: add Primitive variant to FieldsShape.
1 parent 4e4d49d commit 8f081d5

File tree

10 files changed

+59
-23
lines changed

10 files changed

+59
-23
lines changed

src/librustc_codegen_llvm/type_of.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ fn uncached_llvm_type<'a, 'tcx>(
8181
};
8282

8383
match layout.fields {
84-
FieldsShape::Union(_) => {
84+
FieldsShape::Primitive | FieldsShape::Union(_) => {
8585
let fill = cx.type_padding_filler(layout.size, layout.align.abi);
8686
let packed = false;
8787
match name {
@@ -368,7 +368,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
368368
_ => {}
369369
}
370370
match self.fields {
371-
FieldsShape::Union(_) => {
371+
FieldsShape::Primitive | FieldsShape::Union(_) => {
372372
bug!("TyAndLayout::llvm_field_index({:?}): not applicable", self)
373373
}
374374

src/librustc_data_structures/stable_hasher.rs

+6
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ impl<CTX> HashStable<CTX> for ::std::num::NonZeroU32 {
210210
}
211211
}
212212

213+
impl<CTX> HashStable<CTX> for ::std::num::NonZeroUsize {
214+
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
215+
self.get().hash_stable(ctx, hasher)
216+
}
217+
}
218+
213219
impl<CTX> HashStable<CTX> for f32 {
214220
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
215221
let val: u32 = unsafe { ::std::mem::transmute(*self) };

src/librustc_middle/ty/layout.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use std::cmp;
2222
use std::fmt;
2323
use std::iter;
2424
use std::mem;
25+
use std::num::NonZeroUsize;
2526
use std::ops::Bound;
2627

2728
pub trait IntegerExt {
@@ -518,7 +519,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
518519
// The never type.
519520
ty::Never => tcx.intern_layout(Layout {
520521
variants: Variants::Single { index: VariantIdx::new(0) },
521-
fields: FieldsShape::Union(0),
522+
fields: FieldsShape::Primitive,
522523
abi: Abi::Uninhabited,
523524
largest_niche: None,
524525
align: dl.i8_align,
@@ -744,7 +745,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
744745

745746
return Ok(tcx.intern_layout(Layout {
746747
variants: Variants::Single { index },
747-
fields: FieldsShape::Union(variants[index].len()),
748+
fields: FieldsShape::Union(
749+
NonZeroUsize::new(variants[index].len())
750+
.ok_or(LayoutError::Unknown(ty))?,
751+
),
748752
abi,
749753
largest_niche: None,
750754
align,
@@ -1988,7 +1992,7 @@ where
19881992
if index == variant_index &&
19891993
// Don't confuse variants of uninhabited enums with the enum itself.
19901994
// For more details see https://github.com/rust-lang/rust/issues/69763.
1991-
this.fields != FieldsShape::Union(0) =>
1995+
this.fields != FieldsShape::Primitive =>
19921996
{
19931997
this.layout
19941998
}
@@ -2006,7 +2010,10 @@ where
20062010
let tcx = cx.tcx();
20072011
tcx.intern_layout(Layout {
20082012
variants: Variants::Single { index: variant_index },
2009-
fields: FieldsShape::Union(fields),
2013+
fields: match NonZeroUsize::new(fields) {
2014+
Some(fields) => FieldsShape::Union(fields),
2015+
None => FieldsShape::Arbitrary { offsets: vec![], memory_index: vec![] },
2016+
},
20102017
abi: Abi::Uninhabited,
20112018
largest_niche: None,
20122019
align: tcx.data_layout.i8_align,

src/librustc_mir/interpret/validity.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
use std::convert::TryFrom;
88
use std::fmt::Write;
9+
use std::num::NonZeroUsize;
910
use std::ops::RangeInclusive;
1011

1112
use rustc_data_structures::fx::FxHashSet;
@@ -642,10 +643,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
642643
}
643644

644645
#[inline(always)]
645-
fn visit_union(&mut self, op: OpTy<'tcx, M::PointerTag>, fields: usize) -> InterpResult<'tcx> {
646-
// Empty unions are not accepted by rustc. But uninhabited enums
647-
// claim to be unions, so allow them, too.
648-
assert!(op.layout.abi.is_uninhabited() || fields > 0);
646+
fn visit_union(
647+
&mut self,
648+
_op: OpTy<'tcx, M::PointerTag>,
649+
_fields: NonZeroUsize,
650+
) -> InterpResult<'tcx> {
649651
Ok(())
650652
}
651653

src/librustc_mir/interpret/visitor.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use rustc_middle::ty;
66
use rustc_middle::ty::layout::TyAndLayout;
77
use rustc_target::abi::{FieldsShape, VariantIdx, Variants};
88

9+
use std::num::NonZeroUsize;
10+
911
use super::{InterpCx, MPlaceTy, Machine, OpTy};
1012

1113
// A thing that we can project into, and that has a layout.
@@ -130,7 +132,7 @@ macro_rules! make_value_visitor {
130132
}
131133
/// Visits the given value as a union. No automatic recursion can happen here.
132134
#[inline(always)]
133-
fn visit_union(&mut self, _v: Self::V, _fields: usize) -> InterpResult<'tcx>
135+
fn visit_union(&mut self, _v: Self::V, _fields: NonZeroUsize) -> InterpResult<'tcx>
134136
{
135137
Ok(())
136138
}
@@ -208,6 +210,7 @@ macro_rules! make_value_visitor {
208210

209211
// Visit the fields of this value.
210212
match v.layout().fields {
213+
FieldsShape::Primitive => {},
211214
FieldsShape::Union(fields) => {
212215
self.visit_union(v, fields)?;
213216
},

src/librustc_target/abi/call/mips64.rs

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ where
8888
let mut prefix_index = 0;
8989

9090
match arg.layout.fields {
91+
abi::FieldsShape::Primitive => unreachable!(),
9192
abi::FieldsShape::Array { .. } => {
9293
// Arrays are passed indirectly
9394
arg.make_indirect();

src/librustc_target/abi/call/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -308,13 +308,16 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
308308
}
309309

310310
Abi::ScalarPair(..) | Abi::Aggregate { .. } => {
311-
// Helper for computing `homogenous_aggregate`, allowing a custom
311+
// Helper for computing `homogeneous_aggregate`, allowing a custom
312312
// starting offset (used below for handling variants).
313313
let from_fields_at =
314314
|layout: Self,
315315
start: Size|
316316
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
317317
let is_union = match layout.fields {
318+
FieldsShape::Primitive => {
319+
unreachable!("aggregates can't have `FieldsShape::Primitive`")
320+
}
318321
FieldsShape::Array { count, .. } => {
319322
assert_eq!(start, Size::ZERO);
320323

src/librustc_target/abi/call/riscv.rs

+3
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ where
8787
},
8888
Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv),
8989
Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields {
90+
FieldsShape::Primitive => {
91+
unreachable!("aggregates can't have `FieldsShape::Primitive`")
92+
}
9093
FieldsShape::Union(_) => {
9194
if !arg_layout.is_zst() {
9295
return Err(CannotUseFpConv);

src/librustc_target/abi/mod.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub use Primitive::*;
44
use crate::spec::Target;
55

66
use std::convert::{TryFrom, TryInto};
7+
use std::num::NonZeroUsize;
78
use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub};
89

910
use rustc_index::vec::{Idx, IndexVec};
@@ -619,10 +620,11 @@ impl Scalar {
619620
/// Describes how the fields of a type are located in memory.
620621
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
621622
pub enum FieldsShape {
623+
/// Scalar primitives and `!`, which never have fields.
624+
Primitive,
625+
622626
/// All fields start at no offset. The `usize` is the field count.
623-
///
624-
/// In the case of primitives the number of fields is `0`.
625-
Union(usize),
627+
Union(NonZeroUsize),
626628

627629
/// Array/vector-like placement, with all fields of identical types.
628630
Array { stride: Size, count: u64 },
@@ -660,7 +662,8 @@ pub enum FieldsShape {
660662
impl FieldsShape {
661663
pub fn count(&self) -> usize {
662664
match *self {
663-
FieldsShape::Union(count) => count,
665+
FieldsShape::Primitive => 0,
666+
FieldsShape::Union(count) => count.get(),
664667
FieldsShape::Array { count, .. } => {
665668
let usize_count = count as usize;
666669
assert_eq!(usize_count as u64, count);
@@ -672,8 +675,16 @@ impl FieldsShape {
672675

673676
pub fn offset(&self, i: usize) -> Size {
674677
match *self {
678+
FieldsShape::Primitive => {
679+
unreachable!("FieldsShape::offset: `Primitive`s have no fields")
680+
}
675681
FieldsShape::Union(count) => {
676-
assert!(i < count, "tried to access field {} of union with {} fields", i, count);
682+
assert!(
683+
i < count.get(),
684+
"tried to access field {} of union with {} fields",
685+
i,
686+
count
687+
);
677688
Size::ZERO
678689
}
679690
FieldsShape::Array { stride, count } => {
@@ -687,6 +698,9 @@ impl FieldsShape {
687698

688699
pub fn memory_index(&self, i: usize) -> usize {
689700
match *self {
701+
FieldsShape::Primitive => {
702+
unreachable!("FieldsShape::memory_index: `Primitive`s have no fields")
703+
}
690704
FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
691705
FieldsShape::Arbitrary { ref memory_index, .. } => {
692706
let r = memory_index[i];
@@ -718,7 +732,7 @@ impl FieldsShape {
718732
}
719733

720734
(0..self.count()).map(move |i| match *self {
721-
FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
735+
FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
722736
FieldsShape::Arbitrary { .. } => {
723737
if use_small {
724738
inverse_small[i] as usize
@@ -887,7 +901,6 @@ impl Niche {
887901
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
888902
pub struct Layout {
889903
/// Says where the fields are located within the layout.
890-
/// Primitives and uninhabited enums appear as unions without fields.
891904
pub fields: FieldsShape,
892905

893906
/// Encodes information about multi-variant layouts.
@@ -923,7 +936,7 @@ impl Layout {
923936
let align = scalar.value.align(cx);
924937
Layout {
925938
variants: Variants::Single { index: VariantIdx::new(0) },
926-
fields: FieldsShape::Union(0),
939+
fields: FieldsShape::Primitive,
927940
abi: Abi::Scalar(scalar),
928941
largest_niche,
929942
size,

src/test/ui/layout/debug.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,7 @@ LL | type Test = Result<i32, i32>;
316316
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
317317

318318
error: layout_of(i32) = Layout {
319-
fields: Union(
320-
0,
321-
),
319+
fields: Primitive,
322320
variants: Single {
323321
index: 0,
324322
},

0 commit comments

Comments
 (0)