@@ -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> {
189191impl < ' 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
0 commit comments