Rollup merge of #81503 - henryboisdequin:fix-const-fn-arr-err-msg, r=estebank
Suggest to create a new `const` item if the `fn` in the array is a `const fn` Fixes #73734. If the `fn` in the array repeat expression is a `const fn`, suggest creating a new `const` item. On nightly, suggest creating an inline `const` block. This PR also removes the `suggest_const_in_array_repeat_expressions` as it is no longer necessary. Example: ```rust fn main() { // Should not compile but hint to create a new const item (stable) or an inline const block (nightly) let strings: [String; 5] = [String::new(); 5]; println!("{:?}", strings); } ``` Gives this error: ``` error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied --> $DIR/const-fn-in-vec.rs:3:32 | 2 | let strings: [String; 5] = [String::new(); 5]; | ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `String` | = note: the `Copy` trait is required because the repeated element will be copied ``` With this change, this is the error message: ``` error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/const-fn-in-vec.rs:3:32 | LL | let strings: [String; 5] = [String::new(); 5]; | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | = help: moving the function call to a new `const` item will resolve the error ```
This commit is contained in:
commit
f02f7b05b2
@ -228,7 +228,10 @@ pub enum ObligationCauseCode<'tcx> {
|
|||||||
/// Inline asm operand type must be `Sized`.
|
/// Inline asm operand type must be `Sized`.
|
||||||
InlineAsmSized,
|
InlineAsmSized,
|
||||||
/// `[T, ..n]` implies that `T` must be `Copy`.
|
/// `[T, ..n]` implies that `T` must be `Copy`.
|
||||||
RepeatVec,
|
/// If the function in the array repeat expression is a `const fn`,
|
||||||
|
/// display a help message suggesting to move the function call to a
|
||||||
|
/// new `const` item while saying that `T` doesn't implement `Copy`.
|
||||||
|
RepeatVec(bool),
|
||||||
|
|
||||||
/// Types of fields (other than the last, except for packed structs) in a struct must be sized.
|
/// Types of fields (other than the last, except for packed structs) in a struct must be sized.
|
||||||
FieldSized {
|
FieldSized {
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
use crate::dataflow::impls::MaybeInitializedPlaces;
|
use crate::dataflow::impls::MaybeInitializedPlaces;
|
||||||
use crate::dataflow::move_paths::MoveData;
|
use crate::dataflow::move_paths::MoveData;
|
||||||
use crate::dataflow::ResultsCursor;
|
use crate::dataflow::ResultsCursor;
|
||||||
|
use crate::transform::{
|
||||||
|
check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::borrow_check::{
|
use crate::borrow_check::{
|
||||||
borrow_set::BorrowSet,
|
borrow_set::BorrowSet,
|
||||||
@ -1988,18 +1991,24 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
|
|||||||
Operand::Copy(..) | Operand::Constant(..) => {
|
Operand::Copy(..) | Operand::Constant(..) => {
|
||||||
// These are always okay: direct use of a const, or a value that can evidently be copied.
|
// These are always okay: direct use of a const, or a value that can evidently be copied.
|
||||||
}
|
}
|
||||||
Operand::Move(_) => {
|
Operand::Move(place) => {
|
||||||
// Make sure that repeated elements implement `Copy`.
|
// Make sure that repeated elements implement `Copy`.
|
||||||
let span = body.source_info(location).span;
|
let span = body.source_info(location).span;
|
||||||
let ty = operand.ty(body, tcx);
|
let ty = operand.ty(body, tcx);
|
||||||
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) {
|
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) {
|
||||||
|
let ccx = ConstCx::new_with_param_env(tcx, body, self.param_env);
|
||||||
|
let is_const_fn =
|
||||||
|
is_const_fn_in_array_repeat_expression(&ccx, &place, &body);
|
||||||
|
|
||||||
|
debug!("check_rvalue: is_const_fn={:?}", is_const_fn);
|
||||||
|
|
||||||
let def_id = body.source.def_id().expect_local();
|
let def_id = body.source.def_id().expect_local();
|
||||||
self.infcx.report_selection_error(
|
self.infcx.report_selection_error(
|
||||||
&traits::Obligation::new(
|
&traits::Obligation::new(
|
||||||
ObligationCause::new(
|
ObligationCause::new(
|
||||||
span,
|
span,
|
||||||
self.tcx().hir().local_def_id_to_hir_id(def_id),
|
self.tcx().hir().local_def_id_to_hir_id(def_id),
|
||||||
traits::ObligationCauseCode::RepeatVec,
|
traits::ObligationCauseCode::RepeatVec(is_const_fn),
|
||||||
),
|
),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
ty::Binder::bind(ty::TraitRef::new(
|
ty::Binder::bind(ty::TraitRef::new(
|
||||||
|
@ -1231,3 +1231,38 @@ pub fn promote_candidates<'tcx>(
|
|||||||
|
|
||||||
promotions
|
promotions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This function returns `true` if the function being called in the array
|
||||||
|
/// repeat expression is a `const` function.
|
||||||
|
crate fn is_const_fn_in_array_repeat_expression<'tcx>(
|
||||||
|
ccx: &ConstCx<'_, 'tcx>,
|
||||||
|
place: &Place<'tcx>,
|
||||||
|
body: &Body<'tcx>,
|
||||||
|
) -> bool {
|
||||||
|
match place.as_local() {
|
||||||
|
// rule out cases such as: `let my_var = some_fn(); [my_var; N]`
|
||||||
|
Some(local) if body.local_decls[local].is_user_variable() => return false,
|
||||||
|
None => return false,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
for block in body.basic_blocks() {
|
||||||
|
if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) =
|
||||||
|
&block.terminator
|
||||||
|
{
|
||||||
|
if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
|
||||||
|
if let ty::FnDef(def_id, _) = *ty.kind() {
|
||||||
|
if let Some((destination_place, _)) = destination {
|
||||||
|
if destination_place == place {
|
||||||
|
if is_const_fn(ccx.tcx, def_id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
@ -1881,10 +1881,26 @@ fn note_obligation_cause_code<T>(
|
|||||||
ObligationCauseCode::Coercion { source: _, target } => {
|
ObligationCauseCode::Coercion { source: _, target } => {
|
||||||
err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
|
err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
|
||||||
}
|
}
|
||||||
ObligationCauseCode::RepeatVec => {
|
ObligationCauseCode::RepeatVec(is_const_fn) => {
|
||||||
err.note(
|
err.note(
|
||||||
"the `Copy` trait is required because the repeated element will be copied",
|
"the `Copy` trait is required because the repeated element will be copied",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if is_const_fn {
|
||||||
|
err.help(
|
||||||
|
"consider creating a new `const` item and initializing with the result \
|
||||||
|
of the function call to be used in the repeat position, like \
|
||||||
|
`const VAL: Type = const_fn();` and `let x = [VAL; 42];`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.tcx.sess.is_nightly_build() && is_const_fn {
|
||||||
|
err.help(
|
||||||
|
"create an inline `const` block, see PR \
|
||||||
|
#2920 <https://github.com/rust-lang/rfcs/pull/2920> \
|
||||||
|
for more information",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ObligationCauseCode::VariableType(hir_id) => {
|
ObligationCauseCode::VariableType(hir_id) => {
|
||||||
let parent_node = self.tcx.hir().get_parent_node(hir_id);
|
let parent_node = self.tcx.hir().get_parent_node(hir_id);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
This directory contains the source code of the rust project, including:
|
This directory contains the source code of the rust project, including:
|
||||||
|
|
||||||
- The test suite
|
- The test suite
|
||||||
- The bootstrapping build system
|
- The bootstrapping build system
|
||||||
- Various submodules for tools, like rustdoc, rls, etc.
|
- Various submodules for tools, like rustdoc, rls, etc.
|
||||||
|
@ -7,6 +7,8 @@ LL | let _: [Option<Bar>; 2] = [no_copy(); 2];
|
|||||||
= help: the following implementations were found:
|
= help: the following implementations were found:
|
||||||
<Option<T> as Copy>
|
<Option<T> as Copy>
|
||||||
= note: the `Copy` trait is required because the repeated element will be copied
|
= note: the `Copy` trait is required because the repeated element will be copied
|
||||||
|
= help: consider creating a new `const` item and initializing with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
|
||||||
|
= help: create an inline `const` block, see PR #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
7
src/test/ui/consts/const-fn-in-vec.rs
Normal file
7
src/test/ui/consts/const-fn-in-vec.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fn main() {
|
||||||
|
// should hint to create an inline `const` block
|
||||||
|
// or to create a new `const` item
|
||||||
|
let strings: [String; 5] = [String::new(); 5];
|
||||||
|
//~^ ERROR the trait bound `String: Copy` is not satisfied
|
||||||
|
println!("{:?}", strings);
|
||||||
|
}
|
13
src/test/ui/consts/const-fn-in-vec.stderr
Normal file
13
src/test/ui/consts/const-fn-in-vec.stderr
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||||
|
--> $DIR/const-fn-in-vec.rs:4:32
|
||||||
|
|
|
||||||
|
LL | let strings: [String; 5] = [String::new(); 5];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||||
|
|
|
||||||
|
= note: the `Copy` trait is required because the repeated element will be copied
|
||||||
|
= help: consider creating a new `const` item and initializing with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
|
||||||
|
= help: create an inline `const` block, see PR #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user