Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions compiler/rustc_abi/src/callconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
start: Size|
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
let is_union = match layout.fields {
FieldsShape::Opaque => return Err(Heterogeneous),
FieldsShape::Primitive => {
unreachable!("aggregates can't have `FieldsShape::Primitive`")
}
Expand Down Expand Up @@ -148,6 +149,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;

match &self.variants {
Variants::Opaque => return Err(Heterogeneous),
Variants::Single { .. } | Variants::Empty => {}
Variants::Multiple { variants, .. } => {
// Treat enum variants like union members.
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1121,9 +1121,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
use rand::seq::SliceRandom;
// `ReprOptions.field_shuffle_seed` is a deterministic seed we can use to randomize field
// ordering.
let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64(
field_seed.wrapping_add(repr.field_shuffle_seed).as_u64(),
);
let rng_seed = field_seed.wrapping_add(repr.field_shuffle_seed).as_u64();
let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64(rng_seed);

// Shuffle the ordering of the fields.
optimizing.shuffle(&mut rng);
Expand Down Expand Up @@ -1373,6 +1372,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
offsets
}
FieldsShape::Primitive
| FieldsShape::Opaque
| FieldsShape::Array { .. }
| FieldsShape::Union(..) => {
panic!("encountered a non-arbitrary layout during enum layout")
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_abi/src/layout/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug + std::fmt::Display {
cx: &C,
offset: Size,
) -> Option<PointeeInfo>;
fn is_erased_ty(this: TyAndLayout<'a, Self>) -> bool;
fn is_adt(this: TyAndLayout<'a, Self>) -> bool;
fn is_enum(this: TyAndLayout<'a, Self>) -> bool;
fn is_never(this: TyAndLayout<'a, Self>) -> bool;
Expand Down Expand Up @@ -377,9 +378,9 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
{
match self.variants {
Variants::Multiple { .. } => true,
Variants::Empty => false,
Variants::Opaque | Variants::Empty => false,
Variants::Single { .. } => match &self.fields {
FieldsShape::Primitive | FieldsShape::Union(_) => false,
FieldsShape::Opaque | FieldsShape::Primitive | FieldsShape::Union(_) => false,
FieldsShape::Array { count, .. } => {
*count > 0 && self.field(cx, 0).has_variant_dependent_padding(cx)
}
Expand Down Expand Up @@ -474,7 +475,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {

// Visit the fields of this value. For enum values the fields include the discriminant.
match &self.fields {
FieldsShape::Primitive => {
FieldsShape::Opaque | FieldsShape::Primitive => {
out.add_range(base_offset, self.size);
}
&FieldsShape::Union(field_count) => {
Expand Down Expand Up @@ -507,7 +508,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {

// Visit the fields of each variant.
match &self.variants {
Variants::Empty | Variants::Single { index: _ } => { /* done */ }
Variants::Opaque | Variants::Empty | Variants::Single { index: _ } => { /* done */ }
Variants::Multiple { variants, .. } => {
for variant in variants.indices() {
let variant = self.for_variant(cx, variant);
Expand Down
67 changes: 52 additions & 15 deletions compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1224,7 +1224,7 @@ impl Align {
///
/// An example of a rare thing actually affected by preferred alignment is aligning of statics.
/// It is of effectively no consequence for layout in structs and on the stack.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub struct AbiAlign {
pub abi: Align,
Expand Down Expand Up @@ -1416,7 +1416,18 @@ impl Integer {
}

/// Floating-point types.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Debug,
Encodable_NoContext,
Decodable_NoContext
)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub enum Float {
F16,
Expand Down Expand Up @@ -1503,7 +1514,7 @@ impl Numeric {
}

/// Fundamental unit of memory access and layout.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub enum Primitive {
/// The `bool` is the signedness of the `Integer` type.
Expand Down Expand Up @@ -1570,7 +1581,7 @@ impl Primitive {
}

/// Information about one scalar component of a Rust type.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub enum Scalar {
Initialized {
Expand Down Expand Up @@ -1696,9 +1707,12 @@ impl Scalar {

// NOTE: This struct is generic over the FieldIdx for rust-analyzer usage.
/// Describes how the fields of a type are located in memory.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
#[derive(PartialEq, Eq, Hash, Clone, Debug, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub enum FieldsShape<FieldIdx: Idx> {
/// There may or may not be fields, and we know nothing about them. Used for `ty::Erased`.
Opaque,

/// Scalar primitives and `!`, which never have fields.
Primitive,

Expand Down Expand Up @@ -1737,6 +1751,7 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
#[inline]
pub fn count(&self) -> usize {
match *self {
FieldsShape::Opaque => 0,
FieldsShape::Primitive => 0,
FieldsShape::Union(count) => count.get(),
FieldsShape::Array { count, .. } => count.try_into().unwrap(),
Expand All @@ -1747,6 +1762,9 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
#[inline]
pub fn offset(&self, i: usize) -> Size {
match *self {
FieldsShape::Opaque => {
unreachable!("FieldsShape::offset: `Opaque`s have no fields")
}
FieldsShape::Primitive => {
unreachable!("FieldsShape::offset: `Primitive`s have no fields")
}
Expand All @@ -1769,10 +1787,14 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
// Primitives don't really have fields in the way that structs do,
// but having this return an empty iterator for them is unhelpful
// since that makes them look kinda like ZSTs, which they're not.
let pseudofield_count = if let FieldsShape::Primitive = self { 1 } else { self.count() };
let pseudofield_count =
if let FieldsShape::Primitive | FieldsShape::Opaque = self { 1 } else { self.count() };

(0..pseudofield_count).map(move |i| match self {
FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
FieldsShape::Primitive
| FieldsShape::Opaque
| FieldsShape::Union(_)
| FieldsShape::Array { .. } => i,
FieldsShape::Arbitrary { in_memory_order, .. } => in_memory_order[i as u32].index(),
})
}
Expand All @@ -1781,7 +1803,18 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
/// An identifier that specifies the address space that some operation
/// should operate on. Special address spaces have an effect on code generation,
/// depending on the target and the address spaces it implements.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(
Copy,
Clone,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Encodable_NoContext,
Decodable_NoContext
)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub struct AddressSpace(pub u32);

Expand All @@ -1798,7 +1831,7 @@ impl AddressSpace {
}

/// How many scalable vectors are in a `BackendRepr::ScalableVector`?
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub struct NumScalableVectors(pub u8);

Expand Down Expand Up @@ -1847,7 +1880,7 @@ impl IntoDiagArg for NumScalableVectors {
///
/// Generally, a codegen backend will prefer to handle smaller values as a scalar or short vector,
/// and larger values will usually prefer to be represented as memory.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub enum BackendRepr {
Scalar(Scalar),
Expand Down Expand Up @@ -2027,9 +2060,12 @@ impl BackendRepr {

/// Describes the variants of a type.
// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
#[derive(PartialEq, Eq, Hash, Clone, Debug, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
/// We don't know how many variants there are, nor anything about them.
Opaque,

/// The type has no valid variants. Must be uninhabited.
///
/// This is the case for:
Expand Down Expand Up @@ -2069,7 +2105,7 @@ pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
}

// NOTE: This struct is generic over the VariantIdx for rust-analyzer usage.
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub enum TagEncoding<VariantIdx: Idx> {
/// The tag directly stores the discriminant, but possibly with a smaller layout
Expand Down Expand Up @@ -2110,7 +2146,7 @@ pub enum TagEncoding<VariantIdx: Idx> {
},
}

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub struct Niche {
pub offset: Size,
Expand Down Expand Up @@ -2218,7 +2254,7 @@ pub enum NicheOptimizations {
}

// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage.
#[derive(PartialEq, Eq, Hash, Clone)]
#[derive(PartialEq, Eq, Hash, Clone, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub struct LayoutData<FieldIdx: Idx, VariantIdx: Idx> {
/// Says where the fields are located within the layout.
Expand Down Expand Up @@ -2296,6 +2332,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
/// Returns `true` if the given variant is uninhabited.
pub fn is_variant_uninhabited(&self, variant: VariantIdx) -> bool {
match self.variants {
Variants::Opaque => false,
Variants::Empty => true,
Variants::Single { index } => variant != index || self.uninhabited,
Variants::Multiple { ref variants, .. } => {
Expand Down Expand Up @@ -2483,7 +2520,7 @@ pub enum AbiFromStrErr {
///
/// See <https://github.com/rust-lang/rust/issues/113988> for more context.
// NOTE: This struct is generic over the FieldIdx for rust-analyzer usage.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
#[derive(PartialEq, Eq, Hash, Clone, Debug, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub struct VariantLayout<FieldIdx: Idx> {
// FIXME: ideally we'd remove these as variants should not have their own
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_abi/src/wrapping_range.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::ops::RangeFull;
use std::{fmt, iter};

use rustc_macros::{Decodable_NoContext, Encodable_NoContext};

use crate::Size;
#[cfg(feature = "nightly")]
use crate::StableHash;
Expand All @@ -14,7 +16,7 @@ use crate::StableHash;
/// 254 (-2), 255 (-1), 0, 1, 2
///
/// This is intended specifically to mirror LLVM’s `!range` metadata semantics.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable_NoContext, Decodable_NoContext)]
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub struct WrappingRange {
pub start: u128,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1942,6 +1942,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
| ty::UnsafeBinder(_)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Erased(..)
| ty::Bound(_, _)
| ty::Infer(_)
| ty::Error(_)
Expand Down Expand Up @@ -1984,6 +1985,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
| ty::UnsafeBinder(_)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Erased(..)
| ty::Bound(_, _)
| ty::Infer(_)
| ty::Error(_)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_cranelift/src/discriminant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
return;
}
match layout.variants {
Variants::Opaque => unreachable!(),
Variants::Empty => unreachable!("we already handled uninhabited types"),
Variants::Single { index } => {
assert_eq!(index, variant_index);
Expand Down Expand Up @@ -86,6 +87,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
}

let (tag_scalar, tag_field, tag_encoding) = match &layout.variants {
Variants::Opaque => unreachable!(),
Variants::Empty => unreachable!("we already handled uninhabited types"),
Variants::Single { index } => {
let discr_val = layout
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_gcc/src/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
};

match layout.fields {
FieldsShape::Primitive | FieldsShape::Union(_) => {
FieldsShape::Opaque | FieldsShape::Primitive | FieldsShape::Union(_) => {
let fill = cx.type_padding_filler(layout.size, layout.align.abi);
let packed = false;
let attributes = struct_attributes(packed, Some(layout.align.abi));
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,13 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
debug!("type_di_node: {:?} kind: {:?}", t, t.kind());

let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() {
ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
build_basic_type_di_node(cx, t)
}
ty::Never
| ty::Erased(..)
| ty::Bool
| ty::Char
| ty::Int(_)
| ty::Uint(_)
| ty::Float(_) => build_basic_type_di_node(cx, t),
ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t),
ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t, span),
ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id, span),
Expand Down Expand Up @@ -763,6 +767,7 @@ fn build_basic_type_di_node<'ll, 'tcx>(

let (name, encoding) = match t.kind() {
ty::Never => ("!", DW_ATE_unsigned),
ty::Erased(..) => ("{erased}", DW_ATE_unsigned),
ty::Tuple(elements) if elements.is_empty() => {
if cpp_like_debuginfo {
return build_tuple_type_di_node(cx, UniqueTypeId::for_ty(cx.tcx, t));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
),
|cx, enum_type_di_node| {
match enum_type_and_layout.variants {
Variants::Opaque => return smallvec![],
Variants::Empty => {
// We don't generate any members for uninhabited types.
return smallvec![];
Expand Down Expand Up @@ -301,6 +302,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
}
Variants::Single { .. }
| Variants::Empty
| Variants::Opaque
| Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => {
bug!(
"Encountered coroutine with non-direct-tag layout: {:?}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,9 @@ fn compute_discriminant_value<'ll, 'tcx>(
variant_index: VariantIdx,
) -> DiscrResult {
match enum_type_and_layout.layout.variants() {
&Variants::Single { .. } | &Variants::Empty => DiscrResult::NoDiscriminant,
&Variants::Opaque | &Variants::Single { .. } | &Variants::Empty => {
DiscrResult::NoDiscriminant
}
&Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => DiscrResult::Value(
enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ fn build_discr_member_di_node<'ll, 'tcx>(
let containing_scope = enum_or_coroutine_type_di_node;

match enum_or_coroutine_type_and_layout.layout.variants() {
&Variants::Opaque => unreachable!(),
// A single-variant or no-variant enum has no discriminant.
&Variants::Single { .. } | &Variants::Empty => None,

Expand Down
Loading
Loading