Skip to content

Commit dd2559e

Browse files
committed
Auto merge of rust-lang#116167 - RalfJung:structural-eq, r=lcnr
remove StructuralEq trait The documentation given for the trait is outdated: *all* function pointers implement `PartialEq` and `Eq` these days. So the `StructuralEq` trait doesn't really seem to have any reason to exist any more. One side-effect of this PR is that we allow matching on some consts that do not implement `Eq`. However, we already allowed matching on floats and consts containing floats, so this is not new, it is just allowed in more cases now. IMO it makes no sense at all to allow float matching but also sometimes require an `Eq` instance. If we want to require `Eq` we should adjust rust-lang#115893 to check for `Eq`, and rule out float matching for good. Fixes rust-lang#115881
2 parents 0c1fb2a + 0df7810 commit dd2559e

File tree

76 files changed

+266
-529
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+266
-529
lines changed

compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs

-13
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,6 @@ pub fn expand_deriving_eq(
1919
) {
2020
let span = cx.with_def_site_ctxt(span);
2121

22-
let structural_trait_def = TraitDef {
23-
span,
24-
path: path_std!(marker::StructuralEq),
25-
skip_path_as_bound: true, // crucial!
26-
needs_copy_as_bound_if_packed: false,
27-
additional_bounds: Vec::new(),
28-
supports_unions: true,
29-
methods: Vec::new(),
30-
associated_types: Vec::new(),
31-
is_const: false,
32-
};
33-
structural_trait_def.expand(cx, mitem, item, push);
34-
3522
let trait_def = TraitDef {
3623
span,
3724
path: path_std!(cmp::Eq),

compiler/rustc_codegen_cranelift/example/mini_core.rs

-3
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,6 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
104104
#[lang = "structural_peq"]
105105
pub trait StructuralPartialEq {}
106106

107-
#[lang = "structural_teq"]
108-
pub trait StructuralEq {}
109-
110107
#[lang = "not"]
111108
pub trait Not {
112109
type Output;

compiler/rustc_codegen_gcc/example/mini_core.rs

-3
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,6 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
100100
#[lang = "structural_peq"]
101101
pub trait StructuralPartialEq {}
102102

103-
#[lang = "structural_teq"]
104-
pub trait StructuralEq {}
105-
106103
#[lang = "not"]
107104
pub trait Not {
108105
type Output;

compiler/rustc_codegen_gcc/tests/run/static.rs

-3
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@ mod libc {
6161
#[lang = "structural_peq"]
6262
pub trait StructuralPartialEq {}
6363

64-
#[lang = "structural_teq"]
65-
pub trait StructuralEq {}
66-
6764
#[lang = "drop_in_place"]
6865
#[allow(unconditional_recursion)]
6966
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
138138
}
139139
// Trait objects are not allowed in type level constants, as we have no concept for
140140
// resolving their backing type, even if we can do that at const eval time. We may
141-
// hypothetically be able to allow `dyn StructuralEq` trait objects in the future,
141+
// hypothetically be able to allow `dyn StructuralPartialEq` trait objects in the future,
142142
// but it is unclear if this is useful.
143143
ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType),
144144

compiler/rustc_hir/src/lang_items.rs

-2
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,6 @@ language_item_table! {
143143
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
144144
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
145145
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
146-
/// Trait injected by `#[derive(Eq)]`, (i.e. "Total EQ"; no, I will not apologize).
147-
StructuralTeq, sym::structural_teq, structural_teq_trait, Target::Trait, GenericRequirement::None;
148146
Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
149147
Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
150148
Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);

compiler/rustc_middle/src/query/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1360,9 +1360,9 @@ rustc_queries! {
13601360
///
13611361
/// This is only correct for ADTs. Call `is_structural_eq_shallow` to handle all types
13621362
/// correctly.
1363-
query has_structural_eq_impls(ty: Ty<'tcx>) -> bool {
1363+
query has_structural_eq_impl(ty: Ty<'tcx>) -> bool {
13641364
desc {
1365-
"computing whether `{}` implements `PartialStructuralEq` and `StructuralEq`",
1365+
"computing whether `{}` implements `StructuralPartialEq`",
13661366
ty
13671367
}
13681368
}

compiler/rustc_middle/src/ty/util.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1249,19 +1249,18 @@ impl<'tcx> Ty<'tcx> {
12491249
/// Primitive types (`u32`, `str`) have structural equality by definition. For composite data
12501250
/// types, equality for the type as a whole is structural when it is the same as equality
12511251
/// between all components (fields, array elements, etc.) of that type. For ADTs, structural
1252-
/// equality is indicated by an implementation of `PartialStructuralEq` and `StructuralEq` for
1253-
/// that type.
1252+
/// equality is indicated by an implementation of `StructuralPartialEq` for that type.
12541253
///
12551254
/// This function is "shallow" because it may return `true` for a composite type whose fields
1256-
/// are not `StructuralEq`. For example, `[T; 4]` has structural equality regardless of `T`
1255+
/// are not `StructuralPartialEq`. For example, `[T; 4]` has structural equality regardless of `T`
12571256
/// because equality for arrays is determined by the equality of each array element. If you
12581257
/// want to know whether a given call to `PartialEq::eq` will proceed structurally all the way
12591258
/// down, you will need to use a type visitor.
12601259
#[inline]
12611260
pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool {
12621261
match self.kind() {
1263-
// Look for an impl of both `PartialStructuralEq` and `StructuralEq`.
1264-
ty::Adt(..) => tcx.has_structural_eq_impls(self),
1262+
// Look for an impl of `StructuralPartialEq`.
1263+
ty::Adt(..) => tcx.has_structural_eq_impl(self),
12651264

12661265
// Primitive types that satisfy `Eq`.
12671266
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Str | ty::Never => true,

compiler/rustc_mir_build/messages.ftl

+4-4
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
110110
mir_build_float_pattern = floating-point types cannot be used in patterns
111111
112112
mir_build_indirect_structural_match =
113-
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
113+
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]`
114114
115115
mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
116116
@@ -254,7 +254,7 @@ mir_build_non_partial_eq_match =
254254
to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq`
255255
256256
mir_build_nontrivial_structural_match =
257-
to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
257+
to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]`
258258
259259
mir_build_pattern_not_covered = refutable pattern in {$origin}
260260
.pattern_ty = the matched value is of type `{$pattern_ty}`
@@ -297,9 +297,9 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
297297
} into the body
298298
299299
mir_build_type_not_structural =
300-
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
300+
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]`
301301
302-
mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
302+
mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
303303
304304
mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient
305305

compiler/rustc_span/src/symbol.rs

-2
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,6 @@ symbols! {
310310
Some,
311311
SpanCtxt,
312312
String,
313-
StructuralEq,
314313
StructuralPartialEq,
315314
SubdiagnosticMessage,
316315
Sync,
@@ -1625,7 +1624,6 @@ symbols! {
16251624
struct_variant,
16261625
structural_match,
16271626
structural_peq,
1628-
structural_teq,
16291627
sub,
16301628
sub_assign,
16311629
sub_with_overflow,

compiler/rustc_trait_selection/src/traits/structural_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn search_for_structural_match_violation<'tcx>(
3939

4040
/// This implements the traversal over the structure of a given type to try to
4141
/// find instances of ADTs (specifically structs or enums) that do not implement
42-
/// the structural-match traits (`StructuralPartialEq` and `StructuralEq`).
42+
/// `StructuralPartialEq`.
4343
struct Search<'tcx> {
4444
span: Span,
4545

compiler/rustc_ty_utils/src/structural_match.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ use rustc_infer::infer::TyCtxtInferExt;
66
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
77

88
/// This method returns true if and only if `adt_ty` itself has been marked as
9-
/// eligible for structural-match: namely, if it implements both
10-
/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by
11-
/// `#[derive(PartialEq)]` and `#[derive(Eq)]`).
9+
/// eligible for structural-match: namely, if it implements
10+
/// `StructuralPartialEq` (which is injected by `#[derive(PartialEq)]`).
1211
///
1312
/// Note that this does *not* recursively check if the substructure of `adt_ty`
14-
/// implements the traits.
15-
fn has_structural_eq_impls<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
13+
/// implements the trait.
14+
fn has_structural_eq_impl<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
1615
let infcx = &tcx.infer_ctxt().build();
1716
let cause = ObligationCause::dummy();
1817

@@ -21,11 +20,6 @@ fn has_structural_eq_impls<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
2120
let structural_peq_def_id =
2221
infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span));
2322
ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id);
24-
// for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
25-
// the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
26-
let structural_teq_def_id =
27-
infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span));
28-
ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id);
2923

3024
// We deliberately skip *reporting* fulfillment errors (via
3125
// `report_fulfillment_errors`), for two reasons:
@@ -40,5 +34,5 @@ fn has_structural_eq_impls<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
4034
}
4135

4236
pub(crate) fn provide(providers: &mut Providers) {
43-
providers.has_structural_eq_impls = has_structural_eq_impls;
37+
providers.has_structural_eq_impl = has_structural_eq_impl;
4438
}

library/core/src/marker.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ pub trait Unsize<T: ?Sized> {
187187
/// Required trait for constants used in pattern matches.
188188
///
189189
/// Any type that derives `PartialEq` automatically implements this trait,
190-
/// *regardless* of whether its type-parameters implement `Eq`.
190+
/// *regardless* of whether its type-parameters implement `PartialEq`.
191191
///
192192
/// If a `const` item contains some type that does not implement this trait,
193193
/// then that type either (1.) does not implement `PartialEq` (which means the
@@ -200,7 +200,7 @@ pub trait Unsize<T: ?Sized> {
200200
/// a pattern match.
201201
///
202202
/// See also the [structural match RFC][RFC1445], and [issue 63438] which
203-
/// motivated migrating from attribute-based design to this trait.
203+
/// motivated migrating from an attribute-based design to this trait.
204204
///
205205
/// [RFC1445]: https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md
206206
/// [issue 63438]: https://github.com/rust-lang/rust/issues/63438
@@ -218,7 +218,7 @@ marker_impls! {
218218
isize, i8, i16, i32, i64, i128,
219219
bool,
220220
char,
221-
str /* Technically requires `[u8]: StructuralEq` */,
221+
str /* Technically requires `[u8]: StructuralPartialEq` */,
222222
(),
223223
{T, const N: usize} [T; N],
224224
{T} [T],
@@ -275,13 +275,15 @@ marker_impls! {
275275
#[unstable(feature = "structural_match", issue = "31434")]
276276
#[diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
277277
#[lang = "structural_teq"]
278+
#[cfg(bootstrap)]
278279
pub trait StructuralEq {
279280
// Empty.
280281
}
281282

282283
// FIXME: Remove special cases of these types from the compiler pattern checking code and always check `T: StructuralEq` instead
283284
marker_impls! {
284285
#[unstable(feature = "structural_match", issue = "31434")]
286+
#[cfg(bootstrap)]
285287
StructuralEq for
286288
usize, u8, u16, u32, u64, u128,
287289
isize, i8, i16, i32, i64, i128,
@@ -859,6 +861,7 @@ impl<T: ?Sized> Default for PhantomData<T> {
859861
impl<T: ?Sized> StructuralPartialEq for PhantomData<T> {}
860862

861863
#[unstable(feature = "structural_match", issue = "31434")]
864+
#[cfg(bootstrap)]
862865
impl<T: ?Sized> StructuralEq for PhantomData<T> {}
863866

864867
/// Compiler-internal trait used to indicate the type of enum discriminants.
@@ -1038,6 +1041,20 @@ pub trait PointerLike {}
10381041
#[unstable(feature = "adt_const_params", issue = "95174")]
10391042
#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
10401043
#[allow(multiple_supertrait_upcastable)]
1044+
#[cfg(not(bootstrap))]
1045+
pub trait ConstParamTy: StructuralPartialEq + Eq {}
1046+
1047+
/// A marker for types which can be used as types of `const` generic parameters.
1048+
///
1049+
/// These types must have a proper equivalence relation (`Eq`) and it must be automatically
1050+
/// derived (`StructuralPartialEq`). There's a hard-coded check in the compiler ensuring
1051+
/// that all fields are also `ConstParamTy`, which implies that recursively, all fields
1052+
/// are `StructuralPartialEq`.
1053+
#[lang = "const_param_ty"]
1054+
#[unstable(feature = "adt_const_params", issue = "95174")]
1055+
#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
1056+
#[allow(multiple_supertrait_upcastable)]
1057+
#[cfg(bootstrap)]
10411058
pub trait ConstParamTy: StructuralEq + StructuralPartialEq + Eq {}
10421059

10431060
/// Derive macro generating an impl of the trait `ConstParamTy`.

library/core/src/tuple.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use crate::cmp::Ordering::{self, *};
44
use crate::marker::ConstParamTy;
5-
use crate::marker::{StructuralEq, StructuralPartialEq};
5+
use crate::marker::StructuralPartialEq;
66

77
// Recursive macro for implementing n-ary tuple functions and operations
88
//
@@ -64,7 +64,8 @@ macro_rules! tuple_impls {
6464
maybe_tuple_doc! {
6565
$($T)+ @
6666
#[unstable(feature = "structural_match", issue = "31434")]
67-
impl<$($T),+> StructuralEq for ($($T,)+)
67+
#[cfg(bootstrap)]
68+
impl<$($T),+> crate::marker::StructuralEq for ($($T,)+)
6869
{}
6970
}
7071

src/tools/clippy/tests/ui/crashes/ice-6254.rs

-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ fn main() {
1111
// This used to cause an ICE (https://github.com/rust-lang/rust/issues/78071)
1212
match FOO_REF_REF {
1313
FOO_REF_REF => {},
14-
//~^ ERROR: to use a constant of type `Foo` in a pattern, `Foo` must be annotated
15-
//~| NOTE: for more information, see issue #62411 <https://github.com/rust-lang/ru
1614
Foo(_) => {},
1715
}
1816
}

src/tools/clippy/tests/ui/crashes/ice-6254.stderr

-15
This file was deleted.

tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ impl std::marker::ConstParamTy for ImplementsConstParamTy {}
88
struct CantParam(ImplementsConstParamTy);
99

1010
impl std::marker::ConstParamTy for CantParam {}
11-
//~^ error: the type `CantParam` does not `#[derive(Eq)]`
12-
//~| error: the type `CantParam` does not `#[derive(PartialEq)]`
11+
//~^ error: the type `CantParam` does not `#[derive(PartialEq)]`
1312
//~| the trait bound `CantParam: Eq` is not satisfied
1413

1514
#[derive(std::marker::ConstParamTy)]
16-
//~^ error: the type `CantParamDerive` does not `#[derive(Eq)]`
17-
//~| error: the type `CantParamDerive` does not `#[derive(PartialEq)]`
15+
//~^ error: the type `CantParamDerive` does not `#[derive(PartialEq)]`
1816
//~| the trait bound `CantParamDerive: Eq` is not satisfied
1917
struct CantParamDerive(ImplementsConstParamTy);
2018

tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr

+3-22
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,8 @@ LL | impl std::marker::ConstParamTy for CantParam {}
2121
note: required by a bound in `ConstParamTy`
2222
--> $SRC_DIR/core/src/marker.rs:LL:COL
2323

24-
error[E0277]: the type `CantParam` does not `#[derive(Eq)]`
25-
--> $DIR/const_param_ty_impl_no_structural_eq.rs:10:36
26-
|
27-
LL | impl std::marker::ConstParamTy for CantParam {}
28-
| ^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParam`
29-
|
30-
note: required by a bound in `ConstParamTy`
31-
--> $SRC_DIR/core/src/marker.rs:LL:COL
32-
3324
error[E0277]: the trait bound `CantParamDerive: Eq` is not satisfied
34-
--> $DIR/const_param_ty_impl_no_structural_eq.rs:15:10
25+
--> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10
3526
|
3627
LL | #[derive(std::marker::ConstParamTy)]
3728
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive`
@@ -46,7 +37,7 @@ LL | struct CantParamDerive(ImplementsConstParamTy);
4637
|
4738

4839
error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]`
49-
--> $DIR/const_param_ty_impl_no_structural_eq.rs:15:10
40+
--> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10
5041
|
5142
LL | #[derive(std::marker::ConstParamTy)]
5243
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralPartialEq` is not implemented for `CantParamDerive`
@@ -55,16 +46,6 @@ note: required by a bound in `ConstParamTy`
5546
--> $SRC_DIR/core/src/marker.rs:LL:COL
5647
= note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
5748

58-
error[E0277]: the type `CantParamDerive` does not `#[derive(Eq)]`
59-
--> $DIR/const_param_ty_impl_no_structural_eq.rs:15:10
60-
|
61-
LL | #[derive(std::marker::ConstParamTy)]
62-
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParamDerive`
63-
|
64-
note: required by a bound in `ConstParamTy`
65-
--> $SRC_DIR/core/src/marker.rs:LL:COL
66-
= note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
67-
68-
error: aborting due to 6 previous errors
49+
error: aborting due to 4 previous errors
6950

7051
For more information about this error, try `rustc --explain E0277`.

tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![allow(incomplete_features)]
2-
#![feature(adt_const_params, structural_match)]
2+
#![feature(adt_const_params)]
33

44
union Union {
55
a: u8,
@@ -11,7 +11,6 @@ impl PartialEq for Union {
1111
}
1212
}
1313
impl Eq for Union {}
14-
impl std::marker::StructuralEq for Union {}
1514

1615
impl std::marker::ConstParamTy for Union {}
1716
//~^ ERROR the type `Union` does not `#[derive(PartialEq)]`
@@ -28,7 +27,6 @@ impl PartialEq for UnionDerive {
2827
}
2928
}
3029
impl Eq for UnionDerive {}
31-
impl std::marker::StructuralEq for UnionDerive {}
3230

3331

3432
fn main() {}

0 commit comments

Comments
 (0)