Add check to make sure ConstParamTy impls of certain types are gated with #[unstable_feature_bound(unsized_const_params)]

This commit is contained in:
tiif
2025-09-15 08:59:19 +00:00
parent b919a5f518
commit 1a02cd531d

View File

@@ -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();