Skip to content

Commit 2d7d6e8

Browse files
committed
Defer repeat expr Copy check
1 parent 53a31bb commit 2d7d6e8

File tree

4 files changed

+29
-4
lines changed

4 files changed

+29
-4
lines changed

compiler/rustc_hir_typeck/src/expr.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1856,12 +1856,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18561856
return Ty::new_error(tcx, guar);
18571857
}
18581858

1859+
// We defer checking whether the element type is `Copy` as it is possible to have
1860+
// an inference variable as a repeat count and it seems unlikely that `Copy` would
1861+
// have inference side effects required for type checking to succeed.
1862+
if tcx.features().generic_arg_infer() {
1863+
self.deferred_repeat_expr_checks.borrow_mut().push((element, element_ty, count));
18591864
// If the length is 0, we don't create any elements, so we don't copy any.
18601865
// If the length is 1, we don't copy that one element, we move it. Only check
18611866
// for `Copy` if the length is larger, or unevaluated.
1862-
// FIXME(min_const_generic_exprs): We could perhaps defer this check so that
1863-
// we don't require `<?0t as Tr>::CONST` doesn't unnecessarily require `Copy`.
1864-
if count.try_to_target_usize(tcx).is_none_or(|x| x > 1) {
1867+
} else if count.try_to_target_usize(self.tcx).is_none_or(|x| x > 1) {
18651868
self.enforce_repeat_element_needs_copy_bound(element, element_ty);
18661869
}
18671870

@@ -1871,7 +1874,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18711874
}
18721875

18731876
/// Requires that `element_ty` is `Copy` (unless it's a const expression itself).
1874-
fn enforce_repeat_element_needs_copy_bound(
1877+
pub(super) fn enforce_repeat_element_needs_copy_bound(
18751878
&self,
18761879
element: &hir::Expr<'_>,
18771880
element_ty: Ty<'tcx>,

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+16
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
119119
}
120120
}
121121

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+
122138
pub(in super::super) fn check_method_argument_types(
123139
&self,
124140
sp: Span,

compiler/rustc_hir_typeck/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,8 @@ fn typeck_with_inspect<'tcx>(
194194
fcx.write_ty(id, expected_type);
195195
};
196196

197+
fcx.check_repeat_exprs();
198+
197199
fcx.type_inference_fallback();
198200

199201
// Even though coercion casts provide type hints, we check casts after fallback for

compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs

+4
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
6262

6363
pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, hir::BodyId, Ty<'tcx>)>>,
6464

65+
pub(super) deferred_repeat_expr_checks:
66+
RefCell<Vec<(&'tcx hir::Expr<'tcx>, Ty<'tcx>, ty::Const<'tcx>)>>,
67+
6568
/// Whenever we introduce an adjustment from `!` into a type variable,
6669
/// we record that type variable here. This is later used to inform
6770
/// fallback. See the `fallback` module for details.
@@ -96,6 +99,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
9699
deferred_transmute_checks: RefCell::new(Vec::new()),
97100
deferred_asm_checks: RefCell::new(Vec::new()),
98101
deferred_coroutine_interiors: RefCell::new(Vec::new()),
102+
deferred_repeat_expr_checks: RefCell::new(Vec::new()),
99103
diverging_type_vars: RefCell::new(Default::default()),
100104
infer_var_info: RefCell::new(Default::default()),
101105
}

0 commit comments

Comments
 (0)