From 1e653aa96b392a04ed489eadc4cd040bc2859b4b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 6 Feb 2018 15:35:43 +0100 Subject: [PATCH] Report a best guess span if no stack is available anymore --- src/librustc_mir/interpret/const_eval.rs | 7 ++++--- src/librustc_mir/interpret/eval_context.rs | 20 +++++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index ebb62070140..b44e91d7b74 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -24,7 +24,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>( ) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>> { debug!("mk_borrowck_eval_cx: {:?}", instance); let param_env = tcx.param_env(instance.def_id()); - let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, ()); + let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, (), span); // insert a stack frame so any queries have the correct substs ecx.push_stack_frame( instance, @@ -42,7 +42,8 @@ pub fn mk_eval_cx<'a, 'tcx>( param_env: ty::ParamEnv<'tcx>, ) -> EvalResult<'tcx, EvalContext<'a, 'tcx, 'tcx, CompileTimeEvaluator>> { debug!("mk_eval_cx: {:?}, {:?}", instance, param_env); - let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, ()); + let span = tcx.def_span(instance.def_id()); + let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, (), span); let mir = ecx.load_mir(instance.def)?; // insert a stack frame so any queries have the correct substs ecx.push_stack_frame( @@ -93,10 +94,10 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>( param_env: ty::ParamEnv<'tcx>, ) -> (EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>) { debug!("eval_body: {:?}, {:?}", cid, param_env); - let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, ()); // we start out with the best span we have // and try improving it down the road when more information is available let mut span = tcx.def_span(cid.instance.def_id()); + let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, (), mir.map(|mir| mir.span).unwrap_or(span)); let res = (|| { let mut mir = match mir { Some(mir) => mir, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 2dc23e759c8..23ab6be1b46 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -45,6 +45,11 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { /// This prevents infinite loops and huge computations from freezing up const eval. /// Remove once halting problem is solved. pub(crate) steps_remaining: usize, + + /// The span that is used if no more stack frames are available + /// + /// This happens after successful evaluation when the result is inspected + root_span: codemap::Span, } /// A stack frame. @@ -186,6 +191,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M param_env: ty::ParamEnv<'tcx>, machine: M, memory_data: M::MemoryData, + root_span: codemap::Span, ) -> Self { EvalContext { machine, @@ -195,6 +201,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M stack: Vec::new(), stack_limit: tcx.sess.const_eval_stack_frame_limit.get(), steps_remaining: tcx.sess.const_eval_step_limit.get(), + root_span, } } @@ -1594,12 +1601,15 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M }; frames.push(FrameInfo { span, location }); } - let frame = self.frame(); - let bb = &frame.mir.basic_blocks()[frame.block]; - let span = if let Some(stmt) = bb.statements.get(frame.stmt) { - stmt.source_info.span + let span = if let Some(frame) = self.stack().last() { + let bb = &frame.mir.basic_blocks()[frame.block]; + if let Some(stmt) = bb.statements.get(frame.stmt) { + stmt.source_info.span + } else { + bb.terminator().source_info.span + } } else { - bb.terminator().source_info.span + self.root_span }; trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span); (frames, span)