2019-09-25 12:30:25 -07:00
|
|
|
//! Concrete error types for all operations which may be invalid in a certain const context.
|
|
|
|
|
2020-09-29 13:17:38 -07:00
|
|
|
use rustc_errors::{struct_span_err, DiagnosticBuilder};
|
2020-05-07 10:24:20 -07:00
|
|
|
use rustc_hir as hir;
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::def_id::DefId;
|
2020-09-29 17:52:12 -07:00
|
|
|
use rustc_middle::mir;
|
2020-03-11 12:49:08 +01:00
|
|
|
use rustc_session::config::nightly_options;
|
|
|
|
use rustc_session::parse::feature_err;
|
2020-01-01 19:30:57 +01:00
|
|
|
use rustc_span::symbol::sym;
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::{Span, Symbol};
|
2019-09-20 09:00:18 -07:00
|
|
|
|
2020-05-07 10:24:20 -07:00
|
|
|
use super::ConstCx;
|
2019-09-20 09:00:18 -07:00
|
|
|
|
2020-09-17 11:10:36 -07:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
2020-09-02 13:25:19 -07:00
|
|
|
pub enum Status {
|
|
|
|
Allowed,
|
|
|
|
Unstable(Symbol),
|
|
|
|
Forbidden,
|
|
|
|
}
|
|
|
|
|
2020-09-29 17:52:12 -07:00
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
pub enum DiagnosticImportance {
|
|
|
|
/// An operation that must be removed for const-checking to pass.
|
|
|
|
Primary,
|
|
|
|
|
|
|
|
/// An operation that causes const-checking to fail, but is usually a side-effect of a `Primary` operation elsewhere.
|
|
|
|
Secondary,
|
|
|
|
}
|
|
|
|
|
2019-09-20 09:00:18 -07:00
|
|
|
/// An operation that is not *always* allowed in a const context.
|
2019-09-25 11:58:12 -07:00
|
|
|
pub trait NonConstOp: std::fmt::Debug {
|
2020-09-17 11:09:52 -07:00
|
|
|
const STOPS_CONST_CHECKING: bool = false;
|
|
|
|
|
2020-09-02 13:25:19 -07:00
|
|
|
/// Returns an enum indicating whether this operation is allowed within the given item.
|
|
|
|
fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
Status::Forbidden
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 17:52:12 -07:00
|
|
|
fn importance(&self) -> DiagnosticImportance {
|
|
|
|
DiagnosticImportance::Primary
|
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2019-09-20 09:00:18 -07:00
|
|
|
let mut err = struct_span_err!(
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.tcx.sess,
|
2019-09-20 09:00:18 -07:00
|
|
|
span,
|
|
|
|
E0019,
|
|
|
|
"{} contains unimplemented expression type",
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.const_kind()
|
2019-09-20 09:00:18 -07:00
|
|
|
);
|
2020-09-02 13:25:19 -07:00
|
|
|
|
|
|
|
if let Status::Unstable(gate) = self.status_in_item(ccx) {
|
|
|
|
if !ccx.tcx.features().enabled(gate) && nightly_options::is_nightly_build() {
|
|
|
|
err.help(&format!("add `#![feature({})]` to the crate attributes to enable", gate));
|
|
|
|
}
|
2020-05-04 23:33:10 +02:00
|
|
|
}
|
2020-09-02 13:25:19 -07:00
|
|
|
|
2020-03-23 14:02:58 +01:00
|
|
|
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
|
2019-12-22 17:42:04 -05:00
|
|
|
err.note(
|
|
|
|
"A function call isn't allowed in the const's initialization expression \
|
|
|
|
because the expression's value must be known at compile-time.",
|
|
|
|
);
|
|
|
|
err.note(
|
|
|
|
"Remember: you can't use a function call inside a const's initialization \
|
|
|
|
expression! However, you can use it anywhere else.",
|
|
|
|
);
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
2020-09-29 11:19:40 -07:00
|
|
|
|
|
|
|
err
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-17 11:12:13 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Abort;
|
|
|
|
impl NonConstOp for Abort {
|
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
mcf_status_in_item(ccx)
|
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
|
|
|
mcf_build_error(ccx, span, "abort is not stable in const fn")
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-23 11:53:58 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct FloatingPointOp;
|
|
|
|
impl NonConstOp for FloatingPointOp {
|
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
if ccx.const_kind() == hir::ConstContext::ConstFn {
|
|
|
|
Status::Unstable(sym::const_fn_floating_point_arithmetic)
|
|
|
|
} else {
|
|
|
|
Status::Allowed
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2020-09-23 11:53:58 -07:00
|
|
|
feature_err(
|
|
|
|
&ccx.tcx.sess.parse_sess,
|
|
|
|
sym::const_fn_floating_point_arithmetic,
|
|
|
|
span,
|
|
|
|
&format!("floating point arithmetic is not allowed in {}s", ccx.const_kind()),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-20 09:00:18 -07:00
|
|
|
/// A function call where the callee is a pointer.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct FnCallIndirect;
|
|
|
|
impl NonConstOp for FnCallIndirect {
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
|
|
|
ccx.tcx.sess.struct_span_err(span, "function pointers are not allowed in const fn")
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A function call where the callee is not marked as `const`.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct FnCallNonConst(pub DefId);
|
|
|
|
impl NonConstOp for FnCallNonConst {
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
|
|
|
struct_span_err!(
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.tcx.sess,
|
2019-09-20 09:00:18 -07:00
|
|
|
span,
|
|
|
|
E0015,
|
|
|
|
"calls in {}s are limited to constant functions, \
|
|
|
|
tuple structs and tuple variants",
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.const_kind(),
|
2020-09-29 11:19:40 -07:00
|
|
|
)
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A call to a `#[unstable]` const fn or `#[rustc_const_unstable]` function.
|
|
|
|
///
|
|
|
|
/// Contains the name of the feature that would allow the use of this function.
|
|
|
|
#[derive(Debug)]
|
2020-09-17 11:12:13 -07:00
|
|
|
pub struct FnCallUnstable(pub DefId, pub Option<Symbol>);
|
|
|
|
|
2019-09-20 09:00:18 -07:00
|
|
|
impl NonConstOp for FnCallUnstable {
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2019-09-20 09:00:18 -07:00
|
|
|
let FnCallUnstable(def_id, feature) = *self;
|
|
|
|
|
2020-03-23 14:02:58 +01:00
|
|
|
let mut err = ccx.tcx.sess.struct_span_err(
|
2019-12-22 17:42:04 -05:00
|
|
|
span,
|
2020-03-23 14:02:58 +01:00
|
|
|
&format!("`{}` is not yet stable as a const fn", ccx.tcx.def_path_str(def_id)),
|
2019-12-22 17:42:04 -05:00
|
|
|
);
|
2020-09-17 11:12:13 -07:00
|
|
|
|
|
|
|
if ccx.is_const_stable_const_fn() {
|
|
|
|
err.help("Const-stable functions can only call other const-stable functions");
|
|
|
|
} else if nightly_options::is_nightly_build() {
|
|
|
|
if let Some(feature) = feature {
|
|
|
|
err.help(&format!(
|
|
|
|
"add `#![feature({})]` to the crate attributes to enable",
|
|
|
|
feature
|
|
|
|
));
|
|
|
|
}
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
2020-09-29 11:19:40 -07:00
|
|
|
|
|
|
|
err
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-17 11:12:13 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct FnPtrCast;
|
|
|
|
impl NonConstOp for FnPtrCast {
|
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
2020-09-24 16:17:03 -07:00
|
|
|
if ccx.const_kind() != hir::ConstContext::ConstFn {
|
|
|
|
Status::Allowed
|
|
|
|
} else {
|
|
|
|
Status::Unstable(sym::const_fn_fn_ptr_basics)
|
|
|
|
}
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2020-09-24 16:17:03 -07:00
|
|
|
feature_err(
|
|
|
|
&ccx.tcx.sess.parse_sess,
|
|
|
|
sym::const_fn_fn_ptr_basics,
|
|
|
|
span,
|
|
|
|
&format!("function pointer casts are not allowed in {}s", ccx.const_kind()),
|
|
|
|
)
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Generator;
|
|
|
|
impl NonConstOp for Generator {
|
2020-09-29 19:20:05 -07:00
|
|
|
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
|
|
|
|
Status::Forbidden
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
|
|
|
ccx.tcx.sess.struct_span_err(span, "Generators and `async` functions cannot be `const`")
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-20 09:00:18 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct HeapAllocation;
|
|
|
|
impl NonConstOp for HeapAllocation {
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2019-12-22 17:42:04 -05:00
|
|
|
let mut err = struct_span_err!(
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.tcx.sess,
|
2019-12-22 17:42:04 -05:00
|
|
|
span,
|
|
|
|
E0010,
|
|
|
|
"allocations are not allowed in {}s",
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.const_kind()
|
2019-12-22 17:42:04 -05:00
|
|
|
);
|
2020-03-23 14:02:58 +01:00
|
|
|
err.span_label(span, format!("allocation not allowed in {}s", ccx.const_kind()));
|
|
|
|
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
|
2019-09-20 09:00:18 -07:00
|
|
|
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 \
|
2019-12-22 17:42:04 -05:00
|
|
|
be done at compile time.",
|
2019-09-20 09:00:18 -07:00
|
|
|
);
|
|
|
|
}
|
2020-09-29 11:19:40 -07:00
|
|
|
err
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-19 16:03:35 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct InlineAsm;
|
|
|
|
impl NonConstOp for InlineAsm {}
|
|
|
|
|
2019-09-20 09:00:18 -07:00
|
|
|
#[derive(Debug)]
|
2020-09-02 14:54:55 -07:00
|
|
|
pub struct LiveDrop {
|
|
|
|
pub dropped_at: Option<Span>,
|
|
|
|
}
|
2019-09-20 09:00:18 -07:00
|
|
|
impl NonConstOp for LiveDrop {
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
|
|
|
let mut err = struct_span_err!(
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.tcx.sess,
|
2019-12-22 17:42:04 -05:00
|
|
|
span,
|
|
|
|
E0493,
|
|
|
|
"destructors cannot be evaluated at compile-time"
|
2020-06-19 14:46:04 -05:00
|
|
|
);
|
2020-09-29 11:19:40 -07:00
|
|
|
err.span_label(span, format!("{}s cannot evaluate destructors", ccx.const_kind()));
|
2020-09-02 14:54:55 -07:00
|
|
|
if let Some(span) = self.dropped_at {
|
2020-09-29 11:19:40 -07:00
|
|
|
err.span_label(span, "value is dropped here");
|
2020-06-19 14:46:04 -05:00
|
|
|
}
|
2020-09-29 11:19:40 -07:00
|
|
|
err
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2019-11-26 10:00:41 -05:00
|
|
|
pub struct CellBorrow;
|
|
|
|
impl NonConstOp for CellBorrow {
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2019-12-31 21:25:16 +01:00
|
|
|
struct_span_err!(
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.tcx.sess,
|
2019-12-22 17:42:04 -05:00
|
|
|
span,
|
|
|
|
E0492,
|
2019-11-26 10:00:41 -05:00
|
|
|
"cannot borrow a constant which may contain \
|
2019-12-22 17:42:04 -05:00
|
|
|
interior mutability, create a static instead"
|
2019-12-31 21:25:16 +01:00
|
|
|
)
|
2019-11-26 10:00:41 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MutBorrow;
|
2019-09-20 09:00:18 -07:00
|
|
|
impl NonConstOp for MutBorrow {
|
2020-09-02 13:25:19 -07:00
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
// Forbid everywhere except in const fn with a feature gate
|
|
|
|
if ccx.const_kind() == hir::ConstContext::ConstFn {
|
|
|
|
Status::Unstable(sym::const_mut_refs)
|
|
|
|
} else {
|
|
|
|
Status::Forbidden
|
|
|
|
}
|
2019-11-21 14:33:39 -05:00
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2020-06-15 12:05:24 -05:00
|
|
|
let mut err = if ccx.const_kind() == hir::ConstContext::ConstFn {
|
|
|
|
feature_err(
|
|
|
|
&ccx.tcx.sess.parse_sess,
|
|
|
|
sym::const_mut_refs,
|
|
|
|
span,
|
|
|
|
&format!("mutable references are not allowed in {}s", ccx.const_kind()),
|
|
|
|
)
|
|
|
|
} else {
|
2020-09-02 13:25:19 -07:00
|
|
|
let mut err = struct_span_err!(
|
2020-06-15 12:05:24 -05:00
|
|
|
ccx.tcx.sess,
|
|
|
|
span,
|
2020-06-18 14:52:37 -05:00
|
|
|
E0764,
|
2020-06-15 12:05:24 -05:00
|
|
|
"mutable references are not allowed in {}s",
|
|
|
|
ccx.const_kind(),
|
2020-09-02 13:25:19 -07:00
|
|
|
);
|
|
|
|
err.span_label(span, format!("`&mut` is only allowed in `const fn`"));
|
|
|
|
err
|
2020-06-15 12:05:24 -05:00
|
|
|
};
|
2020-03-23 14:02:58 +01:00
|
|
|
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
|
2019-12-22 17:42:04 -05:00
|
|
|
err.note(
|
|
|
|
"References in statics and constants may only refer \
|
2019-11-26 10:00:41 -05:00
|
|
|
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 \
|
2019-12-22 17:42:04 -05:00
|
|
|
static mut or a global UnsafeCell.",
|
|
|
|
);
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
2020-09-29 11:19:40 -07:00
|
|
|
err
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-02 13:25:19 -07:00
|
|
|
// FIXME(ecstaticmorse): Unify this with `MutBorrow`. It has basically the same issues.
|
2018-12-23 19:00:58 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MutAddressOf;
|
|
|
|
impl NonConstOp for MutAddressOf {
|
2020-09-02 13:25:19 -07:00
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
// Forbid everywhere except in const fn with a feature gate
|
|
|
|
if ccx.const_kind() == hir::ConstContext::ConstFn {
|
|
|
|
Status::Unstable(sym::const_mut_refs)
|
|
|
|
} else {
|
|
|
|
Status::Forbidden
|
|
|
|
}
|
2018-12-23 19:00:58 +00:00
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2018-12-23 19:00:58 +00:00
|
|
|
feature_err(
|
2020-03-23 14:02:58 +01:00
|
|
|
&ccx.tcx.sess.parse_sess,
|
2018-12-23 19:00:58 +00:00
|
|
|
sym::const_mut_refs,
|
|
|
|
span,
|
2020-03-23 14:02:58 +01:00
|
|
|
&format!("`&raw mut` is not allowed in {}s", ccx.const_kind()),
|
2019-12-22 17:42:04 -05:00
|
|
|
)
|
2018-12-23 19:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-20 09:00:18 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MutDeref;
|
2019-11-22 19:59:34 -05:00
|
|
|
impl NonConstOp for MutDeref {
|
2020-09-02 13:25:19 -07:00
|
|
|
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
|
|
|
|
Status::Unstable(sym::const_mut_refs)
|
2019-11-22 19:59:34 -05:00
|
|
|
}
|
2020-09-29 14:40:14 -07:00
|
|
|
|
2020-09-29 17:52:12 -07:00
|
|
|
fn importance(&self) -> DiagnosticImportance {
|
|
|
|
// Usually a side-effect of a `MutBorrow` somewhere.
|
|
|
|
DiagnosticImportance::Secondary
|
|
|
|
}
|
|
|
|
|
2020-09-29 14:40:14 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
|
|
|
feature_err(
|
|
|
|
&ccx.tcx.sess.parse_sess,
|
|
|
|
sym::const_mut_refs,
|
|
|
|
span,
|
|
|
|
&format!("mutation through a reference is not allowed in {}s", ccx.const_kind()),
|
|
|
|
)
|
|
|
|
}
|
2019-11-22 19:59:34 -05:00
|
|
|
}
|
2019-09-20 09:00:18 -07:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Panic;
|
|
|
|
impl NonConstOp for Panic {
|
2020-09-02 13:25:19 -07:00
|
|
|
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
|
|
|
|
Status::Unstable(sym::const_panic)
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2019-11-30 07:40:28 +01:00
|
|
|
feature_err(
|
2020-03-23 14:02:58 +01:00
|
|
|
&ccx.tcx.sess.parse_sess,
|
2019-09-20 09:00:18 -07:00
|
|
|
sym::const_panic,
|
|
|
|
span,
|
2020-03-23 14:02:58 +01:00
|
|
|
&format!("panicking in {}s is unstable", ccx.const_kind()),
|
2019-11-30 07:40:28 +01:00
|
|
|
)
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct RawPtrComparison;
|
|
|
|
impl NonConstOp for RawPtrComparison {
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2020-06-20 14:14:30 +02:00
|
|
|
let mut err = ccx
|
|
|
|
.tcx
|
|
|
|
.sess
|
|
|
|
.struct_span_err(span, "pointers cannot be reliably compared during const eval.");
|
2020-06-12 19:25:14 +02:00
|
|
|
err.note(
|
2020-06-16 10:37:34 +02:00
|
|
|
"see issue #53020 <https://github.com/rust-lang/rust/issues/53020> \
|
|
|
|
for more information",
|
2020-06-12 19:25:14 +02:00
|
|
|
);
|
2020-09-29 11:19:40 -07:00
|
|
|
err
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct RawPtrDeref;
|
|
|
|
impl NonConstOp for RawPtrDeref {
|
2020-09-02 13:25:19 -07:00
|
|
|
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
|
|
|
|
Status::Unstable(sym::const_raw_ptr_deref)
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2019-11-30 07:40:28 +01:00
|
|
|
feature_err(
|
2020-03-23 14:02:58 +01:00
|
|
|
&ccx.tcx.sess.parse_sess,
|
2019-12-22 17:42:04 -05:00
|
|
|
sym::const_raw_ptr_deref,
|
|
|
|
span,
|
2020-03-23 14:02:58 +01:00
|
|
|
&format!("dereferencing raw pointers in {}s is unstable", ccx.const_kind(),),
|
2019-11-30 07:40:28 +01:00
|
|
|
)
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct RawPtrToIntCast;
|
|
|
|
impl NonConstOp for RawPtrToIntCast {
|
2020-09-02 13:25:19 -07:00
|
|
|
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
|
|
|
|
Status::Unstable(sym::const_raw_ptr_to_usize_cast)
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2019-11-30 07:40:28 +01:00
|
|
|
feature_err(
|
2020-03-23 14:02:58 +01:00
|
|
|
&ccx.tcx.sess.parse_sess,
|
2019-12-22 17:42:04 -05:00
|
|
|
sym::const_raw_ptr_to_usize_cast,
|
|
|
|
span,
|
2020-03-23 14:02:58 +01:00
|
|
|
&format!("casting pointers to integers in {}s is unstable", ccx.const_kind(),),
|
2019-11-30 07:40:28 +01:00
|
|
|
)
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An access to a (non-thread-local) `static`.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct StaticAccess;
|
|
|
|
impl NonConstOp for StaticAccess {
|
2020-09-02 13:25:19 -07:00
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
if let hir::ConstContext::Static(_) = ccx.const_kind() {
|
|
|
|
Status::Allowed
|
|
|
|
} else {
|
|
|
|
Status::Forbidden
|
|
|
|
}
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2019-12-22 17:42:04 -05:00
|
|
|
let mut err = struct_span_err!(
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.tcx.sess,
|
2019-12-22 17:42:04 -05:00
|
|
|
span,
|
|
|
|
E0013,
|
2020-01-10 13:31:36 +00:00
|
|
|
"{}s cannot refer to statics",
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.const_kind()
|
2019-12-22 17:42:04 -05:00
|
|
|
);
|
2020-01-10 13:31:36 +00:00
|
|
|
err.help(
|
|
|
|
"consider extracting the value of the `static` to a `const`, and referring to that",
|
|
|
|
);
|
2020-03-23 14:02:58 +01:00
|
|
|
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
|
2019-09-20 09:00:18 -07:00
|
|
|
err.note(
|
2020-01-10 13:31:36 +00:00
|
|
|
"`static` and `const` variables can refer to other `const` variables. \
|
|
|
|
A `const` variable, however, cannot refer to a `static` variable.",
|
2019-09-20 09:00:18 -07:00
|
|
|
);
|
2020-01-10 13:31:36 +00:00
|
|
|
err.help("To fix this, the value can be extracted to a `const` and then used.");
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
2020-09-29 11:19:40 -07:00
|
|
|
err
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An access to a thread-local `static`.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ThreadLocalAccess;
|
|
|
|
impl NonConstOp for ThreadLocalAccess {
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2019-12-31 21:25:16 +01:00
|
|
|
struct_span_err!(
|
2020-03-23 14:02:58 +01:00
|
|
|
ccx.tcx.sess,
|
2019-12-22 17:42:04 -05:00
|
|
|
span,
|
|
|
|
E0625,
|
2019-09-20 09:00:18 -07:00
|
|
|
"thread-local statics cannot be \
|
2019-12-22 17:42:04 -05:00
|
|
|
accessed at compile-time"
|
2019-12-31 21:25:16 +01:00
|
|
|
)
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-17 11:12:13 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Transmute;
|
|
|
|
impl NonConstOp for Transmute {
|
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
if ccx.const_kind() != hir::ConstContext::ConstFn {
|
|
|
|
Status::Allowed
|
|
|
|
} else {
|
|
|
|
Status::Unstable(sym::const_fn_transmute)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
|
|
|
let mut err = feature_err(
|
2020-09-24 11:11:53 -07:00
|
|
|
&ccx.tcx.sess.parse_sess,
|
|
|
|
sym::const_fn_transmute,
|
|
|
|
span,
|
|
|
|
&format!("`transmute` is not allowed in {}s", ccx.const_kind()),
|
2020-09-29 11:19:40 -07:00
|
|
|
);
|
|
|
|
err.note("`transmute` is only allowed in constants and statics for now");
|
|
|
|
err
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-20 09:00:18 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnionAccess;
|
|
|
|
impl NonConstOp for UnionAccess {
|
2020-09-02 13:25:19 -07:00
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
2019-09-20 09:00:18 -07:00
|
|
|
// Union accesses are stable in all contexts except `const fn`.
|
2020-09-02 13:25:19 -07:00
|
|
|
if ccx.const_kind() != hir::ConstContext::ConstFn {
|
|
|
|
Status::Allowed
|
|
|
|
} else {
|
|
|
|
Status::Unstable(sym::const_fn_union)
|
|
|
|
}
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2019-11-30 07:40:28 +01:00
|
|
|
feature_err(
|
2020-03-23 14:02:58 +01:00
|
|
|
&ccx.tcx.sess.parse_sess,
|
2019-12-22 17:42:04 -05:00
|
|
|
sym::const_fn_union,
|
|
|
|
span,
|
2019-09-20 09:00:18 -07:00
|
|
|
"unions in const fn are unstable",
|
2019-11-30 07:40:28 +01:00
|
|
|
)
|
2019-09-20 09:00:18 -07:00
|
|
|
}
|
|
|
|
}
|
2020-09-17 11:12:13 -07:00
|
|
|
|
|
|
|
/// See [#64992].
|
|
|
|
///
|
|
|
|
/// [#64992]: https://github.com/rust-lang/rust/issues/64992
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnsizingCast;
|
|
|
|
impl NonConstOp for UnsizingCast {
|
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
2020-09-22 10:21:58 -07:00
|
|
|
mcf_status_in_item(ccx)
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
|
|
|
mcf_build_error(
|
2020-09-17 11:12:13 -07:00
|
|
|
ccx,
|
|
|
|
span,
|
|
|
|
"unsizing casts to types besides slices are not allowed in const fn",
|
2020-09-29 11:19:40 -07:00
|
|
|
)
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-23 21:04:07 -07:00
|
|
|
// Types that cannot appear in the signature or locals of a `const fn`.
|
2020-09-17 11:12:13 -07:00
|
|
|
pub mod ty {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2020-09-29 17:52:12 -07:00
|
|
|
pub struct MutRef(pub mir::LocalKind);
|
2020-09-17 11:12:13 -07:00
|
|
|
impl NonConstOp for MutRef {
|
|
|
|
fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
Status::Unstable(sym::const_mut_refs)
|
|
|
|
}
|
|
|
|
|
2020-09-29 17:52:12 -07:00
|
|
|
fn importance(&self) -> DiagnosticImportance {
|
|
|
|
match self.0 {
|
|
|
|
mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
|
|
|
|
mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
|
|
|
|
DiagnosticImportance::Primary
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2020-09-23 21:04:07 -07:00
|
|
|
feature_err(
|
|
|
|
&ccx.tcx.sess.parse_sess,
|
|
|
|
sym::const_mut_refs,
|
|
|
|
span,
|
|
|
|
&format!("mutable references are not allowed in {}s", ccx.const_kind()),
|
|
|
|
)
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2020-09-29 17:52:12 -07:00
|
|
|
pub struct FnPtr(pub mir::LocalKind);
|
2020-09-17 11:12:13 -07:00
|
|
|
impl NonConstOp for FnPtr {
|
2020-09-29 17:52:12 -07:00
|
|
|
fn importance(&self) -> DiagnosticImportance {
|
|
|
|
match self.0 {
|
|
|
|
mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
|
|
|
|
mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
|
|
|
|
DiagnosticImportance::Primary
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-17 11:12:13 -07:00
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
2020-09-24 16:17:03 -07:00
|
|
|
if ccx.const_kind() != hir::ConstContext::ConstFn {
|
2020-09-17 11:12:13 -07:00
|
|
|
Status::Allowed
|
|
|
|
} else {
|
2020-09-24 16:17:03 -07:00
|
|
|
Status::Unstable(sym::const_fn_fn_ptr_basics)
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2020-09-24 16:17:03 -07:00
|
|
|
feature_err(
|
|
|
|
&ccx.tcx.sess.parse_sess,
|
|
|
|
sym::const_fn_fn_ptr_basics,
|
|
|
|
span,
|
|
|
|
&format!("function pointers cannot appear in {}s", ccx.const_kind()),
|
|
|
|
)
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ImplTrait;
|
|
|
|
impl NonConstOp for ImplTrait {
|
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
mcf_status_in_item(ccx)
|
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
|
|
|
mcf_build_error(ccx, span, "`impl Trait` in const fn is unstable")
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct TraitBound;
|
|
|
|
impl NonConstOp for TraitBound {
|
|
|
|
const STOPS_CONST_CHECKING: bool = true;
|
|
|
|
|
|
|
|
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
mcf_status_in_item(ccx)
|
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
|
|
|
mcf_build_error(
|
2020-09-17 11:12:13 -07:00
|
|
|
ccx,
|
|
|
|
span,
|
|
|
|
"trait bounds other than `Sized` on const fn parameters are unstable",
|
2020-09-29 11:19:40 -07:00
|
|
|
)
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A trait bound with the `?const Trait` opt-out
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct TraitBoundNotConst;
|
|
|
|
impl NonConstOp for TraitBoundNotConst {
|
|
|
|
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
|
|
|
|
Status::Unstable(sym::const_trait_bound_opt_out)
|
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
2020-09-17 11:12:13 -07:00
|
|
|
feature_err(
|
|
|
|
&ccx.tcx.sess.parse_sess,
|
|
|
|
sym::const_trait_bound_opt_out,
|
|
|
|
span,
|
|
|
|
"`?const Trait` syntax is unstable",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn mcf_status_in_item(ccx: &ConstCx<'_, '_>) -> Status {
|
|
|
|
if ccx.const_kind() != hir::ConstContext::ConstFn {
|
|
|
|
Status::Allowed
|
|
|
|
} else {
|
|
|
|
Status::Unstable(sym::const_fn)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 11:19:40 -07:00
|
|
|
fn mcf_build_error(ccx: &ConstCx<'_, 'tcx>, span: Span, msg: &str) -> DiagnosticBuilder<'tcx> {
|
|
|
|
let mut err = struct_span_err!(ccx.tcx.sess, span, E0723, "{}", msg);
|
|
|
|
err.note(
|
|
|
|
"see issue #57563 <https://github.com/rust-lang/rust/issues/57563> \
|
2020-09-17 11:12:13 -07:00
|
|
|
for more information",
|
2020-09-29 11:19:40 -07:00
|
|
|
);
|
|
|
|
err.help("add `#![feature(const_fn)]` to the crate attributes to enable");
|
|
|
|
err
|
2020-09-17 11:12:13 -07:00
|
|
|
}
|