@@ -16,7 +16,7 @@ use rustc_middle::ty::layout::{self, TyAndLayout};
16
16
use rustc_middle::ty::{
17
17
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
18
18
};
19
- use rustc_span::{source_map::DUMMY_SP, Pos, Span};
19
+ use rustc_span::{Pos, Span};
20
20
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
21
21
22
22
use super::{
@@ -83,9 +83,11 @@ pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> {
83
83
////////////////////////////////////////////////////////////////////////////////
84
84
// Current position within the function
85
85
////////////////////////////////////////////////////////////////////////////////
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 initialization, and during unwinding on
88
+ /// frames without cleanup code).
89
+ /// We basically abuse `Result` as `Either`.
90
+ pub(super) loc: Result<mir::Location, Span>,
89
91
}
90
92
91
93
/// What we store about a frame in an interpreter backtrace.
@@ -189,7 +191,14 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
189
191
impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> {
190
192
/// Return the `SourceInfo` of the current instruction.
191
193
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))
195
+ }
196
+
197
+ pub fn current_span(&self) -> Span {
198
+ match self.loc {
199
+ Ok(loc) => self.body.source_info(loc).span,
200
+ Err(span) => span,
201
+ }
193
202
}
194
203
}
195
204
@@ -324,11 +333,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
324
333
325
334
#[inline(always)]
326
335
pub fn cur_span(&self) -> Span {
327
- self.stack()
328
- .last()
329
- .and_then(|f| f.current_source_info())
330
- .map(|si| si.span)
331
- .unwrap_or(self.tcx.span)
336
+ self.stack().last().map(|f| f.current_span()).unwrap_or(self.tcx.span)
332
337
}
333
338
334
339
#[inline(always)]
@@ -640,7 +645,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
640
645
// first push a stack frame so we have access to the local substs
641
646
let pre_frame = Frame {
642
647
body,
643
- loc: Some(mir::Location::START),
648
+ loc: Err(body.span), // Span used for errors caused during preamble.
644
649
return_to_block,
645
650
return_place,
646
651
// 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> {
654
659
655
660
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
656
661
for const_ in &body.required_consts {
662
+ let span = const_.span;
657
663
let const_ =
658
664
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 to this constant.
667
+ // Avoiding doing this when evaluation succeeds.
668
+ self.frame_mut().loc = Err(span);
669
+ err
670
+ })?;
660
671
}
661
672
662
673
// Locals are initially uninitialized.
@@ -683,8 +694,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
683
694
}
684
695
// done
685
696
self.frame_mut().locals = locals;
686
-
687
697
M::after_stack_push(self)?;
698
+ self.frame_mut().loc = Ok(mir::Location::START);
688
699
info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance);
689
700
690
701
Ok(())
@@ -693,7 +704,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
693
704
/// Jump to the given block.
694
705
#[inline]
695
706
pub fn go_to_block(&mut self, target: mir::BasicBlock) {
696
- 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 });
697
708
}
698
709
699
710
/// *Return* to the given `target` basic block.
@@ -715,7 +726,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
715
726
/// If `target` is `None`, that indicates the function does not need cleanup during
716
727
/// unwinding, and we will just keep propagating that upwards.
717
728
pub fn unwind_to_block(&mut self, target: Option<mir::BasicBlock>) {
718
- 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
+ };
719
733
}
720
734
721
735
/// Pops the current frame from the stack, deallocating the
@@ -743,8 +757,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
743
757
assert_eq!(
744
758
unwinding,
745
759
match self.frame().loc {
746
- None => true ,
747
- Some(loc ) => self.body().basic_blocks()[loc.block].is_cleanup ,
760
+ Ok(loc) => self.body().basic_blocks()[loc.block].is_cleanup ,
761
+ Err(_ ) => true ,
748
762
}
749
763
);
750
764
@@ -920,14 +934,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
920
934
pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
921
935
let mut frames = Vec::new();
922
936
for frame in self.stack().iter().rev() {
923
- let source_info = frame.current_source_info();
924
- let lint_root = source_info.and_then(|source_info| {
937
+ let lint_root = frame.current_source_info().and_then(|source_info| {
925
938
match &frame.body.source_scopes[source_info.scope].local_data {
926
939
mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
927
940
mir::ClearCrossCrate::Clear => None,
928
941
}
929
942
});
930
- let span = source_info.map_or(DUMMY_SP, |source_info| source_info.span );
943
+ let span = frame.current_span( );
931
944
932
945
frames.push(FrameInfo { span, instance: frame.instance, lint_root });
933
946
}
0 commit comments