Skip to content

Commit d21e011

Browse files
committed
more precise span for erroneous consts during CTFE/Miri
1 parent 4b4d43f commit d21e011

File tree

5 files changed

+47
-32
lines changed

5 files changed

+47
-32
lines changed

src/librustc_mir/interpret/eval_context.rs

+26-13
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@ pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> {
8383
////////////////////////////////////////////////////////////////////////////////
8484
// Current position within the function
8585
////////////////////////////////////////////////////////////////////////////////
86-
/// If this is `None`, we are unwinding and this function doesn't need any clean-up.
87-
/// Just continue the same as with `Resume`.
88-
pub loc: Option<mir::Location>,
86+
/// If this is `Err`, we are not currently executing any particular statement in
87+
/// this frame (can happen e.g. during frame initialziation, and during unwinding on
88+
/// frames without cleanup code).
89+
/// We basically abuse `Result` as `Either`.
90+
pub(super) loc: Result<mir::Location, Span>,
8991
}
9092

9193
/// What we store about a frame in an interpreter backtrace.
@@ -189,11 +191,14 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
189191
impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> {
190192
/// Return the `SourceInfo` of the current instruction.
191193
pub fn current_source_info(&self) -> Option<&mir::SourceInfo> {
192-
self.loc.map(|loc| self.body.source_info(loc))
194+
self.loc.ok().map(|loc| self.body.source_info(loc))
193195
}
194196

195197
pub fn current_span(&self) -> Span {
196-
self.current_source_info().map(|si| si.span).unwrap_or(self.body.span)
198+
match self.loc {
199+
Ok(loc) => self.body.source_info(loc).span,
200+
Err(span) => span,
201+
}
197202
}
198203
}
199204

@@ -640,7 +645,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
640645
// first push a stack frame so we have access to the local substs
641646
let pre_frame = Frame {
642647
body,
643-
loc: None, // `None` for errors generated before we start evaluating.
648+
loc: Err(body.span), // Span used for errors caused during preamble.
644649
return_to_block,
645650
return_place,
646651
// empty local array, we fill it in below, after we are inside the stack frame and
@@ -654,9 +659,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
654659

655660
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
656661
for const_ in &body.required_consts {
662+
let span = const_.span;
657663
let const_ =
658664
self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal);
659-
self.const_to_op(const_, None)?;
665+
self.const_to_op(const_, None).map_err(|err| {
666+
// If there was an error, set the span of the current frame so this constant.
667+
// Avoiding doing this when evaluation succeeds.
668+
self.frame_mut().loc = Err(span);
669+
err
670+
})?;
660671
}
661672

662673
// Locals are initially uninitialized.
@@ -683,9 +694,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
683694
}
684695
// done
685696
self.frame_mut().locals = locals;
686-
self.frame_mut().loc = Some(mir::Location::START);
687-
688697
M::after_stack_push(self)?;
698+
self.frame_mut().loc = Ok(mir::Location::START);
689699
info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance);
690700

691701
Ok(())
@@ -694,7 +704,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
694704
/// Jump to the given block.
695705
#[inline]
696706
pub fn go_to_block(&mut self, target: mir::BasicBlock) {
697-
self.frame_mut().loc = Some(mir::Location { block: target, statement_index: 0 });
707+
self.frame_mut().loc = Ok(mir::Location { block: target, statement_index: 0 });
698708
}
699709

700710
/// *Return* to the given `target` basic block.
@@ -716,7 +726,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
716726
/// If `target` is `None`, that indicates the function does not need cleanup during
717727
/// unwinding, and we will just keep propagating that upwards.
718728
pub fn unwind_to_block(&mut self, target: Option<mir::BasicBlock>) {
719-
self.frame_mut().loc = target.map(|block| mir::Location { block, statement_index: 0 });
729+
self.frame_mut().loc = match target {
730+
Some(block) => Ok(mir::Location { block, statement_index: 0 }),
731+
None => Err(self.frame_mut().body.span),
732+
};
720733
}
721734

722735
/// Pops the current frame from the stack, deallocating the
@@ -744,8 +757,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
744757
assert_eq!(
745758
unwinding,
746759
match self.frame().loc {
747-
None => true,
748-
Some(loc) => self.body().basic_blocks()[loc.block].is_cleanup,
760+
Ok(loc) => self.body().basic_blocks()[loc.block].is_cleanup,
761+
Err(_) => true,
749762
}
750763
);
751764

src/librustc_mir/interpret/step.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
4747
}
4848

4949
let loc = match self.frame().loc {
50-
Some(loc) => loc,
51-
None => {
50+
Ok(loc) => loc,
51+
Err(_) => {
5252
// We are unwinding and this fn has no cleanup code.
5353
// Just go on unwinding.
5454
trace!("unwinding: skipping frame");
@@ -283,7 +283,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
283283

284284
self.eval_terminator(terminator)?;
285285
if !self.stack().is_empty() {
286-
if let Some(loc) = self.frame().loc {
286+
if let Ok(loc) = self.frame().loc {
287287
info!("// executing {:?}", loc.block);
288288
}
289289
}

src/test/ui/consts/const-err-multi.stderr

+12-6
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,28 @@ LL | #![deny(const_err)]
1313
| ^^^^^^^^^
1414

1515
error: any use of this value will cause an error
16-
--> $DIR/const-err-multi.rs:5:1
16+
--> $DIR/const-err-multi.rs:5:19
1717
|
1818
LL | pub const B: i8 = A;
19-
| ^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
19+
| ------------------^-
20+
| |
21+
| referenced constant has errors
2022

2123
error: any use of this value will cause an error
22-
--> $DIR/const-err-multi.rs:7:1
24+
--> $DIR/const-err-multi.rs:7:19
2325
|
2426
LL | pub const C: u8 = A as u8;
25-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
27+
| ------------------^-------
28+
| |
29+
| referenced constant has errors
2630

2731
error: any use of this value will cause an error
28-
--> $DIR/const-err-multi.rs:9:1
32+
--> $DIR/const-err-multi.rs:9:24
2933
|
3034
LL | pub const D: i8 = 50 - A;
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
35+
| -----------------------^-
36+
| |
37+
| referenced constant has errors
3238

3339
error: aborting due to 4 previous errors
3440

src/test/ui/consts/const-eval/erroneous-const.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ impl<T> PrintName<T> {
77
//~^ WARN this operation will panic at runtime
88
}
99

10-
const fn no_codegen<T>() { //~ERROR evaluation of constant value failed
10+
const fn no_codegen<T>() {
1111
if false {
12-
let _ = PrintName::<T>::VOID;
12+
let _ = PrintName::<T>::VOID; //~ERROR evaluation of constant value failed
1313
}
1414
}
1515

src/test/ui/consts/const-eval/erroneous-const.stderr

+4-8
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,10 @@ LL | #![warn(const_err, unconditional_panic)]
2525
| ^^^^^^^^^
2626

2727
error[E0080]: evaluation of constant value failed
28-
--> $DIR/erroneous-const.rs:10:1
29-
|
30-
LL | / const fn no_codegen<T>() {
31-
LL | | if false {
32-
LL | | let _ = PrintName::<T>::VOID;
33-
LL | | }
34-
LL | | }
35-
| |_^ referenced constant has errors
28+
--> $DIR/erroneous-const.rs:12:17
29+
|
30+
LL | let _ = PrintName::<T>::VOID;
31+
| ^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
3632

3733
error[E0080]: could not evaluate static initializer
3834
--> $DIR/erroneous-const.rs:16:22

0 commit comments

Comments
 (0)