about summary refs log tree commit diff
path: root/src/librustc_const_eval/eval.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc_const_eval/eval.rs')
-rw-r--r--src/librustc_const_eval/eval.rs24
1 files changed, 20 insertions, 4 deletions
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 45a90bf0068..3f68f6aecca 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -364,7 +364,7 @@ pub struct ConstEvalErr {
     pub kind: ErrKind,
 }
 
-#[derive(Clone, PartialEq)]
+#[derive(Clone)]
 pub enum ErrKind {
     CannotCast,
     CannotCastTo(&'static str),
@@ -414,6 +414,7 @@ pub enum ErrKind {
     /// Expected, Got
     TypeMismatch(String, ConstInt),
     BadType(ConstVal),
+    ErroneousReferencedConstant(Box<ConstEvalErr>),
 }
 
 impl From<ConstMathErr> for ErrKind {
@@ -480,6 +481,7 @@ impl ConstEvalErr {
                         expected, got.description()).into_cow()
             },
             BadType(ref i) => format!("value of wrong type: {:?}", i).into_cow(),
+            ErroneousReferencedConstant(_) => "could not evaluate referenced constant".into_cow(),
         }
     }
 }
@@ -696,6 +698,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
 
         let val = match eval_const_expr_partial(tcx, &base, base_hint, fn_args) {
             Ok(val) => val,
+            Err(ConstEvalErr { kind: ErroneousReferencedConstant(
+                box ConstEvalErr { kind: TypeMismatch(_, val), .. }), .. }) |
             Err(ConstEvalErr { kind: TypeMismatch(_, val), .. }) => {
                 // Something like `5i8 as usize` doesn't need a type hint for the base
                 // instead take the type hint from the inner value
@@ -737,19 +741,31 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
                   } else {
                       None
                   };
-                  if let Some((e, ty)) = lookup_const_by_id(tcx, def_id, substs) {
+                  if let Some((expr, ty)) = lookup_const_by_id(tcx, def_id, substs) {
                       let item_hint = match ty {
                           Some(ty) => ty_hint.checked_or(ty),
                           None => ty_hint,
                       };
-                      eval_const_expr_partial(tcx, e, item_hint, None)?
+                      match eval_const_expr_partial(tcx, expr, item_hint, None) {
+                          Ok(val) => val,
+                          Err(err) => {
+                              debug!("bad reference: {:?}, {:?}", err.description(), err.span);
+                              signal!(e, ErroneousReferencedConstant(box err))
+                          },
+                      }
                   } else {
                       signal!(e, NonConstPath);
                   }
               },
               Def::Variant(enum_def, variant_def) => {
                   if let Some(const_expr) = lookup_variant_by_id(tcx, enum_def, variant_def) {
-                      eval_const_expr_partial(tcx, const_expr, ty_hint, None)?
+                      match eval_const_expr_partial(tcx, const_expr, ty_hint, None) {
+                          Ok(val) => val,
+                          Err(err) => {
+                              debug!("bad reference: {:?}, {:?}", err.description(), err.span);
+                              signal!(e, ErroneousReferencedConstant(box err))
+                          },
+                      }
                   } else {
                       signal!(e, UnimplementedConstVal("enum variants"));
                   }