about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs60
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs33
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs2
5 files changed, 57 insertions, 44 deletions
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index b97dd1ae8d5..e0994451172 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -226,7 +226,7 @@ impl Qualif for CustomEq {
         // because that component may be part of an enum variant (e.g.,
         // `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
         // structural-match (`Option::None`).
-        traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty, false).is_some()
+        traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some()
     }
 
     fn in_adt_inherently<'tcx>(
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 14133ebc175..d6dd0f01794 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
@@ -120,37 +120,35 @@ 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, false).map(
-            |non_sm_ty| {
-                with_no_trimmed_paths!(match non_sm_ty.kind() {
-                    ty::Adt(adt, _) => self.adt_derive_msg(*adt),
-                    ty::Dynamic(..) => {
-                        "trait objects cannot be used in patterns".to_string()
-                    }
-                    ty::Opaque(..) => {
-                        "opaque types cannot be used in patterns".to_string()
-                    }
-                    ty::Closure(..) => {
-                        "closures cannot be used in patterns".to_string()
-                    }
-                    ty::Generator(..) | ty::GeneratorWitness(..) => {
-                        "generators cannot be used in patterns".to_string()
-                    }
-                    ty::Float(..) => {
-                        "floating-point numbers cannot be used in patterns".to_string()
-                    }
-                    ty::FnPtr(..) => {
-                        "function pointers cannot be used in patterns".to_string()
-                    }
-                    ty::RawPtr(..) => {
-                        "raw pointers cannot be used in patterns".to_string()
-                    }
-                    _ => {
-                        bug!("use of a value of `{non_sm_ty}` inside a pattern")
-                    }
-                })
-            },
-        )
+        traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
+            with_no_trimmed_paths!(match non_sm_ty.kind() {
+                ty::Adt(adt, _) => self.adt_derive_msg(*adt),
+                ty::Dynamic(..) => {
+                    "trait objects cannot be used in patterns".to_string()
+                }
+                ty::Opaque(..) => {
+                    "opaque types cannot be used in patterns".to_string()
+                }
+                ty::Closure(..) => {
+                    "closures cannot be used in patterns".to_string()
+                }
+                ty::Generator(..) | ty::GeneratorWitness(..) => {
+                    "generators cannot be used in patterns".to_string()
+                }
+                ty::Float(..) => {
+                    "floating-point numbers cannot be used in patterns".to_string()
+                }
+                ty::FnPtr(..) => {
+                    "function pointers cannot be used in patterns".to_string()
+                }
+                ty::RawPtr(..) => {
+                    "raw pointers cannot be used in patterns".to_string()
+                }
+                _ => {
+                    bug!("use of a value of `{non_sm_ty}` inside a pattern")
+                }
+            })
+        })
     }
 
     fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 5397baefb9c..d0a17f712d3 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -60,7 +60,9 @@ pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError
 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::{
+    search_for_adt_const_param_violation, search_for_structural_match_violation,
+};
 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 ea11670ee77..c278752e3d9 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -35,16 +35,28 @@ use std::ops::ControlFlow;
 /// For more background on why Rust has this requirement, and issues
 /// that arose when the requirement was not enforced completely, see
 /// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
-///
-/// When the `valtree_semantics` flag is set, then we also deny additional
-/// types that are not evaluatable to valtrees, such as floats and fn ptrs.
 pub fn search_for_structural_match_violation<'tcx>(
     span: Span,
     tcx: TyCtxt<'tcx>,
     ty: Ty<'tcx>,
-    valtree_semantics: bool,
 ) -> Option<Ty<'tcx>> {
-    ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), valtree_semantics })
+    ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), adt_const_param: false })
+        .break_value()
+}
+
+/// This method traverses the structure of `ty`, trying to find any
+/// types that are not allowed to be used in a const generic.
+///
+/// This is either because the type does not implement `StructuralEq`
+/// and `StructuralPartialEq`, or because the type is intentionally
+/// not supported in const generics (such as floats and raw pointers,
+/// which are allowed in match blocks).
+pub fn search_for_adt_const_param_violation<'tcx>(
+    span: Span,
+    tcx: TyCtxt<'tcx>,
+    ty: Ty<'tcx>,
+) -> Option<Ty<'tcx>> {
+    ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), adt_const_param: true })
         .break_value()
 }
 
@@ -108,8 +120,9 @@ struct Search<'tcx> {
     seen: FxHashSet<hir::def_id::DefId>,
 
     // Additionally deny things that have been allowed in patterns,
-    // but are not evaluatable to a valtree, such as floats and fn ptrs.
-    valtree_semantics: bool,
+    // but are not allowed in adt const params, such as floats and
+    // fn ptrs.
+    adt_const_param: bool,
 }
 
 impl<'tcx> Search<'tcx> {
@@ -167,7 +180,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
             }
 
             ty::FnPtr(..) => {
-                if !self.valtree_semantics {
+                if !self.adt_const_param {
                     return ControlFlow::CONTINUE;
                 } else {
                     return ControlFlow::Break(ty);
@@ -175,7 +188,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
             }
 
             ty::RawPtr(..) => {
-                if !self.valtree_semantics {
+                if !self.adt_const_param {
                     // structural-match ignores substructure of
                     // `*const _`/`*mut _`, so skip `super_visit_with`.
                     //
@@ -197,7 +210,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
             }
 
             ty::Float(_) => {
-                if !self.valtree_semantics {
+                if !self.adt_const_param {
                     return ControlFlow::CONTINUE;
                 } else {
                     return ControlFlow::Break(ty);
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 3bf76ad38ee..ca5defd1688 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -849,7 +849,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
 
             if tcx.features().adt_const_params {
                 if let Some(non_structural_match_ty) =
-                    traits::search_for_structural_match_violation(param.span, tcx, ty, true)
+                    traits::search_for_adt_const_param_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