Skip to content

Commit 188ddf4

Browse files
committed
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 #127042 (comment)
2 parents 78c8573 + 17f8361 commit 188ddf4

File tree

5 files changed

+6
-203
lines changed

5 files changed

+6
-203
lines changed

compiler/rustc_type_ir/src/canonical.rs

+1-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(clippy::derived_hash_with_manual_eq)]
2-
31
use derive_where::derive_where;
42
#[cfg(feature = "nightly")]
53
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
@@ -141,7 +139,7 @@ impl<I: Interner> CanonicalVarInfo<I> {
141139
/// Describes the "kind" of the canonical variable. This is a "kind"
142140
/// in the type-theory sense of the term -- i.e., a "meta" type system
143141
/// that analyzes type-like values.
144-
#[derive_where(Clone, Copy, Hash, Eq, Debug; I: Interner)]
142+
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
145143
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
146144
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
147145
pub enum CanonicalVarKind<I: Interner> {
@@ -169,21 +167,6 @@ pub enum CanonicalVarKind<I: Interner> {
169167
PlaceholderConst(I::PlaceholderConst),
170168
}
171169

172-
// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
173-
impl<I: Interner> PartialEq for CanonicalVarKind<I> {
174-
fn eq(&self, other: &Self) -> bool {
175-
match (self, other) {
176-
(Self::Ty(l0), Self::Ty(r0)) => l0 == r0,
177-
(Self::PlaceholderTy(l0), Self::PlaceholderTy(r0)) => l0 == r0,
178-
(Self::Region(l0), Self::Region(r0)) => l0 == r0,
179-
(Self::PlaceholderRegion(l0), Self::PlaceholderRegion(r0)) => l0 == r0,
180-
(Self::Const(l0), Self::Const(r0)) => l0 == r0,
181-
(Self::PlaceholderConst(l0), Self::PlaceholderConst(r0)) => l0 == r0,
182-
_ => std::mem::discriminant(self) == std::mem::discriminant(other),
183-
}
184-
}
185-
}
186-
187170
impl<I: Interner> CanonicalVarKind<I> {
188171
pub fn universe(self) -> UniverseIndex {
189172
match self {

compiler/rustc_type_ir/src/const_kind.rs

+2-32
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(clippy::derived_hash_with_manual_eq)]
2-
31
use derive_where::derive_where;
42
#[cfg(feature = "nightly")]
53
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -10,10 +8,8 @@ use std::fmt;
108

119
use crate::{self as ty, DebruijnIndex, Interner};
1210

13-
use self::ConstKind::*;
14-
1511
/// Represents a constant in Rust.
16-
#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
12+
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
1713
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
1814
pub enum ConstKind<I: Interner> {
1915
/// A const generic parameter.
@@ -45,23 +41,6 @@ pub enum ConstKind<I: Interner> {
4541
Expr(I::ExprConst),
4642
}
4743

48-
// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
49-
impl<I: Interner> PartialEq for ConstKind<I> {
50-
fn eq(&self, other: &Self) -> bool {
51-
match (self, other) {
52-
(Param(l0), Param(r0)) => l0 == r0,
53-
(Infer(l0), Infer(r0)) => l0 == r0,
54-
(Bound(l0, l1), Bound(r0, r1)) => l0 == r0 && l1 == r1,
55-
(Placeholder(l0), Placeholder(r0)) => l0 == r0,
56-
(Unevaluated(l0), Unevaluated(r0)) => l0 == r0,
57-
(Value(l0, l1), Value(r0, r1)) => l0 == r0 && l1 == r1,
58-
(Error(l0), Error(r0)) => l0 == r0,
59-
(Expr(l0), Expr(r0)) => l0 == r0,
60-
_ => false,
61-
}
62-
}
63-
}
64-
6544
impl<I: Interner> fmt::Debug for ConstKind<I> {
6645
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6746
use ConstKind::*;
@@ -80,7 +59,7 @@ impl<I: Interner> fmt::Debug for ConstKind<I> {
8059
}
8160

8261
/// An unevaluated (potentially generic) constant used in the type-system.
83-
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
62+
#[derive_where(Clone, Copy, Debug, Hash, PartialEq, Eq; I: Interner)]
8463
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
8564
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
8665
pub struct UnevaluatedConst<I: Interner> {
@@ -95,15 +74,6 @@ impl<I: Interner> UnevaluatedConst<I> {
9574
}
9675
}
9776

98-
impl<I: Interner> fmt::Debug for UnevaluatedConst<I> {
99-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100-
f.debug_struct("UnevaluatedConst")
101-
.field("def", &self.def)
102-
.field("args", &self.args)
103-
.finish()
104-
}
105-
}
106-
10777
rustc_index::newtype_index! {
10878
/// A **`const`** **v**ariable **ID**.
10979
#[encodable]

compiler/rustc_type_ir/src/predicate_kind.rs

+1-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(clippy::derived_hash_with_manual_eq)]
2-
31
use derive_where::derive_where;
42
#[cfg(feature = "nightly")]
53
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
@@ -10,7 +8,7 @@ use crate::{self as ty, Interner};
108

119
/// A clause is something that can appear in where bounds or be inferred
1210
/// by implied bounds.
13-
#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
11+
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
1412
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
1513
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
1614
pub enum ClauseKind<I: Interner> {
@@ -40,22 +38,6 @@ pub enum ClauseKind<I: Interner> {
4038
ConstEvaluatable(I::Const),
4139
}
4240

43-
// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
44-
impl<I: Interner> PartialEq for ClauseKind<I> {
45-
fn eq(&self, other: &Self) -> bool {
46-
match (self, other) {
47-
(Self::Trait(l0), Self::Trait(r0)) => l0 == r0,
48-
(Self::RegionOutlives(l0), Self::RegionOutlives(r0)) => l0 == r0,
49-
(Self::TypeOutlives(l0), Self::TypeOutlives(r0)) => l0 == r0,
50-
(Self::Projection(l0), Self::Projection(r0)) => l0 == r0,
51-
(Self::ConstArgHasType(l0, l1), Self::ConstArgHasType(r0, r1)) => l0 == r0 && l1 == r1,
52-
(Self::WellFormed(l0), Self::WellFormed(r0)) => l0 == r0,
53-
(Self::ConstEvaluatable(l0), Self::ConstEvaluatable(r0)) => l0 == r0,
54-
_ => false,
55-
}
56-
}
57-
}
58-
5941
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
6042
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
6143
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]

compiler/rustc_type_ir/src/region_kind.rs

+1-45
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(clippy::derived_hash_with_manual_eq)]
2-
31
use derive_where::derive_where;
42
#[cfg(feature = "nightly")]
53
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -127,7 +125,7 @@ rustc_index::newtype_index! {
127125
/// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
128126
/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
129127
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
130-
#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
128+
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
131129
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
132130
pub enum RegionKind<I: Interner> {
133131
/// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
@@ -179,48 +177,6 @@ pub enum RegionKind<I: Interner> {
179177
ReError(I::ErrorGuaranteed),
180178
}
181179

182-
// This is manually implemented for `RegionKind` because `std::mem::discriminant`
183-
// returns an opaque value that is `PartialEq` but not `PartialOrd`
184-
#[inline]
185-
const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
186-
match value {
187-
ReEarlyParam(_) => 0,
188-
ReBound(_, _) => 1,
189-
ReLateParam(_) => 2,
190-
ReStatic => 3,
191-
ReVar(_) => 4,
192-
RePlaceholder(_) => 5,
193-
ReErased => 6,
194-
ReError(_) => 7,
195-
}
196-
}
197-
198-
// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
199-
// This is manually implemented because a derive would require `I: PartialEq`
200-
impl<I: Interner> PartialEq for RegionKind<I> {
201-
#[inline]
202-
fn eq(&self, other: &RegionKind<I>) -> bool {
203-
regionkind_discriminant(self) == regionkind_discriminant(other)
204-
&& match (self, other) {
205-
(ReEarlyParam(a_r), ReEarlyParam(b_r)) => a_r == b_r,
206-
(ReBound(a_d, a_r), ReBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
207-
(ReLateParam(a_r), ReLateParam(b_r)) => a_r == b_r,
208-
(ReStatic, ReStatic) => true,
209-
(ReVar(a_r), ReVar(b_r)) => a_r == b_r,
210-
(RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
211-
(ReErased, ReErased) => true,
212-
(ReError(_), ReError(_)) => true,
213-
_ => {
214-
debug_assert!(
215-
false,
216-
"This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
217-
);
218-
true
219-
}
220-
}
221-
}
222-
}
223-
224180
impl<I: Interner> fmt::Debug for RegionKind<I> {
225181
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226182
match self {

compiler/rustc_type_ir/src/ty_kind.rs

+1-89
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(clippy::derived_hash_with_manual_eq)]
2-
31
use derive_where::derive_where;
42

53
#[cfg(feature = "nightly")]
@@ -68,7 +66,7 @@ impl AliasTyKind {
6866
/// Types written by the user start out as `hir::TyKind` and get
6967
/// converted to this representation using `<dyn HirTyLowerer>::lower_ty`.
7068
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
71-
#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
69+
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
7270
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
7371
pub enum TyKind<I: Interner> {
7472
/// The primitive boolean type. Written as `bool`.
@@ -259,92 +257,6 @@ impl<I: Interner> TyKind<I> {
259257
}
260258
}
261259

262-
// This is manually implemented for `TyKind` because `std::mem::discriminant`
263-
// returns an opaque value that is `PartialEq` but not `PartialOrd`
264-
#[inline]
265-
const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
266-
match value {
267-
Bool => 0,
268-
Char => 1,
269-
Int(_) => 2,
270-
Uint(_) => 3,
271-
Float(_) => 4,
272-
Adt(_, _) => 5,
273-
Foreign(_) => 6,
274-
Str => 7,
275-
Array(_, _) => 8,
276-
Slice(_) => 9,
277-
RawPtr(_, _) => 10,
278-
Ref(_, _, _) => 11,
279-
FnDef(_, _) => 12,
280-
FnPtr(_) => 13,
281-
Dynamic(..) => 14,
282-
Closure(_, _) => 15,
283-
CoroutineClosure(_, _) => 16,
284-
Coroutine(_, _) => 17,
285-
CoroutineWitness(_, _) => 18,
286-
Never => 19,
287-
Tuple(_) => 20,
288-
Pat(_, _) => 21,
289-
Alias(_, _) => 22,
290-
Param(_) => 23,
291-
Bound(_, _) => 24,
292-
Placeholder(_) => 25,
293-
Infer(_) => 26,
294-
Error(_) => 27,
295-
}
296-
}
297-
298-
// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
299-
// This is manually implemented because a derive would require `I: PartialEq`
300-
impl<I: Interner> PartialEq for TyKind<I> {
301-
#[inline]
302-
fn eq(&self, other: &TyKind<I>) -> bool {
303-
// You might expect this `match` to be preceded with this:
304-
//
305-
// tykind_discriminant(self) == tykind_discriminant(other) &&
306-
//
307-
// but the data patterns in practice are such that a comparison
308-
// succeeds 99%+ of the time, and it's faster to omit it.
309-
match (self, other) {
310-
(Int(a_i), Int(b_i)) => a_i == b_i,
311-
(Uint(a_u), Uint(b_u)) => a_u == b_u,
312-
(Float(a_f), Float(b_f)) => a_f == b_f,
313-
(Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s,
314-
(Foreign(a_d), Foreign(b_d)) => a_d == b_d,
315-
(Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c,
316-
(Pat(a_t, a_c), Pat(b_t, b_c)) => a_t == b_t && a_c == b_c,
317-
(Slice(a_t), Slice(b_t)) => a_t == b_t,
318-
(RawPtr(a_t, a_m), RawPtr(b_t, b_m)) => a_t == b_t && a_m == b_m,
319-
(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,
320-
(FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s,
321-
(FnPtr(a_s), FnPtr(b_s)) => a_s == b_s,
322-
(Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
323-
a_p == b_p && a_r == b_r && a_repr == b_repr
324-
}
325-
(Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
326-
(CoroutineClosure(a_d, a_s), CoroutineClosure(b_d, b_s)) => a_d == b_d && a_s == b_s,
327-
(Coroutine(a_d, a_s), Coroutine(b_d, b_s)) => a_d == b_d && a_s == b_s,
328-
(CoroutineWitness(a_d, a_s), CoroutineWitness(b_d, b_s)) => a_d == b_d && a_s == b_s,
329-
(Tuple(a_t), Tuple(b_t)) => a_t == b_t,
330-
(Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
331-
(Param(a_p), Param(b_p)) => a_p == b_p,
332-
(Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
333-
(Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
334-
(Infer(a_t), Infer(b_t)) => a_t == b_t,
335-
(Error(a_e), Error(b_e)) => a_e == b_e,
336-
(Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true,
337-
_ => {
338-
debug_assert!(
339-
tykind_discriminant(self) != tykind_discriminant(other),
340-
"This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
341-
);
342-
false
343-
}
344-
}
345-
}
346-
}
347-
348260
// This is manually implemented because a derive would require `I: Debug`
349261
impl<I: Interner> fmt::Debug for TyKind<I> {
350262
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

0 commit comments

Comments
 (0)