Add structured errors for `qualify_min_const_fn` checks
This commit is contained in:
parent
bfc10a89c3
commit
5ee5429e00
|
@ -98,6 +98,34 @@ pub trait NonConstOp: std::fmt::Debug {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Abort;
|
||||
impl NonConstOp for Abort {
|
||||
const STOPS_CONST_CHECKING: bool = true;
|
||||
|
||||
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
||||
mcf_status_in_item(ccx)
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
mcf_emit_error(ccx, span, "abort is not stable in const fn")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NonPrimitiveOp;
|
||||
impl NonConstOp for NonPrimitiveOp {
|
||||
const STOPS_CONST_CHECKING: bool = true;
|
||||
|
||||
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
||||
mcf_status_in_item(ccx)
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
mcf_emit_error(ccx, span, "only int, `bool` and `char` operations are stable in const fn")
|
||||
}
|
||||
}
|
||||
|
||||
/// A function call where the callee is a pointer.
|
||||
#[derive(Debug)]
|
||||
pub struct FnCallIndirect;
|
||||
|
@ -130,7 +158,8 @@ impl NonConstOp for FnCallNonConst {
|
|||
///
|
||||
/// Contains the name of the feature that would allow the use of this function.
|
||||
#[derive(Debug)]
|
||||
pub struct FnCallUnstable(pub DefId, pub Symbol);
|
||||
pub struct FnCallUnstable(pub DefId, pub Option<Symbol>);
|
||||
|
||||
impl NonConstOp for FnCallUnstable {
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
let FnCallUnstable(def_id, feature) = *self;
|
||||
|
@ -139,13 +168,51 @@ impl NonConstOp for FnCallUnstable {
|
|||
span,
|
||||
&format!("`{}` is not yet stable as a const fn", ccx.tcx.def_path_str(def_id)),
|
||||
);
|
||||
if nightly_options::is_nightly_build() {
|
||||
err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
|
||||
|
||||
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
|
||||
));
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FnPtrCast;
|
||||
impl NonConstOp for FnPtrCast {
|
||||
const STOPS_CONST_CHECKING: bool = true;
|
||||
|
||||
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
||||
mcf_status_in_item(ccx)
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
mcf_emit_error(ccx, span, "function pointer casts are not allowed in const fn");
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Generator;
|
||||
impl NonConstOp for Generator {
|
||||
const STOPS_CONST_CHECKING: bool = true;
|
||||
|
||||
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
||||
// FIXME: This means generator-only MIR is only forbidden in const fn. This is for
|
||||
// compatibility with the old code. Such MIR should be forbidden everywhere.
|
||||
mcf_status_in_item(ccx)
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
mcf_emit_error(ccx, span, "const fn generators are unstable");
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HeapAllocation;
|
||||
impl NonConstOp for HeapAllocation {
|
||||
|
@ -408,6 +475,24 @@ impl NonConstOp for ThreadLocalAccess {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Transmute;
|
||||
impl NonConstOp for Transmute {
|
||||
const STOPS_CONST_CHECKING: bool = true;
|
||||
|
||||
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
||||
if ccx.const_kind() != hir::ConstContext::ConstFn {
|
||||
Status::Allowed
|
||||
} else {
|
||||
Status::Unstable(sym::const_fn_transmute)
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
mcf_emit_error(ccx, span, "can only call `transmute` from const items, not `const fn`");
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UnionAccess;
|
||||
impl NonConstOp for UnionAccess {
|
||||
|
@ -430,3 +515,135 @@ impl NonConstOp for UnionAccess {
|
|||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
if ccx.const_kind() != hir::ConstContext::ConstFn {
|
||||
Status::Allowed
|
||||
} else {
|
||||
Status::Unstable(sym::const_fn_transmute)
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
mcf_emit_error(
|
||||
ccx,
|
||||
span,
|
||||
"unsizing casts to types besides slices are not allowed in const fn",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub mod ty {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MutRef;
|
||||
impl NonConstOp for MutRef {
|
||||
const STOPS_CONST_CHECKING: bool = true;
|
||||
|
||||
fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
|
||||
Status::Unstable(sym::const_mut_refs)
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
mcf_emit_error(ccx, span, "mutable references in const fn are unstable");
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FnPtr;
|
||||
impl NonConstOp for FnPtr {
|
||||
const STOPS_CONST_CHECKING: bool = true;
|
||||
|
||||
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
||||
// FIXME: This attribute a hack to allow the specialization of the `futures` API. See
|
||||
// #59739. We should have a proper feature gate for this.
|
||||
if ccx.tcx.has_attr(ccx.def_id.to_def_id(), sym::rustc_allow_const_fn_ptr) {
|
||||
Status::Allowed
|
||||
} else {
|
||||
mcf_status_in_item(ccx)
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
mcf_emit_error(ccx, span, "function pointers in const fn are unstable");
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImplTrait;
|
||||
impl NonConstOp for ImplTrait {
|
||||
const STOPS_CONST_CHECKING: bool = true;
|
||||
|
||||
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
|
||||
mcf_status_in_item(ccx)
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
mcf_emit_error(ccx, span, "`impl Trait` in const fn is unstable");
|
||||
}
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
mcf_emit_error(
|
||||
ccx,
|
||||
span,
|
||||
"trait bounds other than `Sized` on const fn parameters are unstable",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait bound with the `?const Trait` opt-out
|
||||
#[derive(Debug)]
|
||||
pub struct TraitBoundNotConst;
|
||||
impl NonConstOp for TraitBoundNotConst {
|
||||
const STOPS_CONST_CHECKING: bool = true;
|
||||
|
||||
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
|
||||
Status::Unstable(sym::const_trait_bound_opt_out)
|
||||
}
|
||||
|
||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||
feature_err(
|
||||
&ccx.tcx.sess.parse_sess,
|
||||
sym::const_trait_bound_opt_out,
|
||||
span,
|
||||
"`?const Trait` syntax is unstable",
|
||||
)
|
||||
.emit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mcf_status_in_item(ccx: &ConstCx<'_, '_>) -> Status {
|
||||
if ccx.const_kind() != hir::ConstContext::ConstFn {
|
||||
Status::Allowed
|
||||
} else {
|
||||
Status::Unstable(sym::const_fn)
|
||||
}
|
||||
}
|
||||
|
||||
fn mcf_emit_error(ccx: &ConstCx<'_, '_>, span: Span, msg: &str) {
|
||||
struct_span_err!(ccx.tcx.sess, span, E0723, "{}", msg)
|
||||
.note(
|
||||
"see issue #57563 <https://github.com/rust-lang/rust/issues/57563> \
|
||||
for more information",
|
||||
)
|
||||
.help("add `#![feature(const_fn)]` to the crate attributes to enable")
|
||||
.emit();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue