mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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
@ -1,16 +1,16 @@
|
||||
// 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_middle::mir;
|
||||
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
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 eval_queries;
|
||||
mod fn_queries;
|
||||
@ -72,12 +72,17 @@ pub(crate) fn eval_to_valtree<'tcx>(
|
||||
Ok(valtree) => Ok(Some(valtree)),
|
||||
Err(err) => {
|
||||
let did = cid.instance.def_id();
|
||||
let s = cid.display(tcx);
|
||||
let global_const_id = cid.display(tcx);
|
||||
match err {
|
||||
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) {
|
||||
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),
|
||||
};
|
||||
diag.emit();
|
||||
|
@ -87,3 +87,110 @@ pub(crate) struct TransientMutBorrowErrRaw {
|
||||
pub span: Span,
|
||||
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 crate::errors::{
|
||||
MutDerefErr, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
|
||||
TransientMutBorrowErr, TransientMutBorrowErrRaw,
|
||||
InteriorMutabilityBorrow, InteriorMutableDataRefer, MutDerefErr, NonConstFmtMacroCall,
|
||||
NonConstFnCall, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
|
||||
TransientMutBorrowErr, TransientMutBorrowErrRaw, UnallowedFnPointerCall,
|
||||
UnallowedHeapAllocations, UnallowedInlineAsm, UnallowedMutableRefs, UnallowedMutableRefsRaw,
|
||||
UnallowedOpInConstContext, UnstableConstFn,
|
||||
};
|
||||
use crate::util::{call_kind, CallDesugaringKind, CallKind};
|
||||
|
||||
@ -97,10 +100,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
ccx.tcx.sess.struct_span_err(
|
||||
span,
|
||||
&format!("function pointer calls are not allowed in {}s", ccx.const_kind()),
|
||||
)
|
||||
ccx.tcx.sess.create_err(UnallowedFnPointerCall { span, kind: ccx.const_kind() })
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,22 +308,13 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
||||
err
|
||||
}
|
||||
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => {
|
||||
struct_span_err!(
|
||||
ccx.tcx.sess,
|
||||
span,
|
||||
E0015,
|
||||
"cannot call non-const formatting macro in {}s",
|
||||
ccx.const_kind(),
|
||||
)
|
||||
ccx.tcx.sess.create_err(NonConstFmtMacroCall { span, kind: ccx.const_kind() })
|
||||
}
|
||||
_ => struct_span_err!(
|
||||
ccx.tcx.sess,
|
||||
_ => ccx.tcx.sess.create_err(NonConstFnCall {
|
||||
span,
|
||||
E0015,
|
||||
"cannot call non-const fn `{}` in {}s",
|
||||
ccx.tcx.def_path_str_with_substs(callee, substs),
|
||||
ccx.const_kind(),
|
||||
),
|
||||
def_path_str: ccx.tcx.def_path_str_with_substs(callee, substs),
|
||||
kind: ccx.const_kind(),
|
||||
}),
|
||||
};
|
||||
|
||||
err.note(&format!(
|
||||
@ -354,10 +345,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let FnCallUnstable(def_id, feature) = *self;
|
||||
|
||||
let mut err = ccx.tcx.sess.struct_span_err(
|
||||
span,
|
||||
&format!("`{}` is not yet stable as a const fn", ccx.tcx.def_path_str(def_id)),
|
||||
);
|
||||
let mut err = ccx
|
||||
.tcx
|
||||
.sess
|
||||
.create_err(UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
|
||||
|
||||
if ccx.is_const_stable_const_fn() {
|
||||
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> {
|
||||
let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
|
||||
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 {
|
||||
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>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let mut err = struct_span_err!(
|
||||
ccx.tcx.sess,
|
||||
ccx.tcx.sess.create_err(UnallowedHeapAllocations {
|
||||
span,
|
||||
E0010,
|
||||
"allocations are not allowed in {}s",
|
||||
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
|
||||
kind: ccx.const_kind(),
|
||||
teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,13 +417,7 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm {
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
struct_span_err!(
|
||||
ccx.tcx.sess,
|
||||
span,
|
||||
E0015,
|
||||
"inline assembly is not allowed in {}s",
|
||||
ccx.const_kind()
|
||||
)
|
||||
ccx.tcx.sess.create_err(UnallowedInlineAsm { span, kind: ccx.const_kind() })
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,12 +463,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow {
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
feature_err(
|
||||
&ccx.tcx.sess.parse_sess,
|
||||
sym::const_refs_to_cell,
|
||||
span,
|
||||
"cannot borrow here, since the borrowed element may contain interior mutability",
|
||||
)
|
||||
ccx.tcx.sess.create_feature_err(InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,32 +478,22 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow {
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let mut err = struct_span_err!(
|
||||
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",
|
||||
);
|
||||
// FIXME: Maybe a more elegant solution to this if else case
|
||||
if let hir::ConstContext::Static(_) = ccx.const_kind() {
|
||||
err.help(
|
||||
"to fix this, the value can be extracted to a separate \
|
||||
`static` item and then referenced",
|
||||
);
|
||||
ccx.tcx.sess.create_err(InteriorMutableDataRefer {
|
||||
span,
|
||||
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>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let raw = match self.0 {
|
||||
hir::BorrowKind::Raw => "raw ",
|
||||
hir::BorrowKind::Ref => "",
|
||||
};
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
ccx.tcx.sess,
|
||||
match self.0 {
|
||||
hir::BorrowKind::Raw => ccx.tcx.sess.create_err(UnallowedMutableRefsRaw {
|
||||
span,
|
||||
E0764,
|
||||
"{}mutable references are not allowed in the final value of {}s",
|
||||
raw,
|
||||
ccx.const_kind(),
|
||||
);
|
||||
|
||||
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
|
||||
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.",
|
||||
);
|
||||
kind: ccx.const_kind(),
|
||||
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
|
||||
}),
|
||||
hir::BorrowKind::Ref => ccx.tcx.sess.create_err(UnallowedMutableRefs {
|
||||
span,
|
||||
kind: ccx.const_kind(),
|
||||
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
|
||||
}),
|
||||
}
|
||||
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_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::registry::Registry;
|
||||
use rustc_errors::{
|
||||
fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee,
|
||||
ErrorGuaranteed, FluentBundle, LazyFallbackBundle, MultiSpan,
|
||||
error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
|
||||
EmissionGuarantee, ErrorGuaranteed, FluentBundle, LazyFallbackBundle, MultiSpan,
|
||||
};
|
||||
use rustc_macros::HashStable_Generic;
|
||||
pub use rustc_span::def_id::StableCrateId;
|
||||
@ -467,6 +467,9 @@ impl Session {
|
||||
feature: Symbol,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
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);
|
||||
err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user