]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #99651 - compiler-errors:fn-and-raw-ptr-in-const-generics, r=oli-obk
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Wed, 27 Jul 2022 15:55:04 +0000 (17:55 +0200)
committerGitHub <noreply@github.com>
Wed, 27 Jul 2022 15:55:04 +0000 (17:55 +0200)
Deeply deny fn and raw ptrs in const generics

I think this is right -- just because we wrap a fn ptr in a wrapper type does not mean we should allow it in a const parameter.

We now reject both of these in the same way:

```
#![feature(adt_const_params)]

#[derive(Eq, PartialEq)]
struct Wrapper();

fn foo<const W: Wrapper>() {}

fn foo2<const F: fn()>() {}
```

This does regress one test (`src/test/ui/consts/refs_check_const_eq-issue-88384.stderr`), but I'm not sure it should've passed in the first place.

cc: ``@b-naber`` who introduced that test^
fixes #99641

18 files changed:
compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
compiler/rustc_middle/src/ty/consts.rs
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/structural_match.rs
compiler/rustc_typeck/src/check/wfcheck.rs
src/test/ui/const-generics/fn-const-param-call.full.stderr
src/test/ui/const-generics/fn-const-param-infer.full.stderr
src/test/ui/const-generics/issues/issue-71381.full.stderr
src/test/ui/const-generics/issues/issue-71382.full.stderr
src/test/ui/const-generics/issues/issue-71611.full.stderr
src/test/ui/const-generics/issues/issue-72352.full.stderr
src/test/ui/const-generics/issues/issue-99641.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-99641.stderr [new file with mode: 0644]
src/test/ui/const-generics/raw-ptr-const-param-deref.full.stderr
src/test/ui/const-generics/raw-ptr-const-param.full.stderr
src/test/ui/consts/refs_check_const_eq-issue-88384.rs
src/test/ui/consts/refs_check_const_eq-issue-88384.stderr

index 29464cf8c4e4fa1856269a66e30828b8c5d5076f..e099445117225e4a268718c01617e1612bcbeb63 100644 (file)
@@ -226,7 +226,7 @@ fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
         // 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, true).is_some()
+        traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some()
     }
 
     fn in_adt_inherently<'tcx>(
index a4e7a12bba3232b5526b7ea107c6c38e401d00a2..f8792edc017b2d8d3a5da6affae1e10302511dce 100644 (file)
@@ -203,7 +203,7 @@ pub fn from_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Se
     pub fn to_valtree(self) -> ty::ValTree<'tcx> {
         match self.kind() {
             ty::ConstKind::Value(valtree) => valtree,
-            _ => bug!("expected ConstKind::Value"),
+            _ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
         }
     }
 
index e32e0b11ba49762bdfcdbd6de2faacd28cba63a2..d6dd0f017941a74aa2a8f84ee5b9eff18412cdcb 100644 (file)
@@ -120,37 +120,35 @@ fn adt_derive_msg(&self, adt_def: AdtDef<'tcx>) -> String {
     }
 
     fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
-        traits::search_for_structural_match_violation(self.span, self.tcx(), ty, true).map(
-            |non_sm_ty| {
-                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::NonStructuralMatchTyKind::Opaque => {
-                        "opaque types cannot be used in patterns".to_string()
-                    }
-                    traits::NonStructuralMatchTyKind::Closure => {
-                        "closures cannot be used in patterns".to_string()
-                    }
-                    traits::NonStructuralMatchTyKind::Generator => {
-                        "generators cannot be used in patterns".to_string()
-                    }
-                    traits::NonStructuralMatchTyKind::Float => {
-                        "floating-point numbers cannot be used in patterns".to_string()
-                    }
-                    traits::NonStructuralMatchTyKind::Param => {
-                        bug!("use of a constant whose type is a parameter inside a pattern")
-                    }
-                    traits::NonStructuralMatchTyKind::Projection => {
-                        bug!("use of a constant whose type is a projection inside a pattern")
-                    }
-                    traits::NonStructuralMatchTyKind::Foreign => {
-                        bug!("use of a value of a foreign type 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 {
index 3ef51b0c27abd9e8273509cda48459690cc12cba..d0a17f712d3dfc24e46c9d8b9c902f6a0dc97813 100644 (file)
@@ -60,8 +60,9 @@
 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, NonStructuralMatchTyKind};
+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,
index 6c0b83fbd0304802969bf5d7133f38cab97a8ca4..c278752e3d9f46459a6027ebcd67307f0020624c 100644 (file)
@@ -6,29 +6,10 @@
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_span::Span;
 use std::ops::ControlFlow;
 
-#[derive(Debug)]
-pub struct NonStructuralMatchTy<'tcx> {
-    pub ty: Ty<'tcx>,
-    pub kind: NonStructuralMatchTyKind<'tcx>,
-}
-
-#[derive(Debug)]
-pub enum NonStructuralMatchTyKind<'tcx> {
-    Adt(AdtDef<'tcx>),
-    Param,
-    Dynamic,
-    Foreign,
-    Opaque,
-    Closure,
-    Generator,
-    Projection,
-    Float,
-}
-
 /// This method traverses the structure of `ty`, trying to find an
 /// instance of an ADT (i.e. struct or enum) that doesn't implement
 /// the structural-match traits, or a generic type parameter
@@ -54,15 +35,28 @@ pub enum NonStructuralMatchTyKind<'tcx> {
 /// 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.
-///
-/// The floats_allowed flag is used to deny constants in floating point
 pub fn search_for_structural_match_violation<'tcx>(
     span: Span,
     tcx: TyCtxt<'tcx>,
     ty: Ty<'tcx>,
-    floats_allowed: bool,
-) -> Option<NonStructuralMatchTy<'tcx>> {
-    ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), floats_allowed })
+) -> Option<Ty<'tcx>> {
+    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()
 }
 
@@ -125,7 +119,10 @@ struct Search<'tcx> {
     /// we will not recur on them again.
     seen: FxHashSet<hir::def_id::DefId>,
 
-    floats_allowed: bool,
+    // Additionally deny things that have been allowed in patterns,
+    // but are not allowed in adt const params, such as floats and
+    // fn ptrs.
+    adt_const_param: bool,
 }
 
 impl<'tcx> Search<'tcx> {
@@ -135,7 +132,7 @@ fn type_marked_structural(&self, adt_ty: Ty<'tcx>) -> bool {
 }
 
 impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
-    type BreakTy = NonStructuralMatchTy<'tcx>;
+    type BreakTy = Ty<'tcx>;
 
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         debug!("Search visiting ty: {:?}", ty);
@@ -143,51 +140,27 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         let (adt_def, substs) = match *ty.kind() {
             ty::Adt(adt_def, substs) => (adt_def, substs),
             ty::Param(_) => {
-                let kind = NonStructuralMatchTyKind::Param;
-                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+                return ControlFlow::Break(ty);
             }
             ty::Dynamic(..) => {
-                let kind = NonStructuralMatchTyKind::Dynamic;
-                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+                return ControlFlow::Break(ty);
             }
             ty::Foreign(_) => {
-                let kind = NonStructuralMatchTyKind::Foreign;
-                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+                return ControlFlow::Break(ty);
             }
             ty::Opaque(..) => {
-                let kind = NonStructuralMatchTyKind::Opaque;
-                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+                return ControlFlow::Break(ty);
             }
             ty::Projection(..) => {
-                let kind = NonStructuralMatchTyKind::Projection;
-                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+                return ControlFlow::Break(ty);
             }
             ty::Closure(..) => {
-                let kind = NonStructuralMatchTyKind::Closure;
-                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+                return ControlFlow::Break(ty);
             }
             ty::Generator(..) | ty::GeneratorWitness(..) => {
-                let kind = NonStructuralMatchTyKind::Generator;
-                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
-            }
-            ty::RawPtr(..) => {
-                // structural-match ignores substructure of
-                // `*const _`/`*mut _`, so skip `super_visit_with`.
-                //
-                // For example, if you have:
-                // ```
-                // struct NonStructural;
-                // #[derive(PartialEq, Eq)]
-                // struct T(*const NonStructural);
-                // const C: T = T(std::ptr::null());
-                // ```
-                //
-                // Even though `NonStructural` does not implement `PartialEq`,
-                // structural equality on `T` does not recur into the raw
-                // pointer. Therefore, one can still use `C` in a pattern.
-                return ControlFlow::CONTINUE;
+                return ControlFlow::Break(ty);
             }
-            ty::FnDef(..) | ty::FnPtr(..) => {
+            ty::FnDef(..) => {
                 // Types of formals and return in `fn(_) -> _` are also irrelevant;
                 // so we do not recur into them via `super_visit_with`
                 return ControlFlow::CONTINUE;
@@ -206,14 +179,41 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 return ControlFlow::CONTINUE;
             }
 
+            ty::FnPtr(..) => {
+                if !self.adt_const_param {
+                    return ControlFlow::CONTINUE;
+                } else {
+                    return ControlFlow::Break(ty);
+                }
+            }
+
+            ty::RawPtr(..) => {
+                if !self.adt_const_param {
+                    // structural-match ignores substructure of
+                    // `*const _`/`*mut _`, so skip `super_visit_with`.
+                    //
+                    // For example, if you have:
+                    // ```
+                    // struct NonStructural;
+                    // #[derive(PartialEq, Eq)]
+                    // struct T(*const NonStructural);
+                    // const C: T = T(std::ptr::null());
+                    // ```
+                    //
+                    // Even though `NonStructural` does not implement `PartialEq`,
+                    // structural equality on `T` does not recur into the raw
+                    // pointer. Therefore, one can still use `C` in a pattern.
+                    return ControlFlow::CONTINUE;
+                } else {
+                    return ControlFlow::Break(ty);
+                }
+            }
+
             ty::Float(_) => {
-                if self.floats_allowed {
+                if !self.adt_const_param {
                     return ControlFlow::CONTINUE;
                 } else {
-                    return ControlFlow::Break(NonStructuralMatchTy {
-                        ty,
-                        kind: NonStructuralMatchTyKind::Float,
-                    });
+                    return ControlFlow::Break(ty);
                 }
             }
 
@@ -239,8 +239,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
 
         if !self.type_marked_structural(ty) {
             debug!("Search found ty: {:?}", ty);
-            let kind = NonStructuralMatchTyKind::Adt(adt_def);
-            return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+            return ControlFlow::Break(ty);
         }
 
         // structural-match does not care about the
index e65955fe86038067ba29845b5450d7e34fe51c7a..bae986de9a23d64a48835a68b8c5b9c24fc7295b 100644 (file)
@@ -848,29 +848,13 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
             let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id));
 
             if tcx.features().adt_const_params {
-                let err = match ty.peel_refs().kind() {
-                    ty::FnPtr(_) => Some("function pointers"),
-                    ty::RawPtr(_) => Some("raw pointers"),
-                    _ => None,
-                };
-
-                if let Some(unsupported_type) = err {
-                    tcx.sess.span_err(
-                        hir_ty.span,
-                        &format!(
-                            "using {} as const generic parameters is forbidden",
-                            unsupported_type
-                        ),
-                    );
-                }
-
                 if let Some(non_structural_match_ty) =
-                    traits::search_for_structural_match_violation(param.span, tcx, ty, false)
+                    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
                     // clearer.
-                    match ty.peel_refs().kind() {
+                    match non_structural_match_ty.kind() {
                         ty::Param(_) => {
                             // Const parameters may not have type parameters as their types,
                             // because we cannot be sure that the type parameter derives `PartialEq`
@@ -902,6 +886,24 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                             .note("floats do not derive `Eq` or `Ord`, which are required for const parameters")
                             .emit();
                         }
+                        ty::FnPtr(_) => {
+                            struct_span_err!(
+                                tcx.sess,
+                                hir_ty.span,
+                                E0741,
+                                "using function pointers as const generic parameters is forbidden",
+                            )
+                            .emit();
+                        }
+                        ty::RawPtr(_) => {
+                            struct_span_err!(
+                                tcx.sess,
+                                hir_ty.span,
+                                E0741,
+                                "using raw pointers as const generic parameters is forbidden",
+                            )
+                            .emit();
+                        }
                         _ => {
                             let mut diag = struct_span_err!(
                                 tcx.sess,
@@ -909,10 +911,10 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                                 E0741,
                                 "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
                                 the type of a const parameter",
-                                non_structural_match_ty.ty,
+                                non_structural_match_ty,
                             );
 
-                            if ty == non_structural_match_ty.ty {
+                            if ty == non_structural_match_ty {
                                 diag.span_label(
                                     hir_ty.span,
                                     format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
index d984449e6ca6e25da8e5830164d7aef324d79a4a..b55c2449858c9fe0b9966d4428b795298b2c2afe 100644 (file)
@@ -1,10 +1,10 @@
-error: using function pointers as const generic parameters is forbidden
+error[E0741]: using function pointers as const generic parameters is forbidden
   --> $DIR/fn-const-param-call.rs:11:25
    |
 LL | struct Wrapper<const F: fn() -> u32>;
    |                         ^^^^^^^^^^^
 
-error: using function pointers as const generic parameters is forbidden
+error[E0741]: using function pointers as const generic parameters is forbidden
   --> $DIR/fn-const-param-call.rs:13:15
    |
 LL | impl<const F: fn() -> u32> Wrapper<F> {
@@ -12,3 +12,4 @@ LL | impl<const F: fn() -> u32> Wrapper<F> {
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0741`.
index f0767a10994a547bccfefb8904e15464e1bb2ba2..2d66a19233269cb7fc93d31465a74a2b44f61efe 100644 (file)
@@ -1,4 +1,4 @@
-error: using function pointers as const generic parameters is forbidden
+error[E0741]: using function pointers as const generic parameters is forbidden
   --> $DIR/fn-const-param-infer.rs:6:25
    |
 LL | struct Checked<const F: fn(usize) -> bool>;
@@ -6,3 +6,4 @@ LL | struct Checked<const F: fn(usize) -> bool>;
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0741`.
index 3950317b3705330e58498bacddfd7c1f5092af43..e17cf96aa3e3d0bdfea2d317753a8bdaf5094c3a 100644 (file)
@@ -10,13 +10,13 @@ error[E0770]: the type of const parameters must not depend on other generic para
 LL |         const FN: unsafe extern "C" fn(Args),
    |                                        ^^^^ the type must not depend on the parameter `Args`
 
-error: using function pointers as const generic parameters is forbidden
+error[E0741]: using function pointers as const generic parameters is forbidden
   --> $DIR/issue-71381.rs:14:61
    |
 LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
    |                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: using function pointers as const generic parameters is forbidden
+error[E0741]: using function pointers as const generic parameters is forbidden
   --> $DIR/issue-71381.rs:23:19
    |
 LL |         const FN: unsafe extern "C" fn(Args),
@@ -24,4 +24,5 @@ LL |         const FN: unsafe extern "C" fn(Args),
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0770`.
+Some errors have detailed explanations: E0741, E0770.
+For more information about an error, try `rustc --explain E0741`.
index 715037bd5f1e86e94f44ea67c3b79a72869e8686..ab2a4e64a838978bade17de81988f5540df5062b 100644 (file)
@@ -1,4 +1,4 @@
-error: using function pointers as const generic parameters is forbidden
+error[E0741]: using function pointers as const generic parameters is forbidden
   --> $DIR/issue-71382.rs:16:23
    |
 LL |     fn test<const FN: fn()>(&self) {
@@ -6,3 +6,4 @@ LL |     fn test<const FN: fn()>(&self) {
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0741`.
index 01a85b745ce395d61e226b92a6dc28db8068efd2..656aa29e19b2595579442e16cea4575ffb83638f 100644 (file)
@@ -4,7 +4,7 @@ error[E0770]: the type of const parameters must not depend on other generic para
 LL | fn func<A, const F: fn(inner: A)>(outer: A) {
    |                               ^ the type must not depend on the parameter `A`
 
-error: using function pointers as const generic parameters is forbidden
+error[E0741]: using function pointers as const generic parameters is forbidden
   --> $DIR/issue-71611.rs:5:21
    |
 LL | fn func<A, const F: fn(inner: A)>(outer: A) {
@@ -12,4 +12,5 @@ LL | fn func<A, const F: fn(inner: A)>(outer: A) {
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0770`.
+Some errors have detailed explanations: E0741, E0770.
+For more information about an error, try `rustc --explain E0741`.
index eedd73c4dcc0afd6542f456ace309328876c1381..92580b33685d190c45541ebb5b930dea8ee4b412 100644 (file)
@@ -1,4 +1,4 @@
-error: using function pointers as const generic parameters is forbidden
+error[E0741]: using function pointers as const generic parameters is forbidden
   --> $DIR/issue-72352.rs:7:42
    |
 LL | unsafe fn unsafely_do_the_thing<const F: fn(&CStr) -> usize>(ptr: *const i8) -> usize {
@@ -6,3 +6,4 @@ LL | unsafe fn unsafely_do_the_thing<const F: fn(&CStr) -> usize>(ptr: *const i8
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0741`.
diff --git a/src/test/ui/const-generics/issues/issue-99641.rs b/src/test/ui/const-generics/issues/issue-99641.rs
new file mode 100644 (file)
index 0000000..fae6d3f
--- /dev/null
@@ -0,0 +1,18 @@
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+fn main() {
+    pub struct Color<const WHITE: (fn(),)>;
+    //~^ ERROR using function pointers
+
+    impl<const WHITE: (fn(),)> Color<WHITE> {
+        //~^ ERROR using function pointers
+        pub fn new() -> Self {
+            Color::<WHITE>
+        }
+    }
+
+    pub const D65: (fn(),) = (|| {},);
+
+    Color::<D65>::new();
+}
diff --git a/src/test/ui/const-generics/issues/issue-99641.stderr b/src/test/ui/const-generics/issues/issue-99641.stderr
new file mode 100644 (file)
index 0000000..349ebba
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0741]: using function pointers as const generic parameters is forbidden
+  --> $DIR/issue-99641.rs:5:35
+   |
+LL |     pub struct Color<const WHITE: (fn(),)>;
+   |                                   ^^^^^^^
+
+error[E0741]: using function pointers as const generic parameters is forbidden
+  --> $DIR/issue-99641.rs:8:23
+   |
+LL |     impl<const WHITE: (fn(),)> Color<WHITE> {
+   |                       ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0741`.
index 04bc46cb4ab12547bee30c4f95e71442e50e8c23..657eee2be24431697ed97a7a1e42a14a2ecc9cd4 100644 (file)
@@ -1,10 +1,10 @@
-error: using raw pointers as const generic parameters is forbidden
+error[E0741]: using raw pointers as const generic parameters is forbidden
   --> $DIR/raw-ptr-const-param-deref.rs:9:23
    |
 LL | struct Const<const P: *const u32>;
    |                       ^^^^^^^^^^
 
-error: using raw pointers as const generic parameters is forbidden
+error[E0741]: using raw pointers as const generic parameters is forbidden
   --> $DIR/raw-ptr-const-param-deref.rs:11:15
    |
 LL | impl<const P: *const u32> Const<P> {
@@ -12,3 +12,4 @@ LL | impl<const P: *const u32> Const<P> {
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0741`.
index 310422aafcd352d05c6adc7a0f2cee6d74ca5b70..69f1aae5681a4371897857de6529bce118bec9a3 100644 (file)
@@ -1,4 +1,4 @@
-error: using raw pointers as const generic parameters is forbidden
+error[E0741]: using raw pointers as const generic parameters is forbidden
   --> $DIR/raw-ptr-const-param.rs:6:23
    |
 LL | struct Const<const P: *const u32>;
@@ -6,3 +6,4 @@ LL | struct Const<const P: *const u32>;
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0741`.
index 204d18ea25de4482ead25c12fd49f9a1bc7b43ff..1496b28bd3ee6f4c2b3f466e9d19f8fbb2d5ed98 100644 (file)
@@ -1,5 +1,3 @@
-// check-pass
-
 #![feature(fn_traits)]
 #![feature(adt_const_params)]
 //~^ WARNING the feature `adt_const_params` is incomplete
@@ -10,8 +8,10 @@ struct CompileTimeSettings{
 }
 
 struct Foo<const T: CompileTimeSettings>;
+//~^ ERROR using function pointers as const generic parameters is forbidden
 
 impl<const T: CompileTimeSettings> Foo<T> {
+    //~^ ERROR using function pointers as const generic parameters is forbidden
     fn call_hooks(){
     }
 }
index f2bad2f552759aa09d381dc757b3cc2c3fa61d2f..4f2f5e244b67e51e005e3cbe20c435da60571f7f 100644 (file)
@@ -1,5 +1,5 @@
 warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/refs_check_const_eq-issue-88384.rs:4:12
+  --> $DIR/refs_check_const_eq-issue-88384.rs:2:12
    |
 LL | #![feature(adt_const_params)]
    |            ^^^^^^^^^^^^^^^^
@@ -7,5 +7,18 @@ LL | #![feature(adt_const_params)]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
 
-warning: 1 warning emitted
+error[E0741]: using function pointers as const generic parameters is forbidden
+  --> $DIR/refs_check_const_eq-issue-88384.rs:10:21
+   |
+LL | struct Foo<const T: CompileTimeSettings>;
+   |                     ^^^^^^^^^^^^^^^^^^^
+
+error[E0741]: using function pointers as const generic parameters is forbidden
+  --> $DIR/refs_check_const_eq-issue-88384.rs:13:15
+   |
+LL | impl<const T: CompileTimeSettings> Foo<T> {
+   |               ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0741`.