Skip to content

Commit 1a02cd5

Browse files
committed
Add check to make sure ConstParamTy impls of certain types are gated with #[unstable_feature_bound(unsized_const_params)]
1 parent b919a5f commit 1a02cd5

File tree

1 file changed

+23
-15
lines changed
  • compiler/rustc_trait_selection/src/traits

1 file changed

+23
-15
lines changed

compiler/rustc_trait_selection/src/traits/misc.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
22
3-
use std::assert_matches::assert_matches;
4-
53
use hir::LangItem;
64
use rustc_ast::Mutability;
75
use rustc_hir as hir;
86
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
97
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
8+
use rustc_span::sym;
109

1110
use crate::regions::InferCtxtRegionExt;
12-
use crate::traits::{self, FulfillmentError, ObligationCause};
11+
use crate::traits::{self, FulfillmentError, Obligation, ObligationCause};
1312

1413
pub enum CopyImplementationError<'tcx> {
1514
InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
@@ -98,10 +97,9 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
9897
tcx: TyCtxt<'tcx>,
9998
param_env: ty::ParamEnv<'tcx>,
10099
self_type: Ty<'tcx>,
101-
lang_item: LangItem,
102100
parent_cause: ObligationCause<'tcx>,
103101
) -> Result<(), ConstParamTyImplementationError<'tcx>> {
104-
assert_matches!(lang_item, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy);
102+
let mut need_unstable_feature_bound = false;
105103

106104
let inner_tys: Vec<_> = match *self_type.kind() {
107105
// Trivially okay as these types are all:
@@ -112,18 +110,14 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
112110

113111
// Handle types gated under `feature(unsized_const_params)`
114112
// FIXME(unsized_const_params): Make `const N: [u8]` work then forbid references
115-
ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not)
116-
if lang_item == LangItem::UnsizedConstParamTy =>
117-
{
113+
ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not) => {
114+
need_unstable_feature_bound = true;
118115
vec![inner_ty]
119116
}
120-
ty::Str if lang_item == LangItem::UnsizedConstParamTy => {
117+
ty::Str => {
118+
need_unstable_feature_bound = true;
121119
vec![Ty::new_slice(tcx, tcx.types.u8)]
122120
}
123-
ty::Str | ty::Slice(..) | ty::Ref(_, _, Mutability::Not) => {
124-
return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
125-
}
126-
127121
ty::Array(inner_ty, _) => vec![inner_ty],
128122

129123
// `str` morally acts like a newtype around `[u8]`
@@ -137,7 +131,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
137131
adt,
138132
args,
139133
parent_cause.clone(),
140-
lang_item,
134+
LangItem::ConstParamTy,
141135
)
142136
.map_err(ConstParamTyImplementationError::InfrigingFields)?;
143137

@@ -153,11 +147,25 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
153147
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
154148
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
155149

150+
// Make sure impls certain types are gated with #[unstable_feature_bound(unsized_const_params)]
151+
if need_unstable_feature_bound {
152+
ocx.register_obligation(Obligation::new(
153+
tcx,
154+
parent_cause.clone(),
155+
param_env,
156+
ty::ClauseKind::UnstableFeature(sym::unsized_const_params),
157+
));
158+
159+
if !ocx.select_all_or_error().is_empty() {
160+
return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
161+
}
162+
}
163+
156164
ocx.register_bound(
157165
parent_cause.clone(),
158166
param_env,
159167
inner_ty,
160-
tcx.require_lang_item(lang_item, parent_cause.span),
168+
tcx.require_lang_item(LangItem::ConstParamTy, parent_cause.span),
161169
);
162170

163171
let errors = ocx.select_all_or_error();

0 commit comments

Comments
 (0)