1
1
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
2
2
3
- use std:: assert_matches:: assert_matches;
4
-
5
3
use hir:: LangItem ;
6
4
use rustc_ast:: Mutability ;
7
5
use rustc_hir as hir;
8
6
use rustc_infer:: infer:: { RegionResolutionError , TyCtxtInferExt } ;
9
7
use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt , TypeVisitableExt , TypingMode } ;
8
+ use rustc_span:: sym;
10
9
11
10
use crate :: regions:: InferCtxtRegionExt ;
12
- use crate :: traits:: { self , FulfillmentError , ObligationCause } ;
11
+ use crate :: traits:: { self , FulfillmentError , Obligation , ObligationCause } ;
13
12
14
13
pub enum CopyImplementationError < ' tcx > {
15
14
InfringingFields ( Vec < ( & ' tcx ty:: FieldDef , Ty < ' tcx > , InfringingFieldsReason < ' tcx > ) > ) ,
@@ -98,10 +97,9 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
98
97
tcx : TyCtxt < ' tcx > ,
99
98
param_env : ty:: ParamEnv < ' tcx > ,
100
99
self_type : Ty < ' tcx > ,
101
- lang_item : LangItem ,
102
100
parent_cause : ObligationCause < ' tcx > ,
103
101
) -> Result < ( ) , ConstParamTyImplementationError < ' tcx > > {
104
- assert_matches ! ( lang_item , LangItem :: ConstParamTy | LangItem :: UnsizedConstParamTy ) ;
102
+ let mut need_unstable_feature_bound = false ;
105
103
106
104
let inner_tys: Vec < _ > = match * self_type. kind ( ) {
107
105
// Trivially okay as these types are all:
@@ -112,18 +110,14 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
112
110
113
111
// Handle types gated under `feature(unsized_const_params)`
114
112
// 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 ;
118
115
vec ! [ inner_ty]
119
116
}
120
- ty:: Str if lang_item == LangItem :: UnsizedConstParamTy => {
117
+ ty:: Str => {
118
+ need_unstable_feature_bound = true ;
121
119
vec ! [ Ty :: new_slice( tcx, tcx. types. u8 ) ]
122
120
}
123
- ty:: Str | ty:: Slice ( ..) | ty:: Ref ( _, _, Mutability :: Not ) => {
124
- return Err ( ConstParamTyImplementationError :: UnsizedConstParamsFeatureRequired ) ;
125
- }
126
-
127
121
ty:: Array ( inner_ty, _) => vec ! [ inner_ty] ,
128
122
129
123
// `str` morally acts like a newtype around `[u8]`
@@ -137,7 +131,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
137
131
adt,
138
132
args,
139
133
parent_cause. clone ( ) ,
140
- lang_item ,
134
+ LangItem :: ConstParamTy ,
141
135
)
142
136
. map_err ( ConstParamTyImplementationError :: InfrigingFields ) ?;
143
137
@@ -153,11 +147,25 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
153
147
let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ;
154
148
let ocx = traits:: ObligationCtxt :: new_with_diagnostics ( & infcx) ;
155
149
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
+
156
164
ocx. register_bound (
157
165
parent_cause. clone ( ) ,
158
166
param_env,
159
167
inner_ty,
160
- tcx. require_lang_item ( lang_item , parent_cause. span ) ,
168
+ tcx. require_lang_item ( LangItem :: ConstParamTy , parent_cause. span ) ,
161
169
) ;
162
170
163
171
let errors = ocx. select_all_or_error ( ) ;
0 commit comments