about summary refs log tree commit diff
diff options
context:
space:
mode:
authortiif <pekyuan@gmail.com>2025-09-15 08:59:19 +0000
committertiif <pekyuan@gmail.com>2025-09-15 08:59:19 +0000
commit1a02cd531d6b5ff154078208daf7816b1657f389 (patch)
tree26d2d9a85b6b36271d338acc21c247e51d9fb5fa
parentb919a5f5183afb876b5206b3b23b249183cb313c (diff)
downloadrust-1a02cd531d6b5ff154078208daf7816b1657f389.tar.gz
rust-1a02cd531d6b5ff154078208daf7816b1657f389.zip
Add check to make sure ConstParamTy impls of certain types are gated with #[unstable_feature_bound(unsized_const_params)]
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs38
1 files changed, 23 insertions, 15 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index 393f458bea2..4c25882daa9 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -1,15 +1,14 @@
 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
 
-use std::assert_matches::assert_matches;
-
 use hir::LangItem;
 use rustc_ast::Mutability;
 use rustc_hir as hir;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
+use rustc_span::sym;
 
 use crate::regions::InferCtxtRegionExt;
-use crate::traits::{self, FulfillmentError, ObligationCause};
+use crate::traits::{self, FulfillmentError, Obligation, ObligationCause};
 
 pub enum CopyImplementationError<'tcx> {
     InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
@@ -98,10 +97,9 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     self_type: Ty<'tcx>,
-    lang_item: LangItem,
     parent_cause: ObligationCause<'tcx>,
 ) -> Result<(), ConstParamTyImplementationError<'tcx>> {
-    assert_matches!(lang_item, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy);
+    let mut need_unstable_feature_bound = false;
 
     let inner_tys: Vec<_> = match *self_type.kind() {
         // Trivially okay as these types are all:
@@ -112,18 +110,14 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
 
         // Handle types gated under `feature(unsized_const_params)`
         // FIXME(unsized_const_params): Make `const N: [u8]` work then forbid references
-        ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not)
-            if lang_item == LangItem::UnsizedConstParamTy =>
-        {
+        ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not) => {
+            need_unstable_feature_bound = true;
             vec![inner_ty]
         }
-        ty::Str if lang_item == LangItem::UnsizedConstParamTy => {
+        ty::Str => {
+            need_unstable_feature_bound = true;
             vec![Ty::new_slice(tcx, tcx.types.u8)]
         }
-        ty::Str | ty::Slice(..) | ty::Ref(_, _, Mutability::Not) => {
-            return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
-        }
-
         ty::Array(inner_ty, _) => vec![inner_ty],
 
         // `str` morally acts like a newtype around `[u8]`
@@ -137,7 +131,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
                 adt,
                 args,
                 parent_cause.clone(),
-                lang_item,
+                LangItem::ConstParamTy,
             )
             .map_err(ConstParamTyImplementationError::InfrigingFields)?;
 
@@ -153,11 +147,25 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
         let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
 
+        // Make sure impls certain types are gated with #[unstable_feature_bound(unsized_const_params)]
+        if need_unstable_feature_bound {
+            ocx.register_obligation(Obligation::new(
+                tcx,
+                parent_cause.clone(),
+                param_env,
+                ty::ClauseKind::UnstableFeature(sym::unsized_const_params),
+            ));
+
+            if !ocx.select_all_or_error().is_empty() {
+                return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
+            }
+        }
+
         ocx.register_bound(
             parent_cause.clone(),
             param_env,
             inner_ty,
-            tcx.require_lang_item(lang_item, parent_cause.span),
+            tcx.require_lang_item(LangItem::ConstParamTy, parent_cause.span),
         );
 
         let errors = ocx.select_all_or_error();