pub kind: ErrKind,
}
-#[derive(Clone, PartialEq)]
+#[derive(Clone)]
pub enum ErrKind {
CannotCast,
CannotCastTo(&'static str),
/// Expected, Got
TypeMismatch(String, ConstInt),
BadType(ConstVal),
+ ErroneousReferencedConstant(Box<ConstEvalErr>),
}
impl From<ConstMathErr> for ErrKind {
expected, got.description()).into_cow()
},
BadType(ref i) => format!("value of wrong type: {:?}", i).into_cow(),
+ ErroneousReferencedConstant(_) => "could not evaluate referenced constant".into_cow(),
}
}
}
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
} 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"));
}
#![feature(slice_patterns)]
#![feature(iter_arith)]
#![feature(question_mark)]
+#![feature(box_patterns)]
+#![feature(box_syntax)]
#[macro_use] extern crate syntax;
#[macro_use] extern crate log;
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, UnimplementedConstVal};
+use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
use rustc_const_eval::EvalHint::ExprTypeChecked;
use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
match err.kind {
UnimplementedConstVal(_) => {},
IndexOpFeatureGated => {},
+ ErroneousReferencedConstant(_) => {},
_ => self.tcx.sess.add_lint(CONST_ERR, expr.id, expr.span,
format!("constant evaluation error: {}. This will \
become a HARD ERROR in the future",
use middle::astconv_util::{prim_ty_to_ty, prohibit_type_params, prohibit_projection};
use middle::const_val::ConstVal;
-use rustc_const_eval::eval_const_expr_partial;
+use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
use rustc_const_eval::EvalHint::UncheckedExprHint;
+use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
use hir::def::{self, Def};
use hir::def_id::DefId;
use middle::resolve_lifetime as rl;
"expected usize value for array length, got {}", val.description());
this.tcx().types.err
},
- Err(ref r) => {
+ // array length errors happen before the global constant check
+ // so we need to report the real error
+ Err(ConstEvalErr { kind: ErroneousReferencedConstant(box r), ..}) |
+ Err(r) => {
let mut err = struct_span_err!(tcx.sess, r.span, E0250,
"array length constant evaluation error: {}",
r.description());
use middle::resolve_lifetime;
use middle::const_val::ConstVal;
use rustc_const_eval::EvalHint::UncheckedExprHint;
-use rustc_const_eval::eval_const_expr_partial;
+use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
+use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
print_err(tcx, e.span, ty_hint, cv);
None
},
+ // enum variant evaluation happens before the global constant check
+ // so we need to report the real error
+ Err(ConstEvalErr { kind: ErroneousReferencedConstant(box err), ..}) |
Err(err) => {
let mut diag = struct_span_err!(tcx.sess, err.span, E0080,
"constant evaluation error: {}",
--- /dev/null
+// 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.
+
+#![deny(const_err)]
+
+pub const A: i8 = -std::i8::MIN; //~ ERROR attempted to negate with overflow
+pub const B: i8 = A;
+pub const C: u8 = A as u8;
+pub const D: i8 = 50 - A;
+
+fn main() {
+}