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 { 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() { - | ^^^^^^^^^^^^^^ `&'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) +} + +fn test() {} +//~^ ERROR `Arc` 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` 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() {} + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`.