Report tcx errors with the span of the currently evaluating statement

This commit is contained in:
Oliver Schneider 2018-02-06 18:33:59 +01:00
parent 1e653aa96b
commit 2f0e077300
No known key found for this signature in database
GPG key ID: A69F8D225B3AD7D9
8 changed files with 41 additions and 65 deletions

View file

@ -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,

View file

@ -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()
}

View file

@ -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(),

View file

@ -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(),
)
}

View file

@ -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);

View file

@ -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,

View file

@ -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))?;

View file

@ -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(){}