From 287eb03838d5ff211706c8df8f5357034219472f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 8 Oct 2024 12:25:26 +0200 Subject: [PATCH] fix/update teach_note from 'escaping mutable ref/ptr' const-check --- compiler/rustc_const_eval/messages.ftl | 51 ++++++++++--------- .../src/check_consts/check.rs | 1 + .../rustc_const_eval/src/check_consts/ops.rs | 6 +-- compiler/rustc_const_eval/src/errors.rs | 12 ++--- tests/ui/error-codes/E0010-teach.stderr | 2 +- 5 files changed, 37 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 73a9a1569f64e..24dbe688f363b 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -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 @@ -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 @@ -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} diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 2cbf242fcf28d..463a66d4e2e46 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -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; diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 6eb33c29e1d89..5c4a899f28a14 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -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(), @@ -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), diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index c60bacb85067f..c943236affc56 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -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, @@ -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, @@ -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, diff --git a/tests/ui/error-codes/E0010-teach.stderr b/tests/ui/error-codes/E0010-teach.stderr index 7634970f36e2e..37a9892ccbf49 100644 --- a/tests/ui/error-codes/E0010-teach.stderr +++ b/tests/ui/error-codes/E0010-teach.stderr @@ -4,7 +4,7 @@ error[E0010]: allocations are not allowed in constants LL | const CON: Vec = 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::::into_vec::` in constants