@@ -23,7 +23,7 @@ pub enum CopyImplementationError<'tcx> {
23
23
24
24
pub enum ConstParamTyImplementationError < ' tcx > {
25
25
InfrigingFields ( Vec < ( & ' tcx ty:: FieldDef , Ty < ' tcx > , InfringingFieldsReason < ' tcx > ) > ) ,
26
- InfringingReferee ( DefId ) ,
26
+ InfringingInnerTy ( DefId ) ,
27
27
NotAnAdtOrBuiltinAllowed ,
28
28
}
29
29
@@ -93,22 +93,21 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
93
93
self_type : Ty < ' tcx > ,
94
94
parent_cause : ObligationCause < ' tcx > ,
95
95
) -> Result < ( ) , ConstParamTyImplementationError < ' tcx > > {
96
- let ( adt, args) = match self_type. kind ( ) {
97
- // Special case for impls like `impl ConstParamTy for &Foo`, where
98
- // Foo doesn't `impl ConstParamTy`. These kinds of impls aren't caught
99
- // by coherence checking since `core`'s impl is restricted to &T where
100
- // T: ConstParamTy.
101
- // `has_concrete_skeleton()` avoids reporting `core`'s blanket impl.
102
- & ty:: Ref ( .., ty, hir:: Mutability :: Not ) if ty. peel_refs ( ) . has_concrete_skeleton ( ) => {
103
- let ty = ty. peel_refs ( ) ;
104
- type_allowed_to_implement_const_param_ty ( tcx, param_env, ty, parent_cause) ?;
105
- // Check the ty behind the ref impls `ConstParamTy` itself. This additional
106
- // logic is needed when checking refs because we need to check not only if
107
- // all fields implement ConstParamTy, but also that the type itself implements
108
- // ConstParamTy. Simply recursing into the ref only checks the former.
109
- if !ty. references_error ( )
110
- && let & ty:: Adt ( adt, _) = ty. kind ( )
111
- {
96
+ // Special case for impls like `impl ConstParamTy for &Foo`, where
97
+ // Foo doesn't `impl ConstParamTy`. These kinds of impls aren't caught
98
+ // by coherence checking since `core`'s impl is restricted to T: ConstParamTy.
99
+ // `has_concrete_skeleton()` avoids reporting `core`'s blanket impl.
100
+ let check_inner_ty = |ty : Ty < ' tcx > , cause| {
101
+ let ty = ty. peel_refs ( ) ;
102
+ if ty. has_concrete_skeleton ( ) {
103
+ type_allowed_to_implement_const_param_ty ( tcx, param_env, ty, cause) ?;
104
+ // Check the inner tys in refs, tuples, arrays, or slices implement `ConstParamTy`.
105
+ // This additional logic is needed because we need to check not only if all fields
106
+ // of the type implement ConstParamTy, but also that the type itself implements
107
+ // ConstParamTy. Simply recursing into the inner type only checks the former.
108
+ // `type_allowed_to_implement_const_param_ty` takes care of other non-ADT types
109
+ // for us.
110
+ if let & ty:: Adt ( adt, _) = ty. kind ( ) {
112
111
let adt_did = adt. did ( ) ;
113
112
let adt_span = tcx. def_span ( adt_did) ;
114
113
let trait_did = tcx. require_lang_item ( hir:: LangItem :: ConstParamTy , Some ( adt_span) ) ;
@@ -130,23 +129,30 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
130
129
) ;
131
130
let errs = ocx. select_all_or_error ( ) ;
132
131
if !errs. is_empty ( ) {
133
- return Err ( ConstParamTyImplementationError :: InfringingReferee ( adt_did) ) ;
132
+ return Err ( ConstParamTyImplementationError :: InfringingInnerTy ( adt_did) ) ;
134
133
}
135
134
}
135
+ }
136
136
137
+ Ok ( ( ) )
138
+ } ;
139
+
140
+ let ( adt, args) = match self_type. kind ( ) {
141
+ // `core` provides these impls, but only where the inner type is `ConstParamTy`,
142
+ // so we need to check and deny impls where the inner type is not `ConstParamTy`
143
+ & ty:: Ref ( .., ty, hir:: Mutability :: Not ) | & ty:: Array ( ty, ..) | & ty:: Slice ( ty) => {
144
+ return check_inner_ty ( ty, parent_cause) ;
145
+ }
146
+
147
+ & ty:: Tuple ( tys) => {
148
+ for ty in tys {
149
+ check_inner_ty ( ty, parent_cause. clone ( ) ) ?;
150
+ }
137
151
return Ok ( ( ) ) ;
138
152
}
139
153
140
154
// `core` provides these impls.
141
- ty:: Uint ( _)
142
- | ty:: Int ( _)
143
- | ty:: Bool
144
- | ty:: Char
145
- | ty:: Str
146
- | ty:: Array ( ..)
147
- | ty:: Slice ( _)
148
- | ty:: Ref ( .., hir:: Mutability :: Not )
149
- | ty:: Tuple ( _) => return Ok ( ( ) ) ,
155
+ ty:: Uint ( _) | ty:: Int ( _) | ty:: Bool | ty:: Char | ty:: Str => return Ok ( ( ) ) ,
150
156
151
157
& ty:: Adt ( adt, args) => ( adt, args) ,
152
158
0 commit comments