Eliminate old CTFE's ErrKind

This commit is contained in:
Oliver Schneider 2018-06-19 16:40:53 +02:00
parent 58fdac638e
commit 6f8fe4eaef
10 changed files with 50 additions and 114 deletions

View File

@ -505,7 +505,7 @@ impl_stable_hash_for!(struct ty::Const<'tcx> {
impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
span,
kind
data
});
impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
@ -514,29 +514,6 @@ 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 });
@ -593,6 +570,8 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
ReadFromReturnPointer |
UnimplementedTraitSelection |
TypeckError |
ResolutionFailed |
CheckMatchError |
DerefFunctionPointer |
ExecuteMemory |
OverflowNeg |

View File

@ -33,16 +33,7 @@ pub enum ConstVal<'tcx> {
#[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)]
@ -69,25 +60,6 @@ impl<'a, 'tcx> ConstEvalErrDescription<'a, 'tcx> {
}
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)
@ -127,24 +99,19 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
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 {
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();
(miri.to_string(), frames)
},
_ => (miri.to_string(), frames),
_ => {},
}
}
_ => (self.description().into_oneline().to_string(), &[]),
};
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)
@ -159,8 +126,8 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
} 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)

View File

@ -150,6 +150,9 @@ pub enum EvalErrorKind<'tcx, O> {
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>),
@ -268,6 +271,10 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
"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",

View File

@ -16,7 +16,8 @@ use rustc_data_structures::obligation_forest::{Error, ForestObligation, Obligati
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;
@ -498,10 +499,11 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
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(),
}))
)
}

View File

@ -13,7 +13,7 @@
//! 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;
@ -462,10 +462,10 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
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())),
}
})
}
@ -577,6 +577,8 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> {
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),
@ -588,20 +590,6 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> {
}
}
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> {

View File

@ -1,6 +1,5 @@
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};
@ -18,7 +17,6 @@ use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory, Memo
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>,
@ -106,7 +104,7 @@ pub fn value_to_const_value<'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,
@ -467,9 +465,8 @@ pub fn const_val_field<'a, '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,
}
})
@ -540,7 +537,7 @@ pub fn const_eval_provider<'a, 'tcx>(
// 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,
});
}
@ -552,7 +549,7 @@ pub fn const_eval_provider<'a, 'tcx>(
// 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,
});
}
@ -566,9 +563,8 @@ pub fn const_eval_provider<'a, 'tcx>(
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() {

View File

@ -280,7 +280,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
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 {
@ -739,7 +739,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
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()),

View File

@ -285,10 +285,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
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,

View File

@ -1209,16 +1209,13 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
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 {
if let EvalErrorKind::ReferencedConstant(_) = err.data.0.kind {
err.report_as_error(
tcx.at(mir.promoted[i].span),
"erroneous constant used",
);
}
}
},
}
}

View File

@ -17,7 +17,7 @@ use rustc::mir::{Constant, Literal, Location, Place, Mir, Operand, Rvalue, Local
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;
@ -145,7 +145,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
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,