@@ -4,10 +4,10 @@ use itertools::Itertools;
44use rustc_data_structures:: fx:: FxIndexSet ;
55use rustc_errors:: codes:: * ;
66use rustc_errors:: { Applicability , Diag , ErrorGuaranteed , MultiSpan , a_or_an, listify, pluralize} ;
7- use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
7+ use rustc_hir:: def:: { CtorKind , CtorOf , DefKind , Res } ;
88use rustc_hir:: def_id:: DefId ;
99use rustc_hir:: intravisit:: Visitor ;
10- use rustc_hir:: { ExprKind , HirId , Node , QPath } ;
10+ use rustc_hir:: { ExprKind , HirId , LangItem , Node , QPath } ;
1111use rustc_hir_analysis:: check:: intrinsicck:: InlineAsmCtxt ;
1212use rustc_hir_analysis:: check:: potentially_plural_count;
1313use rustc_hir_analysis:: hir_ty_lowering:: HirTyLowerer ;
@@ -162,6 +162,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
162162 }
163163 }
164164
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+
165209 pub ( in super :: super ) fn check_method_argument_types (
166210 & self ,
167211 sp : Span ,
0 commit comments