impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
span,
- kind
+ data
});
impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
location
});
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for ::middle::const_val::ErrKind<'gcx> {
- fn hash_stable<W: StableHasherResult>(&self,
- hcx: &mut StableHashingContext<'a>,
- hasher: &mut StableHasher<W>) {
- use middle::const_val::ErrKind::*;
-
- mem::discriminant(self).hash_stable(hcx, hasher);
-
- match *self {
- TypeckError |
- CouldNotResolve |
- CheckMatchError => {
- // nothing to do
- }
- Miri(ref err, ref trace) => {
- err.hash_stable(hcx, hasher);
- trace.hash_stable(hcx, hasher);
- },
- }
- }
-}
-
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
impl_stable_hash_for!(struct ty::GeneratorSubsts<'tcx> { substs });
ReadFromReturnPointer |
UnimplementedTraitSelection |
TypeckError |
+ ResolutionFailed |
+ CheckMatchError |
DerefFunctionPointer |
ExecuteMemory |
OverflowNeg |
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ConstEvalErr<'tcx> {
pub span: Span,
- pub kind: Lrc<ErrKind<'tcx>>,
-}
-
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub enum ErrKind<'tcx> {
-
- CouldNotResolve,
- TypeckError,
- CheckMatchError,
- Miri(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>),
+ pub data: Lrc<(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>)>,
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
}
impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
- pub fn description(&'a self) -> ConstEvalErrDescription<'a, 'tcx> {
- use self::ErrKind::*;
- use self::ConstEvalErrDescription::*;
-
- macro_rules! simple {
- ($msg:expr) => ({ Simple($msg.into_cow()) });
- ($fmt:expr, $($arg:tt)+) => ({
- Simple(format!($fmt, $($arg)+).into_cow())
- })
- }
-
- match *self.kind {
- CouldNotResolve => simple!("could not resolve"),
- TypeckError => simple!("type-checking failed"),
- CheckMatchError => simple!("match-checking failed"),
- Miri(ref err, ref trace) => Backtrace(err, trace),
- }
- }
-
pub fn struct_error(&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str)
message: &str,
lint_root: Option<ast::NodeId>,
) -> Option<DiagnosticBuilder<'tcx>> {
- let (msg, frames): (_, &[_]) = match *self.kind {
- ErrKind::TypeckError | ErrKind::CheckMatchError => return None,
- ErrKind::Miri(ref miri, ref frames) => {
- match miri.kind {
- ::mir::interpret::EvalErrorKind::TypeckError |
- ::mir::interpret::EvalErrorKind::Layout(_) => return None,
- ::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
- inner.struct_generic(tcx, "referenced constant", lint_root)?.emit();
- (miri.to_string(), frames)
- },
- _ => (miri.to_string(), frames),
- }
- }
- _ => (self.description().into_oneline().to_string(), &[]),
- };
+ match self.data.0.kind {
+ ::mir::interpret::EvalErrorKind::TypeckError |
+ ::mir::interpret::EvalErrorKind::ResolutionFailed |
+ ::mir::interpret::EvalErrorKind::CheckMatchError |
+ ::mir::interpret::EvalErrorKind::Layout(_) => return None,
+ ::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
+ inner.struct_generic(tcx, "referenced constant", lint_root)?.emit();
+ },
+ _ => {},
+ }
trace!("reporting const eval failure at {:?}", self.span);
let mut err = if let Some(lint_root) = lint_root {
- let node_id = frames
+ let node_id = self.data.1
.iter()
.rev()
.filter_map(|frame| frame.lint_root)
} else {
struct_error(tcx, message)
};
- err.span_label(self.span, msg);
- for FrameInfo { span, location, .. } in frames {
+ err.span_label(self.span, self.data.0.to_string());
+ for FrameInfo { span, location, .. } in &self.data.1 {
err.span_label(*span, format!("inside call to `{}`", location));
}
Some(err)
UnimplementedTraitSelection,
/// Abort in case type errors are reached
TypeckError,
+ /// Resolution can fail if we are in a too generic context
+ ResolutionFailed,
+ CheckMatchError,
/// Cannot compute this constant because it depends on another one
/// which already produced an error
ReferencedConstant(ConstEvalErr<'tcx>),
"there were unresolved type arguments during trait selection",
TypeckError =>
"encountered constants with type errors, stopping evaluation",
+ ResolutionFailed =>
+ "encountered overly generic constant",
+ CheckMatchError =>
+ "match checking failed",
ReferencedConstant(_) =>
"referenced constant has errors",
Overflow(mir::BinOp::Add) => "attempt to add with overflow",
use rustc_data_structures::obligation_forest::{ObligationProcessor, ProcessResult};
use std::marker::PhantomData;
use hir::def_id::DefId;
-use middle::const_val::{ConstEvalErr, ErrKind};
+use middle::const_val::ConstEvalErr;
+use mir::interpret::EvalErrorKind;
use super::CodeAmbiguity;
use super::CodeProjectionError;
CodeSelectionError(ConstEvalFailure(err)))
}
} else {
+ let err = EvalErrorKind::ResolutionFailed.into();
ProcessResult::Error(
CodeSelectionError(ConstEvalFailure(ConstEvalErr {
span: obligation.cause.span,
- kind: ErrKind::CouldNotResolve.into(),
+ data: (err, Vec::new()).into(),
}))
)
}
//! hand, though we've recently added some macros (e.g.,
//! `BraceStructLiftImpl!`) to help with the tedium.
-use middle::const_val::{self, ConstVal, ConstEvalErr};
+use middle::const_val::{ConstVal, ConstEvalErr};
use ty::{self, Lift, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc_data_structures::accumulate_vec::AccumulateVec;
impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> {
type Lifted = ConstEvalErr<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- tcx.lift(&*self.kind).map(|kind| {
+ tcx.lift(&self.data.0).map(|data| {
ConstEvalErr {
span: self.span,
- kind: Lrc::new(kind),
+ data: Lrc::new((data, self.data.1.clone())),
}
})
}
PathNotFound(ref v) => PathNotFound(v.clone()),
UnimplementedTraitSelection => UnimplementedTraitSelection,
TypeckError => TypeckError,
+ ResolutionFailed => ResolutionFailed,
+ CheckMatchError => CheckMatchError,
ReferencedConstant(ref err) => ReferencedConstant(tcx.lift(err)?),
OverflowNeg => OverflowNeg,
Overflow(op) => Overflow(op),
}
}
-impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> {
- type Lifted = const_val::ErrKind<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- use middle::const_val::ErrKind::*;
-
- Some(match *self {
- CouldNotResolve => CouldNotResolve,
- TypeckError => TypeckError,
- CheckMatchError => CheckMatchError,
- Miri(ref e, ref frames) => return tcx.lift(e).map(|e| Miri(e, frames.clone())),
- })
- }
-}
-
impl<'a, 'tcx> Lift<'tcx> for ty::layout::LayoutError<'a> {
type Lifted = ty::layout::LayoutError<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
use rustc::hir;
-use rustc::middle::const_val::{ConstEvalErr, ErrKind};
-use rustc::middle::const_val::ErrKind::{TypeckError, CheckMatchError};
+use rustc::middle::const_val::{ConstEvalErr};
use rustc::mir;
use rustc::ty::{self, TyCtxt, Ty, Instance};
use rustc::ty::layout::{self, LayoutOf, Primitive};
use std::fmt;
use std::error::Error;
-use rustc_data_structures::sync::Lrc;
pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
let (frames, span) = ecx.generate_stacktrace(None);
let err = ConstEvalErr {
span,
- kind: ErrKind::Miri(err, frames).into(),
+ data: (err, frames).into(),
};
err.report_as_error(
ecx.tcx,
})();
result.map_err(|err| {
let (trace, span) = ecx.generate_stacktrace(None);
- let err = ErrKind::Miri(err, trace);
ConstEvalErr {
- kind: err.into(),
+ data: (err, trace).into(),
span,
}
})
// Do match-check before building MIR
if tcx.check_match(def_id).is_err() {
return Err(ConstEvalErr {
- kind: Lrc::new(CheckMatchError),
+ data: (EvalErrorKind::CheckMatchError.into(), Vec::new()).into(),
span,
});
}
// Do not continue into miri if typeck errors occurred; it will fail horribly
if tables.tainted_by_errors {
return Err(ConstEvalErr {
- kind: Lrc::new(TypeckError),
+ data: (EvalErrorKind::TypeckError.into(), Vec::new()).into(),
span,
});
}
Ok(value_to_const_value(&ecx, val, miri_ty))
}).map_err(|err| {
let (trace, span) = ecx.generate_stacktrace(None);
- let err = ErrKind::Miri(err, trace);
let err = ConstEvalErr {
- kind: err.into(),
+ data: (err, trace).into(),
span,
};
if tcx.is_static(def_id).is_some() {
self.param_env,
def_id,
substs,
- ).ok_or_else(|| EvalErrorKind::TypeckError.into()) // turn error prop into a panic to expose associated type in const issue
+ ).ok_or_else(|| EvalErrorKind::ResolutionFailed.into())
}
pub(super) fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
self.param_env,
def_id,
substs,
- ).ok_or_else(|| EvalErrorKind::TypeckError.into());
+ ).ok_or_else(|| EvalErrorKind::ResolutionFailed.into());
let fn_ptr = self.memory.create_fn_alloc(instance?);
let valty = ValTy {
value: Value::Scalar(fn_ptr.into()),
instance,
promoted: None,
};
- self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|_| {
+ self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
// no need to report anything, the const_eval call takes care of that for statics
assert!(self.tcx.is_static(def_id).is_some());
- EvalErrorKind::TypeckError.into()
+ EvalErrorKind::ReferencedConstant(err).into()
}).map(|val| {
let const_val = match val.val {
ConstVal::Value(val) => val,
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => collect_const(tcx, val, instance.substs, output),
Err(err) => {
- use rustc::middle::const_val::ErrKind;
use rustc::mir::interpret::EvalErrorKind;
- if let ErrKind::Miri(ref miri, ..) = *err.kind {
- if let EvalErrorKind::ReferencedConstant(_) = miri.kind {
- err.report_as_error(
- tcx.at(mir.promoted[i].span),
- "erroneous constant used",
- );
- }
+ if let EvalErrorKind::ReferencedConstant(_) = err.data.0.kind {
+ err.report_as_error(
+ tcx.at(mir.promoted[i].span),
+ "erroneous constant used",
+ );
}
},
}
use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
use rustc::mir::visit::{Visitor, PlaceContext};
-use rustc::middle::const_val::{ConstVal, ConstEvalErr, ErrKind};
+use rustc::middle::const_val::{ConstVal, ConstEvalErr};
use rustc::ty::{TyCtxt, self, Instance};
use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult};
use interpret::EvalContext;
let (frames, span) = self.ecx.generate_stacktrace(None);
let err = ConstEvalErr {
span,
- kind: ErrKind::Miri(err, frames).into(),
+ data: (err, frames).into(),
};
err.report_as_lint(
self.ecx.tcx,