about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2016-04-01 09:19:29 +0200
committerOliver 'ker' Schneider <git-spam-no-reply9815368754983@oli-obk.de>2016-04-03 15:18:16 +0200
commit913a2b4b0525c75ecf915076c4fd1e16187f8b51 (patch)
tree84a18d70e9bf0c37e407e07fef6c34895fa439a0
parenta09f386e8d1c31133f0ce1123fbeaedcff40a77d (diff)
downloadrust-913a2b4b0525c75ecf915076c4fd1e16187f8b51.tar.gz
rust-913a2b4b0525c75ecf915076c4fd1e16187f8b51.zip
check constants even if they are unused in the current crate
-rw-r--r--src/librustc_const_eval/eval.rs23
-rw-r--r--src/librustc_passes/consts.rs13
-rw-r--r--src/test/compile-fail/const-err-early.rs22
-rw-r--r--src/test/compile-fail/const-err.rs7
-rw-r--r--src/test/compile-fail/const-eval-span.rs2
-rw-r--r--src/test/compile-fail/const-pattern-not-const-evaluable.rs6
-rw-r--r--src/test/compile-fail/feature-gate-negate-unsigned.rs3
-rw-r--r--src/test/compile-fail/non-constant-enum-for-vec-repeat.rs2
8 files changed, 60 insertions, 18 deletions
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 4790e481937..5a00b4573de 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -343,10 +343,15 @@ pub fn eval_const_expr(tcx: &TyCtxt, e: &Expr) -> ConstVal {
     match eval_const_expr_partial(tcx, e, ExprTypeChecked, None) {
         Ok(r) => r,
         // non-const path still needs to be a fatal error, because enums are funky
-        Err(ref s) if s.kind == NonConstPath => tcx.sess.span_fatal(s.span, &s.description()),
         Err(s) => {
-            tcx.sess.span_err(s.span, &s.description());
-            Dummy
+            match s.kind {
+                NonConstPath |
+                UnimplementedConstVal(_) => tcx.sess.span_fatal(s.span, &s.description()),
+                _ => {
+                    tcx.sess.span_err(s.span, &s.description());
+                    Dummy
+                }
+            }
         },
     }
 }
@@ -607,6 +612,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
           const_val => signal!(e, NotOn(const_val)),
         }
       }
+      hir::ExprUnary(hir::UnDeref, _) => signal!(e, UnimplementedConstVal("deref operation")),
       hir::ExprBinary(op, ref a, ref b) => {
         let b_ty = match op.node {
             hir::BiShl | hir::BiShr => ty_hint.erase_hint(),
@@ -745,7 +751,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
                   if let Some(const_expr) = lookup_variant_by_id(tcx, enum_def, variant_def) {
                       eval_const_expr_partial(tcx, const_expr, ty_hint, None)?
                   } else {
-                      signal!(e, NonConstPath);
+                      signal!(e, UnimplementedConstVal("enum variants"));
                   }
               }
               Def::Struct(..) => {
@@ -768,6 +774,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
           let callee_val = eval_const_expr_partial(tcx, callee, sub_ty_hint, fn_args)?;
           let did = match callee_val {
               Function(did) => did,
+              Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")),
               callee => signal!(e, CallOn(callee)),
           };
           let (decl, result) = if let Some(fn_like) = lookup_const_fn_by_id(tcx, did) {
@@ -798,7 +805,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
       hir::ExprBlock(ref block) => {
         match block.expr {
             Some(ref expr) => eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)?,
-            None => bug!(),
+            None => signal!(e, UnimplementedConstVal("empty block")),
         }
       }
       hir::ExprType(ref e, _) => eval_const_expr_partial(tcx, &e, ty_hint, fn_args)?,
@@ -840,7 +847,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
             },
 
             Str(ref s) if idx as usize >= s.len() => signal!(e, IndexOutOfBounds),
-            Str(_) => bug!("unimplemented"), // FIXME: return a const char
+            // FIXME: return a const char
+            Str(_) => signal!(e, UnimplementedConstVal("indexing into str")),
             _ => signal!(e, IndexedNonVec),
         }
       }
@@ -894,6 +902,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
             signal!(base, ExpectedConstStruct);
         }
       }
+      hir::ExprAddrOf(..) => signal!(e, UnimplementedConstVal("address operator")),
       _ => signal!(e, MiscCatchAll)
     };
 
@@ -1073,6 +1082,7 @@ fn cast_const_int<'tcx>(tcx: &TyCtxt<'tcx>, val: ConstInt, ty: ty::Ty) -> CastRe
             Ok(Float(val as f64))
         },
         ty::TyFloat(ast::FloatTy::F32) => Ok(Float(val.to_u64().unwrap() as f32 as f64)),
+        ty::TyRawPtr(_) => Err(ErrKind::UnimplementedConstVal("casting an address to a raw ptr")),
         _ => Err(CannotCast),
     }
 }
@@ -1094,6 +1104,7 @@ fn cast_const<'tcx>(tcx: &TyCtxt<'tcx>, val: ConstVal, ty: ty::Ty) -> CastResult
         Bool(b) => cast_const_int(tcx, Infer(b as u64), ty),
         Float(f) => cast_const_float(tcx, f, ty),
         Char(c) => cast_const_int(tcx, Infer(c as u64), ty),
+        Function(_) => Err(UnimplementedConstVal("casting fn pointers")),
         _ => Err(CannotCast),
     }
 }
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index a7f00888735..ba5d8ef45b6 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -28,7 +28,7 @@ use rustc::dep_graph::DepNode;
 use rustc::ty::cast::{CastKind};
 use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs};
 use rustc_const_eval::{eval_const_expr_partial, lookup_const_by_id};
-use rustc_const_eval::ErrKind::IndexOpFeatureGated;
+use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal};
 use rustc_const_eval::EvalHint::ExprTypeChecked;
 use rustc::middle::def::Def;
 use rustc::middle::def_id::DefId;
@@ -110,6 +110,16 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
                 entry.insert(ConstQualif::empty());
             }
         }
+        if let Err(err) = eval_const_expr_partial(self.tcx, expr, ExprTypeChecked, None) {
+            match err.kind {
+                UnimplementedConstVal(_) => {},
+                IndexOpFeatureGated => {},
+                _ => self.tcx.sess.add_lint(CONST_ERR, expr.id, expr.span,
+                                         format!("constant evaluation error: {}. This will \
+                                                 become a HARD ERROR in the future",
+                                                 err.description())),
+            }
+        }
         self.with_mode(mode, |this| {
             this.with_euv(None, |euv| euv.consume_expr(expr));
             this.visit_expr(expr);
@@ -435,6 +445,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                             match eval_const_expr_partial(
                                     self.tcx, ex, ExprTypeChecked, None) {
                                 Ok(_) => {}
+                                Err(ConstEvalErr { kind: UnimplementedConstVal(_), ..}) |
                                 Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {},
                                 Err(msg) => {
                                     self.tcx.sess.add_lint(CONST_ERR, ex.id,
diff --git a/src/test/compile-fail/const-err-early.rs b/src/test/compile-fail/const-err-early.rs
new file mode 100644
index 00000000000..cdcdb919bde
--- /dev/null
+++ b/src/test/compile-fail/const-err-early.rs
@@ -0,0 +1,22 @@
+// Copyright 2016 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_indexing)]
+#![deny(const_err)]
+
+pub const A: i8 = -std::i8::MIN; //~ ERROR attempted to negate with overflow
+pub const B: u8 = 200u8 + 200u8; //~ ERROR attempted to add with overflow
+pub const C: u8 = 200u8 * 4; //~ ERROR attempted to multiply with overflow
+pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR attempted to subtract with overflow
+pub const E: u8 = [5u8][1]; //~ ERROR index out of bounds
+
+fn main() {
+    let _e = [6u8][1];
+}
diff --git a/src/test/compile-fail/const-err.rs b/src/test/compile-fail/const-err.rs
index 882e4cb2d47..45e8fc37d87 100644
--- a/src/test/compile-fail/const-err.rs
+++ b/src/test/compile-fail/const-err.rs
@@ -10,15 +10,11 @@
 
 #![feature(rustc_attrs)]
 #![allow(exceeding_bitshifts)]
-#![deny(const_err)]
 
 fn black_box<T>(_: T) {
     unimplemented!()
 }
 
-const BLA: u8 = 200u8 + 200u8;
-//~^ ERROR attempted to add with overflow
-
 #[rustc_no_mir] // FIXME #29769 MIR overflow checking is TBD.
 fn main() {
     let a = -std::i8::MIN;
@@ -30,7 +26,8 @@ fn main() {
     //~^ WARN attempted to multiply with overflow
     let d = 42u8 - (42u8 + 1);
     //~^ WARN attempted to subtract with overflow
-    let _e = BLA;
+    let _e = [5u8][1];
+    //~^ ERROR const index-expr is out of bounds
     black_box(a);
     black_box(b);
     black_box(c);
diff --git a/src/test/compile-fail/const-eval-span.rs b/src/test/compile-fail/const-eval-span.rs
index 44ab798f491..9fdd24c42fd 100644
--- a/src/test/compile-fail/const-eval-span.rs
+++ b/src/test/compile-fail/const-eval-span.rs
@@ -14,7 +14,7 @@
 struct S(i32);
 
 const CONSTANT: S = S(0);
-//~^ ERROR: constant evaluation error: call on struct [E0080]
+//~^ ERROR: unimplemented constant expression: tuple struct constructors [E0080]
 
 enum E {
     V = CONSTANT,
diff --git a/src/test/compile-fail/const-pattern-not-const-evaluable.rs b/src/test/compile-fail/const-pattern-not-const-evaluable.rs
index ecc43d21a46..4567cd4a74b 100644
--- a/src/test/compile-fail/const-pattern-not-const-evaluable.rs
+++ b/src/test/compile-fail/const-pattern-not-const-evaluable.rs
@@ -17,12 +17,12 @@ enum Cake {
 use Cake::*;
 
 const BOO: (Cake, Cake) = (Marmor, BlackForest);
-//~^ ERROR: constant evaluation error: non-constant path in constant expression [E0471]
+//~^ ERROR: constant evaluation error: unimplemented constant expression: enum variants [E0471]
 const FOO: Cake = BOO.1;
 
 const fn foo() -> Cake {
-    Marmor //~ ERROR: constant evaluation error: non-constant path in constant expression [E0471]
-    //~^ ERROR: non-constant path in constant expression
+    Marmor //~ ERROR: constant evaluation error: unimplemented constant expression: enum variants
+    //~^ ERROR: unimplemented constant expression: enum variants
 }
 
 const WORKS: Cake = Marmor;
diff --git a/src/test/compile-fail/feature-gate-negate-unsigned.rs b/src/test/compile-fail/feature-gate-negate-unsigned.rs
index 4330a4cbeab..93e09c6d8d2 100644
--- a/src/test/compile-fail/feature-gate-negate-unsigned.rs
+++ b/src/test/compile-fail/feature-gate-negate-unsigned.rs
@@ -17,7 +17,8 @@ impl std::ops::Neg for S {
 }
 
 const _MAX: usize = -1;
-//~^ ERROR unary negation of unsigned integer
+//~^ WARN unary negation of unsigned integer
+//~| ERROR unary negation of unsigned integer
 //~| HELP use a cast or the `!` operator
 
 fn main() {
diff --git a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
index a7cabae16be..9564a080b8e 100644
--- a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
+++ b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
@@ -15,5 +15,5 @@ enum State { ST_NULL, ST_WHITESPACE }
 
 fn main() {
     [State::ST_NULL; (State::ST_WHITESPACE as usize)];
-    //~^ ERROR expected constant integer for repeat count, but non-constant path
+    //~^ ERROR expected constant integer for repeat count, but unimplemented constant expression
 }