@@ -108,6 +108,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
108108 let deferred_repeat_expr_checks = deferred_repeat_expr_checks
109109 . drain ( ..)
110110 . 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+
111128 // We want to emit an error if the const is not structurally resolveable as otherwise
112129 // we can find up conservatively proving `Copy` which may infer the repeat expr count
113130 // to something that never required `Copy` in the first place.
@@ -128,12 +145,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
128145 // expr's `Copy` check.
129146 . collect :: < Vec < _ > > ( ) ;
130147
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+
131176 for ( element, element_ty, count) in deferred_repeat_expr_checks {
132177 match count. kind ( ) {
133178 ty:: ConstKind :: Value ( val)
134179 if val. try_to_target_usize ( self . tcx ) . is_none_or ( |count| count > 1 ) =>
135180 {
136- self . enforce_repeat_element_needs_copy_bound ( element, element_ty)
181+ enforce_copy_bound ( element, element_ty)
137182 }
138183 // If the length is 0 or 1 we don't actually copy the element, we either don't create it
139184 // or we just use the one value.
@@ -144,9 +189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
144189 ty:: ConstKind :: Param ( _)
145190 | ty:: ConstKind :: Expr ( _)
146191 | 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) ,
150193
151194 ty:: ConstKind :: Bound ( _, _) | ty:: ConstKind :: Infer ( _) | ty:: ConstKind :: Error ( _) => {
152195 unreachable ! ( )
@@ -155,50 +198,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
155198 }
156199 }
157200
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-
202201 /// Generic function that factors out common logic from function calls,
203202 /// method calls and overloaded operators.
204203 pub ( in super :: super ) fn check_argument_types (
0 commit comments