Auto merge of #128246 - GrigorenkoPV:derive-where, r=compiler-errors
Don't manually implement `PartialEq` for some types in `rustc_type_ir` > > As a follow-up, we should look at not manually implementing PartialEq for these types but instead going thru a derive > > I will try to tackle this later in a separate PR https://github.com/rust-lang/rust/issues/127042#issuecomment-2218838446
This commit is contained in:
commit
188ddf4d6a
@ -1,5 +1,3 @@
|
||||
#![allow(clippy::derived_hash_with_manual_eq)]
|
||||
|
||||
use derive_where::derive_where;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
@ -141,7 +139,7 @@ pub fn expect_placeholder_index(self) -> usize {
|
||||
/// Describes the "kind" of the canonical variable. This is a "kind"
|
||||
/// in the type-theory sense of the term -- i.e., a "meta" type system
|
||||
/// that analyzes type-like values.
|
||||
#[derive_where(Clone, Copy, Hash, Eq, Debug; I: Interner)]
|
||||
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub enum CanonicalVarKind<I: Interner> {
|
||||
@ -169,21 +167,6 @@ pub enum CanonicalVarKind<I: Interner> {
|
||||
PlaceholderConst(I::PlaceholderConst),
|
||||
}
|
||||
|
||||
// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
|
||||
impl<I: Interner> PartialEq for CanonicalVarKind<I> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::Ty(l0), Self::Ty(r0)) => l0 == r0,
|
||||
(Self::PlaceholderTy(l0), Self::PlaceholderTy(r0)) => l0 == r0,
|
||||
(Self::Region(l0), Self::Region(r0)) => l0 == r0,
|
||||
(Self::PlaceholderRegion(l0), Self::PlaceholderRegion(r0)) => l0 == r0,
|
||||
(Self::Const(l0), Self::Const(r0)) => l0 == r0,
|
||||
(Self::PlaceholderConst(l0), Self::PlaceholderConst(r0)) => l0 == r0,
|
||||
_ => std::mem::discriminant(self) == std::mem::discriminant(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> CanonicalVarKind<I> {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
match self {
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![allow(clippy::derived_hash_with_manual_eq)]
|
||||
|
||||
use derive_where::derive_where;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
@ -10,10 +8,8 @@
|
||||
|
||||
use crate::{self as ty, DebruijnIndex, Interner};
|
||||
|
||||
use self::ConstKind::*;
|
||||
|
||||
/// Represents a constant in Rust.
|
||||
#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
|
||||
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum ConstKind<I: Interner> {
|
||||
/// A const generic parameter.
|
||||
@ -45,23 +41,6 @@ pub enum ConstKind<I: Interner> {
|
||||
Expr(I::ExprConst),
|
||||
}
|
||||
|
||||
// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
|
||||
impl<I: Interner> PartialEq for ConstKind<I> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Param(l0), Param(r0)) => l0 == r0,
|
||||
(Infer(l0), Infer(r0)) => l0 == r0,
|
||||
(Bound(l0, l1), Bound(r0, r1)) => l0 == r0 && l1 == r1,
|
||||
(Placeholder(l0), Placeholder(r0)) => l0 == r0,
|
||||
(Unevaluated(l0), Unevaluated(r0)) => l0 == r0,
|
||||
(Value(l0, l1), Value(r0, r1)) => l0 == r0 && l1 == r1,
|
||||
(Error(l0), Error(r0)) => l0 == r0,
|
||||
(Expr(l0), Expr(r0)) => l0 == r0,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for ConstKind<I> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
use ConstKind::*;
|
||||
@ -80,7 +59,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
}
|
||||
|
||||
/// An unevaluated (potentially generic) constant used in the type-system.
|
||||
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
|
||||
#[derive_where(Clone, Copy, Debug, Hash, PartialEq, Eq; I: Interner)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct UnevaluatedConst<I: Interner> {
|
||||
@ -95,15 +74,6 @@ pub fn new(def: I::DefId, args: I::GenericArgs) -> UnevaluatedConst<I> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for UnevaluatedConst<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("UnevaluatedConst")
|
||||
.field("def", &self.def)
|
||||
.field("args", &self.args)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// A **`const`** **v**ariable **ID**.
|
||||
#[encodable]
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![allow(clippy::derived_hash_with_manual_eq)]
|
||||
|
||||
use derive_where::derive_where;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
@ -10,7 +8,7 @@
|
||||
|
||||
/// A clause is something that can appear in where bounds or be inferred
|
||||
/// by implied bounds.
|
||||
#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
|
||||
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum ClauseKind<I: Interner> {
|
||||
@ -40,22 +38,6 @@ pub enum ClauseKind<I: Interner> {
|
||||
ConstEvaluatable(I::Const),
|
||||
}
|
||||
|
||||
// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
|
||||
impl<I: Interner> PartialEq for ClauseKind<I> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::Trait(l0), Self::Trait(r0)) => l0 == r0,
|
||||
(Self::RegionOutlives(l0), Self::RegionOutlives(r0)) => l0 == r0,
|
||||
(Self::TypeOutlives(l0), Self::TypeOutlives(r0)) => l0 == r0,
|
||||
(Self::Projection(l0), Self::Projection(r0)) => l0 == r0,
|
||||
(Self::ConstArgHasType(l0, l1), Self::ConstArgHasType(r0, r1)) => l0 == r0 && l1 == r1,
|
||||
(Self::WellFormed(l0), Self::WellFormed(r0)) => l0 == r0,
|
||||
(Self::ConstEvaluatable(l0), Self::ConstEvaluatable(r0)) => l0 == r0,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![allow(clippy::derived_hash_with_manual_eq)]
|
||||
|
||||
use derive_where::derive_where;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
@ -127,7 +125,7 @@ pub struct RegionVid {}
|
||||
/// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
|
||||
/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
|
||||
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
|
||||
#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
|
||||
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
|
||||
pub enum RegionKind<I: Interner> {
|
||||
/// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
|
||||
@ -179,48 +177,6 @@ pub enum RegionKind<I: Interner> {
|
||||
ReError(I::ErrorGuaranteed),
|
||||
}
|
||||
|
||||
// This is manually implemented for `RegionKind` because `std::mem::discriminant`
|
||||
// returns an opaque value that is `PartialEq` but not `PartialOrd`
|
||||
#[inline]
|
||||
const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
|
||||
match value {
|
||||
ReEarlyParam(_) => 0,
|
||||
ReBound(_, _) => 1,
|
||||
ReLateParam(_) => 2,
|
||||
ReStatic => 3,
|
||||
ReVar(_) => 4,
|
||||
RePlaceholder(_) => 5,
|
||||
ReErased => 6,
|
||||
ReError(_) => 7,
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
|
||||
// This is manually implemented because a derive would require `I: PartialEq`
|
||||
impl<I: Interner> PartialEq for RegionKind<I> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &RegionKind<I>) -> bool {
|
||||
regionkind_discriminant(self) == regionkind_discriminant(other)
|
||||
&& match (self, other) {
|
||||
(ReEarlyParam(a_r), ReEarlyParam(b_r)) => a_r == b_r,
|
||||
(ReBound(a_d, a_r), ReBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
|
||||
(ReLateParam(a_r), ReLateParam(b_r)) => a_r == b_r,
|
||||
(ReStatic, ReStatic) => true,
|
||||
(ReVar(a_r), ReVar(b_r)) => a_r == b_r,
|
||||
(RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
|
||||
(ReErased, ReErased) => true,
|
||||
(ReError(_), ReError(_)) => true,
|
||||
_ => {
|
||||
debug_assert!(
|
||||
false,
|
||||
"This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
|
||||
);
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for RegionKind<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![allow(clippy::derived_hash_with_manual_eq)]
|
||||
|
||||
use derive_where::derive_where;
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
@ -68,7 +66,7 @@ pub fn descr(self) -> &'static str {
|
||||
/// Types written by the user start out as `hir::TyKind` and get
|
||||
/// converted to this representation using `<dyn HirTyLowerer>::lower_ty`.
|
||||
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
|
||||
#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
|
||||
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum TyKind<I: Interner> {
|
||||
/// The primitive boolean type. Written as `bool`.
|
||||
@ -259,92 +257,6 @@ pub fn is_primitive(&self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
// This is manually implemented for `TyKind` because `std::mem::discriminant`
|
||||
// returns an opaque value that is `PartialEq` but not `PartialOrd`
|
||||
#[inline]
|
||||
const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
|
||||
match value {
|
||||
Bool => 0,
|
||||
Char => 1,
|
||||
Int(_) => 2,
|
||||
Uint(_) => 3,
|
||||
Float(_) => 4,
|
||||
Adt(_, _) => 5,
|
||||
Foreign(_) => 6,
|
||||
Str => 7,
|
||||
Array(_, _) => 8,
|
||||
Slice(_) => 9,
|
||||
RawPtr(_, _) => 10,
|
||||
Ref(_, _, _) => 11,
|
||||
FnDef(_, _) => 12,
|
||||
FnPtr(_) => 13,
|
||||
Dynamic(..) => 14,
|
||||
Closure(_, _) => 15,
|
||||
CoroutineClosure(_, _) => 16,
|
||||
Coroutine(_, _) => 17,
|
||||
CoroutineWitness(_, _) => 18,
|
||||
Never => 19,
|
||||
Tuple(_) => 20,
|
||||
Pat(_, _) => 21,
|
||||
Alias(_, _) => 22,
|
||||
Param(_) => 23,
|
||||
Bound(_, _) => 24,
|
||||
Placeholder(_) => 25,
|
||||
Infer(_) => 26,
|
||||
Error(_) => 27,
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
|
||||
// This is manually implemented because a derive would require `I: PartialEq`
|
||||
impl<I: Interner> PartialEq for TyKind<I> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &TyKind<I>) -> bool {
|
||||
// You might expect this `match` to be preceded with this:
|
||||
//
|
||||
// tykind_discriminant(self) == tykind_discriminant(other) &&
|
||||
//
|
||||
// but the data patterns in practice are such that a comparison
|
||||
// succeeds 99%+ of the time, and it's faster to omit it.
|
||||
match (self, other) {
|
||||
(Int(a_i), Int(b_i)) => a_i == b_i,
|
||||
(Uint(a_u), Uint(b_u)) => a_u == b_u,
|
||||
(Float(a_f), Float(b_f)) => a_f == b_f,
|
||||
(Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s,
|
||||
(Foreign(a_d), Foreign(b_d)) => a_d == b_d,
|
||||
(Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c,
|
||||
(Pat(a_t, a_c), Pat(b_t, b_c)) => a_t == b_t && a_c == b_c,
|
||||
(Slice(a_t), Slice(b_t)) => a_t == b_t,
|
||||
(RawPtr(a_t, a_m), RawPtr(b_t, b_m)) => a_t == b_t && a_m == b_m,
|
||||
(Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m,
|
||||
(FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s,
|
||||
(FnPtr(a_s), FnPtr(b_s)) => a_s == b_s,
|
||||
(Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
|
||||
a_p == b_p && a_r == b_r && a_repr == b_repr
|
||||
}
|
||||
(Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
|
||||
(CoroutineClosure(a_d, a_s), CoroutineClosure(b_d, b_s)) => a_d == b_d && a_s == b_s,
|
||||
(Coroutine(a_d, a_s), Coroutine(b_d, b_s)) => a_d == b_d && a_s == b_s,
|
||||
(CoroutineWitness(a_d, a_s), CoroutineWitness(b_d, b_s)) => a_d == b_d && a_s == b_s,
|
||||
(Tuple(a_t), Tuple(b_t)) => a_t == b_t,
|
||||
(Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
|
||||
(Param(a_p), Param(b_p)) => a_p == b_p,
|
||||
(Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
|
||||
(Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
|
||||
(Infer(a_t), Infer(b_t)) => a_t == b_t,
|
||||
(Error(a_e), Error(b_e)) => a_e == b_e,
|
||||
(Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true,
|
||||
_ => {
|
||||
debug_assert!(
|
||||
tykind_discriminant(self) != tykind_discriminant(other),
|
||||
"This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is manually implemented because a derive would require `I: Debug`
|
||||
impl<I: Interner> fmt::Debug for TyKind<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
Loading…
Reference in New Issue
Block a user