Skip to content

Commit bd69f9e

Browse files
committed
Use the correct spans for const error reporting
1 parent 0b04b64 commit bd69f9e

File tree

5 files changed

+44
-36
lines changed

5 files changed

+44
-36
lines changed

src/librustc_mir/interpret/const_eval.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
1919
tcx: TyCtxt<'a, 'tcx, 'tcx>,
2020
instance: Instance<'tcx>,
2121
mir: &'mir mir::Mir<'tcx>,
22+
span: Span,
2223
) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>> {
2324
debug!("mk_borrowck_eval_cx: {:?}", instance);
2425
let param_env = tcx.param_env(instance.def_id());
@@ -27,7 +28,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
2728
// insert a stack frame so any queries have the correct substs
2829
ecx.push_stack_frame(
2930
instance,
30-
mir.span,
31+
span,
3132
mir,
3233
Place::undef(),
3334
StackPopCleanup::None,
@@ -65,7 +66,7 @@ pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
6566
match res {
6667
Ok(val) => Some(val),
6768
Err(mut err) => {
68-
ecx.report(&mut err, true);
69+
ecx.report(&mut err, true, None);
6970
None
7071
}
7172
}
@@ -80,7 +81,7 @@ pub fn eval_body<'a, 'tcx>(
8081
match res {
8182
Ok(val) => Some(val),
8283
Err(mut err) => {
83-
ecx.report(&mut err, true);
84+
ecx.report(&mut err, true, None);
8485
None
8586
}
8687
}
@@ -477,7 +478,7 @@ pub fn const_eval_provider<'a, 'tcx>(
477478
})
478479
}).map_err(|mut err| {
479480
if tcx.is_static(def_id).is_some() {
480-
ecx.report(&mut err, true);
481+
ecx.report(&mut err, true, None);
481482
}
482483
ConstEvalErr {
483484
kind: err.into(),

src/librustc_mir/interpret/eval_context.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc::ty::layout::{self, Size, Align, HasDataLayout, LayoutOf, TyLayout};
1010
use rustc::ty::subst::{Subst, Substs, Kind};
1111
use rustc::ty::{self, Ty, TyCtxt};
1212
use rustc_data_structures::indexed_vec::Idx;
13-
use syntax::codemap::{self, DUMMY_SP};
13+
use syntax::codemap::{self, DUMMY_SP, Span};
1414
use syntax::ast::Mutability;
1515
use rustc::mir::interpret::{
1616
GlobalId, Value, Pointer, PrimVal, PrimValKind,
@@ -1568,7 +1568,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
15681568
Ok(())
15691569
}
15701570

1571-
pub fn report(&self, e: &mut EvalError, as_err: bool) {
1571+
pub fn report(&self, e: &mut EvalError, as_err: bool, explicit_span: Option<Span>) {
15721572
if let EvalErrorKind::TypeckError = e.kind {
15731573
return;
15741574
}
@@ -1604,11 +1604,12 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
16041604
}
16051605
if let Some(frame) = self.stack().last() {
16061606
let block = &frame.mir.basic_blocks()[frame.block];
1607-
let span = if frame.stmt < block.statements.len() {
1607+
let span = explicit_span.unwrap_or_else(|| if frame.stmt < block.statements.len() {
16081608
block.statements[frame.stmt].source_info.span
16091609
} else {
16101610
block.terminator().source_info.span
1611-
};
1611+
});
1612+
trace!("reporting const eval failure at {:?}", span);
16121613
let node_id = self
16131614
.stack()
16141615
.iter()
@@ -1630,6 +1631,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
16301631
let mut last_span = None;
16311632
for &Frame { instance, span, .. } in self.stack().iter().rev() {
16321633
// make sure we don't emit frames that are duplicates of the previous
1634+
if explicit_span == Some(span) {
1635+
continue;
1636+
}
16331637
if let Some(last) = last_span {
16341638
if last == span {
16351639
continue;

src/librustc_mir/transform/instcombine.rs

+26-26
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use rustc_data_structures::indexed_vec::Idx;
2323
use std::mem;
2424
use std::collections::VecDeque;
2525
use transform::{MirPass, MirSource};
26-
use syntax::codemap::{Span, DUMMY_SP};
26+
use syntax::codemap::Span;
2727
use rustc_data_structures::control_flow_graph::ControlFlowGraph;
2828
use rustc::ty::subst::Substs;
2929

@@ -147,7 +147,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for InstCombineVisitor<'a, 'tcx> {
147147
TerminatorKind::SwitchInt { discr: value, .. } |
148148
TerminatorKind::Yield { value, .. } |
149149
TerminatorKind::Assert { cond: value, .. } => {
150-
if let Some((new, ty, span)) = self.optimizations.const_prop.remove(&location) {
150+
if let Some((new, ty, span)) = self.optimizations.terminators.remove(&block) {
151151
let new = self.tcx.mk_const(ty::Const {
152152
val: ConstVal::Value(new),
153153
ty,
@@ -190,13 +190,13 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
190190
}
191191
}
192192

193-
fn eval_constant(&mut self, c: &Constant<'tcx>, span: Span) -> Option<Const<'tcx>> {
193+
fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
194194
if let Some(&val) = self.optimizations.constants.get(c) {
195195
return Some(val);
196196
}
197197
match c.literal {
198198
Literal::Value { value } => match value.val {
199-
ConstVal::Value(v) => Some((v, value.ty, span)),
199+
ConstVal::Value(v) => Some((v, value.ty, c.span)),
200200
ConstVal::Unevaluated(did, substs) => {
201201
let param_env = self.tcx.param_env(self.source.def_id);
202202
let span = self.tcx.def_span(did);
@@ -230,20 +230,19 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
230230
instance,
231231
promoted: Some(index),
232232
};
233-
let span = self.tcx.def_span(self.source.def_id);
234233
let param_env = self.tcx.param_env(self.source.def_id);
235234
let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, param_env)?;
236-
let val = (value, ty, span);
235+
let val = (value, ty, c.span);
237236
trace!("evaluated {:?} to {:?}", c, val);
238237
self.optimizations.constants.insert(c.clone(), val);
239238
Some(val)
240239
}
241240
}
242241
}
243242

244-
fn eval_operand(&mut self, op: &Operand<'tcx>, span: Span) -> Option<Const<'tcx>> {
243+
fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> {
245244
match *op {
246-
Operand::Constant(ref c) => self.eval_constant(c, span),
245+
Operand::Constant(ref c) => self.eval_constant(c),
247246
Operand::Move(ref place) | Operand::Copy(ref place) => match *place {
248247
Place::Local(loc) => self.optimizations.places.get(&loc).cloned(),
249248
// FIXME(oli-obk): field and index projections
@@ -253,13 +252,13 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
253252
}
254253
}
255254

256-
fn simplify_operand(&mut self, op: &Operand<'tcx>, span: Span) -> Option<Const<'tcx>> {
255+
fn simplify_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> {
257256
match *op {
258257
Operand::Constant(ref c) => match c.literal {
259258
Literal::Value { .. } => None,
260-
_ => self.eval_operand(op, span),
259+
_ => self.eval_operand(op),
261260
},
262-
_ => self.eval_operand(op, span),
261+
_ => self.eval_operand(op),
263262
}
264263
}
265264

@@ -270,7 +269,7 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
270269
span: Span,
271270
) -> Option<Const<'tcx>> {
272271
match *rvalue {
273-
Rvalue::Use(ref op) => self.simplify_operand(op, span),
272+
Rvalue::Use(ref op) => self.simplify_operand(op),
274273
Rvalue::Repeat(..) |
275274
Rvalue::Ref(..) |
276275
Rvalue::Cast(..) |
@@ -300,24 +299,24 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
300299
}
301300
let substs = Substs::identity_for_item(self.tcx, self.source.def_id);
302301
let instance = Instance::new(self.source.def_id, substs);
303-
let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir).unwrap();
302+
let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir, span).unwrap();
304303

305-
let val = self.eval_operand(arg, span)?;
304+
let val = self.eval_operand(arg)?;
306305
let prim = ecx.value_to_primval(ValTy { value: val.0, ty: val.1 }).ok()?;
307306
let kind = ecx.ty_to_primval_kind(val.1).ok()?;
308307
match unary_op(op, prim, kind) {
309308
Ok(val) => Some((Value::ByVal(val), place_ty, span)),
310309
Err(mut err) => {
311-
ecx.report(&mut err, false);
310+
ecx.report(&mut err, false, Some(span));
312311
None
313312
},
314313
}
315314
}
316315
Rvalue::CheckedBinaryOp(op, ref left, ref right) |
317316
Rvalue::BinaryOp(op, ref left, ref right) => {
318317
trace!("rvalue binop {:?} for {:?} and {:?}", op, left, right);
319-
let left = self.eval_operand(left, span)?;
320-
let right = self.eval_operand(right, span)?;
318+
let left = self.eval_operand(left)?;
319+
let right = self.eval_operand(right)?;
321320
let def_id = if self.tcx.is_closure(self.source.def_id) {
322321
self.tcx.closure_base_def_id(self.source.def_id)
323322
} else {
@@ -331,7 +330,7 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
331330
}
332331
let substs = Substs::identity_for_item(self.tcx, self.source.def_id);
333332
let instance = Instance::new(self.source.def_id, substs);
334-
let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir).unwrap();
333+
let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir, span).unwrap();
335334

336335
let l = ecx.value_to_primval(ValTy { value: left.0, ty: left.1 }).ok()?;
337336
let r = ecx.value_to_primval(ValTy { value: right.0, ty: right.1 }).ok()?;
@@ -351,15 +350,15 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
351350
kind: EvalErrorKind::OverflowingMath,
352351
backtrace: None,
353352
};
354-
ecx.report(&mut err, false);
353+
ecx.report(&mut err, false, Some(span));
355354
return None;
356355
}
357356
Value::ByVal(val)
358357
};
359358
Some((val, place_ty, span))
360359
},
361360
Err(mut err) => {
362-
ecx.report(&mut err, false);
361+
ecx.report(&mut err, false, Some(span));
363362
None
364363
},
365364
}
@@ -500,7 +499,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
500499
) {
501500
trace!("visit_constant: {:?}", constant);
502501
self.super_constant(constant, location);
503-
self.eval_constant(constant, DUMMY_SP);
502+
self.eval_constant(constant);
504503
}
505504

506505
fn visit_statement(
@@ -554,17 +553,16 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
554553

555554
fn visit_terminator_kind(
556555
&mut self,
557-
_block: BasicBlock,
556+
block: BasicBlock,
558557
kind: &TerminatorKind<'tcx>,
559-
location: Location,
558+
_location: Location,
560559
) {
561-
let span = self.mir.source_info(location).span;
562560
match kind {
563561
TerminatorKind::SwitchInt { discr: value, .. } |
564562
TerminatorKind::Yield { value, .. } |
565563
TerminatorKind::Assert { cond: value, .. } => {
566-
if let Some(value) = self.simplify_operand(value, span) {
567-
self.optimizations.const_prop.insert(location, value);
564+
if let Some(value) = self.simplify_operand(value) {
565+
self.optimizations.terminators.insert(block, value);
568566
}
569567
}
570568
// FIXME: do this optimization for function calls
@@ -578,6 +576,8 @@ struct OptimizationList<'tcx> {
578576
and_stars: FxHashSet<Location>,
579577
arrays_lengths: FxHashMap<Location, Constant<'tcx>>,
580578
const_prop: FxHashMap<Location, Const<'tcx>>,
579+
/// Terminators that get their Operand(s) turned into constants.
580+
terminators: FxHashMap<BasicBlock, Const<'tcx>>,
581581
places: FxHashMap<Local, Const<'tcx>>,
582582
constants: FxHashMap<Constant<'tcx>, Const<'tcx>>,
583583
}

src/test/compile-fail/const-err2.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ fn black_box<T>(_: T) {
1919
fn main() {
2020
let a = -std::i8::MIN;
2121
//~^ ERROR const_err
22-
//~| ERROR const_err
2322
let b = 200u8 + 200u8 + 200u8;
23+
//~^ ERROR const_err
2424
let c = 200u8 * 4;
25+
//~^ ERROR const_err
2526
let d = 42u8 - (42u8 + 1);
27+
//~^ ERROR const_err
2628
let _e = [5u8][1];
2729
black_box(a);
2830
black_box(b);

src/test/compile-fail/const-err3.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ fn black_box<T>(_: T) {
1818
fn main() {
1919
let b = 200u8 + 200u8 + 200u8;
2020
//~^ ERROR const_err
21-
//~| ERROR const_err
2221
let c = 200u8 * 4;
22+
//~^ ERROR const_err
2323
let d = 42u8 - (42u8 + 1);
24+
//~^ ERROR const_err
2425
let _e = [5u8][1];
2526
black_box(b);
2627
black_box(c);

0 commit comments

Comments
 (0)