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