Skip to content

Commit

Permalink
Suggest arry::from_fn for array initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyukang committed Jan 12, 2024
1 parent 174e73a commit 8bc7d6e
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 0 deletions.
10 changes: 10 additions & 0 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1571,12 +1571,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => traits::IsConstable::No,
};

let is_repeatable = match element.kind {
hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
ty::FnDef(_, _) => true,
_ => false,
},
hir::ExprKind::Struct(_, _, _) => true,
_ => false,
};

// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
// don't copy that one element, we move it. Only check for Copy if the length is larger.
if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
let code = traits::ObligationCauseCode::RepeatElementCopy {
is_constable,
is_repeatable,
elt_type: element_ty,
elt_span: element.span,
elt_stmt_span: self
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ pub enum ObligationCauseCode<'tcx> {
/// If element is a `const fn` or const ctor we display a help message suggesting
/// to move it to a new `const` item while saying that `T` doesn't implement `Copy`.
is_constable: IsConstable,
is_repeatable: bool,
elt_type: Ty<'tcx>,
elt_span: Span,
/// Span of the statement/item in which the repeat expression occurs. We can use this to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3110,6 +3110,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
ObligationCauseCode::RepeatElementCopy {
is_constable,
is_repeatable,
elt_type,
elt_span,
elt_stmt_span,
Expand Down Expand Up @@ -3144,6 +3145,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
],
Applicability::MachineApplicable,
);
} else if is_repeatable {
// FIXME: we may suggest array::repeat instead
err.help("consider using `core::array::from_fn` to initialize the array");
err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information");
}

if self.tcx.sess.is_nightly_build()
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/array-slice-vec/repeat_empty_ok.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ LL | let headers = [Header{value: &[]}; 128];
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>`
|
= note: the `Copy` trait is required because this value will be copied for each element of the array
= help: consider using `core::array::from_fn` to initialize the array
= help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information
help: consider annotating `Header<'_>` with `#[derive(Copy)]`
|
LL + #[derive(Copy)]
Expand All @@ -18,6 +20,8 @@ LL | let headers = [Header{value: &[0]}; 128];
| ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>`
|
= note: the `Copy` trait is required because this value will be copied for each element of the array
= help: consider using `core::array::from_fn` to initialize the array
= help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information
help: consider annotating `Header<'_>` with `#[derive(Copy)]`
|
LL + #[derive(Copy)]
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/trait-bounds/issue-119530-sugg-from-fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn foo() -> String { String::new() }

fn main() {
let string_arr = [foo(); 64]; //~ ERROR the trait bound `String: Copy` is not satisfied
}
13 changes: 13 additions & 0 deletions tests/ui/trait-bounds/issue-119530-sugg-from-fn.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/issue-119530-sugg-from-fn.rs:4:23
|
LL | let string_arr = [foo(); 64];
| ^^^^^ the trait `Copy` is not implemented for `String`
|
= note: the `Copy` trait is required because this value will be copied for each element of the array
= help: consider using `core::array::from_fn` to initialize the array
= help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.

0 comments on commit 8bc7d6e

Please sign in to comment.