Rollup merge of #100738 - nidnogg:diagnostics_migr_const_eval, r=davidtwco
Diagnostics migr const eval This PR should eventually contain all diagnostic migrations for the `rustc_const_eval` crate. r? `@davidtwco` `@rustbot` label +A-translation
This commit is contained in:
commit
b54344401a
5 changed files with 228 additions and 115 deletions
|
@ -1,16 +1,16 @@
|
||||||
// Not in interpret to make sure we do not use private implementation details
|
// Not in interpret to make sure we do not use private implementation details
|
||||||
|
|
||||||
|
use crate::errors::MaxNumNodesInConstErr;
|
||||||
|
use crate::interpret::{
|
||||||
|
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
|
||||||
|
Scalar,
|
||||||
|
};
|
||||||
use rustc_hir::Mutability;
|
use rustc_hir::Mutability;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
|
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
|
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
|
||||||
|
|
||||||
use crate::interpret::{
|
|
||||||
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
|
|
||||||
Scalar,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod eval_queries;
|
mod eval_queries;
|
||||||
mod fn_queries;
|
mod fn_queries;
|
||||||
|
@ -72,12 +72,17 @@ pub(crate) fn eval_to_valtree<'tcx>(
|
||||||
Ok(valtree) => Ok(Some(valtree)),
|
Ok(valtree) => Ok(Some(valtree)),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let did = cid.instance.def_id();
|
let did = cid.instance.def_id();
|
||||||
let s = cid.display(tcx);
|
let global_const_id = cid.display(tcx);
|
||||||
match err {
|
match err {
|
||||||
ValTreeCreationError::NodesOverflow => {
|
ValTreeCreationError::NodesOverflow => {
|
||||||
let msg = format!("maximum number of nodes exceeded in constant {}", &s);
|
let msg = format!(
|
||||||
|
"maximum number of nodes exceeded in constant {}",
|
||||||
|
&global_const_id
|
||||||
|
);
|
||||||
let mut diag = match tcx.hir().span_if_local(did) {
|
let mut diag = match tcx.hir().span_if_local(did) {
|
||||||
Some(span) => tcx.sess.struct_span_err(span, &msg),
|
Some(span) => {
|
||||||
|
tcx.sess.create_err(MaxNumNodesInConstErr { span, global_const_id })
|
||||||
|
}
|
||||||
None => tcx.sess.struct_err(&msg),
|
None => tcx.sess.struct_err(&msg),
|
||||||
};
|
};
|
||||||
diag.emit();
|
diag.emit();
|
||||||
|
|
|
@ -87,3 +87,110 @@ pub(crate) struct TransientMutBorrowErrRaw {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub kind: ConstContext,
|
pub kind: ConstContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::max_num_nodes_in_const)]
|
||||||
|
pub(crate) struct MaxNumNodesInConstErr {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub global_const_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::unallowed_fn_pointer_call)]
|
||||||
|
pub(crate) struct UnallowedFnPointerCall {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub kind: ConstContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::unstable_const_fn)]
|
||||||
|
pub(crate) struct UnstableConstFn {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub def_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::unallowed_mutable_refs, code = "E0764")]
|
||||||
|
pub(crate) struct UnallowedMutableRefs {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub kind: ConstContext,
|
||||||
|
#[note(const_eval::teach_note)]
|
||||||
|
pub teach: Option<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::unallowed_mutable_refs_raw, code = "E0764")]
|
||||||
|
pub(crate) struct UnallowedMutableRefsRaw {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub kind: ConstContext,
|
||||||
|
#[note(const_eval::teach_note)]
|
||||||
|
pub teach: Option<()>,
|
||||||
|
}
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::non_const_fmt_macro_call, code = "E0015")]
|
||||||
|
pub(crate) struct NonConstFmtMacroCall {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub kind: ConstContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::non_const_fn_call, code = "E0015")]
|
||||||
|
pub(crate) struct NonConstFnCall {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub def_path_str: String,
|
||||||
|
pub kind: ConstContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::unallowed_op_in_const_context)]
|
||||||
|
pub(crate) struct UnallowedOpInConstContext {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub msg: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::unallowed_heap_allocations, code = "E0010")]
|
||||||
|
pub(crate) struct UnallowedHeapAllocations {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
pub kind: ConstContext,
|
||||||
|
#[note(const_eval::teach_note)]
|
||||||
|
pub teach: Option<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::unallowed_inline_asm, code = "E0015")]
|
||||||
|
pub(crate) struct UnallowedInlineAsm {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub kind: ConstContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::interior_mutable_data_refer, code = "E0492")]
|
||||||
|
pub(crate) struct InteriorMutableDataRefer {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
#[help]
|
||||||
|
pub opt_help: Option<()>,
|
||||||
|
pub kind: ConstContext,
|
||||||
|
#[note(const_eval::teach_note)]
|
||||||
|
pub teach: Option<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(const_eval::interior_mutability_borrow)]
|
||||||
|
pub(crate) struct InteriorMutabilityBorrow {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
|
@ -24,8 +24,11 @@ use rustc_trait_selection::traits::SelectionContext;
|
||||||
|
|
||||||
use super::ConstCx;
|
use super::ConstCx;
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
MutDerefErr, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
|
InteriorMutabilityBorrow, InteriorMutableDataRefer, MutDerefErr, NonConstFmtMacroCall,
|
||||||
TransientMutBorrowErr, TransientMutBorrowErrRaw,
|
NonConstFnCall, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
|
||||||
|
TransientMutBorrowErr, TransientMutBorrowErrRaw, UnallowedFnPointerCall,
|
||||||
|
UnallowedHeapAllocations, UnallowedInlineAsm, UnallowedMutableRefs, UnallowedMutableRefsRaw,
|
||||||
|
UnallowedOpInConstContext, UnstableConstFn,
|
||||||
};
|
};
|
||||||
use crate::util::{call_kind, CallDesugaringKind, CallKind};
|
use crate::util::{call_kind, CallDesugaringKind, CallKind};
|
||||||
|
|
||||||
|
@ -97,10 +100,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
|
||||||
ccx: &ConstCx<'_, 'tcx>,
|
ccx: &ConstCx<'_, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
ccx.tcx.sess.struct_span_err(
|
ccx.tcx.sess.create_err(UnallowedFnPointerCall { span, kind: ccx.const_kind() })
|
||||||
span,
|
|
||||||
&format!("function pointer calls are not allowed in {}s", ccx.const_kind()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,22 +308,13 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => {
|
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => {
|
||||||
struct_span_err!(
|
ccx.tcx.sess.create_err(NonConstFmtMacroCall { span, kind: ccx.const_kind() })
|
||||||
ccx.tcx.sess,
|
|
||||||
span,
|
|
||||||
E0015,
|
|
||||||
"cannot call non-const formatting macro in {}s",
|
|
||||||
ccx.const_kind(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
_ => struct_span_err!(
|
_ => ccx.tcx.sess.create_err(NonConstFnCall {
|
||||||
ccx.tcx.sess,
|
|
||||||
span,
|
span,
|
||||||
E0015,
|
def_path_str: ccx.tcx.def_path_str_with_substs(callee, substs),
|
||||||
"cannot call non-const fn `{}` in {}s",
|
kind: ccx.const_kind(),
|
||||||
ccx.tcx.def_path_str_with_substs(callee, substs),
|
}),
|
||||||
ccx.const_kind(),
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
err.note(&format!(
|
err.note(&format!(
|
||||||
|
@ -354,10 +345,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let FnCallUnstable(def_id, feature) = *self;
|
let FnCallUnstable(def_id, feature) = *self;
|
||||||
|
|
||||||
let mut err = ccx.tcx.sess.struct_span_err(
|
let mut err = ccx
|
||||||
span,
|
.tcx
|
||||||
&format!("`{}` is not yet stable as a const fn", ccx.tcx.def_path_str(def_id)),
|
.sess
|
||||||
);
|
.create_err(UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
|
||||||
|
|
||||||
if ccx.is_const_stable_const_fn() {
|
if ccx.is_const_stable_const_fn() {
|
||||||
err.help("const-stable functions can only call other const-stable functions");
|
err.help("const-stable functions can only call other const-stable functions");
|
||||||
|
@ -392,9 +383,12 @@ impl<'tcx> NonConstOp<'tcx> for Generator {
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
|
let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
|
||||||
if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
|
if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
|
||||||
feature_err(&ccx.tcx.sess.parse_sess, sym::const_async_blocks, span, &msg)
|
ccx.tcx.sess.create_feature_err(
|
||||||
|
UnallowedOpInConstContext { span, msg },
|
||||||
|
sym::const_async_blocks,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
ccx.tcx.sess.struct_span_err(span, &msg)
|
ccx.tcx.sess.create_err(UnallowedOpInConstContext { span, msg })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -407,23 +401,11 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
|
||||||
ccx: &ConstCx<'_, 'tcx>,
|
ccx: &ConstCx<'_, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let mut err = struct_span_err!(
|
ccx.tcx.sess.create_err(UnallowedHeapAllocations {
|
||||||
ccx.tcx.sess,
|
|
||||||
span,
|
span,
|
||||||
E0010,
|
kind: ccx.const_kind(),
|
||||||
"allocations are not allowed in {}s",
|
teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()),
|
||||||
ccx.const_kind()
|
})
|
||||||
);
|
|
||||||
err.span_label(span, format!("allocation not allowed in {}s", ccx.const_kind()));
|
|
||||||
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
|
|
||||||
err.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.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,13 +417,7 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm {
|
||||||
ccx: &ConstCx<'_, 'tcx>,
|
ccx: &ConstCx<'_, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
struct_span_err!(
|
ccx.tcx.sess.create_err(UnallowedInlineAsm { span, kind: ccx.const_kind() })
|
||||||
ccx.tcx.sess,
|
|
||||||
span,
|
|
||||||
E0015,
|
|
||||||
"inline assembly is not allowed in {}s",
|
|
||||||
ccx.const_kind()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,12 +463,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow {
|
||||||
ccx: &ConstCx<'_, 'tcx>,
|
ccx: &ConstCx<'_, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
feature_err(
|
ccx.tcx.sess.create_feature_err(InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
|
||||||
&ccx.tcx.sess.parse_sess,
|
|
||||||
sym::const_refs_to_cell,
|
|
||||||
span,
|
|
||||||
"cannot borrow here, since the borrowed element may contain interior mutability",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,32 +478,22 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow {
|
||||||
ccx: &ConstCx<'_, 'tcx>,
|
ccx: &ConstCx<'_, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let mut err = struct_span_err!(
|
// FIXME: Maybe a more elegant solution to this if else case
|
||||||
ccx.tcx.sess,
|
|
||||||
span,
|
|
||||||
E0492,
|
|
||||||
"{}s cannot refer to interior mutable data",
|
|
||||||
ccx.const_kind(),
|
|
||||||
);
|
|
||||||
err.span_label(
|
|
||||||
span,
|
|
||||||
"this borrow of an interior mutable value may end up in the final value",
|
|
||||||
);
|
|
||||||
if let hir::ConstContext::Static(_) = ccx.const_kind() {
|
if let hir::ConstContext::Static(_) = ccx.const_kind() {
|
||||||
err.help(
|
ccx.tcx.sess.create_err(InteriorMutableDataRefer {
|
||||||
"to fix this, the value can be extracted to a separate \
|
span,
|
||||||
`static` item and then referenced",
|
opt_help: Some(()),
|
||||||
);
|
kind: ccx.const_kind(),
|
||||||
|
teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
ccx.tcx.sess.create_err(InteriorMutableDataRefer {
|
||||||
|
span,
|
||||||
|
opt_help: None,
|
||||||
|
kind: ccx.const_kind(),
|
||||||
|
teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
|
|
||||||
err.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.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,33 +519,18 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow {
|
||||||
ccx: &ConstCx<'_, 'tcx>,
|
ccx: &ConstCx<'_, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let raw = match self.0 {
|
match self.0 {
|
||||||
hir::BorrowKind::Raw => "raw ",
|
hir::BorrowKind::Raw => ccx.tcx.sess.create_err(UnallowedMutableRefsRaw {
|
||||||
hir::BorrowKind::Ref => "",
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut err = struct_span_err!(
|
|
||||||
ccx.tcx.sess,
|
|
||||||
span,
|
span,
|
||||||
E0764,
|
kind: ccx.const_kind(),
|
||||||
"{}mutable references are not allowed in the final value of {}s",
|
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
|
||||||
raw,
|
}),
|
||||||
ccx.const_kind(),
|
hir::BorrowKind::Ref => ccx.tcx.sess.create_err(UnallowedMutableRefs {
|
||||||
);
|
span,
|
||||||
|
kind: ccx.const_kind(),
|
||||||
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
|
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
|
||||||
err.note(
|
}),
|
||||||
"References in statics and constants may only refer \
|
|
||||||
to immutable values.\n\n\
|
|
||||||
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.\n\n\
|
|
||||||
If you really want global mutable state, try using \
|
|
||||||
static mut or a global UnsafeCell.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,3 +29,55 @@ const_eval_mut_deref =
|
||||||
const_eval_transient_mut_borrow = mutable references are not allowed in {$kind}s
|
const_eval_transient_mut_borrow = mutable references are not allowed in {$kind}s
|
||||||
|
|
||||||
const_eval_transient_mut_borrow_raw = raw mutable references are not allowed in {$kind}s
|
const_eval_transient_mut_borrow_raw = raw mutable references are not allowed in {$kind}s
|
||||||
|
|
||||||
|
const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
|
||||||
|
|
||||||
|
const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {$kind}s
|
||||||
|
|
||||||
|
const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
|
||||||
|
|
||||||
|
const_eval_unallowed_mutable_refs =
|
||||||
|
mutable references are not allowed in the final value of {$kind}s
|
||||||
|
.teach_note =
|
||||||
|
References in statics and constants may only refer to immutable values.\n\n
|
||||||
|
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.\n\n
|
||||||
|
If you really want global mutable state, try using static mut or a global UnsafeCell.
|
||||||
|
|
||||||
|
const_eval_unallowed_mutable_refs_raw =
|
||||||
|
raw mutable references are not allowed in the final value of {$kind}s
|
||||||
|
.teach_note =
|
||||||
|
References in statics and constants may only refer to immutable values.\n\n
|
||||||
|
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.\n\n
|
||||||
|
If you really want global mutable state, try using static mut or a global UnsafeCell.
|
||||||
|
|
||||||
|
const_eval_non_const_fmt_macro_call =
|
||||||
|
cannot call non-const formatting macro in {$kind}s
|
||||||
|
|
||||||
|
const_eval_non_const_fn_call =
|
||||||
|
cannot call non-const fn `{$def_path_str}` in {$kind}s
|
||||||
|
|
||||||
|
const_eval_unallowed_op_in_const_context =
|
||||||
|
{$msg}
|
||||||
|
|
||||||
|
const_eval_unallowed_heap_allocations =
|
||||||
|
allocations are not allowed in {$kind}s
|
||||||
|
.label = allocation not allowed in {$kind}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.
|
||||||
|
|
||||||
|
const_eval_unallowed_inline_asm =
|
||||||
|
inline assembly is not allowed in {$kind}s
|
||||||
|
|
||||||
|
const_eval_interior_mutable_data_refer =
|
||||||
|
{$kind}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.
|
||||||
|
|
||||||
|
const_eval_interior_mutability_borrow =
|
||||||
|
cannot borrow here, since the borrowed element may contain interior mutability
|
||||||
|
|
|
@ -20,8 +20,8 @@ use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
|
||||||
use rustc_errors::json::JsonEmitter;
|
use rustc_errors::json::JsonEmitter;
|
||||||
use rustc_errors::registry::Registry;
|
use rustc_errors::registry::Registry;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee,
|
error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
|
||||||
ErrorGuaranteed, FluentBundle, LazyFallbackBundle, MultiSpan,
|
EmissionGuarantee, ErrorGuaranteed, FluentBundle, LazyFallbackBundle, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
pub use rustc_span::def_id::StableCrateId;
|
pub use rustc_span::def_id::StableCrateId;
|
||||||
|
@ -467,6 +467,9 @@ impl Session {
|
||||||
feature: Symbol,
|
feature: Symbol,
|
||||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||||
let mut err = self.parse_sess.create_err(err);
|
let mut err = self.parse_sess.create_err(err);
|
||||||
|
if err.code.is_none() {
|
||||||
|
err.code = std::option::Option::Some(error_code!(E0658));
|
||||||
|
}
|
||||||
add_feature_diagnostics(&mut err, &self.parse_sess, feature);
|
add_feature_diagnostics(&mut err, &self.parse_sess, feature);
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue