Skip to content

Commit 8bc7d6e

Browse files
committed
Suggest arry::from_fn for array initialization
1 parent 174e73a commit 8bc7d6e

File tree

6 files changed

+38
-0
lines changed

6 files changed

+38
-0
lines changed

compiler/rustc_hir_typeck/src/expr.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1571,12 +1571,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15711571
_ => traits::IsConstable::No,
15721572
};
15731573

1574+
let is_repeatable = match element.kind {
1575+
hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
1576+
ty::FnDef(_, _) => true,
1577+
_ => false,
1578+
},
1579+
hir::ExprKind::Struct(_, _, _) => true,
1580+
_ => false,
1581+
};
1582+
15741583
// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
15751584
// don't copy that one element, we move it. Only check for Copy if the length is larger.
15761585
if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
15771586
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
15781587
let code = traits::ObligationCauseCode::RepeatElementCopy {
15791588
is_constable,
1589+
is_repeatable,
15801590
elt_type: element_ty,
15811591
elt_span: element.span,
15821592
elt_stmt_span: self

compiler/rustc_middle/src/traits/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ pub enum ObligationCauseCode<'tcx> {
305305
/// If element is a `const fn` or const ctor we display a help message suggesting
306306
/// to move it to a new `const` item while saying that `T` doesn't implement `Copy`.
307307
is_constable: IsConstable,
308+
is_repeatable: bool,
308309
elt_type: Ty<'tcx>,
309310
elt_span: Span,
310311
/// Span of the statement/item in which the repeat expression occurs. We can use this to

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+5
Original file line numberDiff line numberDiff line change
@@ -3110,6 +3110,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
31103110
}
31113111
ObligationCauseCode::RepeatElementCopy {
31123112
is_constable,
3113+
is_repeatable,
31133114
elt_type,
31143115
elt_span,
31153116
elt_stmt_span,
@@ -3144,6 +3145,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
31443145
],
31453146
Applicability::MachineApplicable,
31463147
);
3148+
} else if is_repeatable {
3149+
// FIXME: we may suggest array::repeat instead
3150+
err.help("consider using `core::array::from_fn` to initialize the array");
3151+
err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information");
31473152
}
31483153

31493154
if self.tcx.sess.is_nightly_build()

tests/ui/array-slice-vec/repeat_empty_ok.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ LL | let headers = [Header{value: &[]}; 128];
55
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>`
66
|
77
= note: the `Copy` trait is required because this value will be copied for each element of the array
8+
= help: consider using `core::array::from_fn` to initialize the array
9+
= help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information
810
help: consider annotating `Header<'_>` with `#[derive(Copy)]`
911
|
1012
LL + #[derive(Copy)]
@@ -18,6 +20,8 @@ LL | let headers = [Header{value: &[0]}; 128];
1820
| ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>`
1921
|
2022
= note: the `Copy` trait is required because this value will be copied for each element of the array
23+
= help: consider using `core::array::from_fn` to initialize the array
24+
= help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information
2125
help: consider annotating `Header<'_>` with `#[derive(Copy)]`
2226
|
2327
LL + #[derive(Copy)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn foo() -> String { String::new() }
2+
3+
fn main() {
4+
let string_arr = [foo(); 64]; //~ ERROR the trait bound `String: Copy` is not satisfied
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0277]: the trait bound `String: Copy` is not satisfied
2+
--> $DIR/issue-119530-sugg-from-fn.rs:4:23
3+
|
4+
LL | let string_arr = [foo(); 64];
5+
| ^^^^^ the trait `Copy` is not implemented for `String`
6+
|
7+
= note: the `Copy` trait is required because this value will be copied for each element of the array
8+
= help: consider using `core::array::from_fn` to initialize the array
9+
= help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)