Auto merge of #116125 - RalfJung:const-param-ty-eq, r=compiler-errors

ConstParamTy: require Eq as supertrait

As discussed with `@BoxyUwu` [on Zulip](https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/.60ConstParamTy.60.20and.20.60Eq.60).

We want to say that valtree equality on const generic params agrees with `==`, but that only makes sense if `==` actually exists, hence we should have an appropriate bound. Valtree equality is an equivalence relation, so such a type can always be `Eq` and not just `PartialEq`.
This commit is contained in:
bors 2023-09-26 05:33:55 +00:00
commit 27b4eb96d1
5 changed files with 44 additions and 6 deletions

View File

@ -41,7 +41,7 @@ pub fn expand_deriving_const_param_ty(
path: path_std!(marker::ConstParamTy), path: path_std!(marker::ConstParamTy),
skip_path_as_bound: false, skip_path_as_bound: false,
needs_copy_as_bound_if_packed: false, needs_copy_as_bound_if_packed: false,
additional_bounds: Vec::new(), additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
supports_unions: false, supports_unions: false,
methods: Vec::new(), methods: Vec::new(),
associated_types: Vec::new(), associated_types: Vec::new(),

View File

@ -2596,7 +2596,9 @@ fn show_candidates(
); );
if let [first, .., last] = &path[..] { if let [first, .., last] = &path[..] {
let sp = first.ident.span.until(last.ident.span); let sp = first.ident.span.until(last.ident.span);
if sp.can_be_used_for_suggestions() { // Our suggestion is empty, so make sure the span is not empty (or we'd ICE).
// Can happen for derive-generated spans.
if sp.can_be_used_for_suggestions() && !sp.is_empty() {
err.span_suggestion_verbose( err.span_suggestion_verbose(
sp, sp,
format!("if you import `{}`, refer to it directly", last.ident), format!("if you import `{}`, refer to it directly", last.ident),

View File

@ -986,11 +986,16 @@ pub trait Tuple {}
pub trait PointerLike {} pub trait PointerLike {}
/// A marker for types which can be used as types of `const` generic parameters. /// A marker for types which can be used as types of `const` generic parameters.
///
/// These types must have a proper equivalence relation (`Eq`) and it must be automatically
/// derived (`StructuralPartialEq`). There's a hard-coded check in the compiler ensuring
/// that all fields are also `ConstParamTy`, which implies that recursively, all fields
/// are `StructuralPartialEq`.
#[lang = "const_param_ty"] #[lang = "const_param_ty"]
#[unstable(feature = "adt_const_params", issue = "95174")] #[unstable(feature = "adt_const_params", issue = "95174")]
#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
#[allow(multiple_supertrait_upcastable)] #[allow(multiple_supertrait_upcastable)]
pub trait ConstParamTy: StructuralEq + StructuralPartialEq {} pub trait ConstParamTy: StructuralEq + StructuralPartialEq + Eq {}
/// Derive macro generating an impl of the trait `ConstParamTy`. /// Derive macro generating an impl of the trait `ConstParamTy`.
#[rustc_builtin_macro] #[rustc_builtin_macro]

View File

@ -10,10 +10,12 @@ struct CantParam(ImplementsConstParamTy);
impl std::marker::ConstParamTy for CantParam {} impl std::marker::ConstParamTy for CantParam {}
//~^ error: the type `CantParam` does not `#[derive(Eq)]` //~^ error: the type `CantParam` does not `#[derive(Eq)]`
//~| error: the type `CantParam` does not `#[derive(PartialEq)]` //~| error: the type `CantParam` does not `#[derive(PartialEq)]`
//~| the trait bound `CantParam: Eq` is not satisfied
#[derive(std::marker::ConstParamTy)] #[derive(std::marker::ConstParamTy)]
//~^ error: the type `CantParamDerive` does not `#[derive(Eq)]` //~^ error: the type `CantParamDerive` does not `#[derive(Eq)]`
//~| error: the type `CantParamDerive` does not `#[derive(PartialEq)]` //~| error: the type `CantParamDerive` does not `#[derive(PartialEq)]`
//~| the trait bound `CantParamDerive: Eq` is not satisfied
struct CantParamDerive(ImplementsConstParamTy); struct CantParamDerive(ImplementsConstParamTy);
fn check<T: std::marker::ConstParamTy>() {} fn check<T: std::marker::ConstParamTy>() {}

View File

@ -1,3 +1,17 @@
error[E0277]: the trait bound `CantParam: Eq` is not satisfied
--> $DIR/const_param_ty_impl_no_structural_eq.rs:10:36
|
LL | impl std::marker::ConstParamTy for CantParam {}
| ^^^^^^^^^ the trait `Eq` is not implemented for `CantParam`
|
note: required by a bound in `ConstParamTy`
--> $SRC_DIR/core/src/marker.rs:LL:COL
help: consider annotating `CantParam` with `#[derive(Eq)]`
|
LL + #[derive(Eq)]
LL | struct CantParam(ImplementsConstParamTy);
|
error[E0277]: the type `CantParam` does not `#[derive(PartialEq)]` error[E0277]: the type `CantParam` does not `#[derive(PartialEq)]`
--> $DIR/const_param_ty_impl_no_structural_eq.rs:10:36 --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:36
| |
@ -16,8 +30,23 @@ LL | impl std::marker::ConstParamTy for CantParam {}
note: required by a bound in `ConstParamTy` note: required by a bound in `ConstParamTy`
--> $SRC_DIR/core/src/marker.rs:LL:COL --> $SRC_DIR/core/src/marker.rs:LL:COL
error[E0277]: the trait bound `CantParamDerive: Eq` is not satisfied
--> $DIR/const_param_ty_impl_no_structural_eq.rs:15:10
|
LL | #[derive(std::marker::ConstParamTy)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive`
|
note: required by a bound in `ConstParamTy`
--> $SRC_DIR/core/src/marker.rs:LL:COL
= note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `CantParamDerive` with `#[derive(Eq)]`
|
LL + #[derive(Eq)]
LL | struct CantParamDerive(ImplementsConstParamTy);
|
error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]` error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]`
--> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:10
| |
LL | #[derive(std::marker::ConstParamTy)] LL | #[derive(std::marker::ConstParamTy)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralPartialEq` is not implemented for `CantParamDerive` | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralPartialEq` is not implemented for `CantParamDerive`
@ -27,7 +56,7 @@ note: required by a bound in `ConstParamTy`
= note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the type `CantParamDerive` does not `#[derive(Eq)]` error[E0277]: the type `CantParamDerive` does not `#[derive(Eq)]`
--> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:10
| |
LL | #[derive(std::marker::ConstParamTy)] LL | #[derive(std::marker::ConstParamTy)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParamDerive` | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParamDerive`
@ -36,6 +65,6 @@ note: required by a bound in `ConstParamTy`
--> $SRC_DIR/core/src/marker.rs:LL:COL --> $SRC_DIR/core/src/marker.rs:LL:COL
= note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0277`.