Skip to content

Commit 5fbb411

Browse files
authored
Rollup merge of #77512 - ecstatic-morse:const-checking-allow-abort, r=RalfJung
Allow `Abort` terminators in all const-contexts We never unwind during const-eval, so we basically have these semantics already. Also I just figured out that these only appear along the cleanup path, which doesn't get const-checked. In other words, this doesn't actually change behavior: the `check-pass` test I added compiles just fine on nightly. r? @RalfJung cc @rust-lang/wg-const-eval
2 parents 23b1e3d + 6ae1da3 commit 5fbb411

File tree

5 files changed

+62
-17
lines changed

5 files changed

+62
-17
lines changed

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

-12
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,6 @@ pub trait NonConstOp: std::fmt::Debug {
4141
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;
4242
}
4343

44-
#[derive(Debug)]
45-
pub struct Abort;
46-
impl NonConstOp for Abort {
47-
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
48-
mcf_status_in_item(ccx)
49-
}
50-
51-
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
52-
mcf_build_error(ccx, span, "abort is not stable in const fn")
53-
}
54-
}
55-
5644
#[derive(Debug)]
5745
pub struct FloatingPointOp;
5846
impl NonConstOp for FloatingPointOp {

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

+11-5
Original file line numberDiff line numberDiff line change
@@ -434,11 +434,13 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
434434
fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &BasicBlockData<'tcx>) {
435435
trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);
436436

437-
// Just as the old checker did, we skip const-checking basic blocks on the unwind path.
438-
// These blocks often drop locals that would otherwise be returned from the function.
437+
// We don't const-check basic blocks on the cleanup path since we never unwind during
438+
// const-eval: a panic causes an immediate compile error. In other words, cleanup blocks
439+
// are unreachable during const-eval.
439440
//
440-
// FIXME: This shouldn't be unsound since a panic at compile time will cause a compiler
441-
// error anyway, but maybe we should do more here?
441+
// We can't be more conservative (e.g., by const-checking cleanup blocks anyways) because
442+
// locals that would never be dropped during normal execution are sometimes dropped during
443+
// unwinding, which means backwards-incompatible live-drop errors.
442444
if block.is_cleanup {
443445
return;
444446
}
@@ -874,12 +876,16 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
874876
}
875877

876878
TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm),
877-
TerminatorKind::Abort => self.check_op(ops::Abort),
878879

879880
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
880881
self.check_op(ops::Generator(hir::GeneratorKind::Gen))
881882
}
882883

884+
TerminatorKind::Abort => {
885+
// Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
886+
span_bug!(self.span, "`Abort` terminator outside of cleanup block")
887+
}
888+
883889
TerminatorKind::Assert { .. }
884890
| TerminatorKind::FalseEdge { .. }
885891
| TerminatorKind::FalseUnwind { .. }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(unwind_attributes, const_panic)]
2+
3+
#[unwind(aborts)]
4+
const fn foo() {
5+
panic!() //~ evaluation of constant value failed
6+
}
7+
8+
const _: () = foo(); //~ any use of this value will cause an error
9+
// Ensure that the CTFE engine handles calls to `#[unwind(aborts)]` gracefully
10+
11+
fn main() {
12+
let _ = foo();
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0080]: evaluation of constant value failed
2+
--> $DIR/unwind-abort.rs:5:5
3+
|
4+
LL | panic!()
5+
| ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:5:5
6+
|
7+
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
8+
9+
error: any use of this value will cause an error
10+
--> $DIR/unwind-abort.rs:8:15
11+
|
12+
LL | const _: () = foo();
13+
| --------------^^^^^-
14+
| |
15+
| referenced constant has errors
16+
|
17+
= note: `#[deny(const_err)]` on by default
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0080`.

src/test/ui/consts/unwind-abort.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// check-pass
2+
3+
#![feature(unwind_attributes, const_panic)]
4+
5+
// `#[unwind(aborts)]` is okay for a `const fn`. We don't unwind in const-eval anyways.
6+
#[unwind(aborts)]
7+
const fn foo() {
8+
panic!()
9+
}
10+
11+
const fn bar() {
12+
foo();
13+
}
14+
15+
fn main() {
16+
bar();
17+
}

0 commit comments

Comments
 (0)