Add check to make sure ConstParamTy impls of certain types are gated with #[unstable_feature_bound(unsized_const_params)]
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user