@@ -4,6 +4,7 @@ use crate::regions::InferCtxtRegionExt;
44use crate :: traits:: { self , FulfillmentError , ObligationCause } ;
55
66use hir:: LangItem ;
7+ use rustc_ast:: Mutability ;
78use rustc_data_structures:: fx:: FxIndexSet ;
89use rustc_hir as hir;
910use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
@@ -19,7 +20,7 @@ pub enum CopyImplementationError<'tcx> {
1920}
2021
2122pub enum ConstParamTyImplementationError < ' tcx > {
22- TypeNotSized ,
23+ UnsizedConstParamsFeatureRequired ,
2324 InvalidInnerTyOfBuiltinTy ( Vec < ( Ty < ' tcx > , InfringingFieldsReason < ' tcx > ) > ) ,
2425 InfrigingFields ( Vec < ( & ' tcx ty:: FieldDef , Ty < ' tcx > , InfringingFieldsReason < ' tcx > ) > ) ,
2526 NotAnAdtOrBuiltinAllowed ,
@@ -79,40 +80,20 @@ pub fn type_allowed_to_implement_copy<'tcx>(
7980 Ok ( ( ) )
8081}
8182
82- /// Checks that the fields of the type (an ADT) all implement `ConstParamTy`.
83+ /// Checks that the fields of the type (an ADT) all implement `(Unsized?) ConstParamTy`.
8384///
84- /// If fields don't implement `ConstParamTy`, return an error containing a list of
85+ /// If fields don't implement `(Unsized?) ConstParamTy`, return an error containing a list of
8586/// those violating fields.
8687///
8788/// If it's not an ADT, int ty, `bool` or `char`, returns `Err(NotAnAdtOrBuiltinAllowed)`.
8889pub fn type_allowed_to_implement_const_param_ty < ' tcx > (
8990 tcx : TyCtxt < ' tcx > ,
9091 param_env : ty:: ParamEnv < ' tcx > ,
9192 self_type : Ty < ' tcx > ,
93+ lang_item : LangItem ,
9294 parent_cause : ObligationCause < ' tcx > ,
9395) -> Result < ( ) , ConstParamTyImplementationError < ' tcx > > {
94- {
95- // Check for sizedness before recursing into ADT fields so that if someone tries to write:
96- // ```rust
97- // #[derive(ConstParamTy)]
98- // struct Foo([u8])
99- // ```
100- // They are told that const parameter types must be sized, instead of it saying that
101- // the trait implementation `[u8]: ConstParamTy` is not satisfied.
102- let infcx = tcx. infer_ctxt ( ) . build ( ) ;
103- let ocx = traits:: ObligationCtxt :: new_with_diagnostics ( & infcx) ;
104-
105- ocx. register_bound (
106- parent_cause. clone ( ) ,
107- param_env,
108- self_type,
109- tcx. require_lang_item ( LangItem :: Sized , Some ( parent_cause. span ) ) ,
110- ) ;
111-
112- if !ocx. select_all_or_error ( ) . is_empty ( ) {
113- return Err ( ConstParamTyImplementationError :: TypeNotSized ) ;
114- }
115- } ;
96+ assert ! ( matches!( lang_item, LangItem :: ConstParamTy | LangItem :: UnsizedConstParamTy ) ) ;
11697
11798 let inner_tys: Vec < _ > = match * self_type. kind ( ) {
11899 // Trivially okay as these types are all:
@@ -121,14 +102,23 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
121102 // - Have structural equality
122103 ty:: Uint ( _) | ty:: Int ( _) | ty:: Bool | ty:: Char => return Ok ( ( ) ) ,
123104
124- ty:: Ref ( ..) => return Err ( ConstParamTyImplementationError :: NotAnAdtOrBuiltinAllowed ) ,
105+ // Handle types gated under `feature(unsized_const_params)`
106+ // FIXME(unsized_const_params): Make `const N: [u8]` work then forbid references
107+ ty:: Slice ( inner_ty) | ty:: Ref ( _, inner_ty, Mutability :: Not )
108+ if lang_item == LangItem :: UnsizedConstParamTy =>
109+ {
110+ vec ! [ inner_ty]
111+ }
112+ ty:: Str if lang_item == LangItem :: UnsizedConstParamTy => {
113+ vec ! [ Ty :: new_slice( tcx, tcx. types. u8 ) ]
114+ }
115+ ty:: Str | ty:: Slice ( ..) | ty:: Ref ( _, _, Mutability :: Not ) => {
116+ return Err ( ConstParamTyImplementationError :: UnsizedConstParamsFeatureRequired ) ;
117+ }
118+
119+ ty:: Array ( inner_ty, _) => vec ! [ inner_ty] ,
125120
126- // Even if we currently require const params to be `Sized` we may aswell handle them correctly
127- // here anyway.
128- ty:: Slice ( inner_ty) | ty:: Array ( inner_ty, _) => vec ! [ inner_ty] ,
129121 // `str` morally acts like a newtype around `[u8]`
130- ty:: Str => vec ! [ Ty :: new_slice( tcx, tcx. types. u8 ) ] ,
131-
132122 ty:: Tuple ( inner_tys) => inner_tys. into_iter ( ) . collect ( ) ,
133123
134124 ty:: Adt ( adt, args) if adt. is_enum ( ) || adt. is_struct ( ) => {
@@ -139,7 +129,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
139129 adt,
140130 args,
141131 parent_cause. clone ( ) ,
142- hir :: LangItem :: ConstParamTy ,
132+ lang_item ,
143133 )
144134 . map_err ( ConstParamTyImplementationError :: InfrigingFields ) ?;
145135
@@ -159,7 +149,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
159149 parent_cause. clone ( ) ,
160150 param_env,
161151 inner_ty,
162- tcx. require_lang_item ( LangItem :: ConstParamTy , Some ( parent_cause. span ) ) ,
152+ tcx. require_lang_item ( lang_item , Some ( parent_cause. span ) ) ,
163153 ) ;
164154
165155 let errors = ocx. select_all_or_error ( ) ;
0 commit comments