about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_errors/diagnostic_builder.rs12
-rw-r--r--src/librustc_errors/lib.rs5
-rw-r--r--src/librustc_trans/mir/constant.rs62
-rw-r--r--src/test/run-make/treat-err-as-bug/Makefile5
-rw-r--r--src/test/run-make/treat-err-as-bug/err.rs13
-rw-r--r--src/test/ui/const-eval/issue-43197.rs21
-rw-r--r--src/test/ui/const-eval/issue-43197.stderr28
7 files changed, 109 insertions, 37 deletions
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 6f6470089d7..5d7c5e2829a 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -82,26 +82,27 @@ impl<'a> DiagnosticBuilder<'a> {
             return;
         }
 
-        match self.level {
+        let is_error = match self.level {
             Level::Bug |
             Level::Fatal |
             Level::PhaseFatal |
             Level::Error => {
-                self.handler.bump_err_count();
+                true
             }
 
             Level::Warning |
             Level::Note |
             Level::Help |
             Level::Cancelled => {
+                false
             }
-        }
+        };
 
         self.handler.emitter.borrow_mut().emit(&self);
         self.cancel();
 
-        if self.level == Level::Error {
-            self.handler.panic_if_treat_err_as_bug();
+        if is_error {
+            self.handler.bump_err_count();
         }
 
         // if self.is_fatal() {
@@ -210,4 +211,3 @@ impl<'a> Drop for DiagnosticBuilder<'a> {
         }
     }
 }
-
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index e873137444d..159d2c7a2df 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -399,7 +399,6 @@ impl Handler {
 
     pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> FatalError {
         self.emit(&sp.into(), msg, Fatal);
-        self.panic_if_treat_err_as_bug();
         FatalError
     }
     pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self,
@@ -408,12 +407,10 @@ impl Handler {
                                                     code: &str)
                                                     -> FatalError {
         self.emit_with_code(&sp.into(), msg, code, Fatal);
-        self.panic_if_treat_err_as_bug();
         FatalError
     }
     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Error);
-        self.panic_if_treat_err_as_bug();
     }
     pub fn mut_span_err<'a, S: Into<MultiSpan>>(&'a self,
                                                 sp: S,
@@ -425,7 +422,6 @@ impl Handler {
     }
     pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
         self.emit_with_code(&sp.into(), msg, code, Error);
-        self.panic_if_treat_err_as_bug();
     }
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Warning);
@@ -494,6 +490,7 @@ impl Handler {
     }
 
     pub fn bump_err_count(&self) {
+        self.panic_if_treat_err_as_bug();
         self.err_count.set(self.err_count.get() + 1);
     }
 
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 98e774a2987..393fa9c0c8e 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -222,15 +222,24 @@ struct MirConstContext<'a, 'tcx: 'a> {
     substs: &'tcx Substs<'tcx>,
 
     /// Values of locals in a constant or const fn.
-    locals: IndexVec<mir::Local, Option<Const<'tcx>>>
+    locals: IndexVec<mir::Local, Option<Result<Const<'tcx>, ConstEvalErr<'tcx>>>>
 }
 
+fn add_err<'tcx, U, V>(failure: &mut Result<U, ConstEvalErr<'tcx>>,
+                       value: &Result<V, ConstEvalErr<'tcx>>)
+{
+    if let &Err(ref err) = value {
+        if failure.is_ok() {
+            *failure = Err(err.clone());
+        }
+    }
+}
 
 impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
     fn new(ccx: &'a CrateContext<'a, 'tcx>,
            mir: &'a mir::Mir<'tcx>,
            substs: &'tcx Substs<'tcx>,
-           args: IndexVec<mir::Local, Const<'tcx>>)
+           args: IndexVec<mir::Local, Result<Const<'tcx>, ConstEvalErr<'tcx>>>)
            -> MirConstContext<'a, 'tcx> {
         let mut context = MirConstContext {
             ccx: ccx,
@@ -249,7 +258,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
     fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
                  def_id: DefId,
                  substs: &'tcx Substs<'tcx>,
-                 args: IndexVec<mir::Local, Const<'tcx>>)
+                 args: IndexVec<mir::Local, Result<Const<'tcx>, ConstEvalErr<'tcx>>>)
                  -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
         let instance = monomorphize::resolve(ccx.shared(), def_id, substs);
         let mir = ccx.tcx().instance_mir(instance.def);
@@ -278,10 +287,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                     mir::StatementKind::Assign(ref dest, ref rvalue) => {
                         let ty = dest.ty(self.mir, tcx);
                         let ty = self.monomorphize(&ty).to_ty(tcx);
-                        match self.const_rvalue(rvalue, ty, span) {
-                            Ok(value) => self.store(dest, value, span),
-                            Err(err) => if failure.is_ok() { failure = Err(err); }
-                        }
+                        let value = self.const_rvalue(rvalue, ty, span);
+                        add_err(&mut failure, &value);
+                        self.store(dest, value, span);
                     }
                     mir::StatementKind::StorageLive(_) |
                     mir::StatementKind::StorageDead(_) |
@@ -301,9 +309,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                 mir::TerminatorKind::Goto { target } => target,
                 mir::TerminatorKind::Return => {
                     failure?;
-                    return Ok(self.locals[mir::RETURN_POINTER].unwrap_or_else(|| {
+                    return self.locals[mir::RETURN_POINTER].clone().unwrap_or_else(|| {
                         span_bug!(span, "no returned value in constant");
-                    }));
+                    });
                 }
 
                 mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, .. } => {
@@ -342,33 +350,30 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
 
                     let mut arg_vals = IndexVec::with_capacity(args.len());
                     for arg in args {
-                        match self.const_operand(arg, span) {
-                            Ok(arg) => { arg_vals.push(arg); },
-                            Err(err) => if failure.is_ok() { failure = Err(err); }
-                        }
+                        let arg_val = self.const_operand(arg, span);
+                        add_err(&mut failure, &arg_val);
+                        arg_vals.push(arg_val);
                     }
                     if let Some((ref dest, target)) = *destination {
-                        if fn_ty.fn_sig(tcx).abi() == Abi::RustIntrinsic {
-                            let value = match &tcx.item_name(def_id).as_str()[..] {
+                        let result = if fn_ty.fn_sig(tcx).abi() == Abi::RustIntrinsic {
+                            match &tcx.item_name(def_id).as_str()[..] {
                                 "size_of" => {
                                     let llval = C_uint(self.ccx,
                                         self.ccx.size_of(substs.type_at(0)));
-                                    Const::new(llval, tcx.types.usize)
+                                    Ok(Const::new(llval, tcx.types.usize))
                                 }
                                 "min_align_of" => {
                                     let llval = C_uint(self.ccx,
                                         self.ccx.align_of(substs.type_at(0)));
-                                    Const::new(llval, tcx.types.usize)
+                                    Ok(Const::new(llval, tcx.types.usize))
                                 }
                                 _ => span_bug!(span, "{:?} in constant", terminator.kind)
-                            };
-                            self.store(dest, value, span);
-                        } else {
-                            match MirConstContext::trans_def(self.ccx, def_id, substs, arg_vals) {
-                                Ok(value) => self.store(dest, value, span),
-                                Err(err) => if failure.is_ok() { failure = Err(err); }
                             }
-                        }
+                        } else {
+                            MirConstContext::trans_def(self.ccx, def_id, substs, arg_vals)
+                        };
+                        add_err(&mut failure, &result);
+                        self.store(dest, result, span);
                         target
                     } else {
                         span_bug!(span, "diverging {:?} in constant", terminator.kind);
@@ -379,7 +384,10 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
         }
     }
 
-    fn store(&mut self, dest: &mir::Lvalue<'tcx>, value: Const<'tcx>, span: Span) {
+    fn store(&mut self,
+             dest: &mir::Lvalue<'tcx>,
+             value: Result<Const<'tcx>, ConstEvalErr<'tcx>>,
+             span: Span) {
         if let mir::Lvalue::Local(index) = *dest {
             self.locals[index] = Some(value);
         } else {
@@ -392,9 +400,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
         let tcx = self.ccx.tcx();
 
         if let mir::Lvalue::Local(index) = *lvalue {
-            return Ok(self.locals[index].unwrap_or_else(|| {
+            return self.locals[index].clone().unwrap_or_else(|| {
                 span_bug!(span, "{:?} not initialized", lvalue)
-            }).as_lvalue());
+            }).map(|v| v.as_lvalue());
         }
 
         let lvalue = match *lvalue {
diff --git a/src/test/run-make/treat-err-as-bug/Makefile b/src/test/run-make/treat-err-as-bug/Makefile
new file mode 100644
index 00000000000..a8fa2d4e0f8
--- /dev/null
+++ b/src/test/run-make/treat-err-as-bug/Makefile
@@ -0,0 +1,5 @@
+-include ../tools.mk
+
+all:
+	$(RUSTC) err.rs -Z treat-err-as-bug 2>&1 \
+	    | grep -q "panicked at 'encountered error with .-Z treat_err_as_bug'"
diff --git a/src/test/run-make/treat-err-as-bug/err.rs b/src/test/run-make/treat-err-as-bug/err.rs
new file mode 100644
index 00000000000..078495663ac
--- /dev/null
+++ b/src/test/run-make/treat-err-as-bug/err.rs
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type="rlib"]
+
+pub static C: u32 = 0-1;
diff --git a/src/test/ui/const-eval/issue-43197.rs b/src/test/ui/const-eval/issue-43197.rs
new file mode 100644
index 00000000000..1d4ded6e712
--- /dev/null
+++ b/src/test/ui/const-eval/issue-43197.rs
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_fn)]
+
+const fn foo(x: u32) -> u32 {
+    x
+}
+
+fn main() {
+    const X: u32 = 0-1;
+    const Y: u32 = foo(0-1);
+    println!("{} {}", X, Y);
+}
diff --git a/src/test/ui/const-eval/issue-43197.stderr b/src/test/ui/const-eval/issue-43197.stderr
new file mode 100644
index 00000000000..5ff80060eac
--- /dev/null
+++ b/src/test/ui/const-eval/issue-43197.stderr
@@ -0,0 +1,28 @@
+warning: constant evaluation error: attempt to subtract with overflow. This will become a HARD ERROR in the future
+  --> $DIR/issue-43197.rs:18:20
+   |
+18 |     const X: u32 = 0-1;
+   |                    ^^^
+   |
+   = note: #[warn(const_err)] on by default
+
+warning: constant evaluation error: attempt to subtract with overflow. This will become a HARD ERROR in the future
+  --> $DIR/issue-43197.rs:19:20
+   |
+19 |     const Y: u32 = foo(0-1);
+   |                    ^^^^^^^^
+
+error[E0080]: constant evaluation error
+  --> $DIR/issue-43197.rs:18:20
+   |
+18 |     const X: u32 = 0-1;
+   |                    ^^^ attempt to subtract with overflow
+
+error[E0080]: constant evaluation error
+  --> $DIR/issue-43197.rs:19:24
+   |
+19 |     const Y: u32 = foo(0-1);
+   |                        ^^^ attempt to subtract with overflow
+
+error: aborting due to 2 previous errors
+