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