@@ -16,7 +16,7 @@ use rustc_middle::ty::layout::{self, TyAndLayout};
1616use rustc_middle:: ty:: {
1717 self , query:: TyCtxtAt , subst:: SubstsRef , ParamEnv , Ty , TyCtxt , TypeFoldable ,
1818} ;
19- use rustc_span:: { source_map :: DUMMY_SP , Pos , Span } ;
19+ use rustc_span:: { Pos , Span } ;
2020use rustc_target:: abi:: { Align , HasDataLayout , LayoutOf , Size , TargetDataLayout } ;
2121
2222use super :: {
@@ -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 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 > ,
8991}
9092
9193/// What we store about a frame in an interpreter backtrace.
@@ -189,7 +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) )
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+ }
193202 }
194203}
195204
@@ -324,11 +333,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
324333
325334 #[ inline( always) ]
326335 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 )
332337 }
333338
334339 #[ inline( always) ]
@@ -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 : Some ( mir :: Location :: START ) ,
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 to 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,8 +694,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
683694 }
684695 // done
685696 self . frame_mut ( ) . locals = locals;
686-
687697 M :: after_stack_push ( self ) ?;
698+ self . frame_mut ( ) . loc = Ok ( mir:: Location :: START ) ;
688699 info ! ( "ENTERING({}) {}" , self . frame_idx( ) , self . frame( ) . instance) ;
689700
690701 Ok ( ( ) )
@@ -693,7 +704,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
693704 /// Jump to the given block.
694705 #[ inline]
695706 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 } ) ;
697708 }
698709
699710 /// *Return* to the given `target` basic block.
@@ -715,7 +726,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
715726 /// If `target` is `None`, that indicates the function does not need cleanup during
716727 /// unwinding, and we will just keep propagating that upwards.
717728 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+ } ;
719733 }
720734
721735 /// 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> {
743757 assert_eq ! (
744758 unwinding,
745759 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 ,
748762 }
749763 ) ;
750764
@@ -920,14 +934,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
920934 pub fn generate_stacktrace ( & self ) -> Vec < FrameInfo < ' tcx > > {
921935 let mut frames = Vec :: new ( ) ;
922936 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| {
925938 match & frame. body . source_scopes [ source_info. scope ] . local_data {
926939 mir:: ClearCrossCrate :: Set ( data) => Some ( data. lint_root ) ,
927940 mir:: ClearCrossCrate :: Clear => None ,
928941 }
929942 } ) ;
930- let span = source_info . map_or ( DUMMY_SP , |source_info| source_info . span ) ;
943+ let span = frame . current_span ( ) ;
931944
932945 frames. push ( FrameInfo { span, instance : frame. instance , lint_root } ) ;
933946 }
0 commit comments