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

fix/update teach_note from 'escaping mutable ref/ptr' const-check #131397

Merged
merged 1 commit into from
Oct 10, 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
51 changes: 26 additions & 25 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,16 @@ const_eval_incompatible_return_types =
const_eval_incompatible_types =
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
.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
.teach_note =
A constant containing interior mutable data behind a reference can allow you to modify that data.
This would make multiple uses of a constant to be able to see different values and allow circumventing
the `Send` and `Sync` requirements for shared mutable data, which is unsound.
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_intern_kind = {$kind ->
[static] static
Expand Down Expand Up @@ -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_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_non_const_fmt_macro_call =
cannot call non-const formatting macro in {const_eval_const_context}s
Expand Down Expand Up @@ -364,30 +384,11 @@ const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in
const_eval_unallowed_heap_allocations =
allocations are 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 =
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 =
{$msg}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
self.check_op(ops::HeapAllocation);
return;
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/src/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow {
DiagImportance::Secondary
}
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
ccx.dcx().create_err(errors::InteriorMutableDataRefer {
ccx.dcx().create_err(errors::InteriorMutableRefEscaping {
span,
opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)),
kind: ccx.const_kind(),
Expand Down Expand Up @@ -430,12 +430,12 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {

fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
match self.0 {
hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::UnallowedMutableRaw {
hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::MutableRawEscaping {
span,
kind: ccx.const_kind(),
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,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(E0764),
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ pub(crate) struct UnstableConstFn {
}

#[derive(Diagnostic)]
#[diag(const_eval_unallowed_mutable_refs, code = E0764)]
pub(crate) struct UnallowedMutableRefs {
#[diag(const_eval_mutable_ref_escaping, code = E0764)]
pub(crate) struct MutableRefEscaping {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
Expand All @@ -128,8 +128,8 @@ pub(crate) struct UnallowedMutableRefs {
}

#[derive(Diagnostic)]
#[diag(const_eval_unallowed_mutable_raw, code = E0764)]
pub(crate) struct UnallowedMutableRaw {
#[diag(const_eval_mutable_raw_escaping, code = E0764)]
pub(crate) struct MutableRawEscaping {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
Expand Down Expand Up @@ -181,8 +181,8 @@ pub(crate) struct UnallowedInlineAsm {
}

#[derive(Diagnostic)]
#[diag(const_eval_interior_mutable_data_refer, code = E0492)]
pub(crate) struct InteriorMutableDataRefer {
#[diag(const_eval_interior_mutable_ref_escaping, code = E0492)]
pub(crate) struct InteriorMutableRefEscaping {
#[primary_span]
#[label]
pub span: Span,
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/error-codes/E0010-teach.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0010]: allocations are not allowed in constants
LL | const CON: Vec<i32> = vec![1, 2, 3];
| ^^^^^^^^^^^^^ 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)

error[E0015]: cannot call non-const fn `slice::<impl [i32]>::into_vec::<std::alloc::Global>` in constants
Expand Down
Loading