@@ -4,6 +4,7 @@ use crate::regions::InferCtxtRegionExt;
4
4
use crate :: traits:: { self , FulfillmentError , ObligationCause } ;
5
5
6
6
use hir:: LangItem ;
7
+ use rustc_ast:: Mutability ;
7
8
use rustc_data_structures:: fx:: FxIndexSet ;
8
9
use rustc_hir as hir;
9
10
use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
@@ -19,7 +20,7 @@ pub enum CopyImplementationError<'tcx> {
19
20
}
20
21
21
22
pub enum ConstParamTyImplementationError < ' tcx > {
22
- TypeNotSized ,
23
+ UnsizedConstParamsFeatureRequired ,
23
24
InvalidInnerTyOfBuiltinTy ( Vec < ( Ty < ' tcx > , InfringingFieldsReason < ' tcx > ) > ) ,
24
25
InfrigingFields ( Vec < ( & ' tcx ty:: FieldDef , Ty < ' tcx > , InfringingFieldsReason < ' tcx > ) > ) ,
25
26
NotAnAdtOrBuiltinAllowed ,
@@ -79,40 +80,20 @@ pub fn type_allowed_to_implement_copy<'tcx>(
79
80
Ok ( ( ) )
80
81
}
81
82
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`.
83
84
///
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
85
86
/// those violating fields.
86
87
///
87
88
/// If it's not an ADT, int ty, `bool` or `char`, returns `Err(NotAnAdtOrBuiltinAllowed)`.
88
89
pub fn type_allowed_to_implement_const_param_ty < ' tcx > (
89
90
tcx : TyCtxt < ' tcx > ,
90
91
param_env : ty:: ParamEnv < ' tcx > ,
91
92
self_type : Ty < ' tcx > ,
93
+ lang_item : LangItem ,
92
94
parent_cause : ObligationCause < ' tcx > ,
93
95
) -> 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 ) ) ;
116
97
117
98
let inner_tys: Vec < _ > = match * self_type. kind ( ) {
118
99
// Trivially okay as these types are all:
@@ -121,14 +102,23 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
121
102
// - Have structural equality
122
103
ty:: Uint ( _) | ty:: Int ( _) | ty:: Bool | ty:: Char => return Ok ( ( ) ) ,
123
104
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] ,
125
120
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] ,
129
121
// `str` morally acts like a newtype around `[u8]`
130
- ty:: Str => vec ! [ Ty :: new_slice( tcx, tcx. types. u8 ) ] ,
131
-
132
122
ty:: Tuple ( inner_tys) => inner_tys. into_iter ( ) . collect ( ) ,
133
123
134
124
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>(
139
129
adt,
140
130
args,
141
131
parent_cause. clone ( ) ,
142
- hir :: LangItem :: ConstParamTy ,
132
+ lang_item ,
143
133
)
144
134
. map_err ( ConstParamTyImplementationError :: InfrigingFields ) ?;
145
135
@@ -159,7 +149,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
159
149
parent_cause. clone ( ) ,
160
150
param_env,
161
151
inner_ty,
162
- tcx. require_lang_item ( LangItem :: ConstParamTy , Some ( parent_cause. span ) ) ,
152
+ tcx. require_lang_item ( lang_item , Some ( parent_cause. span ) ) ,
163
153
) ;
164
154
165
155
let errors = ocx. select_all_or_error ( ) ;
0 commit comments