about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-05-25 17:37:21 +0200
committerGitHub <noreply@github.com>2022-05-25 17:37:21 +0200
commit8a3ad4942ceb02b7c7182fb45b8d063b7db20ae2 (patch)
tree473f7d746cc9dac8c0df0d782e7b3b37239a3f53
parent006707834fc1001631a1c3851f70e4793a9bb370 (diff)
parent86e8bbe4fdf547ad6bbc664282ba29f3ff4be5a6 (diff)
downloadrust-8a3ad4942ceb02b7c7182fb45b8d063b7db20ae2.tar.gz
rust-8a3ad4942ceb02b7c7182fb45b8d063b7db20ae2.zip
Rollup merge of #97351 - b-naber:adt-const-params-structural-match-violation, r=michaelwoerister
Output correct type responsible for structural match violation

Previously we included the outermost type that caused a structural match violation in the error message and stated that that type must be annotated with `#[derive(Eq, PartialEq)]` even if it already had that annotation. This PR outputs the correct type in the error message.

Fixes https://github.com/rust-lang/rust/issues/97278
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs32
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs24
-rw-r--r--src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr4
-rw-r--r--src/test/ui/const-generics/issues/issue-97278.rs14
-rw-r--r--src/test/ui/const-generics/issues/issue-97278.stderr9
7 files changed, 73 insertions, 30 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 880f86aff5d..f694e009ab9 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -121,27 +121,27 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
 
     fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
         traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
-            with_no_trimmed_paths!(match non_sm_ty {
-                traits::NonStructuralMatchTy::Adt(adt) => self.adt_derive_msg(adt),
-                traits::NonStructuralMatchTy::Dynamic => {
+            with_no_trimmed_paths!(match non_sm_ty.kind {
+                traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
+                traits::NonStructuralMatchTyKind::Dynamic => {
                     "trait objects cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Opaque => {
+                traits::NonStructuralMatchTyKind::Opaque => {
                     "opaque types cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Closure => {
+                traits::NonStructuralMatchTyKind::Closure => {
                     "closures cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Generator => {
+                traits::NonStructuralMatchTyKind::Generator => {
                     "generators cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Param => {
+                traits::NonStructuralMatchTyKind::Param => {
                     bug!("use of a constant whose type is a parameter inside a pattern")
                 }
-                traits::NonStructuralMatchTy::Projection => {
+                traits::NonStructuralMatchTyKind::Projection => {
                     bug!("use of a constant whose type is a projection inside a pattern")
                 }
-                traits::NonStructuralMatchTy::Foreign => {
+                traits::NonStructuralMatchTyKind::Foreign => {
                     bug!("use of a value of a foreign type inside a pattern")
                 }
             })
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 81819534e8b..dcfdff68640 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -62,7 +62,7 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapError;
 pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
 pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
 pub use self::structural_match::search_for_structural_match_violation;
-pub use self::structural_match::NonStructuralMatchTy;
+pub use self::structural_match::{NonStructuralMatchTy, NonStructuralMatchTyKind};
 pub use self::util::{
     elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span,
     elaborate_trait_ref, elaborate_trait_refs,
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 67e3bf80486..5465395768c 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -11,7 +11,13 @@ use rustc_span::Span;
 use std::ops::ControlFlow;
 
 #[derive(Debug)]
-pub enum NonStructuralMatchTy<'tcx> {
+pub struct NonStructuralMatchTy<'tcx> {
+    pub ty: Ty<'tcx>,
+    pub kind: NonStructuralMatchTyKind<'tcx>,
+}
+
+#[derive(Debug)]
+pub enum NonStructuralMatchTyKind<'tcx> {
     Adt(AdtDef<'tcx>),
     Param,
     Dynamic,
@@ -137,25 +143,32 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
         let (adt_def, substs) = match *ty.kind() {
             ty::Adt(adt_def, substs) => (adt_def, substs),
             ty::Param(_) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Param);
+                let kind = NonStructuralMatchTyKind::Param;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Dynamic(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Dynamic);
+                let kind = NonStructuralMatchTyKind::Dynamic;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Foreign(_) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Foreign);
+                let kind = NonStructuralMatchTyKind::Foreign;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Opaque(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Opaque);
+                let kind = NonStructuralMatchTyKind::Opaque;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Projection(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Projection);
+                let kind = NonStructuralMatchTyKind::Projection;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Closure(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Closure);
+                let kind = NonStructuralMatchTyKind::Closure;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Generator(..) | ty::GeneratorWitness(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Generator);
+                let kind = NonStructuralMatchTyKind::Generator;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::RawPtr(..) => {
                 // structural-match ignores substructure of
@@ -215,7 +228,8 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
 
         if !self.type_marked_structural(ty) {
             debug!("Search found ty: {:?}", ty);
-            return ControlFlow::Break(NonStructuralMatchTy::Adt(adt_def));
+            let kind = NonStructuralMatchTyKind::Adt(adt_def);
+            return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
         }
 
         // structural-match does not care about the
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 50966868ec7..5c0c5b24ecd 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -827,7 +827,9 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                     );
                 }
 
-                if traits::search_for_structural_match_violation(param.span, tcx, ty).is_some() {
+                if let Some(non_structural_match_ty) =
+                    traits::search_for_structural_match_violation(param.span, tcx, ty)
+                {
                     // We use the same error code in both branches, because this is really the same
                     // issue: we just special-case the message for type parameters to make it
                     // clearer.
@@ -853,19 +855,23 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                         )
                         .emit();
                     } else {
-                        struct_span_err!(
+                        let mut diag = struct_span_err!(
                             tcx.sess,
                             hir_ty.span,
                             E0741,
                             "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
                             the type of a const parameter",
-                            ty,
-                        )
-                        .span_label(
-                            hir_ty.span,
-                            format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
-                        )
-                        .emit();
+                            non_structural_match_ty.ty,
+                        );
+
+                        if ty == non_structural_match_ty.ty {
+                            diag.span_label(
+                                hir_ty.span,
+                                format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
+                            );
+                        }
+
+                        diag.emit();
                     }
                 }
             } else {
diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
index e1c20e6ae78..16fabd1e88f 100644
--- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
@@ -1,8 +1,8 @@
-error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+error[E0741]: `(dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
   --> $DIR/issue-63322-forbid-dyn.rs:9:18
    |
 LL | fn test<const T: &'static dyn A>() {
-   |                  ^^^^^^^^^^^^^^ `&'static (dyn A + 'static)` doesn't derive both `PartialEq` and `Eq`
+   |                  ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-97278.rs b/src/test/ui/const-generics/issues/issue-97278.rs
new file mode 100644
index 00000000000..da0a9776fd4
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-97278.rs
@@ -0,0 +1,14 @@
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+use std::sync::Arc;
+
+#[derive(PartialEq, Eq)]
+enum Bar {
+    Bar(Arc<i32>)
+}
+
+fn test<const BAR: Bar>() {}
+//~^ ERROR `Arc<i32>` must be annotated with `#[derive(PartialEq, Eq)]`
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-97278.stderr b/src/test/ui/const-generics/issues/issue-97278.stderr
new file mode 100644
index 00000000000..ff13cb505ab
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-97278.stderr
@@ -0,0 +1,9 @@
+error[E0741]: `Arc<i32>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+  --> $DIR/issue-97278.rs:11:20
+   |
+LL | fn test<const BAR: Bar>() {}
+   |                    ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0741`.