Skip to content

Commit

Permalink
Rollup merge of rust-lang#77512 - ecstatic-morse:const-checking-allow…
Browse files Browse the repository at this point in the history
…-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
  • Loading branch information
Dylan-DPC authored Oct 5, 2020
2 parents 23b1e3d + 6ae1da3 commit 5fbb411
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 17 deletions.
12 changes: 0 additions & 12 deletions compiler/rustc_mir/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,6 @@ pub trait NonConstOp: std::fmt::Debug {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;
}

#[derive(Debug)]
pub struct Abort;
impl NonConstOp for Abort {
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
mcf_status_in_item(ccx)
}

fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
mcf_build_error(ccx, span, "abort is not stable in const fn")
}
}

#[derive(Debug)]
pub struct FloatingPointOp;
impl NonConstOp for FloatingPointOp {
Expand Down
16 changes: 11 additions & 5 deletions compiler/rustc_mir/src/transform/check_consts/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,11 +434,13 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &BasicBlockData<'tcx>) {
trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);

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

TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm),
TerminatorKind::Abort => self.check_op(ops::Abort),

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

TerminatorKind::Abort => {
// Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
span_bug!(self.span, "`Abort` terminator outside of cleanup block")
}

TerminatorKind::Assert { .. }
| TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. }
Expand Down
13 changes: 13 additions & 0 deletions src/test/ui/consts/const-eval/unwind-abort.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#![feature(unwind_attributes, const_panic)]

#[unwind(aborts)]
const fn foo() {
panic!() //~ evaluation of constant value failed
}

const _: () = foo(); //~ any use of this value will cause an error
// Ensure that the CTFE engine handles calls to `#[unwind(aborts)]` gracefully

fn main() {
let _ = foo();
}
21 changes: 21 additions & 0 deletions src/test/ui/consts/const-eval/unwind-abort.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0080]: evaluation of constant value failed
--> $DIR/unwind-abort.rs:5:5
|
LL | panic!()
| ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:5:5
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: any use of this value will cause an error
--> $DIR/unwind-abort.rs:8:15
|
LL | const _: () = foo();
| --------------^^^^^-
| |
| referenced constant has errors
|
= note: `#[deny(const_err)]` on by default

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0080`.
17 changes: 17 additions & 0 deletions src/test/ui/consts/unwind-abort.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// check-pass

#![feature(unwind_attributes, const_panic)]

// `#[unwind(aborts)]` is okay for a `const fn`. We don't unwind in const-eval anyways.
#[unwind(aborts)]
const fn foo() {
panic!()
}

const fn bar() {
foo();
}

fn main() {
bar();
}

0 comments on commit 5fbb411

Please sign in to comment.