Skip to content

Commit c14d33a

Browse files
committed
Report tcx errors with the span of the currently evaluating statement
1 parent 253ac3f commit c14d33a

File tree

9 files changed

+48
-70
lines changed

9 files changed

+48
-70
lines changed

src/librustc_mir/interpret/const_eval.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
2424
) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>> {
2525
debug!("mk_borrowck_eval_cx: {:?}", instance);
2626
let param_env = tcx.param_env(instance.def_id());
27-
let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, (), span);
27+
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
2828
// insert a stack frame so any queries have the correct substs
2929
ecx.push_stack_frame(
3030
instance,
@@ -43,7 +43,7 @@ pub fn mk_eval_cx<'a, 'tcx>(
4343
) -> EvalResult<'tcx, EvalContext<'a, 'tcx, 'tcx, CompileTimeEvaluator>> {
4444
debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
4545
let span = tcx.def_span(instance.def_id());
46-
let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, (), span);
46+
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
4747
let mir = ecx.load_mir(instance.def)?;
4848
// insert a stack frame so any queries have the correct substs
4949
ecx.push_stack_frame(
@@ -96,8 +96,9 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
9696
debug!("eval_body: {:?}, {:?}", cid, param_env);
9797
// we start out with the best span we have
9898
// and try improving it down the road when more information is available
99-
let mut span = tcx.def_span(cid.instance.def_id());
100-
let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, (), mir.map(|mir| mir.span).unwrap_or(span));
99+
let span = tcx.def_span(cid.instance.def_id());
100+
let mut span = mir.map(|mir| mir.span).unwrap_or(span);
101+
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
101102
let res = (|| {
102103
let mut mir = match mir {
103104
Some(mir) => mir,

src/librustc_mir/interpret/eval_context.rs

+18-46
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ use rustc::hir::def_id::DefId;
55
use rustc::hir::map::definitions::DefPathData;
66
use rustc::middle::const_val::{ConstVal, ErrKind};
77
use rustc::mir;
8-
use rustc::traits::Reveal;
98
use rustc::ty::layout::{self, Size, Align, HasDataLayout, LayoutOf, TyLayout};
10-
use rustc::ty::subst::{Subst, Substs, Kind};
9+
use rustc::ty::subst::{Subst, Substs};
1110
use rustc::ty::{self, Ty, TyCtxt};
11+
use rustc::ty::maps::TyCtxtAt;
1212
use rustc_data_structures::indexed_vec::Idx;
1313
use rustc::middle::const_val::FrameInfo;
14-
use syntax::codemap::{self, DUMMY_SP, Span};
14+
use syntax::codemap::{self, Span};
1515
use syntax::ast::Mutability;
1616
use rustc::mir::interpret::{
1717
GlobalId, Value, Pointer, PrimVal, PrimValKind,
@@ -27,7 +27,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
2727
pub machine: M,
2828

2929
/// The results of the type checker, from rustc.
30-
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
30+
pub tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
3131

3232
/// Bounds in scope for polymorphic evaluations.
3333
pub param_env: ty::ParamEnv<'tcx>,
@@ -45,11 +45,6 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
4545
/// This prevents infinite loops and huge computations from freezing up const eval.
4646
/// Remove once halting problem is solved.
4747
pub(crate) steps_remaining: usize,
48-
49-
/// The span that is used if no more stack frames are available
50-
///
51-
/// This happens after successful evaluation when the result is inspected
52-
root_span: codemap::Span,
5348
}
5449

5550
/// A stack frame.
@@ -154,15 +149,15 @@ impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout
154149
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> layout::HasTyCtxt<'tcx> for &'a EvalContext<'a, 'mir, 'tcx, M> {
155150
#[inline]
156151
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
157-
self.tcx
152+
*self.tcx
158153
}
159154
}
160155

161156
impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> layout::HasTyCtxt<'tcx>
162157
for &'c &'b mut EvalContext<'a, 'mir, 'tcx, M> {
163158
#[inline]
164159
fn tcx<'d>(&'d self) -> TyCtxt<'d, 'tcx, 'tcx> {
165-
self.tcx
160+
*self.tcx
166161
}
167162
}
168163

@@ -187,11 +182,10 @@ impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf<Ty<'tcx>>
187182

188183
impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
189184
pub fn new(
190-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
185+
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
191186
param_env: ty::ParamEnv<'tcx>,
192187
machine: M,
193188
memory_data: M::MemoryData,
194-
root_span: codemap::Span,
195189
) -> Self {
196190
EvalContext {
197191
machine,
@@ -201,7 +195,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
201195
stack: Vec::new(),
202196
stack_limit: tcx.sess.const_eval_stack_frame_limit.get(),
203197
steps_remaining: tcx.sess.const_eval_step_limit.get(),
204-
root_span,
205198
}
206199
}
207200

@@ -255,15 +248,15 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
255248
pub(super) fn resolve(&self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, ty::Instance<'tcx>> {
256249
let substs = self.tcx.trans_apply_param_substs(self.substs(), &substs);
257250
ty::Instance::resolve(
258-
self.tcx,
251+
*self.tcx,
259252
self.param_env,
260253
def_id,
261254
substs,
262255
).ok_or(EvalErrorKind::TypeckError.into()) // turn error prop into a panic to expose associated type in const issue
263256
}
264257

265258
pub(super) fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
266-
ty.is_sized(self.tcx, self.param_env, DUMMY_SP)
259+
ty.is_sized(*self.tcx, self.param_env, self.tcx.span)
267260
}
268261

269262
pub fn load_mir(
@@ -290,7 +283,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
290283
// miri doesn't care about lifetimes, and will choke on some crazy ones
291284
// let's simply get rid of them
292285
let without_lifetimes = self.tcx.erase_regions(&ty);
293-
let substituted = without_lifetimes.subst(self.tcx, substs);
286+
let substituted = without_lifetimes.subst(*self.tcx, substs);
294287
let substituted = self.tcx.fully_normalize_monormophic_ty(&substituted);
295288
substituted
296289
}
@@ -721,7 +714,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
721714
ty::TyClosure(def_id, substs) => {
722715
let substs = self.tcx.trans_apply_param_substs(self.substs(), &substs);
723716
let instance = ty::Instance::resolve_closure(
724-
self.tcx,
717+
*self.tcx,
725718
def_id,
726719
substs,
727720
ty::ClosureKind::FnOnce,
@@ -744,8 +737,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
744737
let place = self.eval_place(place)?;
745738
let discr_val = self.read_discriminant_value(place, ty)?;
746739
if let ty::TyAdt(adt_def, _) = ty.sty {
747-
trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(self.tcx).collect::<Vec<_>>());
748-
if adt_def.discriminants(self.tcx).all(|v| {
740+
trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(*self.tcx).collect::<Vec<_>>());
741+
if adt_def.discriminants(*self.tcx).all(|v| {
749742
discr_val != v.val
750743
})
751744
{
@@ -793,7 +786,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
793786

794787
pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> {
795788
use rustc::mir::Operand::*;
796-
let ty = self.monomorphize(op.ty(self.mir(), self.tcx), self.substs());
789+
let ty = self.monomorphize(op.ty(self.mir(), *self.tcx), self.substs());
797790
match *op {
798791
// FIXME: do some more logic on `move` to invalidate the old location
799792
Copy(ref place) |
@@ -901,7 +894,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
901894
}
902895
layout::Variants::Tagged { .. } => {
903896
let discr_val = dest_ty.ty_adt_def().unwrap()
904-
.discriminant_for_variant(self.tcx, variant_index)
897+
.discriminant_for_variant(*self.tcx, variant_index)
905898
.val;
906899

907900
let (discr_dest, discr) = self.place_field(dest, mir::Field::new(0), layout)?;
@@ -1408,7 +1401,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
14081401
}
14091402
(_, &ty::TyDynamic(ref data, _)) => {
14101403
let trait_ref = data.principal().unwrap().with_self_ty(
1411-
self.tcx,
1404+
*self.tcx,
14121405
src_pointee_ty,
14131406
);
14141407
let trait_ref = self.tcx.erase_regions(&trait_ref);
@@ -1597,18 +1590,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
15971590
};
15981591
frames.push(FrameInfo { span, location });
15991592
}
1600-
let span = if let Some(frame) = self.stack().last() {
1601-
let bb = &frame.mir.basic_blocks()[frame.block];
1602-
if let Some(stmt) = bb.statements.get(frame.stmt) {
1603-
stmt.source_info.span
1604-
} else {
1605-
bb.terminator().source_info.span
1606-
}
1607-
} else {
1608-
self.root_span
1609-
};
16101593
trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
1611-
(frames, span)
1594+
(frames, self.tcx.span)
16121595
}
16131596

16141597
pub fn report(&self, e: &mut EvalError, as_err: bool, explicit_span: Option<Span>) {
@@ -1656,7 +1639,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
16561639
});
16571640
trace!("reporting const eval failure at {:?}", span);
16581641
let mut err = if as_err {
1659-
::rustc::middle::const_val::struct_error(self.tcx, span, "constant evaluation error")
1642+
::rustc::middle::const_val::struct_error(*self.tcx, span, "constant evaluation error")
16601643
} else {
16611644
let node_id = self
16621645
.stack()
@@ -1718,14 +1701,3 @@ impl<'mir, 'tcx> Frame<'mir, 'tcx> {
17181701
return Ok(old);
17191702
}
17201703
}
1721-
1722-
// TODO(solson): Upstream these methods into rustc::ty::layout.
1723-
1724-
pub fn resolve_drop_in_place<'a, 'tcx>(
1725-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
1726-
ty: Ty<'tcx>,
1727-
) -> ty::Instance<'tcx> {
1728-
let def_id = tcx.require_lang_item(::rustc::middle::lang_items::DropInPlaceFnLangItem);
1729-
let substs = tcx.intern_substs(&[Kind::from(ty)]);
1730-
ty::Instance::resolve(tcx, ty::ParamEnv::empty(Reveal::All), def_id, substs).unwrap()
1731-
}

src/librustc_mir/interpret/memory.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian};
22
use std::collections::{btree_map, BTreeMap, HashMap, HashSet, VecDeque};
33
use std::{ptr, io};
44

5-
use rustc::ty::{Instance, TyCtxt};
5+
use rustc::ty::Instance;
6+
use rustc::ty::maps::TyCtxtAt;
67
use rustc::ty::layout::{self, Align, TargetDataLayout};
78
use syntax::ast::Mutability;
89

@@ -51,11 +52,11 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
5152
/// The current stack frame. Used to check accesses against locks.
5253
pub cur_frame: usize,
5354

54-
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
55+
pub tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
5556
}
5657

5758
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
58-
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
59+
pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
5960
Memory {
6061
data,
6162
alloc_kind: HashMap::new(),

src/librustc_mir/interpret/place.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
209209
extra: PlaceExtra::None,
210210
}
211211
} else {
212-
let instance = ty::Instance::mono(self.tcx, static_.def_id);
212+
let instance = ty::Instance::mono(*self.tcx, static_.def_id);
213213
let cid = GlobalId {
214214
instance,
215215
promoted: None
@@ -445,7 +445,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
445445

446446
pub fn place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
447447
self.monomorphize(
448-
place.ty(self.mir(), self.tcx).to_ty(self.tcx),
448+
place.ty(self.mir(), *self.tcx).to_ty(*self.tcx),
449449
self.substs(),
450450
)
451451
}

src/librustc_mir/interpret/step.rs

+4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
5151
// Some statements (e.g. box) push new stack frames. We have to record the stack frame number
5252
// *before* executing the statement.
5353
let frame_idx = self.cur_frame();
54+
self.tcx.span = stmt.source_info.span;
55+
self.memory.tcx.span = stmt.source_info.span;
5456

5557
match stmt.kind {
5658
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> {
99101

100102
fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx> {
101103
trace!("{:?}", terminator.kind);
104+
self.tcx.span = terminator.source_info.span;
105+
self.memory.tcx.span = terminator.source_info.span;
102106
self.eval_terminator(terminator)?;
103107
if !self.stack.is_empty() {
104108
trace!("// {:?}", self.frame().block);

src/librustc_mir/interpret/terminator/mod.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use syntax::codemap::Span;
55
use syntax::abi::Abi;
66

77
use rustc::mir::interpret::{EvalResult, PrimVal, Value};
8-
use super::{EvalContext, eval_context,
9-
Place, Machine, ValTy};
8+
use super::{EvalContext, Place, Machine, ValTy};
109

1110
use rustc_data_structures::indexed_vec::Idx;
1211
use interpret::memory::HasMemory;
@@ -72,10 +71,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
7271
ty::TyFnPtr(sig) => {
7372
let fn_ptr = self.value_to_primval(func)?.to_ptr()?;
7473
let instance = self.memory.get_fn(fn_ptr)?;
75-
let instance_ty = instance.ty(self.tcx);
74+
let instance_ty = instance.ty(*self.tcx);
7675
match instance_ty.sty {
7776
ty::TyFnDef(..) => {
78-
let real_sig = instance_ty.fn_sig(self.tcx);
77+
let real_sig = instance_ty.fn_sig(*self.tcx);
7978
let sig = self.tcx.erase_late_bound_regions_and_normalize(&sig);
8079
let real_sig = self.tcx.erase_late_bound_regions_and_normalize(&real_sig);
8180
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> {
8887
}
8988
ty::TyFnDef(def_id, substs) => (
9089
self.resolve(def_id, substs)?,
91-
func.ty.fn_sig(self.tcx),
90+
func.ty.fn_sig(*self.tcx),
9291
),
9392
_ => {
9493
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> {
117116
let ty = self.tcx.trans_apply_param_substs(self.substs(), &ty);
118117
trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
119118

120-
let instance = eval_context::resolve_drop_in_place(self.tcx, ty);
119+
let instance = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
121120
self.drop_place(
122121
place,
123122
instance,

src/librustc_mir/interpret/traits.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ use rustc::ty::layout::{Size, Align, LayoutOf};
33
use syntax::ast::Mutability;
44

55
use rustc::mir::interpret::{PrimVal, Value, MemoryPointer, EvalResult};
6-
use super::{EvalContext, eval_context,
7-
Machine};
6+
use super::{EvalContext, Machine};
87

98
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
109
/// 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> {
3433
None,
3534
)?;
3635

37-
let drop = eval_context::resolve_drop_in_place(self.tcx, ty);
36+
let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
3837
let drop = self.memory.create_fn_alloc(drop);
3938
self.memory.write_ptr_sized_unsigned(vtable, ptr_align, PrimVal::Ptr(drop))?;
4039

src/test/ui/infinite-recursion-const-fn.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
//https://github.com/rust-lang/rust/issues/31364
1212

1313
#![feature(const_fn)]
14-
const fn a() -> usize { b() }
15-
const fn b() -> usize { a() } //~ ERROR constant evaluation error
14+
const fn a() -> usize { b() } //~ ERROR constant evaluation error
15+
const fn b() -> usize { a() }
1616
const ARR: [i32; a()] = [5; 6];
1717

1818
fn main(){}

src/test/ui/infinite-recursion-const-fn.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
error[E0080]: constant evaluation error
2-
--> $DIR/infinite-recursion-const-fn.rs:15:25
2+
--> $DIR/infinite-recursion-const-fn.rs:14:25
33
|
4-
14 | const fn a() -> usize { b() }
5-
| --- inside call to `b`
6-
15 | const fn b() -> usize { a() } //~ ERROR constant evaluation error
4+
14 | const fn a() -> usize { b() } //~ ERROR constant evaluation error
75
| ^^^
86
| |
97
| reached the configured maximum number of stack frames
8+
| inside call to `b`
9+
15 | const fn b() -> usize { a() }
10+
| ---
11+
| |
1012
| inside call to `a`
1113
| inside call to `a`
1214
| inside call to `a`

0 commit comments

Comments
 (0)