Auto merge of #137045 - BoxyUwU:defer_repeat_expr_checks, r= · rust-lang/rust@9053a8a (original) (raw)
`@@ -6,10 +6,10 @@ use rustc_errors::codes::*;
`
6
6
`use rustc_errors::{
`
7
7
`Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, a_or_an, listify, pluralize,
`
8
8
`};
`
9
``
`-
use rustc_hir::def::{CtorOf, DefKind, Res};
`
``
9
`+
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
`
10
10
`use rustc_hir::def_id::DefId;
`
11
11
`use rustc_hir::intravisit::Visitor;
`
12
``
`-
use rustc_hir::{ExprKind, HirId, Node, QPath};
`
``
12
`+
use rustc_hir::{ExprKind, HirId, LangItem, Node, QPath};
`
13
13
`use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
`
14
14
`use rustc_hir_analysis::check::potentially_plural_count;
`
15
15
`use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
`
`@@ -119,6 +119,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
`
119
119
`}
`
120
120
`}
`
121
121
``
``
122
`+
pub(in super::super) fn check_repeat_exprs(&self) {
`
``
123
`+
let mut deferred_repeat_expr_checks = self.deferred_repeat_expr_checks.borrow_mut();
`
``
124
`+
debug!("FnCtxt::check_repeat_exprs: {} deferred checks", deferred_repeat_expr_checks.len());
`
``
125
`+
for (element, element_ty, count) in deferred_repeat_expr_checks.drain(..) {
`
``
126
`+
let count = self
`
``
127
`+
.try_structurally_resolve_const(element.span, self.normalize(element.span, count));
`
``
128
+
``
129
`+
// If the length is 0, we don't create any elements, so we don't copy any.
`
``
130
`+
// If the length is 1, we don't copy that one element, we move it. Only check
`
``
131
`` +
// for Copy
if the length is larger, or unevaluated.
``
``
132
`+
if count.try_to_target_usize(self.tcx).is_none_or(|x| x > 1) {
`
``
133
`+
self.enforce_repeat_element_needs_copy_bound(element, element_ty);
`
``
134
`+
}
`
``
135
`+
}
`
``
136
`+
}
`
``
137
+
``
138
`` +
/// Requires that element_ty
is Copy
(unless it's a const expression itself).
``
``
139
`+
fn enforce_repeat_element_needs_copy_bound(
`
``
140
`+
&self,
`
``
141
`+
element: &hir::Expr<'_>,
`
``
142
`+
element_ty: Ty<'tcx>,
`
``
143
`+
) {
`
``
144
`+
let tcx = self.tcx;
`
``
145
`+
// Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy.
`
``
146
`+
match &element.kind {
`
``
147
`+
hir::ExprKind::ConstBlock(..) => return,
`
``
148
`+
hir::ExprKind::Path(qpath) => {
`
``
149
`+
let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
`
``
150
`+
if let Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::AnonConst, _) = res
`
``
151
`+
{
`
``
152
`+
return;
`
``
153
`+
}
`
``
154
`+
}
`
``
155
`+
_ => {}
`
``
156
`+
}
`
``
157
`+
// If someone calls a const fn or constructs a const value, they can extract that
`
``
158
`+
// out into a separate constant (or a const block in the future), so we check that
`
``
159
`+
// to tell them that in the diagnostic. Does not affect typeck.
`
``
160
`+
let is_constable = match element.kind {
`
``
161
`+
hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
`
``
162
`+
ty::FnDef(def_id, _) if tcx.is_stable_const_fn(def_id) => traits::IsConstable::Fn,
`
``
163
`+
_ => traits::IsConstable::No,
`
``
164
`+
},
`
``
165
`+
hir::ExprKind::Path(qpath) => {
`
``
166
`+
match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
`
``
167
`+
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
`
``
168
`+
_ => traits::IsConstable::No,
`
``
169
`+
}
`
``
170
`+
}
`
``
171
`+
_ => traits::IsConstable::No,
`
``
172
`+
};
`
``
173
+
``
174
`+
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
`
``
175
`+
let code =
`
``
176
`+
traits::ObligationCauseCode::RepeatElementCopy { is_constable, elt_span: element.span };
`
``
177
`+
self.require_type_meets(element_ty, element.span, code, lang_item);
`
``
178
`+
}
`
``
179
+
122
180
`pub(in super::super) fn check_method_argument_types(
`
123
181
`&self,
`
124
182
`sp: Span,
`