Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest inline const blocks for array initialization #126899

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2915,54 +2915,28 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
ObligationCauseCode::RepeatElementCopy {
is_constable,
elt_type,
elt_type: _,
elt_span,
elt_stmt_span,
elt_stmt_span: _,
} => {
err.note(
"the `Copy` trait is required because this value will be copied for each element of the array",
);
let value_kind = match is_constable {
IsConstable::Fn => Some("the result of the function call"),
IsConstable::Ctor => Some("the result of the constructor"),
_ => None,
};
let sm = tcx.sess.source_map();
if let Some(value_kind) = value_kind
if matches!(is_constable, IsConstable::Fn | IsConstable::Ctor)
&& let Ok(snip) = sm.span_to_snippet(elt_span)
{
let help_msg = format!(
"consider creating a new `const` item and initializing it with {value_kind} \
to be used in the repeat position"
);
let indentation = sm.indentation_before(elt_stmt_span).unwrap_or_default();
err.multipart_suggestion(
help_msg,
vec![
(
elt_stmt_span.shrink_to_lo(),
format!(
"const ARRAY_REPEAT_VALUE: {elt_type} = {snip};\n{indentation}"
),
),
(elt_span, "ARRAY_REPEAT_VALUE".to_string()),
],
err.span_suggestion(
elt_span,
"create an inline `const` block",
format!("const {{ {snip} }}"),
Applicability::MachineApplicable,
);
} else {
// 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 tcx.sess.is_nightly_build()
&& matches!(is_constable, IsConstable::Fn | IsConstable::Ctor)
{
err.help(
"create an inline `const` block, see RFC #2920 \
<https://github.com/rust-lang/rfcs/pull/2920> for more information",
);
}
}
ObligationCauseCode::VariableType(hir_id) => {
if let Some(typeck_results) = &self.typeck_results
Expand Down
8 changes: 3 additions & 5 deletions tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@ LL | let _: [Option<Bar>; 2] = [no_copy(); 2];
|
= note: required for `Option<Bar>` to implement `Copy`
= note: the `Copy` trait is required because this value will be copied for each element of the array
= help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
help: consider annotating `Bar` with `#[derive(Copy)]`
|
LL + #[derive(Copy)]
LL | struct Bar;
|
help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position
|
LL ~ const ARRAY_REPEAT_VALUE: Option<Bar> = no_copy();
LL ~ let _: [Option<Bar>; 2] = [ARRAY_REPEAT_VALUE; 2];
help: create an inline `const` block
|
LL | let _: [Option<Bar>; 2] = [const { no_copy() }; 2];
| ~~~~~~~~~~~~~~~~~~~

error: aborting due to 1 previous error

Expand Down
11 changes: 4 additions & 7 deletions tests/ui/consts/const-blocks/trait-error.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,18 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/trait-error.rs:5:6
|
LL | [Foo(String::new()); 4];
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`, which is required by `Foo<String>: Copy`
| ^^^^^^^^^^^^^^^^^^
| |
| the trait `Copy` is not implemented for `String`, which is required by `Foo<String>: Copy`
| help: create an inline `const` block: `const { Foo(String::new()) }`
|
note: required for `Foo<String>` to implement `Copy`
--> $DIR/trait-error.rs:1:10
|
LL | #[derive(Copy, Clone)]
| ^^^^ unsatisfied trait bound introduced in this `derive` macro
= note: the `Copy` trait is required because this value will be copied for each element of the array
= help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position
|
LL ~ const ARRAY_REPEAT_VALUE: Foo<String> = Foo(String::new());
LL ~ [ARRAY_REPEAT_VALUE; 4];
|

error: aborting due to 1 previous error

Expand Down
33 changes: 12 additions & 21 deletions tests/ui/consts/const-fn-in-vec.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,36 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/const-fn-in-vec.rs:1:47
|
LL | static _MAYBE_STRINGS: [Option<String>; 5] = [None; 5];
| ^^^^ the trait `Copy` is not implemented for `String`, which is required by `Option<String>: Copy`
| ^^^^
| |
| the trait `Copy` is not implemented for `String`, which is required by `Option<String>: Copy`
| help: create an inline `const` block: `const { None }`
|
= note: required for `Option<String>` to implement `Copy`
= note: the `Copy` trait is required because this value will be copied for each element of the array
= help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position
|
LL + const ARRAY_REPEAT_VALUE: Option<String> = None;
LL ~ static _MAYBE_STRINGS: [Option<String>; 5] = [ARRAY_REPEAT_VALUE; 5];
|

error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/const-fn-in-vec.rs:7:34
|
LL | let _strings: [String; 5] = [String::new(); 5];
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
| ^^^^^^^^^^^^^
| |
| the trait `Copy` is not implemented for `String`
| help: create an inline `const` block: `const { String::new() }`
|
= note: the `Copy` trait is required because this value will be copied for each element of the array
= help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position
|
LL ~ const ARRAY_REPEAT_VALUE: String = String::new();
LL ~ let _strings: [String; 5] = [ARRAY_REPEAT_VALUE; 5];
|

error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/const-fn-in-vec.rs:9:48
|
LL | let _maybe_strings: [Option<String>; 5] = [None; 5];
| ^^^^ the trait `Copy` is not implemented for `String`, which is required by `Option<String>: Copy`
| ^^^^
| |
| the trait `Copy` is not implemented for `String`, which is required by `Option<String>: Copy`
| help: create an inline `const` block: `const { None }`
|
= note: required for `Option<String>` to implement `Copy`
= note: the `Copy` trait is required because this value will be copied for each element of the array
= help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position
|
LL ~ const ARRAY_REPEAT_VALUE: Option<String> = None;
LL ~ let _maybe_strings: [Option<String>; 5] = [ARRAY_REPEAT_VALUE; 5];
|

error: aborting due to 3 previous errors

Expand Down
Loading