From 1a08b96a0bb7c170130144214787b4a46aa5eb17 Mon Sep 17 00:00:00 2001 From: Michael Benfield Date: Thu, 25 Aug 2022 01:14:23 +0000 Subject: [PATCH 1/2] Change name of "dataful" variant to "untagged" This is in anticipation of a new enum layout, in which the niche optimization may be applied even when multiple variants have data. --- .../src/discriminant.rs | 11 +++++----- .../src/debuginfo/metadata/enums/cpp_like.rs | 18 ++++++++--------- .../src/debuginfo/metadata/enums/mod.rs | 6 +++--- .../src/debuginfo/metadata/enums/native.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 8 ++++---- .../rustc_const_eval/src/interpret/operand.rs | 6 +++--- .../rustc_const_eval/src/interpret/place.rs | 4 ++-- compiler/rustc_middle/src/ty/layout.rs | 20 +++++++++---------- compiler/rustc_target/src/abi/mod.rs | 4 ++-- src/test/debuginfo/msvc-pretty-enums.rs | 6 +++--- ...-scalarpair-payload-might-be-uninit.stderr | 4 ++-- .../layout/zero-sized-array-enum-niche.stderr | 2 +- 12 files changed, 46 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index e41ae1fbdbac5..97b395bcd0518 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -42,10 +42,10 @@ pub(crate) fn codegen_set_discriminant<'tcx>( Variants::Multiple { tag: _, tag_field, - tag_encoding: TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, + tag_encoding: TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start }, variants: _, } => { - if variant_index != dataful_variant { + if variant_index != untagged_variant { let niche = place.place_field(fx, mir::Field::new(tag_field)); let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); let niche_value = ty::ScalarInt::try_from_uint( @@ -113,7 +113,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>( let res = CValue::by_val(val, dest_layout); dest.write_cvalue(fx, res); } - TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { // Rebase from niche values to discriminants, and check // whether the result is in range for the niche variants. @@ -169,8 +169,9 @@ pub(crate) fn codegen_get_discriminant<'tcx>( fx.bcx.ins().iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32())) }; - let dataful_variant = fx.bcx.ins().iconst(cast_to, i64::from(dataful_variant.as_u32())); - let discr = fx.bcx.ins().select(is_niche, niche_discr, dataful_variant); + let untagged_variant = + fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32())); + let discr = fx.bcx.ins().select(is_niche, niche_discr, untagged_variant); let res = CValue::by_val(discr, dest_layout); dest.write_cvalue(fx, res); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index daec9303b2c67..129e336c7e431 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -99,7 +99,7 @@ const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0; /// compiler versions. /// /// Niche-tag enums have one special variant, usually called the -/// "dataful variant". This variant has a field that +/// "untagged variant". This variant has a field that /// doubles as the tag of the enum. The variant is active when the value of /// that field is within a pre-defined range. Therefore the variant struct /// has a `DISCR_BEGIN` and `DISCR_END` field instead of `DISCR_EXACT` in @@ -249,7 +249,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( None, ), Variants::Multiple { - tag_encoding: TagEncoding::Niche { dataful_variant, .. }, + tag_encoding: TagEncoding::Niche { untagged_variant, .. }, ref variants, tag_field, .. @@ -260,7 +260,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( enum_type_di_node, variants.indices(), tag_field, - Some(dataful_variant), + Some(untagged_variant), ), } }, @@ -391,7 +391,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>( enum_type_di_node: &'ll DIType, variant_indices: impl Iterator + Clone, tag_field: usize, - dataful_variant_index: Option, + untagged_variant_index: Option, ) -> SmallVec<&'ll DIType> { let tag_base_type = super::tag_base_type(cx, enum_type_and_layout); @@ -436,7 +436,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>( variant_names_type_di_node, tag_base_type, tag_field, - dataful_variant_index, + untagged_variant_index, ) } @@ -472,7 +472,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( enum_or_generator_type_and_layout: TyAndLayout<'tcx>, enum_or_generator_type_di_node: &'ll DIType, variant_index: VariantIdx, - dataful_variant_index: Option, + untagged_variant_index: Option, variant_struct_type_di_node: &'ll DIType, variant_names_type_di_node: &'ll DIType, tag_base_type_di_node: &'ll DIType, @@ -517,7 +517,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( } } DiscrResult::Range(min, max) => { - assert_eq!(Some(variant_index), dataful_variant_index); + assert_eq!(Some(variant_index), untagged_variant_index); if is_128_bits { DiscrKind::Range128(min, max) } else { @@ -757,7 +757,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( discr_type_di_node: &'ll DIType, tag_base_type: Ty<'tcx>, tag_field: usize, - dataful_variant_index: Option, + untagged_variant_index: Option, ) -> SmallVec<&'ll DIType> { let tag_base_type_di_node = type_di_node(cx, tag_base_type); let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1); @@ -776,7 +776,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( enum_type_and_layout, enum_type_di_node, variant_member_info.variant_index, - dataful_variant_index, + untagged_variant_index, variant_member_info.variant_struct_type_di_node, discr_type_di_node, tag_base_type_di_node, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 9b3d080bfd6aa..14044d0f99b98 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -417,7 +417,7 @@ impl DiscrResult { /// Returns the discriminant value corresponding to the variant index. /// /// Will return `None` if there is less than two variants (because then the enum won't have) -/// a tag, and if this is the dataful variant of a niche-layout enum (because then there is no +/// a tag, and if this is the untagged variant of a niche-layout enum (because then there is no /// single discriminant value). fn compute_discriminant_value<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, @@ -430,11 +430,11 @@ fn compute_discriminant_value<'ll, 'tcx>( enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val, ), &Variants::Multiple { - tag_encoding: TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant }, + tag_encoding: TagEncoding::Niche { ref niche_variants, niche_start, untagged_variant }, tag, .. } => { - if variant_index == dataful_variant { + if variant_index == untagged_variant { let valid_range = enum_type_and_layout .for_variant(cx, variant_index) .largest_niche diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index dae90a43f2659..becbccc434d9a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -378,7 +378,7 @@ fn build_discr_member_di_node<'ll, 'tcx>( /// /// The DW_AT_discr_value is optional, and is omitted if /// - This is the only variant of a univariant enum (i.e. their is no discriminant) -/// - This is the "dataful" variant of a niche-layout enum +/// - This is the "untagged" variant of a niche-layout enum /// (where only the other variants are identified by a single value) /// /// There is only ever a single member, the type of which is a struct that describes the diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 04b8c8636f634..13d8f6eddd1de 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -244,7 +244,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { }; bx.intcast(tag.immediate(), cast_to, signed) } - TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { // Rebase from niche values to discriminants, and check // whether the result is in range for the niche variants. let niche_llty = bx.cx().immediate_backend_type(tag.layout); @@ -302,7 +302,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx.select( is_niche, niche_discr, - bx.cx().const_uint(cast_to, dataful_variant.as_u32() as u64), + bx.cx().const_uint(cast_to, untagged_variant.as_u32() as u64), ) } } @@ -337,11 +337,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } Variants::Multiple { tag_encoding: - TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start }, tag_field, .. } => { - if variant_index != dataful_variant { + if variant_index != untagged_variant { let niche = self.project_field(bx, tag_field); let niche_llty = bx.cx().immediate_backend_type(niche.layout); let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 35c2cf8102dc5..efa33e1851084 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -718,7 +718,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Return the cast value, and the index. (discr_val, index.0) } - TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { let tag_val = tag_val.to_scalar(); // Compute the variant this niche value/"tag" corresponds to. With niche layout, // discriminant (encoded in niche/tag) and variant index are the same. @@ -736,7 +736,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if !ptr_valid { throw_ub!(InvalidTag(dbg_val)) } - dataful_variant + untagged_variant } Ok(tag_bits) => { let tag_bits = tag_bits.assert_bits(tag_layout.size); @@ -766,7 +766,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert!(usize::try_from(variant_index).unwrap() < variants_len); VariantIdx::from_u32(variant_index) } else { - dataful_variant + untagged_variant } } }; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index a03b0dfb6038b..81b0b5a745982 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -817,7 +817,7 @@ where } abi::Variants::Multiple { tag_encoding: - TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start }, tag: tag_layout, tag_field, .. @@ -825,7 +825,7 @@ where // No need to validate that the discriminant here because the // `TyAndLayout::for_variant()` call earlier already checks the variant is valid. - if variant_index != dataful_variant { + if variant_index != untagged_variant { let variants_start = niche_variants.start().as_u32(); let variant_index_relative = variant_index .as_u32() diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 2c587b76f025f..0a5463a021fec 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1047,7 +1047,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { assert!(def.is_enum()); // The current code for niche-filling relies on variant indices - // instead of actual discriminants, so dataful enums with + // instead of actual discriminants, so untagged enums with // explicit discriminants (RFC #2363) would misbehave. let no_explicit_discriminants = def .variants() @@ -1058,7 +1058,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Niche-filling enum optimization. if !def.repr().inhibit_enum_layout_opt() && no_explicit_discriminants { - let mut dataful_variant = None; + let mut untagged_variant = None; let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0); // Find one non-ZST variant. @@ -1068,11 +1068,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } for f in fields { if !f.is_zst() { - if dataful_variant.is_none() { - dataful_variant = Some(v); + if untagged_variant.is_none() { + untagged_variant = Some(v); continue 'variants; } else { - dataful_variant = None; + untagged_variant = None; break 'variants; } } @@ -1081,10 +1081,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } if niche_variants.start() > niche_variants.end() { - dataful_variant = None; + untagged_variant = None; } - if let Some(i) = dataful_variant { + if let Some(i) = untagged_variant { let count = (niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1) as u128; @@ -1152,7 +1152,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { variants: Variants::Multiple { tag: niche_scalar, tag_encoding: TagEncoding::Niche { - dataful_variant: i, + untagged_variant: i, niche_variants, niche_start, }, @@ -2559,11 +2559,11 @@ where // using more niches than just null (e.g., the first page of // the address space, or unaligned pointers). Variants::Multiple { - tag_encoding: TagEncoding::Niche { dataful_variant, .. }, + tag_encoding: TagEncoding::Niche { untagged_variant, .. }, tag_field, .. } if this.fields.offset(tag_field) == offset => { - Some(this.for_variant(cx, dataful_variant)) + Some(this.for_variant(cx, untagged_variant)) } _ => Some(this), }; diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 92ce4d91d84d1..bcaf209f84b65 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1130,7 +1130,7 @@ pub enum TagEncoding { /// Niche (values invalid for a type) encoding the discriminant: /// Discriminant and variant index coincide. - /// The variant `dataful_variant` contains a niche at an arbitrary + /// The variant `untagged_variant` contains a niche at an arbitrary /// offset (field `tag_field` of the enum), which for a variant with /// discriminant `d` is set to /// `(d - niche_variants.start).wrapping_add(niche_start)`. @@ -1139,7 +1139,7 @@ pub enum TagEncoding { /// `None` has a null pointer for the second tuple field, and /// `Some` is the identity function (with a non-null reference). Niche { - dataful_variant: VariantIdx, + untagged_variant: VariantIdx, niche_variants: RangeInclusive, niche_start: u128, }, diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index 45d5ddf5c0ebc..7f1be6f27847c 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -53,8 +53,8 @@ // cdb-command: dx niche128_none // cdb-check: niche128_none : None [Type: enum2$ >] -// cdb-command: dx wrapping_niche128_dataful -// cdb-check: wrapping_niche128_dataful : X [Type: enum2$] +// cdb-command: dx wrapping_niche128_untagged +// cdb-check: wrapping_niche128_untagged : X [Type: enum2$] // cdb-check: [+0x[...]] __0 [Type: msvc_pretty_enums::Wrapping128] // cdb-command: dx wrapping_niche128_none1 @@ -213,7 +213,7 @@ fn main() { let niche128_some = Some(NonZeroI128::new(123456).unwrap()); let niche128_none: Option = None; - let wrapping_niche128_dataful = + let wrapping_niche128_untagged = unsafe { Wrapping128Niche::X(Wrapping128(340282366920938463463374607431768211454)) }; let wrapping_niche128_none1 = Wrapping128Niche::Y; let wrapping_niche128_none2 = Wrapping128Niche::Z; diff --git a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index 6deb1f271a728..bfabe2d12f7ff 100644 --- a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -411,7 +411,7 @@ error: layout_of(NicheFirst) = Layout { valid_range: 0..=4, }, tag_encoding: Niche { - dataful_variant: 0, + untagged_variant: 0, niche_variants: 1..=2, niche_start: 3, }, @@ -555,7 +555,7 @@ error: layout_of(NicheSecond) = Layout { valid_range: 0..=4, }, tag_encoding: Niche { - dataful_variant: 0, + untagged_variant: 0, niche_variants: 1..=2, niche_start: 3, }, diff --git a/src/test/ui/layout/zero-sized-array-enum-niche.stderr b/src/test/ui/layout/zero-sized-array-enum-niche.stderr index 56d3a52bb7ff9..a3e82070e0f52 100644 --- a/src/test/ui/layout/zero-sized-array-enum-niche.stderr +++ b/src/test/ui/layout/zero-sized-array-enum-niche.stderr @@ -353,7 +353,7 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = Layout { valid_range: 0..=1, }, tag_encoding: Niche { - dataful_variant: 1, + untagged_variant: 1, niche_variants: 0..=0, niche_start: 1, }, From d7a750b50436fbd228b176f6438566625e235990 Mon Sep 17 00:00:00 2001 From: Michael Benfield Date: Tue, 8 Mar 2022 19:07:01 +0000 Subject: [PATCH 2/2] Use niche-filling optimization even when multiple variants have data. Fixes #46213 --- compiler/rustc_ast/src/ast.rs | 3 +- .../rustc_const_eval/src/interpret/operand.rs | 10 +- .../rustc_const_eval/src/interpret/place.rs | 6 +- .../src/obligation_forest/mod.rs | 4 + compiler/rustc_errors/src/lib.rs | 4 +- compiler/rustc_hir/src/hir.rs | 15 +- compiler/rustc_middle/src/mir/syntax.rs | 3 +- compiler/rustc_middle/src/thir.rs | 12 +- compiler/rustc_middle/src/ty/layout.rs | 314 +++++++++++------- src/librustdoc/clean/types.rs | 3 +- src/test/ui/stats/hir-stats.rs | 1 + src/test/ui/stats/hir-stats.stderr | 44 +-- src/test/ui/structs-enums/type-sizes.rs | 79 +++++ 13 files changed, 339 insertions(+), 159 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f25fdc942b085..e38572f609b31 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3075,7 +3075,8 @@ mod size_asserts { static_assert_size!(Block, 48); static_assert_size!(Expr, 104); static_assert_size!(ExprKind, 72); - static_assert_size!(Fn, 192); + #[cfg(not(bootstrap))] + static_assert_size!(Fn, 184); static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItemKind, 24); static_assert_size!(GenericArg, 24); diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index efa33e1851084..ba041810bd19e 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -780,13 +780,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Some nodes are used a lot. Make sure they don't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64", not(bootstrap)))] mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // These are in alphabetical order, which is easy to maintain. - static_assert_size!(Immediate, 56); - static_assert_size!(ImmTy<'_>, 72); - static_assert_size!(Operand, 64); - static_assert_size!(OpTy<'_>, 88); + static_assert_size!(Immediate, 48); + static_assert_size!(ImmTy<'_>, 64); + static_assert_size!(Operand, 56); + static_assert_size!(OpTy<'_>, 80); } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 81b0b5a745982..b328892906df2 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -890,6 +890,8 @@ mod size_asserts { static_assert_size!(MemPlaceMeta, 24); static_assert_size!(MemPlace, 40); static_assert_size!(MPlaceTy<'_>, 64); - static_assert_size!(Place, 48); - static_assert_size!(PlaceTy<'_>, 72); + #[cfg(not(bootstrap))] + static_assert_size!(Place, 40); + #[cfg(not(bootstrap))] + static_assert_size!(PlaceTy<'_>, 64); } diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 07a96dd7dbbf1..e351b650a16c1 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -117,6 +117,10 @@ pub trait ObligationProcessor { } /// The result type used by `process_obligation`. +// `repr(C)` to inhibit the niche filling optimization. Otherwise, the `match` appearing +// in `process_obligations` is significantly slower, which can substantially affect +// benchmarks like `rustc-perf`'s inflate and keccak. +#[repr(C)] #[derive(Debug)] pub enum ProcessResult { Unchanged, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 37ff6dcff7d79..513225e160645 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -69,8 +69,8 @@ pub type PResult<'a, T> = Result>; // (See also the comment on `DiagnosticBuilder`'s `diagnostic` field.) #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16); -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24); +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64", not(bootstrap)))] +rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16); #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)] pub enum SuggestionStyle { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 50e7c5d2d04c8..a668c0e95ce4b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3473,12 +3473,15 @@ mod size_asserts { static_assert_size!(FnDecl<'_>, 40); static_assert_size!(ForeignItem<'_>, 72); static_assert_size!(ForeignItemKind<'_>, 40); - static_assert_size!(GenericArg<'_>, 40); + #[cfg(not(bootstrap))] + static_assert_size!(GenericArg<'_>, 32); static_assert_size!(GenericBound<'_>, 48); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 80); - static_assert_size!(ImplItem<'_>, 88); - static_assert_size!(ImplItemKind<'_>, 40); + #[cfg(not(bootstrap))] + static_assert_size!(ImplItem<'_>, 80); + #[cfg(not(bootstrap))] + static_assert_size!(ImplItemKind<'_>, 32); static_assert_size!(Item<'_>, 80); static_assert_size!(ItemKind<'_>, 48); static_assert_size!(Local<'_>, 64); @@ -3490,8 +3493,10 @@ mod size_asserts { static_assert_size!(QPath<'_>, 24); static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); - static_assert_size!(TraitItem<'_>, 96); - static_assert_size!(TraitItemKind<'_>, 56); + #[cfg(not(bootstrap))] + static_assert_size!(TraitItem<'static>, 88); + #[cfg(not(bootstrap))] + static_assert_size!(TraitItemKind<'_>, 48); static_assert_size!(Ty<'_>, 72); static_assert_size!(TyKind<'_>, 56); } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index bf63b8efaf7a2..e149535bec7b5 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1231,7 +1231,8 @@ pub enum BinOp { mod size_asserts { use super::*; // These are in alphabetical order, which is easy to maintain. - static_assert_size!(AggregateKind<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(AggregateKind<'_>, 40); static_assert_size!(Operand<'_>, 24); static_assert_size!(Place<'_>, 16); static_assert_size!(PlaceElem<'_>, 24); diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 7e543929b0f3a..c50f8b0eebe1a 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -825,8 +825,12 @@ mod size_asserts { static_assert_size!(Block, 56); static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 40); - static_assert_size!(Pat<'_>, 72); - static_assert_size!(PatKind<'_>, 56); - static_assert_size!(Stmt<'_>, 56); - static_assert_size!(StmtKind<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(Pat<'_>, 64); + #[cfg(not(bootstrap))] + static_assert_size!(PatKind<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(Stmt<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(StmtKind<'_>, 40); } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0a5463a021fec..abb7ddd88b14d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -22,7 +22,7 @@ use rustc_target::abi::call::{ use rustc_target::abi::*; use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target}; -use std::cmp; +use std::cmp::{self, Ordering}; use std::fmt; use std::iter; use std::num::NonZeroUsize; @@ -1046,131 +1046,191 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // that allow representation optimization.) assert!(def.is_enum()); - // The current code for niche-filling relies on variant indices - // instead of actual discriminants, so untagged enums with - // explicit discriminants (RFC #2363) would misbehave. - let no_explicit_discriminants = def - .variants() - .iter_enumerated() - .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32())); - - let mut niche_filling_layout = None; - - // Niche-filling enum optimization. - if !def.repr().inhibit_enum_layout_opt() && no_explicit_discriminants { - let mut untagged_variant = None; - let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0); + // Until we've decided whether to use the tagged or + // niche filling LayoutS, we don't want to intern the + // variant layouts, so we can't store them in the + // overall LayoutS. Store the overall LayoutS + // and the variant LayoutSs here until then. + struct TmpLayout<'tcx> { + layout: LayoutS<'tcx>, + variants: IndexVec>, + } - // Find one non-ZST variant. - 'variants: for (v, fields) in variants.iter_enumerated() { - if absent(fields) { - continue 'variants; + let calculate_niche_filling_layout = + || -> Result>, LayoutError<'tcx>> { + // The current code for niche-filling relies on variant indices + // instead of actual discriminants, so enums with + // explicit discriminants (RFC #2363) would misbehave. + if def.repr().inhibit_enum_layout_opt() + || def + .variants() + .iter_enumerated() + .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32())) + { + return Ok(None); } - for f in fields { - if !f.is_zst() { - if untagged_variant.is_none() { - untagged_variant = Some(v); - continue 'variants; - } else { - untagged_variant = None; - break 'variants; - } - } + + if variants.len() < 2 { + return Ok(None); } - niche_variants = *niche_variants.start().min(&v)..=v; - } - if niche_variants.start() > niche_variants.end() { - untagged_variant = None; - } + let mut align = dl.aggregate_align; + let mut variant_layouts = variants + .iter_enumerated() + .map(|(j, v)| { + let mut st = self.univariant_uninterned( + ty, + v, + &def.repr(), + StructKind::AlwaysSized, + )?; + st.variants = Variants::Single { index: j }; + + align = align.max(st.align); + + Ok(st) + }) + .collect::, _>>()?; + + let largest_variant_index = match variant_layouts + .iter_enumerated() + .max_by_key(|(_i, layout)| layout.size.bytes()) + .map(|(i, _layout)| i) + { + None => return Ok(None), + Some(i) => i, + }; - if let Some(i) = untagged_variant { - let count = (niche_variants.end().as_u32() - - niche_variants.start().as_u32() - + 1) as u128; + let all_indices = VariantIdx::new(0)..=VariantIdx::new(variants.len() - 1); + let needs_disc = |index: VariantIdx| { + index != largest_variant_index && !absent(&variants[index]) + }; + let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap() + ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap(); + + let count = niche_variants.size_hint().1.unwrap() as u128; // Find the field with the largest niche - let niche_candidate = variants[i] + let (field_index, niche, (niche_start, niche_scalar)) = match variants + [largest_variant_index] .iter() .enumerate() .filter_map(|(j, field)| Some((j, field.largest_niche?))) - .max_by_key(|(_, niche)| niche.available(dl)); - - if let Some((field_index, niche, (niche_start, niche_scalar))) = - niche_candidate.and_then(|(field_index, niche)| { - Some((field_index, niche, niche.reserve(self, count)?)) - }) + .max_by_key(|(_, niche)| niche.available(dl)) + .and_then(|(j, niche)| Some((j, niche, niche.reserve(self, count)?))) { - let mut align = dl.aggregate_align; - let st = variants - .iter_enumerated() - .map(|(j, v)| { - let mut st = self.univariant_uninterned( - ty, - v, - &def.repr(), - StructKind::AlwaysSized, - )?; - st.variants = Variants::Single { index: j }; + None => return Ok(None), + Some(x) => x, + }; - align = align.max(st.align); + let niche_offset = niche.offset + + variant_layouts[largest_variant_index].fields.offset(field_index); + let niche_size = niche.value.size(dl); + let size = variant_layouts[largest_variant_index].size.align_to(align.abi); - Ok(tcx.intern_layout(st)) - }) - .collect::, _>>()?; + let all_variants_fit = + variant_layouts.iter_enumerated_mut().all(|(i, layout)| { + if i == largest_variant_index { + return true; + } - let offset = st[i].fields().offset(field_index) + niche.offset; + layout.largest_niche = None; - // Align the total size to the largest alignment. - let size = st[i].size().align_to(align.abi); + if layout.size <= niche_offset { + // This variant will fit before the niche. + return true; + } - let abi = if st.iter().all(|v| v.abi().is_uninhabited()) { - Abi::Uninhabited - } else if align == st[i].align() && size == st[i].size() { - // When the total alignment and size match, we can use the - // same ABI as the scalar variant with the reserved niche. - match st[i].abi() { - Abi::Scalar(_) => Abi::Scalar(niche_scalar), - Abi::ScalarPair(first, second) => { - // Only the niche is guaranteed to be initialised, - // so use union layout for the other primitive. - if offset.bytes() == 0 { - Abi::ScalarPair(niche_scalar, second.to_union()) - } else { - Abi::ScalarPair(first.to_union(), niche_scalar) + // Determine if it'll fit after the niche. + let this_align = layout.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 (j, offset) in offsets.iter_mut().enumerate() { + if !variants[i][j].is_zst() { + *offset += this_offset; + } } } - _ => Abi::Aggregate { sized: true }, + _ => { + panic!("Layout of fields should be Arbitrary for variants") + } } - } else { - Abi::Aggregate { sized: true } - }; - let largest_niche = Niche::from_scalar(dl, offset, niche_scalar); - - niche_filling_layout = Some(LayoutS { - variants: Variants::Multiple { - tag: niche_scalar, - tag_encoding: TagEncoding::Niche { - untagged_variant: i, - niche_variants, - niche_start, - }, - tag_field: 0, - variants: st, - }, - fields: FieldsShape::Arbitrary { - offsets: vec![offset], - memory_index: vec![0], - }, - abi, - largest_niche, - size, - align, + // It can't be a Scalar or ScalarPair because the offset isn't 0. + if !layout.abi.is_uninhabited() { + layout.abi = Abi::Aggregate { sized: true }; + } + layout.size += this_offset; + + true }); + + if !all_variants_fit { + return Ok(None); } - } - } + + let largest_niche = Niche::from_scalar(dl, niche_offset, niche_scalar); + + let others_zst = variant_layouts.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; + + let abi = if variant_layouts.iter().all(|v| v.abi.is_uninhabited()) { + Abi::Uninhabited + } else if same_size && same_align && others_zst { + match variant_layouts[largest_variant_index].abi { + // When the total alignment and size match, we can use the + // same ABI as the scalar variant with the reserved niche. + Abi::Scalar(_) => Abi::Scalar(niche_scalar), + Abi::ScalarPair(first, second) => { + // Only the niche is guaranteed to be initialised, + // so use union layouts for the other primitive. + if niche_offset == Size::ZERO { + Abi::ScalarPair(niche_scalar, second.to_union()) + } else { + Abi::ScalarPair(first.to_union(), niche_scalar) + } + } + _ => Abi::Aggregate { sized: true }, + } + } else { + Abi::Aggregate { sized: true } + }; + + let layout = LayoutS { + variants: Variants::Multiple { + tag: niche_scalar, + tag_encoding: TagEncoding::Niche { + untagged_variant: largest_variant_index, + niche_variants, + niche_start, + }, + tag_field: 0, + variants: IndexVec::new(), + }, + fields: FieldsShape::Arbitrary { + offsets: vec![niche_offset], + memory_index: vec![0], + }, + abi, + largest_niche, + size, + align, + }; + + Ok(Some(TmpLayout { layout, variants: variant_layouts })) + }; + + let niche_filling_layout = calculate_niche_filling_layout()?; let (mut min, mut max) = (i128::MAX, i128::MIN); let discr_type = def.repr().discr_type(); @@ -1425,15 +1485,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag); - let layout_variants = - layout_variants.into_iter().map(|v| tcx.intern_layout(v)).collect(); - let tagged_layout = LayoutS { variants: Variants::Multiple { tag, tag_encoding: TagEncoding::Direct, tag_field: 0, - variants: layout_variants, + variants: IndexVec::new(), }, fields: FieldsShape::Arbitrary { offsets: vec![Size::ZERO], @@ -1445,20 +1502,45 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { size, }; - let best_layout = match (tagged_layout, niche_filling_layout) { - (tagged_layout, Some(niche_filling_layout)) => { + let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants }; + + let mut best_layout = match (tagged_layout, niche_filling_layout) { + (tl, Some(nl)) => { // Pick the smaller layout; otherwise, // pick the layout with the larger niche; otherwise, // pick tagged as it has simpler codegen. - cmp::min_by_key(tagged_layout, niche_filling_layout, |layout| { - let niche_size = layout.largest_niche.map_or(0, |n| n.available(dl)); - (layout.size, cmp::Reverse(niche_size)) - }) + use Ordering::*; + let niche_size = |tmp_l: &TmpLayout<'_>| { + tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl)) + }; + match ( + tl.layout.size.cmp(&nl.layout.size), + niche_size(&tl).cmp(&niche_size(&nl)), + ) { + (Greater, _) => nl, + (Equal, Less) => nl, + _ => tl, + } } - (tagged_layout, None) => tagged_layout, + (tl, None) => tl, + }; + + // Now we can intern the variant layouts and store them in the enum layout. + best_layout.layout.variants = match best_layout.layout.variants { + Variants::Multiple { tag, tag_encoding, tag_field, .. } => Variants::Multiple { + tag, + tag_encoding, + tag_field, + variants: best_layout + .variants + .into_iter() + .map(|layout| tcx.intern_layout(layout)) + .collect(), + }, + _ => bug!(), }; - tcx.intern_layout(best_layout) + tcx.intern_layout(best_layout.layout) } // Types with no meaningful known layout. diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d6bb7c6c4fc89..2077cf71b2ef7 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2532,7 +2532,8 @@ mod size_asserts { // These are in alphabetical order, which is easy to maintain. static_assert_size!(Crate, 72); // frequently moved by-value static_assert_size!(DocFragment, 32); - static_assert_size!(GenericArg, 64); + #[cfg(not(bootstrap))] + static_assert_size!(GenericArg, 56); static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 56); static_assert_size!(Item, 56); diff --git a/src/test/ui/stats/hir-stats.rs b/src/test/ui/stats/hir-stats.rs index a24b3ada57e59..5102574d4be3e 100644 --- a/src/test/ui/stats/hir-stats.rs +++ b/src/test/ui/stats/hir-stats.rs @@ -1,6 +1,7 @@ // check-pass // compile-flags: -Zhir-stats // only-x86_64 +// ignore-stage1 // The aim here is to include at least one of every different type of top-level // AST/HIR node reported by `-Zhir-stats`. diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 0a736f7be834e..c8ceb6ff22df2 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -21,39 +21,39 @@ ast-stats-1 - MacCall 32 ( 0.4%) 1 ast-stats-1 - Expr 96 ( 1.1%) 3 ast-stats-1 Param 160 ( 1.9%) 4 40 ast-stats-1 FnDecl 200 ( 2.4%) 5 40 -ast-stats-1 Variant 240 ( 2.8%) 2 120 +ast-stats-1 Variant 240 ( 2.9%) 2 120 ast-stats-1 Block 288 ( 3.4%) 6 48 ast-stats-1 GenericBound 352 ( 4.2%) 4 88 ast-stats-1 - Trait 352 ( 4.2%) 4 ast-stats-1 AssocItem 416 ( 4.9%) 4 104 ast-stats-1 - TyAlias 208 ( 2.5%) 2 ast-stats-1 - Fn 208 ( 2.5%) 2 -ast-stats-1 GenericParam 520 ( 6.1%) 5 104 -ast-stats-1 PathSegment 720 ( 8.5%) 30 24 -ast-stats-1 Expr 832 ( 9.8%) 8 104 +ast-stats-1 GenericParam 480 ( 5.7%) 5 96 +ast-stats-1 PathSegment 720 ( 8.6%) 30 24 +ast-stats-1 Expr 832 ( 9.9%) 8 104 ast-stats-1 - Path 104 ( 1.2%) 1 ast-stats-1 - Match 104 ( 1.2%) 1 ast-stats-1 - Struct 104 ( 1.2%) 1 ast-stats-1 - Lit 208 ( 2.5%) 2 ast-stats-1 - Block 312 ( 3.7%) 3 -ast-stats-1 Pat 840 ( 9.9%) 7 120 +ast-stats-1 Pat 840 (10.0%) 7 120 ast-stats-1 - Struct 120 ( 1.4%) 1 ast-stats-1 - Wild 120 ( 1.4%) 1 ast-stats-1 - Ident 600 ( 7.1%) 5 -ast-stats-1 Ty 1_344 (15.9%) 14 96 +ast-stats-1 Ty 1_344 (16.0%) 14 96 ast-stats-1 - Rptr 96 ( 1.1%) 1 ast-stats-1 - Ptr 96 ( 1.1%) 1 ast-stats-1 - ImplicitSelf 192 ( 2.3%) 2 ast-stats-1 - Path 960 (11.4%) 10 -ast-stats-1 Item 1_656 (19.6%) 9 184 +ast-stats-1 Item 1_656 (19.7%) 9 184 ast-stats-1 - Trait 184 ( 2.2%) 1 ast-stats-1 - Enum 184 ( 2.2%) 1 ast-stats-1 - ForeignMod 184 ( 2.2%) 1 ast-stats-1 - Impl 184 ( 2.2%) 1 ast-stats-1 - Fn 368 ( 4.4%) 2 -ast-stats-1 - Use 552 ( 6.5%) 3 +ast-stats-1 - Use 552 ( 6.6%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 8_456 +ast-stats-1 Total 8_416 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -86,12 +86,12 @@ ast-stats-2 - Trait 352 ( 3.8%) 4 ast-stats-2 AssocItem 416 ( 4.5%) 4 104 ast-stats-2 - TyAlias 208 ( 2.3%) 2 ast-stats-2 - Fn 208 ( 2.3%) 2 -ast-stats-2 GenericParam 520 ( 5.7%) 5 104 -ast-stats-2 PathSegment 792 ( 8.6%) 33 24 -ast-stats-2 Pat 840 ( 9.1%) 7 120 +ast-stats-2 GenericParam 480 ( 5.2%) 5 96 +ast-stats-2 PathSegment 792 ( 8.7%) 33 24 +ast-stats-2 Pat 840 ( 9.2%) 7 120 ast-stats-2 - Struct 120 ( 1.3%) 1 ast-stats-2 - Wild 120 ( 1.3%) 1 -ast-stats-2 - Ident 600 ( 6.5%) 5 +ast-stats-2 - Ident 600 ( 6.6%) 5 ast-stats-2 Expr 936 (10.2%) 9 104 ast-stats-2 - Path 104 ( 1.1%) 1 ast-stats-2 - Match 104 ( 1.1%) 1 @@ -99,12 +99,12 @@ ast-stats-2 - Struct 104 ( 1.1%) 1 ast-stats-2 - InlineAsm 104 ( 1.1%) 1 ast-stats-2 - Lit 208 ( 2.3%) 2 ast-stats-2 - Block 312 ( 3.4%) 3 -ast-stats-2 Ty 1_344 (14.6%) 14 96 +ast-stats-2 Ty 1_344 (14.7%) 14 96 ast-stats-2 - Rptr 96 ( 1.0%) 1 ast-stats-2 - Ptr 96 ( 1.0%) 1 ast-stats-2 - ImplicitSelf 192 ( 2.1%) 2 ast-stats-2 - Path 960 (10.5%) 10 -ast-stats-2 Item 2_024 (22.0%) 11 184 +ast-stats-2 Item 2_024 (22.1%) 11 184 ast-stats-2 - Trait 184 ( 2.0%) 1 ast-stats-2 - Enum 184 ( 2.0%) 1 ast-stats-2 - ExternCrate 184 ( 2.0%) 1 @@ -113,7 +113,7 @@ ast-stats-2 - Impl 184 ( 2.0%) 1 ast-stats-2 - Fn 368 ( 4.0%) 2 ast-stats-2 - Use 736 ( 8.0%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 9_184 +ast-stats-2 Total 9_144 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size @@ -121,7 +121,7 @@ hir-stats ---------------------------------------------------------------- hir-stats ForeignItemRef 24 ( 0.2%) 1 24 hir-stats Mod 32 ( 0.3%) 1 32 hir-stats ExprField 40 ( 0.4%) 1 40 -hir-stats TraitItemRef 56 ( 0.5%) 2 28 +hir-stats TraitItemRef 56 ( 0.6%) 2 28 hir-stats Param 64 ( 0.6%) 2 32 hir-stats Local 64 ( 0.6%) 1 64 hir-stats InlineAsm 72 ( 0.7%) 1 72 @@ -135,11 +135,11 @@ hir-stats - Semi 32 ( 0.3%) 1 hir-stats - Expr 32 ( 0.3%) 1 hir-stats FnDecl 120 ( 1.2%) 3 40 hir-stats Attribute 128 ( 1.3%) 4 32 +hir-stats GenericArg 128 ( 1.3%) 4 32 +hir-stats - Type 32 ( 0.3%) 1 +hir-stats - Lifetime 96 ( 0.9%) 3 hir-stats GenericArgs 144 ( 1.4%) 3 48 hir-stats Variant 160 ( 1.6%) 2 80 -hir-stats GenericArg 160 ( 1.6%) 4 40 -hir-stats - Type 40 ( 0.4%) 1 -hir-stats - Lifetime 120 ( 1.2%) 3 hir-stats GenericBound 192 ( 1.9%) 4 48 hir-stats - Trait 192 ( 1.9%) 4 hir-stats WherePredicate 216 ( 2.1%) 3 72 @@ -151,7 +151,7 @@ hir-stats - Wild 88 ( 0.9%) 1 hir-stats - Struct 88 ( 0.9%) 1 hir-stats - Binding 264 ( 2.6%) 3 hir-stats Generics 560 ( 5.5%) 10 56 -hir-stats Expr 768 ( 7.5%) 12 64 +hir-stats Expr 768 ( 7.6%) 12 64 hir-stats - Path 64 ( 0.6%) 1 hir-stats - Struct 64 ( 0.6%) 1 hir-stats - Match 64 ( 0.6%) 1 @@ -173,5 +173,5 @@ hir-stats - Path 936 ( 9.2%) 13 hir-stats Path 1_536 (15.1%) 32 48 hir-stats PathSegment 2_240 (22.0%) 40 56 hir-stats ---------------------------------------------------------------- -hir-stats Total 10_200 +hir-stats Total 10_168 hir-stats diff --git a/src/test/ui/structs-enums/type-sizes.rs b/src/test/ui/structs-enums/type-sizes.rs index 73a11a5e743f6..7a23f13630a43 100644 --- a/src/test/ui/structs-enums/type-sizes.rs +++ b/src/test/ui/structs-enums/type-sizes.rs @@ -120,6 +120,54 @@ pub enum AlwaysTaggedBecauseItHasNoNiche { B } +pub enum NicheFilledMultipleFields { + A(bool, u8), + B(u8), + C(u8), + D(bool), + E, + F, + G, +} + +struct BoolInTheMiddle(std::num::NonZeroU16, bool, u8); + +enum NicheWithData { + A, + B([u16; 5]), + Largest { a1: u32, a2: BoolInTheMiddle, a3: u32 }, + C, + D(u32, u32), +} + +// A type with almost 2^16 invalid values. +#[repr(u16)] +pub enum NicheU16 { + _0, +} + +pub enum EnumManyVariant { + Dataful(u8, X), + + // 0x100 niche variants. + _00, _01, _02, _03, _04, _05, _06, _07, _08, _09, _0A, _0B, _0C, _0D, _0E, _0F, + _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _1A, _1B, _1C, _1D, _1E, _1F, + _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _2A, _2B, _2C, _2D, _2E, _2F, + _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _3A, _3B, _3C, _3D, _3E, _3F, + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _4A, _4B, _4C, _4D, _4E, _4F, + _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _5A, _5B, _5C, _5D, _5E, _5F, + _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _6A, _6B, _6C, _6D, _6E, _6F, + _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _7A, _7B, _7C, _7D, _7E, _7F, + _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _8A, _8B, _8C, _8D, _8E, _8F, + _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _9A, _9B, _9C, _9D, _9E, _9F, + _A0, _A1, _A2, _A3, _A4, _A5, _A6, _A7, _A8, _A9, _AA, _AB, _AC, _AD, _AE, _AF, + _B0, _B1, _B2, _B3, _B4, _B5, _B6, _B7, _B8, _B9, _BA, _BB, _BC, _BD, _BE, _BF, + _C0, _C1, _C2, _C3, _C4, _C5, _C6, _C7, _C8, _C9, _CA, _CB, _CC, _CD, _CE, _CF, + _D0, _D1, _D2, _D3, _D4, _D5, _D6, _D7, _D8, _D9, _DA, _DB, _DC, _DD, _DE, _DF, + _E0, _E1, _E2, _E3, _E4, _E5, _E6, _E7, _E8, _E9, _EA, _EB, _EC, _ED, _EE, _EF, + _F0, _F1, _F2, _F3, _F4, _F5, _F6, _F7, _F8, _F9, _FA, _FB, _FC, _FD, _FE, _FF, +} + pub fn main() { assert_eq!(size_of::(), 1 as usize); assert_eq!(size_of::(), 4 as usize); @@ -170,4 +218,35 @@ pub fn main() { assert_eq!(size_of::(), 8); assert_eq!(size_of::>(), 8); assert_eq!(size_of::>>(), 8); + + assert_eq!(size_of::(), 2); + assert_eq!(size_of::>(), 2); + assert_eq!(size_of::>>(), 2); + + struct S1{ a: u16, b: std::num::NonZeroU16, c: u16, d: u8, e: u32, f: u64, g:[u8;2] } + assert_eq!(size_of::(), 24); + assert_eq!(size_of::>(), 24); + + assert_eq!(size_of::(), 12); + assert_eq!(size_of::>(), 12); + assert_eq!(size_of::>>(), 12); + assert_eq!( + size_of::>>>(), + size_of::<(&(), NicheWithData)>() + ); + + pub enum FillPadding { A(std::num::NonZeroU8, u32), B } + assert_eq!(size_of::(), 8); + assert_eq!(size_of::>(), 8); + assert_eq!(size_of::>>(), 8); + + assert_eq!(size_of::>(), 4); + assert_eq!(size_of::>>(), 4); + assert_eq!(size_of::>(), 4); + + assert_eq!(size_of::>(), 6); + assert_eq!(size_of::>(), 4); + assert_eq!(size_of::>>(), 4); + assert_eq!(size_of::>>(), 6); + assert_eq!(size_of::>>(), 6); }