Report tcx errors with the span of the currently evaluating statement
This commit is contained in:
parent
1e653aa96b
commit
2f0e077300
8 changed files with 41 additions and 65 deletions
|
@ -24,7 +24,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
|
|||
) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>> {
|
||||
debug!("mk_borrowck_eval_cx: {:?}", instance);
|
||||
let param_env = tcx.param_env(instance.def_id());
|
||||
let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, (), span);
|
||||
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
|
||||
// insert a stack frame so any queries have the correct substs
|
||||
ecx.push_stack_frame(
|
||||
instance,
|
||||
|
@ -43,7 +43,7 @@ pub fn mk_eval_cx<'a, 'tcx>(
|
|||
) -> EvalResult<'tcx, EvalContext<'a, 'tcx, 'tcx, CompileTimeEvaluator>> {
|
||||
debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
|
||||
let span = tcx.def_span(instance.def_id());
|
||||
let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, (), span);
|
||||
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
|
||||
let mir = ecx.load_mir(instance.def)?;
|
||||
// insert a stack frame so any queries have the correct substs
|
||||
ecx.push_stack_frame(
|
||||
|
@ -96,8 +96,9 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
|
|||
debug!("eval_body: {:?}, {:?}", cid, param_env);
|
||||
// we start out with the best span we have
|
||||
// and try improving it down the road when more information is available
|
||||
let mut span = tcx.def_span(cid.instance.def_id());
|
||||
let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, (), mir.map(|mir| mir.span).unwrap_or(span));
|
||||
let span = tcx.def_span(cid.instance.def_id());
|
||||
let mut span = mir.map(|mir| mir.span).unwrap_or(span);
|
||||
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
|
||||
let res = (|| {
|
||||
let mut mir = match mir {
|
||||
Some(mir) => mir,
|
||||
|
|
|
@ -5,13 +5,13 @@ use rustc::hir::def_id::DefId;
|
|||
use rustc::hir::map::definitions::DefPathData;
|
||||
use rustc::middle::const_val::{ConstVal, ErrKind};
|
||||
use rustc::mir;
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::ty::layout::{self, Size, Align, HasDataLayout, LayoutOf, TyLayout};
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::maps::TyCtxtAt;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc::middle::const_val::FrameInfo;
|
||||
use syntax::codemap::{self, DUMMY_SP, Span};
|
||||
use syntax::codemap::{self, Span};
|
||||
use syntax::ast::Mutability;
|
||||
use rustc::mir::interpret::{
|
||||
GlobalId, Value, Pointer, PrimVal, PrimValKind,
|
||||
|
@ -27,7 +27,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
|
|||
pub machine: M,
|
||||
|
||||
/// The results of the type checker, from rustc.
|
||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
|
||||
/// Bounds in scope for polymorphic evaluations.
|
||||
pub param_env: ty::ParamEnv<'tcx>,
|
||||
|
@ -45,11 +45,6 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
|
|||
/// This prevents infinite loops and huge computations from freezing up const eval.
|
||||
/// Remove once halting problem is solved.
|
||||
pub(crate) steps_remaining: usize,
|
||||
|
||||
/// The span that is used if no more stack frames are available
|
||||
///
|
||||
/// This happens after successful evaluation when the result is inspected
|
||||
root_span: codemap::Span,
|
||||
}
|
||||
|
||||
/// A stack frame.
|
||||
|
@ -154,7 +149,7 @@ impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout
|
|||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> layout::HasTyCtxt<'tcx> for &'a EvalContext<'a, 'mir, 'tcx, M> {
|
||||
#[inline]
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||
self.tcx
|
||||
*self.tcx
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,7 +157,7 @@ impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> layout::HasTyCtxt<'tcx>
|
|||
for &'c &'b mut EvalContext<'a, 'mir, 'tcx, M> {
|
||||
#[inline]
|
||||
fn tcx<'d>(&'d self) -> TyCtxt<'d, 'tcx, 'tcx> {
|
||||
self.tcx
|
||||
*self.tcx
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,11 +182,10 @@ impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf<Ty<'tcx>>
|
|||
|
||||
impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
machine: M,
|
||||
memory_data: M::MemoryData,
|
||||
root_span: codemap::Span,
|
||||
) -> Self {
|
||||
EvalContext {
|
||||
machine,
|
||||
|
@ -201,7 +195,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
stack: Vec::new(),
|
||||
stack_limit: tcx.sess.const_eval_stack_frame_limit.get(),
|
||||
steps_remaining: tcx.sess.const_eval_step_limit.get(),
|
||||
root_span,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +248,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
pub(super) fn resolve(&self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, ty::Instance<'tcx>> {
|
||||
let substs = self.tcx.trans_apply_param_substs(self.substs(), &substs);
|
||||
ty::Instance::resolve(
|
||||
self.tcx,
|
||||
*self.tcx,
|
||||
self.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
|
@ -263,7 +256,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
}
|
||||
|
||||
pub(super) fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
|
||||
ty.is_sized(self.tcx.at(DUMMY_SP), self.param_env)
|
||||
ty.is_sized(self.tcx, self.param_env)
|
||||
}
|
||||
|
||||
pub fn load_mir(
|
||||
|
@ -290,7 +283,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
// miri doesn't care about lifetimes, and will choke on some crazy ones
|
||||
// let's simply get rid of them
|
||||
let without_lifetimes = self.tcx.erase_regions(&ty);
|
||||
let substituted = without_lifetimes.subst(self.tcx, substs);
|
||||
let substituted = without_lifetimes.subst(*self.tcx, substs);
|
||||
let substituted = self.tcx.fully_normalize_monormophic_ty(&substituted);
|
||||
substituted
|
||||
}
|
||||
|
@ -725,7 +718,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
ty::TyClosure(def_id, substs) => {
|
||||
let substs = self.tcx.trans_apply_param_substs(self.substs(), &substs);
|
||||
let instance = ty::Instance::resolve_closure(
|
||||
self.tcx,
|
||||
*self.tcx,
|
||||
def_id,
|
||||
substs,
|
||||
ty::ClosureKind::FnOnce,
|
||||
|
@ -748,8 +741,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
let place = self.eval_place(place)?;
|
||||
let discr_val = self.read_discriminant_value(place, ty)?;
|
||||
if let ty::TyAdt(adt_def, _) = ty.sty {
|
||||
trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(self.tcx).collect::<Vec<_>>());
|
||||
if adt_def.discriminants(self.tcx).all(|v| {
|
||||
trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(*self.tcx).collect::<Vec<_>>());
|
||||
if adt_def.discriminants(*self.tcx).all(|v| {
|
||||
discr_val != v.val
|
||||
})
|
||||
{
|
||||
|
@ -797,7 +790,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
|
||||
pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> {
|
||||
use rustc::mir::Operand::*;
|
||||
let ty = self.monomorphize(op.ty(self.mir(), self.tcx), self.substs());
|
||||
let ty = self.monomorphize(op.ty(self.mir(), *self.tcx), self.substs());
|
||||
match *op {
|
||||
// FIXME: do some more logic on `move` to invalidate the old location
|
||||
Copy(ref place) |
|
||||
|
@ -905,7 +898,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
}
|
||||
layout::Variants::Tagged { .. } => {
|
||||
let discr_val = dest_ty.ty_adt_def().unwrap()
|
||||
.discriminant_for_variant(self.tcx, variant_index)
|
||||
.discriminant_for_variant(*self.tcx, variant_index)
|
||||
.val;
|
||||
|
||||
let (discr_dest, discr) = self.place_field(dest, mir::Field::new(0), layout)?;
|
||||
|
@ -1412,7 +1405,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
}
|
||||
(_, &ty::TyDynamic(ref data, _)) => {
|
||||
let trait_ref = data.principal().unwrap().with_self_ty(
|
||||
self.tcx,
|
||||
*self.tcx,
|
||||
src_pointee_ty,
|
||||
);
|
||||
let trait_ref = self.tcx.erase_regions(&trait_ref);
|
||||
|
@ -1601,18 +1594,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
};
|
||||
frames.push(FrameInfo { span, location });
|
||||
}
|
||||
let span = if let Some(frame) = self.stack().last() {
|
||||
let bb = &frame.mir.basic_blocks()[frame.block];
|
||||
if let Some(stmt) = bb.statements.get(frame.stmt) {
|
||||
stmt.source_info.span
|
||||
} else {
|
||||
bb.terminator().source_info.span
|
||||
}
|
||||
} else {
|
||||
self.root_span
|
||||
};
|
||||
trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
|
||||
(frames, span)
|
||||
(frames, self.tcx.span)
|
||||
}
|
||||
|
||||
pub fn report(&self, e: &mut EvalError, as_err: bool, explicit_span: Option<Span>) {
|
||||
|
@ -1660,7 +1643,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
});
|
||||
trace!("reporting const eval failure at {:?}", span);
|
||||
let mut err = if as_err {
|
||||
::rustc::middle::const_val::struct_error(self.tcx, span, "constant evaluation error")
|
||||
::rustc::middle::const_val::struct_error(*self.tcx, span, "constant evaluation error")
|
||||
} else {
|
||||
let node_id = self
|
||||
.stack()
|
||||
|
@ -1722,14 +1705,3 @@ impl<'mir, 'tcx> Frame<'mir, 'tcx> {
|
|||
return Ok(old);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(solson): Upstream these methods into rustc::ty::layout.
|
||||
|
||||
pub fn resolve_drop_in_place<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> ty::Instance<'tcx> {
|
||||
let def_id = tcx.require_lang_item(::rustc::middle::lang_items::DropInPlaceFnLangItem);
|
||||
let substs = tcx.intern_substs(&[ty.into()]);
|
||||
ty::Instance::resolve(tcx, ty::ParamEnv::empty(Reveal::All), def_id, substs).unwrap()
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian};
|
|||
use std::collections::{btree_map, BTreeMap, HashMap, HashSet, VecDeque};
|
||||
use std::{ptr, io};
|
||||
|
||||
use rustc::ty::{Instance, TyCtxt};
|
||||
use rustc::ty::Instance;
|
||||
use rustc::ty::maps::TyCtxtAt;
|
||||
use rustc::ty::layout::{self, Align, TargetDataLayout};
|
||||
use syntax::ast::Mutability;
|
||||
|
||||
|
@ -51,11 +52,11 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
|
|||
/// The current stack frame. Used to check accesses against locks.
|
||||
pub cur_frame: usize,
|
||||
|
||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
|
||||
pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
|
||||
Memory {
|
||||
data,
|
||||
alloc_kind: HashMap::new(),
|
||||
|
|
|
@ -209,7 +209,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
|||
extra: PlaceExtra::None,
|
||||
}
|
||||
} else {
|
||||
let instance = ty::Instance::mono(self.tcx, static_.def_id);
|
||||
let instance = ty::Instance::mono(*self.tcx, static_.def_id);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
|
@ -445,7 +445,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
|||
|
||||
pub fn place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
|
||||
self.monomorphize(
|
||||
place.ty(self.mir(), self.tcx).to_ty(self.tcx),
|
||||
place.ty(self.mir(), *self.tcx).to_ty(*self.tcx),
|
||||
self.substs(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -51,6 +51,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
|||
// Some statements (e.g. box) push new stack frames. We have to record the stack frame number
|
||||
// *before* executing the statement.
|
||||
let frame_idx = self.cur_frame();
|
||||
self.tcx.span = stmt.source_info.span;
|
||||
self.memory.tcx.span = stmt.source_info.span;
|
||||
|
||||
match stmt.kind {
|
||||
Assign(ref place, ref rvalue) => self.eval_rvalue_into_place(rvalue, place)?,
|
||||
|
@ -99,6 +101,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
|||
|
||||
fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx> {
|
||||
trace!("{:?}", terminator.kind);
|
||||
self.tcx.span = terminator.source_info.span;
|
||||
self.memory.tcx.span = terminator.source_info.span;
|
||||
self.eval_terminator(terminator)?;
|
||||
if !self.stack.is_empty() {
|
||||
trace!("// {:?}", self.frame().block);
|
||||
|
|
|
@ -5,8 +5,7 @@ use syntax::codemap::Span;
|
|||
use syntax::abi::Abi;
|
||||
|
||||
use rustc::mir::interpret::{EvalResult, PrimVal, Value};
|
||||
use super::{EvalContext, eval_context,
|
||||
Place, Machine, ValTy};
|
||||
use super::{EvalContext, Place, Machine, ValTy};
|
||||
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use interpret::memory::HasMemory;
|
||||
|
@ -72,10 +71,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
|||
ty::TyFnPtr(sig) => {
|
||||
let fn_ptr = self.value_to_primval(func)?.to_ptr()?;
|
||||
let instance = self.memory.get_fn(fn_ptr)?;
|
||||
let instance_ty = instance.ty(self.tcx);
|
||||
let instance_ty = instance.ty(*self.tcx);
|
||||
match instance_ty.sty {
|
||||
ty::TyFnDef(..) => {
|
||||
let real_sig = instance_ty.fn_sig(self.tcx);
|
||||
let real_sig = instance_ty.fn_sig(*self.tcx);
|
||||
let sig = self.tcx.erase_late_bound_regions_and_normalize(&sig);
|
||||
let real_sig = self.tcx.erase_late_bound_regions_and_normalize(&real_sig);
|
||||
if !self.check_sig_compat(sig, real_sig)? {
|
||||
|
@ -88,7 +87,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
|||
}
|
||||
ty::TyFnDef(def_id, substs) => (
|
||||
self.resolve(def_id, substs)?,
|
||||
func.ty.fn_sig(self.tcx),
|
||||
func.ty.fn_sig(*self.tcx),
|
||||
),
|
||||
_ => {
|
||||
let msg = format!("can't handle callee of type {:?}", func.ty);
|
||||
|
@ -117,7 +116,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
|||
let ty = self.tcx.trans_apply_param_substs(self.substs(), &ty);
|
||||
trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
|
||||
|
||||
let instance = eval_context::resolve_drop_in_place(self.tcx, ty);
|
||||
let instance = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
|
||||
self.drop_place(
|
||||
place,
|
||||
instance,
|
||||
|
|
|
@ -3,8 +3,7 @@ use rustc::ty::layout::{Size, Align, LayoutOf};
|
|||
use syntax::ast::Mutability;
|
||||
|
||||
use rustc::mir::interpret::{PrimVal, Value, MemoryPointer, EvalResult};
|
||||
use super::{EvalContext, eval_context,
|
||||
Machine};
|
||||
use super::{EvalContext, Machine};
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for
|
||||
|
@ -34,7 +33,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
|||
None,
|
||||
)?;
|
||||
|
||||
let drop = eval_context::resolve_drop_in_place(self.tcx, ty);
|
||||
let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
|
||||
let drop = self.memory.create_fn_alloc(drop);
|
||||
self.memory.write_ptr_sized_unsigned(vtable, ptr_align, PrimVal::Ptr(drop))?;
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
//https://github.com/rust-lang/rust/issues/31364
|
||||
|
||||
#![feature(const_fn)]
|
||||
const fn a() -> usize { b() }
|
||||
const fn b() -> usize { a() } //~ ERROR constant evaluation error
|
||||
const fn a() -> usize { b() } //~ ERROR constant evaluation error
|
||||
const fn b() -> usize { a() }
|
||||
const ARR: [i32; a()] = [5; 6];
|
||||
|
||||
fn main(){}
|
||||
|
|
Loading…
Add table
Reference in a new issue