@@ -115,6 +115,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
115
115
let deferred_repeat_expr_checks = deferred_repeat_expr_checks
116
116
. drain ( ..)
117
117
. flat_map ( |( element, element_ty, count) | {
118
+ // Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy
119
+ // so we don't need to attempt to structurally resolve the repeat count which may unnecessarily error.
120
+ match & element. kind {
121
+ hir:: ExprKind :: ConstBlock ( ..) => return None ,
122
+ hir:: ExprKind :: Path ( qpath) => {
123
+ let res = self . typeck_results . borrow ( ) . qpath_res ( qpath, element. hir_id ) ;
124
+ if let Res :: Def (
125
+ DefKind :: Const | DefKind :: AssocConst | DefKind :: AnonConst ,
126
+ _,
127
+ ) = res
128
+ {
129
+ return None ;
130
+ }
131
+ }
132
+ _ => { }
133
+ }
134
+
118
135
// We want to emit an error if the const is not structurally resolveable as otherwise
119
136
// we can find up conservatively proving `Copy` which may infer the repeat expr count
120
137
// to something that never required `Copy` in the first place.
@@ -135,12 +152,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
135
152
// expr's `Copy` check.
136
153
. collect :: < Vec < _ > > ( ) ;
137
154
155
+ let enforce_copy_bound = |element : & hir:: Expr < ' _ > , element_ty| {
156
+ // If someone calls a const fn or constructs a const value, they can extract that
157
+ // out into a separate constant (or a const block in the future), so we check that
158
+ // to tell them that in the diagnostic. Does not affect typeck.
159
+ let is_constable = match element. kind {
160
+ hir:: ExprKind :: Call ( func, _args) => match * self . node_ty ( func. hir_id ) . kind ( ) {
161
+ ty:: FnDef ( def_id, _) if self . tcx . is_stable_const_fn ( def_id) => {
162
+ traits:: IsConstable :: Fn
163
+ }
164
+ _ => traits:: IsConstable :: No ,
165
+ } ,
166
+ hir:: ExprKind :: Path ( qpath) => {
167
+ match self . typeck_results . borrow ( ) . qpath_res ( & qpath, element. hir_id ) {
168
+ Res :: Def ( DefKind :: Ctor ( _, CtorKind :: Const ) , _) => traits:: IsConstable :: Ctor ,
169
+ _ => traits:: IsConstable :: No ,
170
+ }
171
+ }
172
+ _ => traits:: IsConstable :: No ,
173
+ } ;
174
+
175
+ let lang_item = self . tcx . require_lang_item ( LangItem :: Copy , None ) ;
176
+ let code = traits:: ObligationCauseCode :: RepeatElementCopy {
177
+ is_constable,
178
+ elt_span : element. span ,
179
+ } ;
180
+ self . require_type_meets ( element_ty, element. span , code, lang_item) ;
181
+ } ;
182
+
138
183
for ( element, element_ty, count) in deferred_repeat_expr_checks {
139
184
match count. kind ( ) {
140
185
ty:: ConstKind :: Value ( val)
141
186
if val. try_to_target_usize ( self . tcx ) . is_none_or ( |count| count > 1 ) =>
142
187
{
143
- self . enforce_repeat_element_needs_copy_bound ( element, element_ty)
188
+ enforce_copy_bound ( element, element_ty)
144
189
}
145
190
// If the length is 0 or 1 we don't actually copy the element, we either don't create it
146
191
// or we just use the one value.
@@ -151,9 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
151
196
ty:: ConstKind :: Param ( _)
152
197
| ty:: ConstKind :: Expr ( _)
153
198
| ty:: ConstKind :: Placeholder ( _)
154
- | ty:: ConstKind :: Unevaluated ( _) => {
155
- self . enforce_repeat_element_needs_copy_bound ( element, element_ty)
156
- }
199
+ | ty:: ConstKind :: Unevaluated ( _) => enforce_copy_bound ( element, element_ty) ,
157
200
158
201
ty:: ConstKind :: Bound ( _, _) | ty:: ConstKind :: Infer ( _) | ty:: ConstKind :: Error ( _) => {
159
202
unreachable ! ( )
@@ -162,50 +205,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
162
205
}
163
206
}
164
207
165
- /// Requires that `element_ty` is `Copy` (unless it's a const expression itself).
166
- pub ( super ) fn enforce_repeat_element_needs_copy_bound (
167
- & self ,
168
- element : & hir:: Expr < ' _ > ,
169
- element_ty : Ty < ' tcx > ,
170
- ) {
171
- // Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy.
172
- match & element. kind {
173
- hir:: ExprKind :: ConstBlock ( ..) => return ,
174
- hir:: ExprKind :: Path ( qpath) => {
175
- let res = self . typeck_results . borrow ( ) . qpath_res ( qpath, element. hir_id ) ;
176
- if let Res :: Def ( DefKind :: Const | DefKind :: AssocConst | DefKind :: AnonConst , _) = res
177
- {
178
- return ;
179
- }
180
- }
181
- _ => { }
182
- }
183
-
184
- // If someone calls a const fn or constructs a const value, they can extract that
185
- // out into a separate constant (or a const block in the future), so we check that
186
- // to tell them that in the diagnostic. Does not affect typeck.
187
- let is_constable = match element. kind {
188
- hir:: ExprKind :: Call ( func, _args) => match * self . node_ty ( func. hir_id ) . kind ( ) {
189
- ty:: FnDef ( def_id, _) if self . tcx . is_stable_const_fn ( def_id) => {
190
- traits:: IsConstable :: Fn
191
- }
192
- _ => traits:: IsConstable :: No ,
193
- } ,
194
- hir:: ExprKind :: Path ( qpath) => {
195
- match self . typeck_results . borrow ( ) . qpath_res ( & qpath, element. hir_id ) {
196
- Res :: Def ( DefKind :: Ctor ( _, CtorKind :: Const ) , _) => traits:: IsConstable :: Ctor ,
197
- _ => traits:: IsConstable :: No ,
198
- }
199
- }
200
- _ => traits:: IsConstable :: No ,
201
- } ;
202
-
203
- let lang_item = self . tcx . require_lang_item ( LangItem :: Copy , None ) ;
204
- let code =
205
- traits:: ObligationCauseCode :: RepeatElementCopy { is_constable, elt_span : element. span } ;
206
- self . require_type_meets ( element_ty, element. span , code, lang_item) ;
207
- }
208
-
209
208
pub ( in super :: super ) fn check_method_argument_types (
210
209
& self ,
211
210
sp : Span ,
0 commit comments