diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index aafb124986e14..1ad2a464b940d 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -33,7 +33,7 @@ rustc_index::newtype_index! { /// `b` is `FieldIdx(1)` in `VariantIdx(0)`, /// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and /// `f` is `FieldIdx(1)` in `VariantIdx(0)`. - #[derive(HashStable_Generic)] + #[stable_hash_generic] #[encodable] #[orderable] pub struct FieldIdx {} @@ -57,7 +57,7 @@ rustc_index::newtype_index! { /// /// `struct`s, `tuples`, and `unions`s are considered to have a single variant /// with variant index zero, aka [`FIRST_VARIANT`]. - #[derive(HashStable_Generic)] + #[stable_hash_generic] #[encodable] #[orderable] pub struct VariantIdx { diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 594d6d294d75a..b227410a3bc74 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -28,6 +28,8 @@ #![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] +#![feature(pattern_type_macro)] +#![feature(pattern_types)] #![feature(ptr_alignment_type)] #![feature(rustc_attrs)] #![feature(sized_hierarchy)] diff --git a/compiler/rustc_hir_id/src/lib.rs b/compiler/rustc_hir_id/src/lib.rs index d07bc88e66afc..d6deed59b625d 100644 --- a/compiler/rustc_hir_id/src/lib.rs +++ b/compiler/rustc_hir_id/src/lib.rs @@ -151,7 +151,7 @@ rustc_index::newtype_index! { /// integers starting at zero, so a mapping that maps all or most nodes within /// an "item-like" to something else can be implemented by a `Vec` instead of a /// tree or hash map. - #[derive(HashStable_Generic)] + #[stable_hash_generic] #[encodable] #[orderable] pub struct ItemLocalId {} diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs index 2b444932f8548..96424b0ebcc72 100644 --- a/compiler/rustc_index_macros/src/lib.rs +++ b/compiler/rustc_index_macros/src/lib.rs @@ -34,7 +34,17 @@ mod newtype; /// optimizations. The default max value is 0xFFFF_FF00. /// - `#[gate_rustc_only]`: makes parts of the generated code nightly-only. #[proc_macro] -#[cfg_attr(feature = "nightly", allow_internal_unstable(step_trait, rustc_attrs, trusted_step))] +#[cfg_attr( + feature = "nightly", + allow_internal_unstable( + step_trait, + rustc_attrs, + trusted_step, + pattern_types, + pattern_type_macro, + structural_match, + ) +)] pub fn newtype_index(input: TokenStream) -> TokenStream { newtype::newtype(input) } diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs index eedbe630cf2c4..282403294db95 100644 --- a/compiler/rustc_index_macros/src/newtype.rs +++ b/compiler/rustc_index_macros/src/newtype.rs @@ -18,12 +18,14 @@ impl Parse for Newtype { braced!(body in input); // Any additional `#[derive]` macro paths to apply - let mut derive_paths: Vec = Vec::new(); let mut debug_format: Option = None; let mut max = None; let mut consts = Vec::new(); let mut encodable = false; let mut ord = false; + let mut stable_hash = false; + let mut stable_hash_generic = false; + let mut stable_hash_no_context = false; let mut gate_rustc_only = quote! {}; let mut gate_rustc_only_cfg = quote! { all() }; @@ -42,6 +44,18 @@ impl Parse for Newtype { ord = true; false } + "stable_hash" => { + stable_hash = true; + false + } + "stable_hash_generic" => { + stable_hash_generic = true; + false + } + "stable_hash_no_context" => { + stable_hash_no_context = true; + false + } "max" => { let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else { @@ -111,12 +125,6 @@ impl Parse for Newtype { } else { quote! {} }; - - if ord { - derive_paths.push(parse_quote!(Ord)); - derive_paths.push(parse_quote!(PartialOrd)); - } - let step = if ord { quote! { #gate_rustc_only @@ -139,6 +147,38 @@ impl Parse for Newtype { Self::index(start).checked_sub(u).map(Self::from_usize) } } + impl ::std::cmp::Ord for #name { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_u32().cmp(&other.as_u32()) + } + } + impl ::std::cmp::PartialOrd for #name { + fn partial_cmp(&self, other: &Self) -> Option { + self.as_u32().partial_cmp(&other.as_u32()) + } + } + } + } else { + quote! {} + }; + + let hash_stable = if stable_hash { + quote! { + #gate_rustc_only + impl<'__ctx> ::rustc_data_structures::stable_hasher::HashStable<::rustc_middle::ich::StableHashingContext<'__ctx>> for #name { + fn hash_stable(&self, hcx: &mut ::rustc_middle::ich::StableHashingContext<'__ctx>, hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { + self.as_u32().hash_stable(hcx, hasher) + } + } + } + } else if stable_hash_generic || stable_hash_no_context { + quote! { + #gate_rustc_only + impl ::rustc_data_structures::stable_hasher::HashStable for #name { + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { + self.as_u32().hash_stable(hcx, hasher) + } + } } } else { quote! {} @@ -154,11 +194,13 @@ impl Parse for Newtype { Ok(Self(quote! { #(#attrs)* - #[derive(Clone, Copy, PartialEq, Eq, Hash, #(#derive_paths),*)] - #[cfg_attr(#gate_rustc_only_cfg, rustc_layout_scalar_valid_range_end(#max))] + #[derive(Clone, Copy)] #[cfg_attr(#gate_rustc_only_cfg, rustc_pass_by_value)] #vis struct #name { + #[cfg(not(#gate_rustc_only_cfg))] private_use_as_methods_instead: u32, + #[cfg(#gate_rustc_only_cfg)] + private_use_as_methods_instead: pattern_type!(u32 is 0..=#max), } #(#consts)* @@ -226,7 +268,7 @@ impl Parse for Newtype { /// Prefer using `from_u32`. #[inline] #vis const unsafe fn from_u32_unchecked(value: u32) -> Self { - Self { private_use_as_methods_instead: value } + Self { private_use_as_methods_instead: unsafe { std::mem::transmute(value) } } } /// Extracts the value of this index as a `usize`. @@ -238,7 +280,7 @@ impl Parse for Newtype { /// Extracts the value of this index as a `u32`. #[inline] #vis const fn as_u32(self) -> u32 { - self.private_use_as_methods_instead + unsafe { std::mem::transmute(self.private_use_as_methods_instead) } } /// Extracts the value of this index as a `usize`. @@ -278,6 +320,8 @@ impl Parse for Newtype { #step + #hash_stable + impl From<#name> for u32 { #[inline] fn from(v: #name) -> u32 { @@ -306,6 +350,23 @@ impl Parse for Newtype { } } + impl ::std::cmp::Eq for #name {} + + impl ::std::cmp::PartialEq for #name { + fn eq(&self, other: &Self) -> bool { + self.as_u32().eq(&other.as_u32()) + } + } + + #gate_rustc_only + impl ::std::marker::StructuralPartialEq for #name {} + + impl ::std::hash::Hash for #name { + fn hash(&self, state: &mut H) { + self.as_u32().hash(state) + } + } + #encodable_impls #debug_impl })) diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 990ed8f48fb84..678520e8ce0c8 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -159,7 +159,7 @@ rustc_index::newtype_index! { /// /// * The subscope with `first_statement_index == 1` is scope of `c`, /// and thus does not include EXPR_2, but covers the `...`. - #[derive(HashStable)] + #[stable_hash] #[encodable] #[orderable] pub struct FirstStatementIndex {} diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index fd4c64b9a61c2..0bf5094a27c03 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -10,7 +10,7 @@ use rustc_span::Span; rustc_index::newtype_index! { /// Used by [`CoverageKind::BlockMarker`] to mark blocks during THIR-to-MIR /// lowering, so that those blocks can be identified later. - #[derive(HashStable)] + #[stable_hash] #[encodable] #[debug_format = "BlockMarkerId({})"] pub struct BlockMarkerId {} @@ -26,7 +26,7 @@ rustc_index::newtype_index! { /// /// Note that LLVM handles counter IDs as `uint32_t`, so there is no need /// to use a larger representation on the Rust side. - #[derive(HashStable)] + #[stable_hash] #[encodable] #[orderable] #[debug_format = "CounterId({})"] @@ -43,7 +43,7 @@ rustc_index::newtype_index! { /// /// Note that LLVM handles expression IDs as `uint32_t`, so there is no need /// to use a larger representation on the Rust side. - #[derive(HashStable)] + #[stable_hash] #[encodable] #[orderable] #[debug_format = "ExpressionId({})"] @@ -203,7 +203,7 @@ rustc_index::newtype_index! { /// /// After that pass is complete, the coverage graph no longer exists, so a /// BCB is effectively an opaque ID. - #[derive(HashStable)] + #[stable_hash] #[encodable] #[orderable] #[debug_format = "bcb{}"] diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9d0e4b5e6dfa6..953042d0dec2d 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -840,7 +840,7 @@ impl SourceInfo { // Variables and temps rustc_index::newtype_index! { - #[derive(HashStable)] + #[stable_hash] #[encodable] #[orderable] #[debug_format = "_{}"] @@ -1283,7 +1283,7 @@ rustc_index::newtype_index! { /// https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis /// [`CriticalCallEdges`]: ../../rustc_mir_transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/ - #[derive(HashStable)] + #[stable_hash] #[encodable] #[orderable] #[debug_format = "bb{}"] @@ -1417,7 +1417,7 @@ impl<'tcx> BasicBlockData<'tcx> { // Scopes rustc_index::newtype_index! { - #[derive(HashStable)] + #[stable_hash] #[encodable] #[debug_format = "scope[{}]"] pub struct SourceScope { @@ -1556,7 +1556,7 @@ pub struct UserTypeProjection { } rustc_index::newtype_index! { - #[derive(HashStable)] + #[stable_hash] #[encodable] #[orderable] #[debug_format = "promoted[{}]"] diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 70954b4cb7829..d7d5d63d45a73 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -13,7 +13,7 @@ use super::{ConstValue, SourceInfo}; use crate::ty::{self, CoroutineArgsExt, Ty}; rustc_index::newtype_index! { - #[derive(HashStable)] + #[stable_hash] #[encodable] #[debug_format = "_s{}"] pub struct CoroutineSavedLocal {} diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 18456e763078d..881165706a034 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -44,7 +44,7 @@ macro_rules! thir_with_elements { ) => { $( newtype_index! { - #[derive(HashStable)] + #[stable_hash] #[debug_format = $format] pub struct $id {} } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 2c5e4957d0aed..b8399215cf810 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -716,7 +716,7 @@ impl<'a> LocalSetInContextMut<'a> { } rustc_index::newtype_index! { - #[derive(HashStable)] + #[stable_hash] #[encodable] #[debug_format = "UserType({})"] pub struct UserTypeAnnotationIndex { diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 9e8de4926c6ed..a1e5d810afc02 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -161,7 +161,7 @@ struct TOFinder<'a, 'tcx> { } rustc_index::newtype_index! { - #[derive(Ord, PartialOrd)] + #[orderable] #[debug_format = "_c{}"] struct ConditionIndex {} } diff --git a/compiler/rustc_monomorphize/src/graph_checks/statics.rs b/compiler/rustc_monomorphize/src/graph_checks/statics.rs index a764d307b3d4b..90993e55906f2 100644 --- a/compiler/rustc_monomorphize/src/graph_checks/statics.rs +++ b/compiler/rustc_monomorphize/src/graph_checks/statics.rs @@ -30,7 +30,7 @@ impl From for StaticNodeIdx { } newtype_index! { - #[derive(Ord, PartialOrd)] + #[orderable] struct StaticSccIdx {} } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 3d9fc7f5c998d..498ca60a48e30 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -122,7 +122,7 @@ rustc_index::newtype_index! { /// is the outer fn. /// /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index - #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] + #[stable_hash_no_context] #[encodable] #[orderable] #[debug_format = "DebruijnIndex({})"] @@ -332,7 +332,7 @@ rustc_index::newtype_index! { /// declared, but a type name in a non-zero universe is a placeholder /// type -- an idealized representative of "types in general" that we /// use for checking generic functions. - #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] + #[stable_hash_no_context] #[encodable] #[orderable] #[debug_format = "U{}"] @@ -387,7 +387,7 @@ impl Default for UniverseIndex { } rustc_index::newtype_index! { - #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] + #[stable_hash_generic] #[encodable] #[orderable] #[debug_format = "{}"] diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index e08c274f9f147..6a2fb95e467fd 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -4,7 +4,7 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] -use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext}; use rustc_type_ir_macros::GenericTypeVisitable; use self::RegionKind::*; @@ -16,7 +16,7 @@ rustc_index::newtype_index! { #[orderable] #[debug_format = "'?{}"] #[gate_rustc_only] - #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] + #[stable_hash_no_context] pub struct RegionVid {} }