@@ -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 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 > ,
89
91
}
90
92
91
93
/// What we store about a frame in an interpreter backtrace.
@@ -189,11 +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) )
193
195
}
194
196
195
197
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
+ }
197
202
}
198
203
}
199
204
@@ -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 : None , // `None` for errors generated before we start evaluating .
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 so 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,9 +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
- self . frame_mut ( ) . loc = Some ( mir:: Location :: START ) ;
687
-
688
697
M :: after_stack_push ( self ) ?;
698
+ self . frame_mut ( ) . loc = Ok ( mir:: Location :: START ) ;
689
699
info ! ( "ENTERING({}) {}" , self . frame_idx( ) , self . frame( ) . instance) ;
690
700
691
701
Ok ( ( ) )
@@ -694,7 +704,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
694
704
/// Jump to the given block.
695
705
#[ inline]
696
706
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 } ) ;
698
708
}
699
709
700
710
/// *Return* to the given `target` basic block.
@@ -716,7 +726,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
716
726
/// If `target` is `None`, that indicates the function does not need cleanup during
717
727
/// unwinding, and we will just keep propagating that upwards.
718
728
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
+ } ;
720
733
}
721
734
722
735
/// 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> {
744
757
assert_eq ! (
745
758
unwinding,
746
759
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 ,
749
762
}
750
763
) ;
751
764
0 commit comments