@@ -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