]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_typeck/src/check/wfcheck.rs
Rollup merge of #99651 - compiler-errors:fn-and-raw-ptr-in-const-generics, r=oli-obk
[rust.git] / compiler / rustc_typeck / src / check / wfcheck.rs
index 1b80e4edca91086ea154a26531a00ace1c22abe8..bae986de9a23d64a48835a68b8c5b9c24fc7295b 100644 (file)
@@ -2,7 +2,7 @@
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
@@ -183,7 +183,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
             // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
             match (tcx.impl_polarity(def_id), impl_.polarity) {
                 (ty::ImplPolarity::Positive, _) => {
-                    check_impl(tcx, item, impl_.self_ty, &impl_.of_trait);
+                    check_impl(tcx, item, impl_.self_ty, &impl_.of_trait, impl_.constness);
                 }
                 (ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
                     // FIXME(#27579): what amount of WF checking do we need for neg impls?
@@ -474,7 +474,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
         unsatisfied_bounds.sort();
 
         if !unsatisfied_bounds.is_empty() {
-            let plural = if unsatisfied_bounds.len() > 1 { "s" } else { "" };
+            let plural = pluralize!(unsatisfied_bounds.len());
             let mut err = tcx.sess.struct_span_err(
                 gat_item_hir.span,
                 &format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),
@@ -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`"),
@@ -1242,6 +1244,7 @@ fn check_impl<'tcx>(
     item: &'tcx hir::Item<'tcx>,
     ast_self_ty: &hir::Ty<'_>,
     ast_trait_ref: &Option<hir::TraitRef<'_>>,
+    constness: hir::Constness,
 ) {
     enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
         match *ast_trait_ref {
@@ -1251,11 +1254,19 @@ fn check_impl<'tcx>(
                 // won't hold).
                 let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap();
                 let trait_ref = wfcx.normalize(ast_trait_ref.path.span, None, trait_ref);
+                let trait_pred = ty::TraitPredicate {
+                    trait_ref,
+                    constness: match constness {
+                        hir::Constness::Const => ty::BoundConstness::ConstIfConst,
+                        hir::Constness::NotConst => ty::BoundConstness::NotConst,
+                    },
+                    polarity: ty::ImplPolarity::Positive,
+                };
                 let obligations = traits::wf::trait_obligations(
                     wfcx.infcx,
                     wfcx.param_env,
                     wfcx.body_id,
-                    &trait_ref,
+                    &trait_pred,
                     ast_trait_ref.path.span,
                     item,
                 );