Rollup merge of #131397 - RalfJung:const-escaping-ref-teach, r=chenyukang
fix/update teach_note from 'escaping mutable ref/ptr' const-check The old note was quite confusing since it talked about statics, but the message is also shown for consts. So let's reword to something that is true for both of them.
This commit is contained in:
commit
a2c43eb806
5 changed files with 37 additions and 35 deletions
|
@ -134,14 +134,16 @@ const_eval_incompatible_return_types =
|
||||||
const_eval_incompatible_types =
|
const_eval_incompatible_types =
|
||||||
calling a function with argument of type {$callee_ty} passing data of type {$caller_ty}
|
calling a function with argument of type {$callee_ty} passing data of type {$caller_ty}
|
||||||
|
|
||||||
const_eval_interior_mutable_data_refer =
|
const_eval_interior_mutable_ref_escaping =
|
||||||
{const_eval_const_context}s cannot refer to interior mutable data
|
{const_eval_const_context}s cannot refer to interior mutable data
|
||||||
.label = this borrow of an interior mutable value may end up in the final value
|
.label = this borrow of an interior mutable value may end up in the final value
|
||||||
.help = to fix this, the value can be extracted to a separate `static` item and then referenced
|
.help = to fix this, the value can be extracted to a separate `static` item and then referenced
|
||||||
.teach_note =
|
.teach_note =
|
||||||
A constant containing interior mutable data behind a reference can allow you to modify that data.
|
References that escape into the final value of a constant or static must be immutable.
|
||||||
This would make multiple uses of a constant to be able to see different values and allow circumventing
|
This is to avoid accidentally creating shared mutable state.
|
||||||
the `Send` and `Sync` requirements for shared mutable data, which is unsound.
|
|
||||||
|
|
||||||
|
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
|
||||||
|
|
||||||
const_eval_intern_kind = {$kind ->
|
const_eval_intern_kind = {$kind ->
|
||||||
[static] static
|
[static] static
|
||||||
|
@ -229,6 +231,24 @@ const_eval_modified_global =
|
||||||
|
|
||||||
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
|
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
|
||||||
|
|
||||||
|
const_eval_mutable_raw_escaping =
|
||||||
|
raw mutable pointers are not allowed in the final value of {const_eval_const_context}s
|
||||||
|
.teach_note =
|
||||||
|
Pointers that escape into the final value of a constant or static must be immutable.
|
||||||
|
This is to avoid accidentally creating shared mutable state.
|
||||||
|
|
||||||
|
|
||||||
|
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
|
||||||
|
|
||||||
|
const_eval_mutable_ref_escaping =
|
||||||
|
mutable references are not allowed in the final value of {const_eval_const_context}s
|
||||||
|
.teach_note =
|
||||||
|
References that escape into the final value of a constant or static must be immutable.
|
||||||
|
This is to avoid accidentally creating shared mutable state.
|
||||||
|
|
||||||
|
|
||||||
|
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
|
||||||
|
|
||||||
const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead
|
const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead
|
||||||
const_eval_non_const_fmt_macro_call =
|
const_eval_non_const_fmt_macro_call =
|
||||||
cannot call non-const formatting macro in {const_eval_const_context}s
|
cannot call non-const formatting macro in {const_eval_const_context}s
|
||||||
|
@ -364,30 +384,11 @@ const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in
|
||||||
const_eval_unallowed_heap_allocations =
|
const_eval_unallowed_heap_allocations =
|
||||||
allocations are not allowed in {const_eval_const_context}s
|
allocations are not allowed in {const_eval_const_context}s
|
||||||
.label = allocation not allowed in {const_eval_const_context}s
|
.label = allocation not allowed in {const_eval_const_context}s
|
||||||
.teach_note = The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
|
.teach_note =
|
||||||
|
The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created.
|
||||||
|
|
||||||
const_eval_unallowed_inline_asm =
|
const_eval_unallowed_inline_asm =
|
||||||
inline assembly is not allowed in {const_eval_const_context}s
|
inline assembly is not allowed in {const_eval_const_context}s
|
||||||
const_eval_unallowed_mutable_raw =
|
|
||||||
raw mutable pointers are not allowed in the final value of {const_eval_const_context}s
|
|
||||||
.teach_note =
|
|
||||||
References in statics and constants may only refer to immutable values.
|
|
||||||
|
|
||||||
|
|
||||||
Statics are shared everywhere, and if they refer to mutable data one might violate memory
|
|
||||||
safety since holding multiple mutable references to shared data is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
If you really want global mutable state, try using static mut or a global UnsafeCell.
|
|
||||||
|
|
||||||
const_eval_unallowed_mutable_refs =
|
|
||||||
mutable references are not allowed in the final value of {const_eval_const_context}s
|
|
||||||
.teach_note =
|
|
||||||
Statics are shared everywhere, and if they refer to mutable data one might violate memory
|
|
||||||
safety since holding multiple mutable references to shared data is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
If you really want global mutable state, try using static mut or a global UnsafeCell.
|
|
||||||
|
|
||||||
const_eval_unallowed_op_in_const_context =
|
const_eval_unallowed_op_in_const_context =
|
||||||
{$msg}
|
{$msg}
|
||||||
|
|
|
@ -666,6 +666,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This can be called on stable via the `vec!` macro.
|
||||||
if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) {
|
if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) {
|
||||||
self.check_op(ops::HeapAllocation);
|
self.check_op(ops::HeapAllocation);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -402,7 +402,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow {
|
||||||
DiagImportance::Secondary
|
DiagImportance::Secondary
|
||||||
}
|
}
|
||||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
||||||
ccx.dcx().create_err(errors::InteriorMutableDataRefer {
|
ccx.dcx().create_err(errors::InteriorMutableRefEscaping {
|
||||||
span,
|
span,
|
||||||
opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)),
|
opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)),
|
||||||
kind: ccx.const_kind(),
|
kind: ccx.const_kind(),
|
||||||
|
@ -430,12 +430,12 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {
|
||||||
|
|
||||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::UnallowedMutableRaw {
|
hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::MutableRawEscaping {
|
||||||
span,
|
span,
|
||||||
kind: ccx.const_kind(),
|
kind: ccx.const_kind(),
|
||||||
teach: ccx.tcx.sess.teach(E0764),
|
teach: ccx.tcx.sess.teach(E0764),
|
||||||
}),
|
}),
|
||||||
hir::BorrowKind::Ref => ccx.dcx().create_err(errors::UnallowedMutableRefs {
|
hir::BorrowKind::Ref => ccx.dcx().create_err(errors::MutableRefEscaping {
|
||||||
span,
|
span,
|
||||||
kind: ccx.const_kind(),
|
kind: ccx.const_kind(),
|
||||||
teach: ccx.tcx.sess.teach(E0764),
|
teach: ccx.tcx.sess.teach(E0764),
|
||||||
|
|
|
@ -118,8 +118,8 @@ pub(crate) struct UnstableConstFn {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(const_eval_unallowed_mutable_refs, code = E0764)]
|
#[diag(const_eval_mutable_ref_escaping, code = E0764)]
|
||||||
pub(crate) struct UnallowedMutableRefs {
|
pub(crate) struct MutableRefEscaping {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub kind: ConstContext,
|
pub kind: ConstContext,
|
||||||
|
@ -128,8 +128,8 @@ pub(crate) struct UnallowedMutableRefs {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(const_eval_unallowed_mutable_raw, code = E0764)]
|
#[diag(const_eval_mutable_raw_escaping, code = E0764)]
|
||||||
pub(crate) struct UnallowedMutableRaw {
|
pub(crate) struct MutableRawEscaping {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub kind: ConstContext,
|
pub kind: ConstContext,
|
||||||
|
@ -181,8 +181,8 @@ pub(crate) struct UnallowedInlineAsm {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(const_eval_interior_mutable_data_refer, code = E0492)]
|
#[diag(const_eval_interior_mutable_ref_escaping, code = E0492)]
|
||||||
pub(crate) struct InteriorMutableDataRefer {
|
pub(crate) struct InteriorMutableRefEscaping {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0010]: allocations are not allowed in constants
|
||||||
LL | const CON: Vec<i32> = vec![1, 2, 3];
|
LL | const CON: Vec<i32> = vec![1, 2, 3];
|
||||||
| ^^^^^^^^^^^^^ allocation not allowed in constants
|
| ^^^^^^^^^^^^^ allocation not allowed in constants
|
||||||
|
|
|
|
||||||
= note: The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
|
= note: The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created.
|
||||||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `slice::<impl [i32]>::into_vec::<std::alloc::Global>` in constants
|
error[E0015]: cannot call non-const fn `slice::<impl [i32]>::into_vec::<std::alloc::Global>` in constants
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue