about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan MacKenzie <ecstaticmorse@gmail.com>2020-09-17 11:09:52 -0700
committerDylan MacKenzie <ecstaticmorse@gmail.com>2020-09-22 10:05:58 -0700
commitbfc10a89c3a1cf2398b4cd8de342577ea96fe98a (patch)
tree22c7bb46c4c80b8b3da5c2a778233314b237dbf5
parent7fb9587a3ce4c689f7cab3aa5112aad9d421301f (diff)
downloadrust-bfc10a89c3a1cf2398b4cd8de342577ea96fe98a.tar.gz
rust-bfc10a89c3a1cf2398b4cd8de342577ea96fe98a.zip
Allow errors to abort const checking when emitted
This is a hack for parity with `qualify_min_const_fn`, which only
emitted a single error.
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/ops.rs2
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs24
2 files changed, 22 insertions, 4 deletions
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs
index 66b81b3d111..1f0c93eed55 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -62,6 +62,8 @@ pub enum Status {
 
 /// An operation that is not *always* allowed in a const context.
 pub trait NonConstOp: std::fmt::Debug {
+    const STOPS_CONST_CHECKING: bool = false;
+
     /// Returns an enum indicating whether this operation is allowed within the given item.
     fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
         Status::Forbidden
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index af9d7cc1aa5..2c6e12e40bc 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -176,6 +176,8 @@ pub struct Validator<'mir, 'tcx> {
 
     /// The span of the current statement.
     span: Span,
+
+    const_checking_stopped: bool,
 }
 
 impl Deref for Validator<'mir, 'tcx> {
@@ -188,7 +190,12 @@ impl Deref for Validator<'mir, 'tcx> {
 
 impl Validator<'mir, 'tcx> {
     pub fn new(ccx: &'mir ConstCx<'mir, 'tcx>) -> Self {
-        Validator { span: ccx.body.span, ccx, qualifs: Default::default() }
+        Validator {
+            span: ccx.body.span,
+            ccx,
+            qualifs: Default::default(),
+            const_checking_stopped: false,
+        }
     }
 
     pub fn check_body(&mut self) {
@@ -226,13 +233,22 @@ impl Validator<'mir, 'tcx> {
 
     /// Emits an error if an expression cannot be evaluated in the current context.
     pub fn check_op(&mut self, op: impl NonConstOp) {
-        ops::non_const(self.ccx, op, self.span);
+        self.check_op_spanned(op, self.span);
     }
 
     /// Emits an error at the given `span` if an expression cannot be evaluated in the current
     /// context.
-    pub fn check_op_spanned(&mut self, op: impl NonConstOp, span: Span) {
-        ops::non_const(self.ccx, op, span);
+    pub fn check_op_spanned<O: NonConstOp>(&mut self, op: O, span: Span) {
+        // HACK: This is for strict equivalence with the old `qualify_min_const_fn` pass, which
+        // only emitted one error per function. It should be removed and the test output updated.
+        if self.const_checking_stopped {
+            return;
+        }
+
+        let err_emitted = ops::non_const(self.ccx, op, span);
+        if err_emitted && O::STOPS_CONST_CHECKING {
+            self.const_checking_stopped = true;
+        }
     }
 
     fn check_static(&mut self, def_id: DefId, span: Span) {