about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-26 05:33:55 +0000
committerbors <bors@rust-lang.org>2023-09-26 05:33:55 +0000
commit27b4eb96d13106332d511be2ea6d0c008a57aa6e (patch)
tree93dbb7a7e712d667f64b0642ee7994c2eaa6e2e8
parenta6dce3bac50f14d6ef10f74b82c16e90bdb47d36 (diff)
parentad509633a261999ba9d73aff908d48da77e0245f (diff)
downloadrust-27b4eb96d13106332d511be2ea6d0c008a57aa6e.tar.gz
rust-27b4eb96d13106332d511be2ea6d0c008a57aa6e.zip
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`.
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs4
-rw-r--r--library/core/src/marker.rs7
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs2
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr35
5 files changed, 44 insertions, 6 deletions
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 2c8e6f99c67..8027ca2e7bb 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -41,7 +41,7 @@ pub fn expand_deriving_const_param_ty(
         path: path_std!(marker::ConstParamTy),
         skip_path_as_bound: 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,
         methods: Vec::new(),
         associated_types: Vec::new(),
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 9b7fd76d103..907a6b1c46c 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2596,7 +2596,9 @@ fn show_candidates(
             );
             if let [first, .., last] = &path[..] {
                 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(
                         sp,
                         format!("if you import `{}`, refer to it directly", last.ident),
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 5ec751e5168..5ed82e26a0a 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -986,11 +986,16 @@ pub trait Tuple {}
 pub trait PointerLike {}
 
 /// 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"]
 #[unstable(feature = "adt_const_params", issue = "95174")]
 #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
 #[allow(multiple_supertrait_upcastable)]
-pub trait ConstParamTy: StructuralEq + StructuralPartialEq {}
+pub trait ConstParamTy: StructuralEq + StructuralPartialEq + Eq {}
 
 /// Derive macro generating an impl of the trait `ConstParamTy`.
 #[rustc_builtin_macro]
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
index 08f7c5cb542..7174d1ec4f2 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
@@ -10,10 +10,12 @@ struct CantParam(ImplementsConstParamTy);
 impl std::marker::ConstParamTy for CantParam {}
 //~^ error: the type `CantParam` does not `#[derive(Eq)]`
 //~| error: the type `CantParam` does not `#[derive(PartialEq)]`
+//~| the trait bound `CantParam: Eq` is not satisfied
 
 #[derive(std::marker::ConstParamTy)]
 //~^ error: the type `CantParamDerive` does not `#[derive(Eq)]`
 //~| error: the type `CantParamDerive` does not `#[derive(PartialEq)]`
+//~| the trait bound `CantParamDerive: Eq` is not satisfied
 struct CantParamDerive(ImplementsConstParamTy);
 
 fn check<T: std::marker::ConstParamTy>() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
index 43c5b96dc7c..2cf7cc07dbe 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
@@ -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)]`
   --> $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`
   --> $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)]`
-  --> $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)]
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^ 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)
 
 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)]
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^ 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
    = 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`.