Skip to content

Commit 5ee5429

Browse files
Add structured errors for qualify_min_const_fn checks
1 parent bfc10a8 commit 5ee5429

File tree

1 file changed

+220
-3
lines changed
  • compiler/rustc_mir/src/transform/check_consts

1 file changed

+220
-3
lines changed

compiler/rustc_mir/src/transform/check_consts/ops.rs

Lines changed: 220 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,34 @@ pub trait NonConstOp: std::fmt::Debug {
9898
}
9999
}
100100

101+
#[derive(Debug)]
102+
pub struct Abort;
103+
impl NonConstOp for Abort {
104+
const STOPS_CONST_CHECKING: bool = true;
105+
106+
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
107+
mcf_status_in_item(ccx)
108+
}
109+
110+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
111+
mcf_emit_error(ccx, span, "abort is not stable in const fn")
112+
}
113+
}
114+
115+
#[derive(Debug)]
116+
pub struct NonPrimitiveOp;
117+
impl NonConstOp for NonPrimitiveOp {
118+
const STOPS_CONST_CHECKING: bool = true;
119+
120+
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
121+
mcf_status_in_item(ccx)
122+
}
123+
124+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
125+
mcf_emit_error(ccx, span, "only int, `bool` and `char` operations are stable in const fn")
126+
}
127+
}
128+
101129
/// A function call where the callee is a pointer.
102130
#[derive(Debug)]
103131
pub struct FnCallIndirect;
@@ -130,7 +158,8 @@ impl NonConstOp for FnCallNonConst {
130158
///
131159
/// Contains the name of the feature that would allow the use of this function.
132160
#[derive(Debug)]
133-
pub struct FnCallUnstable(pub DefId, pub Symbol);
161+
pub struct FnCallUnstable(pub DefId, pub Option<Symbol>);
162+
134163
impl NonConstOp for FnCallUnstable {
135164
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
136165
let FnCallUnstable(def_id, feature) = *self;
@@ -139,13 +168,51 @@ impl NonConstOp for FnCallUnstable {
139168
span,
140169
&format!("`{}` is not yet stable as a const fn", ccx.tcx.def_path_str(def_id)),
141170
);
142-
if nightly_options::is_nightly_build() {
143-
err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
171+
172+
if ccx.is_const_stable_const_fn() {
173+
err.help("Const-stable functions can only call other const-stable functions");
174+
} else if nightly_options::is_nightly_build() {
175+
if let Some(feature) = feature {
176+
err.help(&format!(
177+
"add `#![feature({})]` to the crate attributes to enable",
178+
feature
179+
));
180+
}
144181
}
145182
err.emit();
146183
}
147184
}
148185

186+
#[derive(Debug)]
187+
pub struct FnPtrCast;
188+
impl NonConstOp for FnPtrCast {
189+
const STOPS_CONST_CHECKING: bool = true;
190+
191+
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
192+
mcf_status_in_item(ccx)
193+
}
194+
195+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
196+
mcf_emit_error(ccx, span, "function pointer casts are not allowed in const fn");
197+
}
198+
}
199+
200+
#[derive(Debug)]
201+
pub struct Generator;
202+
impl NonConstOp for Generator {
203+
const STOPS_CONST_CHECKING: bool = true;
204+
205+
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
206+
// FIXME: This means generator-only MIR is only forbidden in const fn. This is for
207+
// compatibility with the old code. Such MIR should be forbidden everywhere.
208+
mcf_status_in_item(ccx)
209+
}
210+
211+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
212+
mcf_emit_error(ccx, span, "const fn generators are unstable");
213+
}
214+
}
215+
149216
#[derive(Debug)]
150217
pub struct HeapAllocation;
151218
impl NonConstOp for HeapAllocation {
@@ -408,6 +475,24 @@ impl NonConstOp for ThreadLocalAccess {
408475
}
409476
}
410477

478+
#[derive(Debug)]
479+
pub struct Transmute;
480+
impl NonConstOp for Transmute {
481+
const STOPS_CONST_CHECKING: bool = true;
482+
483+
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
484+
if ccx.const_kind() != hir::ConstContext::ConstFn {
485+
Status::Allowed
486+
} else {
487+
Status::Unstable(sym::const_fn_transmute)
488+
}
489+
}
490+
491+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
492+
mcf_emit_error(ccx, span, "can only call `transmute` from const items, not `const fn`");
493+
}
494+
}
495+
411496
#[derive(Debug)]
412497
pub struct UnionAccess;
413498
impl NonConstOp for UnionAccess {
@@ -430,3 +515,135 @@ impl NonConstOp for UnionAccess {
430515
.emit();
431516
}
432517
}
518+
519+
/// See [#64992].
520+
///
521+
/// [#64992]: https://github.com/rust-lang/rust/issues/64992
522+
#[derive(Debug)]
523+
pub struct UnsizingCast;
524+
impl NonConstOp for UnsizingCast {
525+
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
526+
if ccx.const_kind() != hir::ConstContext::ConstFn {
527+
Status::Allowed
528+
} else {
529+
Status::Unstable(sym::const_fn_transmute)
530+
}
531+
}
532+
533+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
534+
mcf_emit_error(
535+
ccx,
536+
span,
537+
"unsizing casts to types besides slices are not allowed in const fn",
538+
);
539+
}
540+
}
541+
542+
pub mod ty {
543+
use super::*;
544+
545+
#[derive(Debug)]
546+
pub struct MutRef;
547+
impl NonConstOp for MutRef {
548+
const STOPS_CONST_CHECKING: bool = true;
549+
550+
fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
551+
Status::Unstable(sym::const_mut_refs)
552+
}
553+
554+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
555+
mcf_emit_error(ccx, span, "mutable references in const fn are unstable");
556+
}
557+
}
558+
559+
#[derive(Debug)]
560+
pub struct FnPtr;
561+
impl NonConstOp for FnPtr {
562+
const STOPS_CONST_CHECKING: bool = true;
563+
564+
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
565+
// FIXME: This attribute a hack to allow the specialization of the `futures` API. See
566+
// #59739. We should have a proper feature gate for this.
567+
if ccx.tcx.has_attr(ccx.def_id.to_def_id(), sym::rustc_allow_const_fn_ptr) {
568+
Status::Allowed
569+
} else {
570+
mcf_status_in_item(ccx)
571+
}
572+
}
573+
574+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
575+
mcf_emit_error(ccx, span, "function pointers in const fn are unstable");
576+
}
577+
}
578+
579+
#[derive(Debug)]
580+
pub struct ImplTrait;
581+
impl NonConstOp for ImplTrait {
582+
const STOPS_CONST_CHECKING: bool = true;
583+
584+
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
585+
mcf_status_in_item(ccx)
586+
}
587+
588+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
589+
mcf_emit_error(ccx, span, "`impl Trait` in const fn is unstable");
590+
}
591+
}
592+
593+
#[derive(Debug)]
594+
pub struct TraitBound;
595+
impl NonConstOp for TraitBound {
596+
const STOPS_CONST_CHECKING: bool = true;
597+
598+
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
599+
mcf_status_in_item(ccx)
600+
}
601+
602+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
603+
mcf_emit_error(
604+
ccx,
605+
span,
606+
"trait bounds other than `Sized` on const fn parameters are unstable",
607+
);
608+
}
609+
}
610+
611+
/// A trait bound with the `?const Trait` opt-out
612+
#[derive(Debug)]
613+
pub struct TraitBoundNotConst;
614+
impl NonConstOp for TraitBoundNotConst {
615+
const STOPS_CONST_CHECKING: bool = true;
616+
617+
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
618+
Status::Unstable(sym::const_trait_bound_opt_out)
619+
}
620+
621+
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
622+
feature_err(
623+
&ccx.tcx.sess.parse_sess,
624+
sym::const_trait_bound_opt_out,
625+
span,
626+
"`?const Trait` syntax is unstable",
627+
)
628+
.emit()
629+
}
630+
}
631+
}
632+
633+
fn mcf_status_in_item(ccx: &ConstCx<'_, '_>) -> Status {
634+
if ccx.const_kind() != hir::ConstContext::ConstFn {
635+
Status::Allowed
636+
} else {
637+
Status::Unstable(sym::const_fn)
638+
}
639+
}
640+
641+
fn mcf_emit_error(ccx: &ConstCx<'_, '_>, span: Span, msg: &str) {
642+
struct_span_err!(ccx.tcx.sess, span, E0723, "{}", msg)
643+
.note(
644+
"see issue #57563 <https://github.com/rust-lang/rust/issues/57563> \
645+
for more information",
646+
)
647+
.help("add `#![feature(const_fn)]` to the crate attributes to enable")
648+
.emit();
649+
}

0 commit comments

Comments
 (0)