11//! Miscellaneous type-system utilities that are too small to deserve their own modules.
22
3- use std:: assert_matches:: assert_matches;
4-
53use hir:: LangItem ;
64use rustc_ast:: Mutability ;
75use rustc_hir as hir;
86use rustc_infer:: infer:: { RegionResolutionError , TyCtxtInferExt } ;
97use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt , TypeVisitableExt , TypingMode } ;
8+ use rustc_span:: sym;
109
1110use crate :: regions:: InferCtxtRegionExt ;
12- use crate :: traits:: { self , FulfillmentError , ObligationCause } ;
11+ use crate :: traits:: { self , FulfillmentError , Obligation , ObligationCause } ;
1312
1413pub 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