Skip to content

Commit

Permalink
Rollup merge of #100738 - nidnogg:diagnostics_migr_const_eval, r=davi…
Browse files Browse the repository at this point in the history
…dtwco

Diagnostics migr const eval

This PR should eventually contain all diagnostic migrations for the `rustc_const_eval` crate.

r? `@davidtwco`
`@rustbot` label +A-translation
  • Loading branch information
compiler-errors committed Aug 26, 2022
2 parents 181b041 + 5101688 commit b543444
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 115 deletions.
21 changes: 13 additions & 8 deletions compiler/rustc_const_eval/src/const_eval/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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();
Expand Down
107 changes: 107 additions & 0 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
156 changes: 51 additions & 105 deletions compiler/rustc_const_eval/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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() })
}
}

Expand Down Expand Up @@ -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!(
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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 })
}
}
}
Expand All @@ -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(()),
})
}
}

Expand All @@ -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() })
}
}

Expand Down Expand Up @@ -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)
}
}

Expand All @@ -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",
);
}
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.",
);
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(()),
})
}
err
}
}

Expand All @@ -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,
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.",
);
match self.0 {
hir::BorrowKind::Raw => ccx.tcx.sess.create_err(UnallowedMutableRefsRaw {
span,
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
}
}

Expand Down
Loading

0 comments on commit b543444

Please sign in to comment.