From f7cf361f3cdda167130295789b0a38350aa35a5d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 29 May 2026 21:57:45 -0700 Subject: [PATCH] =?UTF-8?q?compiler:=20`ops::RangeInclusive`=20=E2=86=92?= =?UTF-8?q?=20`range::RangeInclusive`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The type's been stable for over 6 weeks now, so let's use it! It's better for cases like this one where it's stored in a data structure. Probably won't be materially faster, but does make the variant slightly smaller and lets some more things be `Copy`. --- compiler/rustc_abi/src/layout.rs | 9 ++++++--- compiler/rustc_abi/src/lib.rs | 5 +++-- compiler/rustc_codegen_cranelift/src/discriminant.rs | 8 ++++---- .../src/debuginfo/metadata/enums/mod.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/operand.rs | 8 ++++---- compiler/rustc_codegen_ssa/src/mir/place.rs | 2 +- .../rustc_const_eval/src/interpret/discriminant.rs | 10 +++++----- compiler/rustc_data_structures/src/stable_hash.rs | 6 +++--- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_public/src/unstable/convert/mod.rs | 8 ++++---- compiler/rustc_transmute/src/layout/tree.rs | 8 ++++---- 11 files changed, 36 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 8ab80c77ff9a5..733a1956231b1 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1,6 +1,7 @@ use std::collections::BTreeSet; use std::fmt::{self, Write}; use std::ops::Deref; +use std::range::RangeInclusive; use std::{cmp, iter}; use rustc_hashes::Hash64; @@ -631,11 +632,13 @@ impl LayoutCalculator { let all_indices = variants.indices(); 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 niche_variants = RangeInclusive { + start: all_indices.clone().find(|v| needs_disc(*v)).unwrap(), + last: all_indices.rev().find(|v| needs_disc(*v)).unwrap(), + }; let count = - (niche_variants.end().index() as u128 - niche_variants.start().index() as u128) + 1; + (niche_variants.last.index() as u128 - niche_variants.start.index() as u128) + 1; // Use the largest niche in the largest variant. let niche = variant_layouts[largest_variant_index].largest_niche?; diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 5e1a95d620f2a..166c8bea6f354 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -40,7 +40,8 @@ use std::fmt; #[cfg(feature = "nightly")] use std::iter::Step; use std::num::{NonZeroUsize, ParseIntError}; -use std::ops::{Add, AddAssign, Deref, Mul, RangeFull, RangeInclusive, Sub}; +use std::ops::{Add, AddAssign, Deref, Mul, RangeFull, Sub}; +use std::range::RangeInclusive; use std::str::FromStr; use bitflags::bitflags; @@ -1958,7 +1959,7 @@ pub enum Variants { } // NOTE: This struct is generic over the VariantIdx for rust-analyzer usage. -#[derive(PartialEq, Eq, Hash, Clone, Debug)] +#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] #[cfg_attr(feature = "nightly", derive(StableHash))] pub enum TagEncoding { /// The tag directly stores the discriminant, but possibly with a smaller layout diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index a08b0e0cbfc59..8818e8634952e 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -55,7 +55,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>( if variant_index != untagged_variant { let niche = place.place_field(fx, tag_field); let niche_type = fx.clif_type(niche.layout().ty).unwrap(); - let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); + let niche_value = variant_index.as_u32() - niche_variants.start.as_u32(); let niche_value = (niche_value as u128).wrapping_add(niche_start); let niche_value = match niche_type { types::I128 => { @@ -133,7 +133,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>( dest.write_cvalue(fx, res); } TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { - let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32(); + let relative_max = niche_variants.last.as_u32() - niche_variants.start.as_u32(); // We have a subrange `niche_start..=niche_end` inside `range`. // If the value of the tag is inside this subrange, it's a @@ -162,7 +162,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>( // } let is_niche = codegen_icmp_imm(fx, IntCC::Equal, tag, niche_start as i128); let tagged_discr = - fx.bcx.ins().iconst(cast_to, niche_variants.start().as_u32() as i64); + fx.bcx.ins().iconst(cast_to, niche_variants.start.as_u32() as i64); (is_niche, tagged_discr, 0) } else { // The special cases don't apply, so we'll have to go with @@ -184,7 +184,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>( relative_discr, i128::from(relative_max), ); - (is_niche, cast_tag, niche_variants.start().as_u32() as u128) + (is_niche, cast_tag, niche_variants.start.as_u32() as u128) }; let tagged_discr = if delta == 0 { 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 f7fe0eb8cb3b8..86060f068eaf0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -426,7 +426,7 @@ fn compute_discriminant_value<'ll, 'tcx>( DiscrResult::Range(min, max) } else { let value = (variant_index.as_u32() as u128) - .wrapping_sub(niche_variants.start().as_u32() as u128) + .wrapping_sub(niche_variants.start.as_u32() as u128) .wrapping_add(niche_start); let value = tag.size(cx).truncate(value); DiscrResult::Value(value) diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 83fce5a5c8deb..c0c71edd4d905 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -494,7 +494,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { // `layout_sanity_check` ensures that we only get here for cases where the discriminant // value and the variant index match, since that's all `Niche` can encode. - let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32(); + let relative_max = niche_variants.last.as_u32() - niche_variants.start.as_u32(); let niche_start_const = bx.cx().const_uint_big(tag_llty, niche_start); // We have a subrange `niche_start..=niche_end` inside `range`. @@ -523,7 +523,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { // } let is_niche = bx.icmp(IntPredicate::IntEQ, tag, niche_start_const); let tagged_discr = - bx.cx().const_uint(cast_to, niche_variants.start().as_u32() as u64); + bx.cx().const_uint(cast_to, niche_variants.start.as_u32() as u64); (is_niche, tagged_discr, 0) } else { // Thanks to parameter attributes and load metadata, LLVM already knows @@ -549,7 +549,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { { let impossible = niche_start .wrapping_add(u128::from(untagged_variant.as_u32())) - .wrapping_sub(u128::from(niche_variants.start().as_u32())); + .wrapping_sub(u128::from(niche_variants.start.as_u32())); let impossible = bx.cx().const_uint_big(tag_llty, impossible); let ne = bx.icmp(IntPredicate::IntNE, tag, impossible); bx.assume(ne); @@ -633,7 +633,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { ) }; - (is_niche, cast_tag, niche_variants.start().as_u32() as u128) + (is_niche, cast_tag, niche_variants.start.as_u32() as u128) }; let tagged_discr = if delta == 0 { diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 53518fd816f31..ebc993f14ea03 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -500,7 +500,7 @@ pub(super) fn codegen_tag_value<'tcx, V>( // around the `niche`'s type. // The easiest way to do that is to do wrapping arithmetic on `u128` and then // masking off any extra bits that occur because we did the arithmetic with too many bits. - let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); + let niche_value = variant_index.as_u32() - niche_variants.start.as_u32(); let niche_value = (niche_value as u128).wrapping_add(niche_start); let niche_value = niche_value & niche_layout.size.unsigned_int_max(); diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index c50d9db8be639..a1776c6ba3d13 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -142,8 +142,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { 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. - let variants_start = niche_variants.start().as_u32(); - let variants_end = niche_variants.end().as_u32(); + let variants_start = niche_variants.start.as_u32(); + let variants_last = niche_variants.last.as_u32(); let variant = match tag_val.try_to_scalar_int() { Err(dbg_val) => { // So this is a pointer then, and casting to an int failed. @@ -151,7 +151,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // The niche must be just 0, and the ptr not null, then we know this is // okay. Everything else, we conservatively reject. let ptr_valid = niche_start == 0 - && variants_start == variants_end + && variants_start == variants_last && !self.scalar_may_be_null(tag_val)?; if !ptr_valid { throw_ub!(InvalidTag(dbg_val)) @@ -169,7 +169,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let variant_index_relative = variant_index_relative_val.to_scalar().to_bits(tag_val.layout.size)?; // Check if this is in the range that indicates an actual discriminant. - if variant_index_relative <= u128::from(variants_end - variants_start) { + if variant_index_relative <= u128::from(variants_last - variants_start) { let variant_index_relative = u32::try_from(variant_index_relative) .expect("we checked that this fits into a u32"); // Then computing the absolute variant idx should not overflow any more. @@ -309,7 +309,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { niche_variants.contains(&variant_index), "invalid variant index for this enum" ); - let variants_start = niche_variants.start().as_u32(); + let variants_start = niche_variants.start.as_u32(); let variant_index_relative = variant_index.as_u32().strict_sub(variants_start); // We need to use machine arithmetic when taking into account `niche_start`: // tag_val = variant_index_relative + niche_start_val diff --git a/compiler/rustc_data_structures/src/stable_hash.rs b/compiler/rustc_data_structures/src/stable_hash.rs index 07a5e06c6bdde..79d45121226f7 100644 --- a/compiler/rustc_data_structures/src/stable_hash.rs +++ b/compiler/rustc_data_structures/src/stable_hash.rs @@ -527,14 +527,14 @@ impl StableHash for ::std::mem::Discriminant { } } -impl StableHash for ::std::ops::RangeInclusive +impl StableHash for ::std::range::RangeInclusive where T: StableHash, { #[inline] fn stable_hash(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { - self.start().stable_hash(hcx, hasher); - self.end().stable_hash(hcx, hasher); + self.start.stable_hash(hcx, hasher); + self.last.stable_hash(hcx, hasher); } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 168aa5e9b0219..98f2a6a2603e7 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1097,7 +1097,7 @@ where } else { VariantIdx::from_u32(0) }; - assert_eq!(tagged_variant, *niche_variants.start()); + assert_eq!(tagged_variant, niche_variants.start); if *niche_start == 0 { // The other variant is encoded as "null", so we can recurse searching for // a pointer here. This relies on the fact that the codegen backend diff --git a/compiler/rustc_public/src/unstable/convert/mod.rs b/compiler/rustc_public/src/unstable/convert/mod.rs index f20406631e3ff..1ec0b9a30534d 100644 --- a/compiler/rustc_public/src/unstable/convert/mod.rs +++ b/compiler/rustc_public/src/unstable/convert/mod.rs @@ -6,7 +6,7 @@ //! For contributors, please make sure to avoid calling rustc's internal functions and queries. //! These should be done via `rustc_public_bridge` APIs, but it's possible to access ADT fields directly. -use std::ops::RangeInclusive; +use std::{ops, range}; use rustc_public_bridge::Tables; use rustc_public_bridge::context::CompilerCtxt; @@ -95,16 +95,16 @@ where } } -impl<'tcx, T> Stable<'tcx> for RangeInclusive +impl<'tcx, T> Stable<'tcx> for range::RangeInclusive where T: Stable<'tcx>, { - type T = RangeInclusive; + type T = ops::RangeInclusive; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { - RangeInclusive::new(self.start().stable(tables, cx), self.end().stable(tables, cx)) + ops::RangeInclusive::new(self.start.stable(tables, cx), self.last.stable(tables, cx)) } } diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index b63baa71a312f..d7aeb6b06b82f 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -421,12 +421,12 @@ pub(crate) mod rustc { ) }; - match layout.variants() { + match *layout.variants() { Variants::Empty => Ok(Self::uninhabited()), Variants::Single { index } => { // `Variants::Single` on enums with variants denotes that // the enum delegates its layout to the variant at `index`. - layout_of_variant(*index, None) + layout_of_variant(index, None) } Variants::Multiple { tag: _, tag_encoding, tag_field, .. } => { // `Variants::Multiple` denotes an enum with multiple @@ -435,12 +435,12 @@ pub(crate) mod rustc { // For enums (but not coroutines), the tag field is // currently always the first field of the layout. - assert_eq!(*tag_field, FieldIdx::ZERO); + assert_eq!(tag_field, FieldIdx::ZERO); let variants = def.discriminants(cx.tcx()).try_fold( Self::uninhabited(), |variants, (idx, _discriminant)| { - let variant = layout_of_variant(idx, Some(tag_encoding.clone()))?; + let variant = layout_of_variant(idx, Some(tag_encoding))?; Result::::Ok(variants.or(variant)) }, )?;